diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp --- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp +++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp @@ -433,6 +433,7 @@ } Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) { + uint64_t LineTableIndex = 0; for (const auto &LineTable : DI.DebugLines) { writeInitialLength(LineTable.Format, LineTable.Length, OS, DI.IsLittleEndian); @@ -461,6 +462,10 @@ emitFileEntry(OS, File); OS.write('\0'); + uint8_t AddrSize = DI.Is64BitAddrSize ? 8 : 4; + if (DI.CompileUnits.size() > LineTableIndex) + AddrSize = DI.CompileUnits[LineTableIndex++].AddrSize; + for (auto Op : LineTable.Opcodes) { writeInteger((uint8_t)Op.Opcode, OS, DI.IsLittleEndian); if (Op.Opcode == 0) { @@ -470,8 +475,9 @@ case dwarf::DW_LNE_set_address: case dwarf::DW_LNE_set_discriminator: // TODO: Test this error. - if (Error Err = writeVariableSizedInteger( - Op.Data, DI.CompileUnits[0].AddrSize, OS, DI.IsLittleEndian)) + // FIXME: The operands of set_discriminator is not an address. + if (Error Err = writeVariableSizedInteger(Op.Data, AddrSize, OS, + DI.IsLittleEndian)) return Err; break; case dwarf::DW_LNE_define_file: diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml --- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-line.yaml @@ -317,3 +317,90 @@ IncludeDirs: [] Files: [] Opcodes: [] + +## h) Test that if the line table has an associated compilation unit, yaml2obj will use the address size +## of the compilation unit's otherwise yaml2obj will infer it from the object file. + +# RUN: yaml2obj --docnum=8 %s -o %t8.o +# RUN: llvm-readelf --hex-dump=.debug_line %t8.o | FileCheck %s --check-prefix=ADDRSIZE + +# ADDRSIZE: Hex dump of section '.debug_line': +# ADDRSIZE-NEXT: 0x00000000 34120000 02003412 00000101 010e0d00 4.....4......... +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^-------- header_length (4-byte) +## ^- minimum_instruction_length (1-byte) +## ^- default_is_stmt (1-byte) +## ^- line_base (1-byte) +## ^- line_range (1-byte) +## ^- opcode_base (1-byte) +## ^- null byte for terminating include_directories +# ADDRSIZE-NEXT: 0x00000010 00000902 78563412 34120000 02003412 ....xV4.4.....4. +## ^- null byte for terminating file_names +## ^- DW_LNS_extended_op +## ^- extended op length (ULEB128) 0x09 +## ^- DW_LNE_set_address +## ^------- address (4-byte) +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^--- header_length (4-byte) +# ADDRSIZE-NEXT: 0x00000020 00000101 010e0d00 00000902 efcdab90 ................ +## ---- +## ^- minimum_instruction_length (1-byte) +## ^- default_is_stmt (1-byte) +## ^- line_base (1-byte) +## ^- line_range (1-byte) +## ^- opcode_base (1-byte) +## ^- null byte for terminating include_directories +## ^- null byte for terminating file_names +## ^- DW_LNS_extended_op +## ^- extended op length (ULEB128) 0x09 +## ^- DW_LNE_set_address +## ^------- address (8-byte) +# ADDRSIZE-NEXT: 0x00000030 78563412 xV4. +## -------- + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_info: + - Version: 4 + AbbrOffset: 0x00 + AddrSize: 0x04 + debug_line: + - Length: 0x1234 + Version: 2 + PrologueLength: 0x1234 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 1 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [] + IncludeDirs: [] + Files: [] + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 0x12345678 + - Length: 0x1234 + Version: 2 + PrologueLength: 0x1234 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 1 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [] + IncludeDirs: [] + Files: [] + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 0x1234567890abcdef