[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 &LT) 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