[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