[llvm] 8daa326 - [DWARFYAML] Make the unit_length and header_length fields optional.

Xing GUO via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 05:35:28 PDT 2020


Author: Xing GUO
Date: 2020-08-26T20:35:10+08:00
New Revision: 8daa3264a3329ad34a0b210afdd8699f27d66db2

URL: https://github.com/llvm/llvm-project/commit/8daa3264a3329ad34a0b210afdd8699f27d66db2
DIFF: https://github.com/llvm/llvm-project/commit/8daa3264a3329ad34a0b210afdd8699f27d66db2.diff

LOG: [DWARFYAML] Make the unit_length and header_length fields optional.

This patch makes the unit_length and header_length fields of line tables
optional. yaml2obj is able to infer them for us.

Reviewed By: jhenderson

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

Added: 
    

Modified: 
    llvm/include/llvm/ObjectYAML/DWARFYAML.h
    llvm/lib/ObjectYAML/DWARFEmitter.cpp
    llvm/lib/ObjectYAML/DWARFYAML.cpp
    llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml
    llvm/tools/obj2yaml/dwarf2yaml.cpp
    llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
index 005936d1a8ab..9625d02ea324 100644
--- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
@@ -137,9 +137,9 @@ struct LineTableOpcode {
 
 struct LineTable {
   dwarf::DwarfFormat Format;
-  uint64_t Length;
+  Optional<uint64_t> Length;
   uint16_t Version;
-  uint64_t PrologueLength;
+  Optional<uint64_t> PrologueLength;
   uint8_t MinInstLength;
   uint8_t MaxOpsPerInst;
   uint8_t DefaultIsStmt;

diff  --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp
index ead629f9a741..bbcf56cc0cec 100644
--- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp
@@ -448,89 +448,113 @@ static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
   encodeULEB128(File.Length, OS);
 }
 
+static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
+                                 uint8_t OpcodeBase, uint8_t AddrSize,
+                                 raw_ostream &OS, bool IsLittleEndian) {
+  writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);
+  if (Op.Opcode == 0) {
+    encodeULEB128(Op.ExtLen, OS);
+    writeInteger((uint8_t)Op.SubOpcode, OS, IsLittleEndian);
+    switch (Op.SubOpcode) {
+    case dwarf::DW_LNE_set_address:
+      cantFail(
+          writeVariableSizedInteger(Op.Data, AddrSize, OS, IsLittleEndian));
+      break;
+    case dwarf::DW_LNE_define_file:
+      emitFileEntry(OS, Op.FileEntry);
+      break;
+    case dwarf::DW_LNE_set_discriminator:
+      encodeULEB128(Op.Data, OS);
+      break;
+    case dwarf::DW_LNE_end_sequence:
+      break;
+    default:
+      for (auto OpByte : Op.UnknownOpcodeData)
+        writeInteger((uint8_t)OpByte, OS, IsLittleEndian);
+    }
+  } else if (Op.Opcode < OpcodeBase) {
+    switch (Op.Opcode) {
+    case dwarf::DW_LNS_copy:
+    case dwarf::DW_LNS_negate_stmt:
+    case dwarf::DW_LNS_set_basic_block:
+    case dwarf::DW_LNS_const_add_pc:
+    case dwarf::DW_LNS_set_prologue_end:
+    case dwarf::DW_LNS_set_epilogue_begin:
+      break;
+
+    case dwarf::DW_LNS_advance_pc:
+    case dwarf::DW_LNS_set_file:
+    case dwarf::DW_LNS_set_column:
+    case dwarf::DW_LNS_set_isa:
+      encodeULEB128(Op.Data, OS);
+      break;
+
+    case dwarf::DW_LNS_advance_line:
+      encodeSLEB128(Op.SData, OS);
+      break;
+
+    case dwarf::DW_LNS_fixed_advance_pc:
+      writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);
+      break;
+
+    default:
+      for (auto OpData : Op.StandardOpcodeData) {
+        encodeULEB128(OpData, OS);
+      }
+    }
+  }
+}
+
 Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
