diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -332,7 +332,8 @@ } void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) { - int RefSize = 4; // FIXME: Support DWARF-64 + int RefSize = + dwarf::getDwarfOffsetByteSize(MCOS->getContext().getDwarfFormat()); size_t Offset = LineStrings.add(Path); if (UseRelocs) { MCContext &Ctx = MCOS->getContext(); @@ -472,10 +473,20 @@ // Create a symbol for the end of the section (to be set when we get there). MCSymbol *LineEndSym = context.createTempSymbol(); - // The first 4 bytes is the total length of the information for this - // compilation unit (not including these 4 bytes for the length). - emitAbsValue( - *MCOS, MakeStartMinusEndExpr(context, *LineStartSym, *LineEndSym, 4), 4); + unsigned UnitLengthBytes = + dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat()); + unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat()); + + if (context.getDwarfFormat() == dwarf::DWARF64) + // Emit DWARF64 mark. + MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64); + + // The length field does not include itself and, in case of the 64-bit DWARF + // format, the DWARF64 mark. + emitAbsValue(*MCOS, + MakeStartMinusEndExpr(context, *LineStartSym, *LineEndSym, + UnitLengthBytes), + OffsetSize); // Next 2 bytes is the Version. unsigned LineTableVersion = context.getDwarfVersion(); @@ -483,7 +494,7 @@ // Keep track of the bytes between the very start and where the header length // comes out. - unsigned PreHeaderLengthBytes = 4 + 2; + unsigned PreHeaderLengthBytes = UnitLengthBytes + 2; // In v5, we get address info next. if (LineTableVersion >= 5) { @@ -495,12 +506,12 @@ // Create a symbol for the end of the prologue (to be set when we get there). MCSymbol *ProEndSym = context.createTempSymbol(); // Lprologue_end - // Length of the prologue, is the next 4 bytes. This is actually the length - // from after the length word, to the end of the prologue. + // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is + // actually the length from after the length word, to the end of the prologue. emitAbsValue(*MCOS, MakeStartMinusEndExpr(context, *LineStartSym, *ProEndSym, - (PreHeaderLengthBytes + 4)), - 4); + (PreHeaderLengthBytes + OffsetSize)), + OffsetSize); // Parameters of the state machine, are next. MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment()); diff --git a/llvm/test/MC/ELF/gen-dwarf64.s b/llvm/test/MC/ELF/gen-dwarf64.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/gen-dwarf64.s @@ -0,0 +1,24 @@ +## This checks that llvm-mc is able to produce 64-bit debug info. + +# RUN: llvm-mc -g -dwarf-version 5 -dwarf64 -triple x86_64 %s -filetype=obj -o %t5.o +# RUN: llvm-readobj -r %t5.o | FileCheck --check-prefixes=REL,REL5 %s +# RUN: llvm-dwarfdump -v %t5.o | FileCheck --check-prefixes=DUMP,DUMP5 %s + +## The references to other debug info sections are 64-bit, as required for DWARF64. +# REL5: Section ({{[0-9]+}}) .rela.debug_line { +# REL5-NEXT: R_X86_64_64 .debug_line_str 0x0 +# REL5-NEXT: R_X86_64_64 .debug_line_str 0x + +# DUMP: .debug_line contents: +# DUMP-NEXT: debug_line[0x00000000] +# DUMP-NEXT: Line table prologue: +# DUMP-NEXT: total_length: +# DUMP-NEXT: format: DWARF64 +# DUMP5: include_directories[ 0] = .debug_line_str[0x0000000000000000] = "[[DIR:.+]]" +# DUMP5-NEXT: file_names[ 0]: +# DUMP5-NEXT: name: .debug_line_str[0x00000000[[FILEOFF:[[:xdigit:]]{8}]]] = "[[FILE:.+]]" +# DUMP5-NEXT: dir_index: 0 + +# DUMP5: .debug_line_str contents: +# DUMP5-NEXT: 0x00000000: "[[DIR]]" +# DUMP5-NEXT: 0x[[FILEOFF]]: "[[FILE]]"