Skip to content

Commit dd55499

Browse files
committed
[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
1 parent 1d1c1f8 commit dd55499

File tree

5 files changed

+195
-12
lines changed

5 files changed

+195
-12
lines changed

llvm/include/llvm/ObjectYAML/DWARFYAML.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ struct LineTable {
145145
uint8_t DefaultIsStmt;
146146
uint8_t LineBase;
147147
uint8_t LineRange;
148-
uint8_t OpcodeBase;
149-
std::vector<uint8_t> StandardOpcodeLengths;
148+
Optional<uint8_t> OpcodeBase;
149+
Optional<std::vector<uint8_t>> StandardOpcodeLengths;
150150
std::vector<StringRef> IncludeDirs;
151151
std::vector<File> Files;
152152
std::vector<LineTableOpcode> Opcodes;

llvm/lib/ObjectYAML/DWARFEmitter.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,21 @@ static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
552552
}
553553
}
554554

555+
static std::vector<uint8_t>
556+
getStandardOpcodeLengths(uint16_t Version, Optional<uint8_t> OpcodeBase) {
557+
// If the opcode_base field isn't specified, we returns the
558+
// standard_opcode_lengths array according to the version by default.
559+
std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
560+
0, 0, 1, 0, 0, 1};
561+
if (Version == 2) {
562+
// DWARF v2 uses the same first 9 standard opcodes as v3-5.
563+
StandardOpcodeLengths.resize(9);
564+
} else if (OpcodeBase) {
565+
StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
566+
}
567+
return StandardOpcodeLengths;
568+
}
569+
555570
Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
556571
for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
557572
// 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) {
566581
writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);
567582
writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);
568583
writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);
569-
writeInteger(LineTable.OpcodeBase, BufferOS, DI.IsLittleEndian);
570584

571-
for (uint8_t OpcodeLength : LineTable.StandardOpcodeLengths)
585+
std::vector<uint8_t> StandardOpcodeLengths =
586+
LineTable.StandardOpcodeLengths.getValueOr(
587+
getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));
588+
uint8_t OpcodeBase = LineTable.OpcodeBase
589+
? *LineTable.OpcodeBase
590+
: StandardOpcodeLengths.size() + 1;
591+
writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
592+
for (uint8_t OpcodeLength : StandardOpcodeLengths)
572593
writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
573594

574595
for (StringRef IncludeDir : LineTable.IncludeDirs) {
@@ -585,8 +606,8 @@ Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
585606
LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();
586607

587608
for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
588-
writeLineTableOpcode(Op, LineTable.OpcodeBase, DI.Is64BitAddrSize ? 8 : 4,
589-
BufferOS, DI.IsLittleEndian);
609+
writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
610+
DI.IsLittleEndian);
590611