-  for (const auto &LineTable : DI.DebugLines) {
-    writeInitialLength(LineTable.Format, LineTable.Length, OS,
-                       DI.IsLittleEndian);
-    writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian);
-    writeDWARFOffset(LineTable.PrologueLength, LineTable.Format, OS, DI.IsLittleEndian);
-    writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian);
+  for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
+    // Buffer holds the bytes following the header_length (or prologue_length in
+    // DWARFv2) field to the end of the line number program itself.
+    std::string Buffer;
+    raw_string_ostream BufferOS(Buffer);
+
+    writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);
+    // TODO: Add support for emitting DWARFv5 line table.
     if (LineTable.Version >= 4)
-      writeInteger((uint8_t)LineTable.MaxOpsPerInst, OS, DI.IsLittleEndian);
-    writeInteger((uint8_t)LineTable.DefaultIsStmt, OS, DI.IsLittleEndian);
-    writeInteger((uint8_t)LineTable.LineBase, OS, DI.IsLittleEndian);
-    writeInteger((uint8_t)LineTable.LineRange, OS, DI.IsLittleEndian);
-    writeInteger((uint8_t)LineTable.OpcodeBase, OS, DI.IsLittleEndian);
-
-    for (auto OpcodeLength : LineTable.StandardOpcodeLengths)
-      writeInteger((uint8_t)OpcodeLength, OS, DI.IsLittleEndian);
-
-    for (auto IncludeDir : LineTable.IncludeDirs) {
-      OS.write(IncludeDir.data(), IncludeDir.size());
-      OS.write('\0');
+      writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);
+    writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);
+    writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);
+    writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);
+    writeInteger(LineTable.OpcodeBase, BufferOS, DI.IsLittleEndian);
+
+    for (uint8_t OpcodeLength : LineTable.StandardOpcodeLengths)
+      writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
+
+    for (StringRef IncludeDir : LineTable.IncludeDirs) {
+      BufferOS.write(IncludeDir.data(), IncludeDir.size());
+      BufferOS.write('\0');
     }
-    OS.write('\0');
+    BufferOS.write('\0');
 
-    for (auto File : LineTable.Files)
-      emitFileEntry(OS, File);
-    OS.write('\0');
+    for (const DWARFYAML::File &File : LineTable.Files)
+      emitFileEntry(BufferOS, File);
+    BufferOS.write('\0');
 
