forked from OSchip/llvm-project
[DWARFYAML] Make the opcode_base and the standard_opcode_lengths fields optional.
This patch makes the opcode_base and the standard_opcode_lengths fields of the line table optional. When both of them are not specified, yaml2obj emits them according to the line table's version. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D88355
This commit is contained in:
parent
1d1c1f8ff2
commit
dd55499472
|
@ -145,8 +145,8 @@ struct LineTable {
|
|||
uint8_t DefaultIsStmt;
|
||||
uint8_t LineBase;
|
||||
uint8_t LineRange;
|
||||
uint8_t OpcodeBase;
|
||||
std::vector<uint8_t> StandardOpcodeLengths;
|
||||
Optional<uint8_t> OpcodeBase;
|
||||
Optional<std::vector<uint8_t>> StandardOpcodeLengths;
|
||||
std::vector<StringRef> IncludeDirs;
|
||||
std::vector<File> Files;
|
||||
std::vector<LineTableOpcode> Opcodes;
|
||||
|
|
|
@ -552,6 +552,21 @@ static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
|
|||
}
|
||||
}
|
||||
|
||||
static std::vector<uint8_t>
|
||||
getStandardOpcodeLengths(uint16_t Version, Optional<uint8_t> OpcodeBase) {
|
||||
// If the opcode_base field isn't specified, we returns the
|
||||
// standard_opcode_lengths array according to the version by default.
|
||||
std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
|
||||
0, 0, 1, 0, 0, 1};
|
||||
if (Version == 2) {
|
||||
// DWARF v2 uses the same first 9 standard opcodes as v3-5.
|
||||
StandardOpcodeLengths.resize(9);
|
||||
} else if (OpcodeBase) {
|
||||
StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
|
||||
}
|
||||
return StandardOpcodeLengths;
|
||||
}
|
||||
|
||||
Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
||||
for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
|
||||
// Buffer holds the bytes following the header_length (or prologue_length in
|
||||
|
@ -566,9 +581,15 @@ Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|||
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)
|
||||
std::vector<uint8_t> StandardOpcodeLengths =
|
||||
LineTable.StandardOpcodeLengths.getValueOr(
|
||||
getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));
|
||||
uint8_t OpcodeBase = LineTable.OpcodeBase
|
||||
? *LineTable.OpcodeBase
|
||||
: StandardOpcodeLengths.size() + 1;
|
||||
writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
|
||||
for (uint8_t OpcodeLength : StandardOpcodeLengths)
|
||||
writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
|
||||
|
||||
for (StringRef IncludeDir : LineTable.IncludeDirs) {
|
||||
|
@ -585,8 +606,8 @@ Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|||
LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();
|
||||
|
||||
for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
|
||||
writeLineTableOpcode(Op, LineTable.OpcodeBase, DI.Is64BitAddrSize ? 8 : 4,
|
||||
BufferOS, DI.IsLittleEndian);
|
||||
writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
|
||||
DI.IsLittleEndian);
|
||||
|
||||
uint64_t Length;
|
||||
if (LineTable.Length) {
|
||||
|
|
|
@ -244,8 +244,8 @@ void MappingTraits<DWARFYAML::LineTable>::mapping(
|
|||
IO.mapRequired("DefaultIsStmt", LineTable.DefaultIsStmt);
|
||||
IO.mapRequired("LineBase", LineTable.LineBase);
|
||||
IO.mapRequired("LineRange", LineTable.LineRange);
|
||||
IO.mapRequired("OpcodeBase", LineTable.OpcodeBase);
|
||||
IO.mapRequired("StandardOpcodeLengths", LineTable.StandardOpcodeLengths);
|
||||
IO.mapOptional("OpcodeBase", LineTable.OpcodeBase);
|
||||
IO.mapOptional("StandardOpcodeLengths", LineTable.StandardOpcodeLengths);
|
||||
IO.mapOptional("IncludeDirs", LineTable.IncludeDirs);
|
||||
IO.mapOptional("Files", LineTable.Files);
|
||||
IO.mapOptional("Opcodes", LineTable.Opcodes);
|
||||
|
|
|
@ -668,3 +668,163 @@ DWARF:
|
|||
## Specify the ExtLen field.
|
||||
ExtLen: 0x1234
|
||||
SubOpcode: DW_LNE_end_sequence
|
||||
|
||||
## m) Test how yaml2obj generates the opcode_base and the
|
||||
## standard_opcode_lengths fields.
|
||||
|
||||
## Both the opcode_base and the standard_opcode_lengths fields are not
|
||||
## specified (DWARFv2).
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DVERSION=2 -DMAXOPSPERINST='' %s -o %t13.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t13.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODEBASEV2
|
||||
|
||||
# OPCODEBASEV2: Hex dump of section '.debug_line':
|
||||
# OPCODEBASEV2-NEXT: 0x00000000 16000000 02001000 00000101 00010a00 ................
|
||||
## ^- opcode_base (10)
|
||||
## ^- standard_opcode_lengths[DW_LNS_copy] = 0
|
||||
# OPCODEBASEV2-NEXT: 0x00000010 01010101 00000001 0000 ..........
|
||||
## ^- standard_opcode_lengths[DW_LNS_advance_pc] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_advance_line] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_file] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_column] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_negate_stmt] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_basic_block] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_const_add_pc] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
|
||||
## ^--- terminators for include_directories and file_names
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
DWARF:
|
||||
debug_line:
|
||||
- Version: [[VERSION=4]]
|
||||
MinInstLength: 1
|
||||
[[MAXOPSPERINST=MaxOpsPerInst: 0]]
|
||||
DefaultIsStmt: 1
|
||||
LineBase: 0
|
||||
LineRange: 1
|
||||
OpcodeBase: [[OPCODEBASE=<none>]]
|
||||
StandardOpcodeLengths: [[STANDARDOPCODELENGTHS=<none>]]
|
||||
|
||||
## Both the opcode_base and the standard_opcode_lengths fields are not
|
||||
## specified (DWARFv3).
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DVERSION=3 -DMAXOPSPERINST='' %s -o %t14.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t14.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODEBASEV3
|
||||
|
||||
# OPCODEBASEV3: Hex dump of section '.debug_line':
|
||||
# OPCODEBASEV3-NEXT: 0x00000000 19000000 03001300 00000101 00010d00 ................
|
||||
## ^- opcode_base (13)
|
||||
## ^- standard_opcode_lengths[DW_LNS_copy] = 0
|
||||
# OPCODEBASEV3-NEXT: 0x00000010 01010101 00000001 00000100 00 .............
|
||||
## ^- standard_opcode_lengths[DW_LNS_advance_pc] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_advance_line] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_file] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_column] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_negate_stmt] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_basic_block] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_const_add_pc] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_isa] = 1
|
||||
## ^---- terminators for include_directories and file_names
|
||||
|
||||
## Both the opcode_base and the standard_opcode_lengths fields are not
|
||||
## specified (DWARFv4).
|
||||
|
||||
# RUN: yaml2obj --docnum=13 %s -o %t15.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t15.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODEBASEV4
|
||||
|
||||
# OPCODEBASEV4: Hex dump of section '.debug_line':
|
||||
# OPCODEBASEV4-NEXT: 0x00000000 1a000000 04001400 00000100 0100010d ................
|
||||
## ^- opcode_base (13)
|
||||
# OPCODEBASEV4-NEXT: 0x00000010 00010101 01000000 01000001 0000 ..............
|
||||
## ^- standard_opcode_lengths[DW_LNS_copy] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_advance_pc] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_advance_line] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_file] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_column] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_negate_stmt] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_basic_block] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_const_add_pc] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
|
||||
## ^- standard_opcode_lengths[DW_LNS_set_isa] = 1
|
||||
## ^--- terminators for include_directories and file_names
|
||||
|
||||
## Specify the opcode_base field (opcode_base == 0).
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=0 %s -o %t16.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t16.o | \
|
||||
# RUN: FileCheck %s --check-prefix=ZERO-OPCODEBASE
|
||||
|
||||
# ZERO-OPCODEBASE: Hex dump of section '.debug_line':
|
||||
# ZERO-OPCODEBASE-NEXT: 0x00000000 0e000000 04000800 00000100 01000100 ................
|
||||
## ^- opcode_base (0)
|
||||
# ZERO-OPCODEBASE-NEXT: 0x00000010 0000 ..
|
||||
## ^--- terminators for include_directories and file_names
|
||||
|
||||
## Specify the opcode_base field (opcode_base != 0, opcode_base - 1 < 12).
|
||||
## The standard_opcode_lengths array will be truncated.
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=4 %s -o %t17.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t17.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODEBASE
|
||||
|
||||
# OPCODEBASE: Hex dump of section '.debug_line':
|
||||
# OPCODEBASE-NEXT: 0x00000000 11000000 04000b00 00000100 01000104 ................
|
||||
## ^- opcode_base (4)
|
||||
# OPCODEBASE-NEXT: 0x00000010 00010100 00 .....
|
||||
## ^----- standard_opcode_lengths (3-byte)
|
||||
## ^---- terminators for include_directories and file_names
|
||||
|
||||
## Specify the opcode_base field (opcode_base != 0, opcode_base - 1 > 12).
|
||||
## The standard_opcode_lengths array will be extended.
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=20 %s -o %t18.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t18.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODEBASE1
|
||||
|
||||
# OPCODEBASE1: Hex dump of section '.debug_line':
|
||||
# OPCODEBASE1-NEXT: 0x00000000 21000000 04001b00 00000100 01000114 !...............
|
||||
## ^- opcode_base (20)
|
||||
# OPCODEBASE1-NEXT: 0x00000010 00010101 01000000 01000001 00000000 ................
|
||||
## ^------------------------- standard_opcode_lengths defined in DWARFv5 (12-byte)
|
||||
## ^------- extended standard_opcode_lengths (7-byte)
|
||||
# OPCODEBASE1-NEXT: 0x00000020 00000000 00 .....
|
||||
## ------
|
||||
## ^---- terminators for include_directories and file_names
|
||||
|
||||
## Specify the standard_opcode_lengths field.
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DSTANDARDOPCODELENGTHS=[0,1,0] %s -o %t19.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t19.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODELENGTHS
|
||||
|
||||
# OPCODELENGTHS: Hex dump of section '.debug_line':
|
||||
# OPCODELENGTHS-NEXT: 0x00000000 11000000 04000b00 00000100 01000104 ................
|
||||
## ^- opcode_base (4)
|
||||
# OPCODELENGTHS-NEXT: 0x00000010 00010000 00 .....
|
||||
## ^----- standard_opcode_lengths (3-byte)
|
||||
## ^---- terminators for include_directories and file_names
|
||||
|
||||
## Specify both the opcode_base and the standard_opcode_lengths fields.
|
||||
|
||||
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=2 -DSTANDARDOPCODELENGTHS=[0,1,0] %s -o %t20.o
|
||||
# RUN: llvm-readelf --hex-dump=.debug_line %t20.o | \
|
||||
# RUN: FileCheck %s --check-prefix=OPCODEBASE-LENGTHS
|
||||
|
||||
# OPCODEBASE-LENGTHS: Hex dump of section '.debug_line':
|
||||
# OPCODEBASE-LENGTHS-NEXT: 0x00000000 11000000 04000b00 00000100 01000102 ................
|
||||
## ^- opcode_base (2)
|
||||
# OPCODEBASE-LENGTHS-NEXT: 0x00000010 00010000 00 .....
|
||||
## ^----- standard_opcode_lengths (3-byte)
|
||||
## ^---- terminators for include_directories and file_names
|
||||
|
|
|
@ -378,9 +378,9 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
|||
DebugLines.LineRange = LineData.getU8(&Offset);
|
||||
DebugLines.OpcodeBase = LineData.getU8(&Offset);
|
||||
|
||||
DebugLines.StandardOpcodeLengths.reserve(DebugLines.OpcodeBase - 1);
|
||||
DebugLines.StandardOpcodeLengths.emplace();
|
||||
for (uint8_t i = 1; i < DebugLines.OpcodeBase; ++i)
|
||||
DebugLines.StandardOpcodeLengths.push_back(LineData.getU8(&Offset));
|
||||
DebugLines.StandardOpcodeLengths->push_back(LineData.getU8(&Offset));
|
||||
|
||||
while (Offset < EndPrologue) {
|
||||
StringRef Dir = LineData.getCStr(&Offset);
|
||||
|
@ -422,7 +422,7 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
|||
while (Offset < StartExt + *NewOp.ExtLen)
|
||||
NewOp.UnknownOpcodeData.push_back(LineData.getU8(&Offset));
|
||||
}
|
||||
} else if (NewOp.Opcode < DebugLines.OpcodeBase) {
|
||||
} else if (NewOp.Opcode < *DebugLines.OpcodeBase) {
|
||||
switch (NewOp.Opcode) {
|
||||
case dwarf::DW_LNS_copy:
|
||||
case dwarf::DW_LNS_negate_stmt:
|
||||
|
@ -449,7 +449,9 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
|||
|
||||
default:
|
||||
for (uint8_t i = 0;
|
||||
i < DebugLines.StandardOpcodeLengths[NewOp.Opcode - 1]; ++i)
|
||||
i <
|
||||
DebugLines.StandardOpcodeLengths.getValue()[NewOp.Opcode - 1];
|
||||
++i)
|
||||
NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue