[llvm] r318838 - [DWARF] Fix handling of extended line-number opcodes

Paul Robinson via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 22 07:14:49 PST 2017


Author: probinson
Date: Wed Nov 22 07:14:49 2017
New Revision: 318838

URL: http://llvm.org/viewvc/llvm-project?rev=318838&view=rev
Log:
[DWARF] Fix handling of extended line-number opcodes

Differential Revision: https://reviews.llvm.org/D40200

Added:
    llvm/trunk/test/DebugInfo/X86/dwarfdump-bogus-LNE.s
Modified:
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
    llvm/trunk/test/MC/ELF/discriminator.s

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp?rev=318838&r1=318837&r2=318838&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp Wed Nov 22 07:14:49 2017
@@ -427,9 +427,15 @@ bool DWARFDebugLine::LineTable::parse(co
     if (Opcode == 0) {
       // Extended Opcodes always start with a zero opcode followed by
       // a uleb128 length so you can skip ones you don't know about
-      uint32_t ExtOffset = *OffsetPtr;
       uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
-      uint32_t ArgSize = Len - (*OffsetPtr - ExtOffset);
+      uint32_t ExtOffset = *OffsetPtr;
+
+      // Tolerate zero-length; assume length is correct and soldier on.
+      if (Len == 0) {
+        if (OS)
+          *OS << "Badly formed extended line op (length 0)\n";
+        continue;
+      }
 
       uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
       if (OS)
@@ -508,11 +514,24 @@ bool DWARFDebugLine::LineTable::parse(co
         break;
 
       default:
-        // Length doesn't include the zero opcode byte or the length itself, but
-        // it does include the sub_opcode, so we have to adjust for that below
-        (*OffsetPtr) += ArgSize;
+        if (OS)
+          *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
+              << format(" length %" PRIx64, Len);
+        // Len doesn't include the zero opcode byte or the length itself, but
+        // it does include the sub_opcode, so we have to adjust for that.
+        (*OffsetPtr) += Len - 1;
         break;
       }
+      // Make sure the stated and parsed lengths are the same.
+      // Otherwise we have an unparseable line-number program.
+      if (*OffsetPtr - ExtOffset != Len) {
+        fprintf(stderr, "Unexpected line op length at offset 0x%8.8" PRIx32
+                " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32 "\n",
+                ExtOffset, Len, *OffsetPtr - ExtOffset);
+        // Skip the rest of the line-number program.
+        *OffsetPtr = EndOffset;
+        return false;
+      }
     } else if (Opcode < Prologue.OpcodeBase) {
       if (OS)
         *OS << LNStandardString(Opcode);

Added: llvm/trunk/test/DebugInfo/X86/dwarfdump-bogus-LNE.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dwarfdump-bogus-LNE.s?rev=318838&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dwarfdump-bogus-LNE.s (added)
+++ llvm/trunk/test/DebugInfo/X86/dwarfdump-bogus-LNE.s Wed Nov 22 07:14:49 2017
@@ -0,0 +1,152 @@
+# Test object to verify dwarfdump handles a syntactically correct line-number
+# program containing unrecognized extended opcodes.
+# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o
+# RUN: llvm-dwarfdump -v %t.o | FileCheck %s
+# RUN: llvm-dwarfdump -v %t.o 2>&1 | FileCheck %s --check-prefix=ERR
+
+        .section .text
+        # Dummy function
+foo:    ret
+
+# FIXME: When we can dump a line-table without a unit, we could remove
+# the .debug_abbrev and .debug_info sections from this test.
+        .section .debug_abbrev,"", at progbits
+        .byte 0x01  # Abbrev code
+        .byte 0x11  # DW_TAG_compile_unit
+        .byte 0x00  # DW_CHILDREN_no
+        .byte 0x10  # DW_AT_stmt_list
+        .byte 0x17  # DW_FORM_sec_offset
+        .byte 0x00  # EOM(1)
+        .byte 0x00  # EOM(2)
+
+        .section .debug_info,"", at progbits
+        .long  CU_end-CU_version  # Length of Unit
+CU_version:
+        .short 4               # DWARF version number
+        .long .debug_abbrev    # Offset Into Abbrev. Section
+        .byte 8                # Address Size (in bytes)
+# The compile-unit DIE, with DW_AT_stmt_list.
+        .byte 1
+        .long LT_start
+        .byte 0 # NULL
+CU_end:
+
+        .long  CU2_end-CU2_version  # Length of Unit
+CU2_version:
+        .short 4               # DWARF version number
+        .long .debug_abbrev    # Offset Into Abbrev. Section
+        .byte 8                # Address Size (in bytes)
+# The compile-unit DIE, with DW_AT_stmt_list.
+        .byte 1
+        .long LT2_start
+        .byte 0 # NULL
+CU2_end:
+
+        .section .debug_line,"", at progbits
+# CHECK-LABEL: .debug_line contents:
+
+# DWARF v4 line-table header.
+LT_start:
+        .long   LT_end-LT_version   # Length of Unit (DWARF-32 format)
+LT_version:
+        .short  4               # DWARF version number
+        .long   LT_header_end-LT_params     # Length of Prologue
+LT_params:
+        .byte   1               # Minimum Instruction Length
+        .byte   1               # Maximum Operations per Instruction
+        .byte   1               # Default is_stmt
+        .byte   -5              # Line Base
+        .byte   14              # Line Range
+        .byte   13              # Opcode Base
+        .byte   0               # Standard Opcode Lengths
+        .byte   1
+        .byte   1
+        .byte   1
+        .byte   1
+        .byte   0
+        .byte   0
+        .byte   0
+        .byte   1
+        .byte   0
+        .byte   0
+        .byte   1
+        # No directories.
+        .byte   0
+        # No files.
+        .byte   0
+LT_header_end:
+        # Bogus extended opcode with zero length.
+        .byte   0               # Extended opcode indicator.
+        .byte   0               # LEB length of extended opcode + operands.
+        # Real opcode and operand.
+        .byte   0
+        .byte   9
+        .byte   2               # DW_LNE_set_address
+        .quad   .text
+        # Bogus extended opcode with multibyte LEB length.
+        .byte   0
+        .byte   0x82            # Length of 2 but with additional length byte.
+        .byte   0               # Additional length byte.
+        .byte   0x47            # Unrecognized opcode...
+        .byte   0               # with its 1-byte operand.
+        # Proper end-sequence opcode.
+        .byte   0
+        .byte   1
+        .byte   1               # DW_LNE_end_sequence
+LT_end:
+
+# CHECK:      Line table prologue:
+# CHECK:      version: 4
+# Exact prologue length isn't important but it tells us where to expect the
+# line-number program to start, and we do want to verify those offsets.
+# CHECK-NEXT: prologue_length: 0x00000014
+# CHECK:      0x0000001e: 00 Badly formed extended line op
+# CHECK-NEXT: 0x00000020: 00 DW_LNE_set_address
+# CHECK-NEXT: 0x0000002b: 00 Unrecognized extended op 0x47 length 2
+# CHECK-NEXT: 0x00000030: 00 DW_LNE_end_sequence
+# CHECK-NEXT: 0x0000000000000000 {{.*}} is_stmt end_sequence
+
+
+# DWARF v4 line-table header #2.
+LT2_start:
+        .long   LT2_end-LT2_version   # Length of Unit (DWARF-32 format)
+LT2_version:
+        .short  4               # DWARF version number
+        .long   LT2_header_end-LT2_params   # Length of Prologue
+LT2_params:
+        .byte   1               # Minimum Instruction Length
+        .byte   1               # Maximum Operations per Instruction
+        .byte   1               # Default is_stmt
+        .byte   -5              # Line Base
+        .byte   14              # Line Range
+        .byte   13              # Opcode Base
+        .byte   0               # Standard Opcode Lengths
+        .byte   1
+        .byte   1
+        .byte   1
+        .byte   1
+        .byte   0
+        .byte   0
+        .byte   0
+        .byte   1
+        .byte   0
+        .byte   0
+        .byte   1
+        # No directories.
+        .byte   0
+        # No files.
+        .byte   0
+LT2_header_end:
+        # Real opcode and operand.
+        .byte   0
+        .byte   9
+        .byte   2               # DW_LNE_set_address
+        .quad   .text
+        # Real opcode with incorrect length.
+        .byte   0
+        .byte   2               # Wrong length, should be 1.
+        .byte   1               # DW_LNE_end_sequence
+LT2_end:
+
+# ERR:      Unexpected line op length at offset 0x0000005e
+# ERR-SAME: expected 0x02 found 0x01

Modified: llvm/trunk/test/MC/ELF/discriminator.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/discriminator.s?rev=318838&r1=318837&r2=318838&view=diff
==============================================================================
--- llvm/trunk/test/MC/ELF/discriminator.s (original)
+++ llvm/trunk/test/MC/ELF/discriminator.s Wed Nov 22 07:14:49 2017
@@ -17,7 +17,7 @@ foo:
         .long   34                      # Length of Unit
         .short  4                       # DWARF version number
         .long   .L.debug_abbrev_begin   # Offset Into Abbrev. Section
-        .byte   8                       # Address Size (in bytes)
+        .byte   4                       # Address Size (in bytes)
         .byte   1                       # Abbrev [1] 0xb:0x1b DW_TAG_compile_unit
         .long   info_string0            # DW_AT_producer
         .short  12                      # DW_AT_language
@@ -58,4 +58,4 @@ foo:
 
 # DWARF-DUMP: Address            Line   Column File   ISA Discriminator Flags
 # DWARF-DUMP: ------------------ ------ ------ ------ --- ------------- -------------
-# DWARF-DUMP: 0x0001021300000000     1      0      1   0             1  is_stmt
+# DWARF-DUMP: 0x0000000000000000     2      0      1   0             1  is_stmt




More information about the llvm-commits mailing list