-    uint8_t AddrSize = DI.Is64BitAddrSize ? 8 : 4;
-
-    for (auto Op : LineTable.Opcodes) {
-      writeInteger((uint8_t)Op.Opcode, OS, DI.IsLittleEndian);
-      if (Op.Opcode == 0) {
-        encodeULEB128(Op.ExtLen, OS);
-        writeInteger((uint8_t)Op.SubOpcode, OS, DI.IsLittleEndian);
-        switch (Op.SubOpcode) {
-        case dwarf::DW_LNE_set_address:
-          cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OS,
-                                             DI.IsLittleEndian));
-          break;
-        case dwarf::DW_LNE_define_file:
-          emitFileEntry(OS, Op.FileEntry);
-          break;
-        case dwarf::DW_LNE_set_discriminator:
-          encodeULEB128(Op.Data, OS);
-          break;
-        case dwarf::DW_LNE_end_sequence:
-          break;
-        default:
-          for (auto OpByte : Op.UnknownOpcodeData)
-            writeInteger((uint8_t)OpByte, OS, DI.IsLittleEndian);
-        }
-      } else if (Op.Opcode < LineTable.OpcodeBase) {
-        switch (Op.Opcode) {
-        case dwarf::DW_LNS_copy:
-        case dwarf::DW_LNS_negate_stmt:
-        case dwarf::DW_LNS_set_basic_block:
-        case dwarf::DW_LNS_const_add_pc:
-        case dwarf::DW_LNS_set_prologue_end:
-        case dwarf::DW_LNS_set_epilogue_begin:
-          break;
-
-        case dwarf::DW_LNS_advance_pc:
-        case dwarf::DW_LNS_set_file:
-        case dwarf::DW_LNS_set_column:
-        case dwarf::DW_LNS_set_isa:
-          encodeULEB128(Op.Data, OS);
-          break;
-
-        case dwarf::DW_LNS_advance_line:
-          encodeSLEB128(Op.SData, OS);
-          break;
-
-        case dwarf::DW_LNS_fixed_advance_pc:
-          writeInteger((uint16_t)Op.Data, OS, DI.IsLittleEndian);
-          break;
-
-        default:
-          for (auto OpData : Op.StandardOpcodeData) {
-            encodeULEB128(OpData, OS);
-          }
-        }
-      }
+    uint64_t HeaderLength =
+        LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();
+
+    for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
+      writeLineTableOpcode(Op, LineTable.OpcodeBase, DI.Is64BitAddrSize ? 8 : 4,
+                           BufferOS, DI.IsLittleEndian);
+
+    uint64_t Length;
+    if (LineTable.Length) {
+      Length = *LineTable.Length;
+    } else {
+      Length = 2; // sizeof(version)
+      Length +=
+          (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)
+      Length += Buffer.size();
     }
+
+    writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);
+    writeInteger(LineTable.Version, OS, DI.IsLittleEndian);
+    writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
+    OS.write(Buffer.data(), Buffer.size());
   }
 
   return Error::success();

diff  --git a/llvm/lib/ObjectYAML/DWARFYAML.cpp b/llvm/lib/ObjectYAML/DWARFYAML.cpp
index 0e453596c9d7..39de3ff18f37 100644
--- a/llvm/lib/ObjectYAML/DWARFYAML.cpp
+++ b/llvm/lib/ObjectYAML/DWARFYAML.cpp
@@ -230,9 +230,9 @@ void MappingTraits<DWARFYAML::LineTableOpcode>::mapping(
 void MappingTraits<DWARFYAML::LineTable>::mapping(
     IO &IO, DWARFYAML::LineTable &LineTable) {
   IO.mapOptional("Format", LineTable.Format, dwarf::DWARF32);
-  IO.mapRequired("Length", LineTable.Length);
+  IO.mapOptional("Length", LineTable.Length);
   IO.mapRequired("Version", LineTable.Version);
-  IO.mapRequired("PrologueLength", LineTable.PrologueLength);
+  IO.mapOptional("PrologueLength", LineTable.PrologueLength);
   IO.mapRequired("MinInstLength", LineTable.MinInstLength);
   if(LineTable.Version >= 4)
     IO.mapRequired("MaxOpsPerInst", LineTable.MaxOpsPerInst);

diff  --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml
index 77f7e6151731..78d873d91670 100644
--- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml
@@ -479,3 +479,115 @@ DWARF:
           ExtLen:    0x09
           SubOpcode: DW_LNE_set_discriminator
           Data:      0x1234
+
+## j) Test that yaml2obj is able to infer the length and header_length fields.
+
+# RUN: yaml2obj --docnum=10 %s -o %t10.o
+# RUN: llvm-readelf --hex-dump=.debug_line %t10.o | FileCheck %s --check-prefix=INFER-LENGTH
+
+#      INFER-LENGTH: Hex dump of section '.debug_line':
+# INFER-LENGTH-NEXT: 0x00000000 2e000000 04002500 00000101 01fb0e04 ......%.........
+##                              ^-------                            unit_length (4-byte) 0x2e
+##                                       ^---                       version (2-byte)
+##                                           ^--------              header_length (4-byte) 0x25
+##                                                    ^-            minimum_instruction_length (1-byte)
+##                                                      ^-          maximum_operations_per_instruction (1-byte)
+##                                                         ^-       default_is_stmt (1-byte)
+##                                                           ^-     line_base (1-byte) -5
+##                                                             ^-   line_range (1-byte)
+##                                                               ^- opcode_base (1-byte)
+# INFER-LENGTH-NEXT: 0x00000010 00010174 656d7031 0074656d 70320000 ...temp1.temp2..
+##                              ^-----                              standard_opcode_lengths (3-byte)
+##                                    ^-------------                include_directories[1] "temp1\0"
+##                                                  ^------------   include_directories[2] "temp1\0"
+##                                                               ^- include_directories null byte
+# INFER-LENGTH-NEXT: 0x00000020 612e6300 01000062 2e630002 00000000 a.c....b.c......
+##                              ^-------                            file_names[1] file name "a.c\0"
+##                                       ^-                         file_names[1] directory index (ULEB128) 0x01
+##                                         ^-                       file_names[1] file length (ULEB128) 0x00
+##                                           ^-                     file_names[1] modification time 0x00
+##                                             ^--------            file_names[2] file name "b.c\0"
+##                                                      ^-          file_names[2] directory index (ULEB128) 0x02
+##                                                         ^-       file_names[2] file length (ULEB128) 0x00
+##                                                           ^-     file_names[2] modification time 0x00
+##                                                             ^-   file_names null byte
+##                                                               ^- DW_LNS_extended_op
+# INFER-LENGTH-NEXT: 0x00000030 0101ffff ffff2500 00000000 00000400 ......%.........
+##                              ^-                                  extended op length (ULEB128) 0x01
+##                                ^-                                DW_LNE_end_sequence
+##                                  ^--------------------------     unit_length (12-byte)
+##                                                             ^--- version (2-byte)
+# INFER-LENGTH-NEXT: 0x00000040 18000000 00000000 010101fb 0e040001 ................
+##                              ^----------------                   header_length (8-byte)
+##                                                ^-                minimum_instruction_length (1-byte)
+##                                                  ^-              maximum_operations_per_instruction (1-byte)
+##                                                    ^-            default_is_stmt (1-byte)
+##                                                      ^-          line_base (1-byte) -5
+##                                                         ^-       line_range (1-byte)
+##                                                           ^-     opcode_base (1-byte)
+##                                                             ^--- standard_opcode_lengths (3-byte)
+# INFER-LENGTH-NEXT: 0x00000050 0174656d 70330000 632e6300 01000000 .temp3..c.c.....
+##                              --
+##                                ^------------                     include_directories[1] "temp3\0"
+##                                             ^-                   include_directories null byte
+##                                                ^-------          file_names[1] file name "a.c\0"
+##                                                         ^-       file_names[1] directory index (ULEB128) 0x01
+##                                                           ^-     file_names[1] file length (ULEB128) 0x00
+##                                                             ^-   file_names[1] modification time 0x00
+##                                                               ^- file_names null byte
+# INFER-LENGTH-NEXT: 0x00000060 000101                              ...
+##                              ^-                                  DW_LNS_extended_op
+##                                ^-                                extended op length (ULEB128) 0x01
+##                                  ^-                              DW_LNE_end_sequence
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+DWARF:
+  debug_line:
+    - Version:               4
+      MinInstLength:         1
+      MaxOpsPerInst:         1
+      DefaultIsStmt:         1
+      LineBase:              251
+      LineRange:             14
+      OpcodeBase:            4
+      StandardOpcodeLengths: [ 0, 1, 1 ]
+      IncludeDirs:
+        - temp1
+        - temp2
+      Files:
+        - Name:    a.c
+          DirIdx:  1
+          ModTime: 0
+          Length:  0
+        - Name:    b.c
+          DirIdx:  2
+          ModTime: 0
+          Length:  0
+      Opcodes:
+        - Opcode:    DW_LNS_extended_op
+          ExtLen:    1
+          SubOpcode: DW_LNE_end_sequence
+    - Format:                DWARF64
+      Version:               4
+      MinInstLength:         1
+      MaxOpsPerInst:         1
+      DefaultIsStmt:         1
+      LineBase:              251
+      LineRange:             14
+      OpcodeBase:            4
+      StandardOpcodeLengths: [ 0, 1, 1 ]
+      IncludeDirs:
+        - temp3
+      Files:
+        - Name:    c.c
+          DirIdx:  1
+          ModTime: 0
+          Length:  0
+      Opcodes:
+        - Opcode:    DW_LNS_extended_op
+          ExtLen:    1
+          SubOpcode: DW_LNE_end_sequence

diff  --git a/llvm/tools/obj2yaml/dwarf2yaml.cpp b/llvm/tools/obj2yaml/dwarf2yaml.cpp
index fdb8c4c41c96..13e502dc73ad 100644
--- a/llvm/tools/obj2yaml/dwarf2yaml.cpp
+++ b/llvm/tools/obj2yaml/dwarf2yaml.cpp
@@ -317,13 +317,15 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
         DebugLines.Format = dwarf::DWARF32;
         DebugLines.Length = LengthOrDWARF64Prefix;
       }
-      uint64_t LineTableLength = DebugLines.Length;
+      assert(DebugLines.Length);
+      uint64_t LineTableLength = *DebugLines.Length;
       uint64_t SizeOfPrologueLength =
           DebugLines.Format == dwarf::DWARF64 ? 8 : 4;
       DebugLines.Version = LineData.getU16(&Offset);
       DebugLines.PrologueLength =
           LineData.getUnsigned(&Offset, SizeOfPrologueLength);
-      const uint64_t EndPrologue = DebugLines.PrologueLength + Offset;
+      assert(DebugLines.PrologueLength);
+      const uint64_t EndPrologue = *DebugLines.PrologueLength + Offset;
 
       DebugLines.MinInstLength = LineData.getU8(&Offset);
       if (DebugLines.Version >= 4)

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index c38d61146a41..9bc278c60412 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -2196,9 +2196,7 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineSequence) {
               - Value:           0x0000000000000001
               - Value:           0x0000000000000000
     debug_line:
-      - Length:          68
-        Version:         2
-        PrologueLength:  34
+      - Version:         2
         MinInstLength:   1
         DefaultIsStmt:   1
         LineBase:        251
@@ -2265,9 +2263,7 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
               - Value:           0x0000000000000001
               - Value:           0x0000000000000000
     debug_line:
-      - Length:          61
-        Version:         2
-        PrologueLength:  34
+      - Version:         2
         MinInstLength:   1
         DefaultIsStmt:   1
         LineBase:        251
@@ -2336,9 +2332,7 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineTablePorlogueDirIndex) {
               - Value:           0x0000000000000001
               - Value:           0x0000000000000000
     debug_line:
-      - Length:          61
-        Version:         2
-        PrologueLength:  34
+      - Version:         2
         MinInstLength:   1
         DefaultIsStmt:   1
         LineBase:        251
@@ -2408,9 +2402,7 @@ TEST(DWARFDebugInfo, TestDwarfVerifyDuplicateFileWarning) {
               - Value:           0x0000000000000001
               - Value:           0x0000000000000000
     debug_line:
-      - Length:          71
-        Version:         2
-        PrologueLength:  44
+      - Version:         2
         MinInstLength:   1
         DefaultIsStmt:   1
         LineBase:        251
@@ -2495,9 +2487,7 @@ TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
               - Value:           0x000000000000000D
               - Value:           0x0000000000000000
     debug_line:
-      - Length:          60
-        Version:         2
-        PrologueLength:  34
+      - Version:         2
         MinInstLength:   1
         DefaultIsStmt:   1
         LineBase:        251


        


More information about the llvm-commits mailing list