[llvm] 6e0c9e4 - [DebugInfo] Prevent crash when .debug_line line_range is zero
James Henderson via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 9 06:00:37 PDT 2020
Author: James Henderson
Date: 2020-03-09T12:59:43Z
New Revision: 6e0c9e46967e1dc701a8be66c5fd250c78d9a73e
URL: https://github.com/llvm/llvm-project/commit/6e0c9e46967e1dc701a8be66c5fd250c78d9a73e
DIFF: https://github.com/llvm/llvm-project/commit/6e0c9e46967e1dc701a8be66c5fd250c78d9a73e.diff
LOG: [DebugInfo] Prevent crash when .debug_line line_range is zero
The line_range value of a debug line program header is used in divisions
related to special opcodes and DW_LNS_const_add_pc opcodes. As such, a
value of 0 cannot be used. This change introduces a new warning, if such
a situation is identified, and does not perform the relevant
calculations.
Reviewed by: probinson, aprantl
Differential Revision: https://reviews.llvm.org/D43470
Added:
Modified:
llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index d2208abad58b..1de94aed470b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -401,6 +401,7 @@ class DWARFDebugLine {
uint64_t LineTableOffset;
bool ReportAdvanceAddrProblem = true;
+ bool ReportBadLineRange = true;
function_ref<void(Error)> ErrorHandler;
};
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index 08f47aab8dcf..ff23f61b5b9f 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -603,11 +603,27 @@ DWARFDebugLine::ParsingState::advanceAddrForOpcode(uint8_t Opcode,
uint64_t OpcodeOffset) {
assert(Opcode == DW_LNS_const_add_pc ||
Opcode >= LineTable->Prologue.OpcodeBase);
+ if (ReportBadLineRange && LineTable->Prologue.LineRange == 0) {
+ StringRef OpcodeName =
+ getOpcodeName(Opcode, LineTable->Prologue.OpcodeBase);
+ 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",
+ LineTableOffset, OpcodeName.data(), OpcodeOffset));
+ ReportBadLineRange = false;
+ }
+
uint8_t OpcodeValue = Opcode;
if (Opcode == DW_LNS_const_add_pc)
OpcodeValue = 255;
uint8_t AdjustedOpcode = OpcodeValue - LineTable->Prologue.OpcodeBase;
- uint64_t OperationAdvance = AdjustedOpcode / LineTable->Prologue.LineRange;
+ uint64_t OperationAdvance =
+ LineTable->Prologue.LineRange != 0
+ ? AdjustedOpcode / LineTable->Prologue.LineRange
+ : 0;
uint64_t AddrOffset = advanceAddr(OperationAdvance, Opcode, OpcodeOffset);
return {AddrOffset, AdjustedOpcode};
}
@@ -648,9 +664,11 @@ DWARFDebugLine::ParsingState::handleSpecialOpcode(uint8_t Opcode,
DWARFDebugLine::ParsingState::AddrAndAdjustedOpcode AddrAdvanceResult =
advanceAddrForOpcode(Opcode, OpcodeOffset);
- int32_t LineOffset =
- LineTable->Prologue.LineBase +
- (AddrAdvanceResult.AdjustedOpcode % LineTable->Prologue.LineRange);
+ int32_t LineOffset = 0;
+ if (LineTable->Prologue.LineRange != 0)
+ LineOffset =
+ LineTable->Prologue.LineBase +
+ (AddrAdvanceResult.AdjustedOpcode % LineTable->Prologue.LineRange);
Row.Line += LineOffset;
return {AddrAdvanceResult.AddrDelta, LineOffset};
}
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
index 0164100f6595..5585a590f3e5 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
@@ -961,6 +961,46 @@ INSTANTIATE_TEST_CASE_P(
std::make_tuple(
4, 2, true)), ); // Test one higher than permitted V4 (error).
+struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>,
+ AdjustAddressFixtureBase {
+ void SetUp() override { 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 {
+ if (LineRange == 0)
+ return Base + AdvanceIncr;
+ return AdjustAddressFixtureBase::getAdjustedAddr(Base, ConstIncr,
+ SpecialIncr, 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;
More information about the llvm-commits
mailing list