591612
uint64_t Length;
592613
if (LineTable.Length) {

llvm/lib/ObjectYAML/DWARFYAML.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ void MappingTraits<DWARFYAML::LineTable>::mapping(
244244
IO.mapRequired("DefaultIsStmt", LineTable.DefaultIsStmt);
245245
IO.mapRequired("LineBase", LineTable.LineBase);
246246
IO.mapRequired("LineRange", LineTable.LineRange);
247-
IO.mapRequired("OpcodeBase", LineTable.OpcodeBase);
248-
IO.mapRequired("StandardOpcodeLengths", LineTable.StandardOpcodeLengths);
247+
IO.mapOptional("OpcodeBase", LineTable.OpcodeBase);
248+
IO.mapOptional("StandardOpcodeLengths", LineTable.StandardOpcodeLengths);
249249
IO.mapOptional("IncludeDirs", LineTable.IncludeDirs);
250250
IO.mapOptional("Files", LineTable.Files);
251251
IO.mapOptional("Opcodes", LineTable.Opcodes);

llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,3 +668,163 @@ DWARF:
668668
## Specify the ExtLen field.
669669
ExtLen: 0x1234
670670
SubOpcode: DW_LNE_end_sequence
671+
672+
## m) Test how yaml2obj generates the opcode_base and the
673+
## standard_opcode_lengths fields.
674+
675+
## Both the opcode_base and the standard_opcode_lengths fields are not
676+
## specified (DWARFv2).
677+
678+
# RUN: yaml2obj --docnum=13 -DVERSION=2 -DMAXOPSPERINST='' %s -o %t13.o
679+
# RUN: llvm-readelf --hex-dump=.debug_line %t13.o | \
680+
# RUN: FileCheck %s --check-prefix=OPCODEBASEV2
681+
682+
# OPCODEBASEV2: Hex dump of section '.debug_line':
683+
# OPCODEBASEV2-NEXT: 0x00000000 16000000 02001000 00000101 00010a00 ................
684+
## ^- opcode_base (10)
685+
## ^- standard_opcode_lengths[DW_LNS_copy] = 0
686+
# OPCODEBASEV2-NEXT: 0x00000010 01010101 00000001 0000 ..........
687+
## ^- standard_opcode_lengths[DW_LNS_advance_pc] = 1
688+
## ^- standard_opcode_lengths[DW_LNS_advance_line] = 1
689+
## ^- standard_opcode_lengths[DW_LNS_set_file] = 1
690+
## ^- standard_opcode_lengths[DW_LNS_set_column] = 1
691+
## ^- standard_opcode_lengths[DW_LNS_negate_stmt] = 0
692+
## ^- standard_opcode_lengths[DW_LNS_set_basic_block] = 0
693+
## ^- standard_opcode_lengths[DW_LNS_const_add_pc] = 0
694+
## ^- standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
695+
## ^--- terminators for include_directories and file_names
696+
697+
--- !ELF
698+
FileHeader:
699+
Class: ELFCLASS64
700+
Data: ELFDATA2LSB
701+
Type: ET_EXEC
702+
DWARF:
703+
debug_line:
704+
- Version: [[VERSION=4]]
705+
MinInstLength: 1
706+
[[MAXOPSPERINST=MaxOpsPerInst: 0]]
707+
DefaultIsStmt: 1
708+
LineBase: 0
709+
LineRange: 1
710+
OpcodeBase: [[OPCODEBASE=<none>]]
711+
StandardOpcodeLengths: [[STANDARDOPCODELENGTHS=<none>]]
712+
713+
## Both the opcode_base and the standard_opcode_lengths fields are not
714+
## specified (DWARFv3).
715+
716+
# RUN: yaml2obj --docnum=13 -DVERSION=3 -DMAXOPSPERINST='' %s -o %t14.o
717+
# RUN: llvm-readelf --hex-dump=.debug_line %t14.o | \
718+
# RUN: FileCheck %s --check-prefix=OPCODEBASEV3
719+
720+
# OPCODEBASEV3: Hex dump of section '.debug_line':
721+
# OPCODEBASEV3-NEXT: 0x00000000 19000000 03001300 00000101 00010d00 ................
722+
## ^- opcode_base (13)
723+
## ^- standard_opcode_lengths[DW_LNS_copy] = 0
724+
# OPCODEBASEV3-NEXT: 0x00000010 01010101 00000001 00000100 00 .............
725+
## ^- standard_opcode_lengths[DW_LNS_advance_pc] = 1
726+
## ^- standard_opcode_lengths[DW_LNS_advance_line] = 1
727+
## ^- standard_opcode_lengths[DW_LNS_set_file] = 1
728+
## ^- standard_opcode_lengths[DW_LNS_set_column] = 1
729+
## ^- standard_opcode_lengths[DW_LNS_negate_stmt] = 0
730+
## ^- standard_opcode_lengths[DW_LNS_set_basic_block] = 0
731+
## ^- standard_opcode_lengths[DW_LNS_const_add_pc] = 0
732+
## ^- standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
733+
## ^- standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
734+
## ^- standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
735+
## ^- standard_opcode_lengths[DW_LNS_set_isa] = 1
736+
## ^---- terminators for include_directories and file_names
737+
738+
## Both the opcode_base and the standard_opcode_lengths fields are not
739+
## specified (DWARFv4).
740+
741+
# RUN: yaml2obj --docnum=13 %s -o %t15.o
742+
# RUN: llvm-readelf --hex-dump=.debug_line %t15.o | \
743+
# RUN: FileCheck %s --check-prefix=OPCODEBASEV4
744+
745+
# OPCODEBASEV4: Hex dump of section '.debug_line':
746+
# OPCODEBASEV4-NEXT: 0x00000000 1a000000 04001400 00000100 0100010d ................
747+
## ^- opcode_base (13)
748+
# OPCODEBASEV4-NEXT: 0x00000010 00010101 01000000 01000001 0000 ..............
749+
## ^- standard_opcode_lengths[DW_LNS_copy] = 0
750+
## ^- standard_opcode_lengths[DW_LNS_advance_pc] = 1
751+
## ^- standard_opcode_lengths[DW_LNS_advance_line] = 1
752+
## ^- standard_opcode_lengths[DW_LNS_set_file] = 1
753+
## ^- standard_opcode_lengths[DW_LNS_set_column] = 1
754+
## ^- standard_opcode_lengths[DW_LNS_negate_stmt] = 0
755+
## ^- standard_opcode_lengths[DW_LNS_set_basic_block] = 0
756+
## ^- standard_opcode_lengths[DW_LNS_const_add_pc] = 0
757+
## ^- standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
758+
## ^- standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
759+
## ^- standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
760+
## ^- standard_opcode_lengths[DW_LNS_set_isa] = 1
761+
## ^--- terminators for include_directories and file_names
762+
763+
## Specify the opcode_base field (opcode_base == 0).
764+
765+
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=0 %s -o %t16.o
766+
# RUN: llvm-readelf --hex-dump=.debug_line %t16.o | \
767+
# RUN: FileCheck %s --check-prefix=ZERO-OPCODEBASE
768+
769+
# ZERO-OPCODEBASE: Hex dump of section '.debug_line':
770+
# ZERO-OPCODEBASE-NEXT: 0x00000000 0e000000 04000800 00000100 01000100 ................
771+
## ^- opcode_base (0)
772+
# ZERO-OPCODEBASE-NEXT: 0x00000010 0000 ..
773+
## ^--- terminators for include_directories and file_names
774+
775+
## Specify the opcode_base field (opcode_base != 0, opcode_base - 1 < 12).
776+
## The standard_opcode_lengths array will be truncated.
777+
778+
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=4 %s -o %t17.o
779+
# RUN: llvm-readelf --hex-dump=.debug_line %t17.o | \
780+
# RUN: FileCheck %s --check-prefix=OPCODEBASE
781+
782+
# OPCODEBASE: Hex dump of section '.debug_line':
783+
# OPCODEBASE-NEXT: 0x00000000 11000000 04000b00 00000100 01000104 ................
784+
## ^- opcode_base (4)
785+
# OPCODEBASE-NEXT: 0x00000010 00010100 00 .....
786+
## ^----- standard_opcode_lengths (3-byte)
787+
## ^---- terminators for include_directories and file_names
788+
789+
## Specify the opcode_base field (opcode_base != 0, opcode_base - 1 > 12).
790+
## The standard_opcode_lengths array will be extended.
791+
792+
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=20 %s -o %t18.o
793+
# RUN: llvm-readelf --hex-dump=.debug_line %t18.o | \
794+
# RUN: FileCheck %s --check-prefix=OPCODEBASE1
795+
796+
# OPCODEBASE1: Hex dump of section '.debug_line':
797+
# OPCODEBASE1-NEXT: 0x00000000 21000000 04001b00 00000100 01000114 !...............
798+
## ^- opcode_base (20)
799+
# OPCODEBASE1-NEXT: 0x00000010 00010101 01000000 01000001 00000000 ................
800+
## ^------------------------- standard_opcode_lengths defined in DWARFv5 (12-byte)
801+
## ^------- extended standard_opcode_lengths (7-byte)
802+
# OPCODEBASE1-NEXT: 0x00000020 00000000 00 .....
803+
## ------
804+
## ^---- terminators for include_directories and file_names
805+
806+
## Specify the standard_opcode_lengths field.
807+
808+
# RUN: yaml2obj --docnum=13 -DSTANDARDOPCODELENGTHS=[0,1,0] %s -o %t19.o
809+
# RUN: llvm-readelf --hex-dump=.debug_line %t19.o | \
810+
# RUN: FileCheck %s --check-prefix=OPCODELENGTHS
811+
812+
# OPCODELENGTHS: Hex dump of section '.debug_line':
813+
# OPCODELENGTHS-NEXT: 0x00000000 11000000 04000b00 00000100 01000104 ................
814+
## ^- opcode_base (4)
815+
# OPCODELENGTHS-NEXT: 0x00000010 00010000 00 .....
816+
## ^----- standard_opcode_lengths (3-byte)
817+
## ^---- terminators for include_directories and file_names
818+
819+
## Specify both the opcode_base and the standard_opcode_lengths fields.
820+
821+
# RUN: yaml2obj --docnum=13 -DOPCODEBASE=2 -DSTANDARDOPCODELENGTHS=[0,1,0] %s -o %t20.o
822+
# RUN: llvm-readelf --hex-dump=.debug_line %t20.o | \
823+
# RUN: FileCheck %s --check-prefix=OPCODEBASE-LENGTHS
824+
825+
# OPCODEBASE-LENGTHS: Hex dump of section '.debug_line':
826+
# OPCODEBASE-LENGTHS-NEXT: 0x00000000 11000000 04000b00 00000100 01000102 ................
827+
## ^- opcode_base (2)
828+
# OPCODEBASE-LENGTHS-NEXT: 0x00000010 00010000 00 .....
829+
## ^----- standard_opcode_lengths (3-byte)
830+
## ^---- terminators for include_directories and file_names

llvm/tools/obj2yaml/dwarf2yaml.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,9 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
378378
DebugLines.LineRange = LineData.getU8(&Offset);
379379
DebugLines.OpcodeBase = LineData.getU8(&Offset);
380380

381-
DebugLines.StandardOpcodeLengths.reserve(DebugLines.OpcodeBase - 1);
381+
DebugLines.StandardOpcodeLengths.emplace();
382382
for (uint8_t i = 1; i < DebugLines.OpcodeBase; ++i)
383-
DebugLines.StandardOpcodeLengths.push_back(LineData.getU8(&Offset));
383+
DebugLines.StandardOpcodeLengths->push_back(LineData.getU8(&Offset));
384384

385385
while (Offset < EndPrologue) {
386386
StringRef Dir = LineData.getCStr(&Offset);
@@ -422,7 +422,7 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
422422
while (Offset < StartExt + *NewOp.ExtLen)
423423
NewOp.UnknownOpcodeData.push_back(LineData.getU8(&Offset));
424424
}
425-
} else if (NewOp.Opcode < DebugLines.OpcodeBase) {
425+
} else if (NewOp.Opcode < *DebugLines.OpcodeBase) {
426426
switch (NewOp.Opcode) {
427427
case dwarf::DW_LNS_copy:
428428
case dwarf::DW_LNS_negate_stmt:
@@ -449,7 +449,9 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
449449

450450
default:
451451
for (uint8_t i = 0;
452-
i < DebugLines.StandardOpcodeLengths[NewOp.Opcode - 1]; ++i)
452+
i <
453+
DebugLines.StandardOpcodeLengths.getValue()[NewOp.Opcode - 1];
454+
++i)
453455
NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset));
454456
}
455457
}

0 commit comments

Comments
 (0)