Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -270,15 +270,20 @@ void DwarfCompileUnit::initStmtList() { // Define start line table label for each Compile Unit. - MCSymbol *LineTableStartSym = - Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID()); + MCSymbol *LineTableStartSym; + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + if (DD->useSectionsAsReferences()) { + LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol(); + } else { + LineTableStartSym = + Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID()); + } // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. For split dwarf this is // left in the skeleton CU and so not included. // The line table entries are not always emitted in assembly, so it // is not okay to use line_table_start here. - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); StmtListValue = addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym, TLOF.getDwarfLineSection()->getBeginSymbol()); @@ -410,9 +415,10 @@ void DwarfCompileUnit::attachRangesOrLowHighPC( DIE &Die, SmallVector Ranges) { - if (Ranges.size() == 1) { - const auto &single = Ranges.front(); - attachLowHighPC(Die, single.getStart(), single.getEnd()); + if (Ranges.size() == 1 || DD->useSectionsAsReferences()) { + const RangeSpan &Front = Ranges.front(); + const RangeSpan &Back = Ranges.back(); + attachLowHighPC(Die, Front.getStart(), Back.getEnd()); } else addScopeRangeList(Die, std::move(Ranges)); } @@ -834,7 +840,7 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) { // Don't bother labeling the .dwo unit, as its offset isn't used. - if (!Skeleton) { + if (!Skeleton && !DD->useSectionsAsReferences()) { LabelBegin = Asm->createTempSymbol("cu_begin"); Asm->OutStreamer->EmitLabel(LabelBegin); } Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -258,6 +258,10 @@ /// Use inlined strings. bool UseInlineStrings = false; + /// True if the sections itself must be used as references and don't create + /// temp symbols inside DWARF sections. + bool UseSectionsAsReferences = false; + /// DWARF5 Experimental Options /// @{ bool HasDwarfAccelTables; @@ -501,6 +505,11 @@ /// Returns whether to use inline strings. bool useInlineStrings() const { return UseInlineStrings; } + /// Returns whether to use sections as labels rather than temp symbols. + bool useSectionsAsReferences() const { + return UseSectionsAsReferences; + } + // Experimental DWARF5 features. /// Returns whether or not to emit tables that dwarf consumers can Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -123,6 +123,13 @@ clEnumVal(Disable, "Disabled")), cl::init(Default)); +static cl::opt DwarfSectionsAsReferences( + "dwarf-sections-as-references", cl::Hidden, + cl::desc("Use sections+offset as references rather than labels."), + cl::values(clEnumVal(Default, "Default for platform"), + clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), + cl::init(Default)); + enum LinkageNameOption { DefaultLinkageNames, AllLinkageNames, @@ -310,6 +317,10 @@ // Use dwarf 4 by default if nothing is requested. DwarfVersion = DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION; + // Use sections as references in DWARF v2. + UseSectionsAsReferences = + DwarfVersion == 2 && DwarfSectionsAsReferences == Enable; + // Work around a GDB bug. GDB doesn't support the standard opcode; // SCE doesn't support GNU's; LLDB prefers the standard opcode, which // is defined as of DWARF 3. @@ -737,7 +748,7 @@ // ranges for all subprogram DIEs for mach-o. DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; if (unsigned NumRanges = TheCU.getRanges().size()) { - if (NumRanges > 1) + if (NumRanges > 1 && !useSectionsAsReferences()) // A DW_AT_low_pc attribute may also be specified in combination with // DW_AT_ranges to specify the default base address for use in // location lists (see Section 2.6.2) and range lists (see Section @@ -1565,7 +1576,13 @@ Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); Asm->OutStreamer->AddComment("Offset of Compilation Unit Info"); - Asm->emitDwarfSymbolReference(TheU->getLabelBegin()); + if (useSectionsAsReferences()) { + Asm->EmitLabelPlusOffset(TheU->getSection()->getBeginSymbol(), + TheU->getDebugSectionOffset(), + Asm->MAI->getCodePointerSize()); + } else { + Asm->emitDwarfSymbolReference(TheU->getLabelBegin()); + } Asm->OutStreamer->AddComment("Compilation Unit Length"); Asm->EmitInt32(TheU->getLength()); @@ -1864,7 +1881,13 @@ Asm->OutStreamer->AddComment("DWARF Arange version number"); Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); Asm->OutStreamer->AddComment("Offset Into Debug Info Section"); - Asm->emitDwarfSymbolReference(CU->getLabelBegin()); + if (useSectionsAsReferences()) { + Asm->EmitLabelPlusOffset(CU->getSection()->getBeginSymbol(), + CU->getDebugSectionOffset(), + Asm->MAI->getCodePointerSize()); + } else { + Asm->emitDwarfSymbolReference(CU->getLabelBegin()); + } Asm->OutStreamer->AddComment("Address Size (in bytes)"); Asm->EmitInt8(PtrSize); Asm->OutStreamer->AddComment("Segment Size (in bytes)"); Index: test/DebugInfo/X86/sections_as_references.ll =================================================================== --- /dev/null +++ test/DebugInfo/X86/sections_as_references.ll @@ -0,0 +1,54 @@ +; RUN: llc -filetype=asm -O0 -mtriple=x86_64-linux-gnu < %s -dwarf-sections-as-references=Enable -dwarf-inlined-strings=Enable -dwarf-version 2 -debugger-tune=lldb | FileCheck %s + +; CHECK: .file + +; CHECK-NOT: .L + +; CHECK: .section .debug_abbrev +; CHECK-NOT: DW_FORM_str{{p|x}} +; CHECK-NOT: .L + +; CHECK: .section .debug_info +; CHECK-NOT: .L +; CHECK: .short 2 # DWARF version number +; CHECK-NOT: .L +; CHECK: .long .debug_abbrev # Offset Into Abbrev. Section +; CHECK-NOT: .L +; CHECK: .long .debug_line # DW_AT_stmt_list +; CHECK-NOT: .L +; CHECK: .long .debug_abbrev # Offset Into Abbrev. Section +; CHECK-NOT: .L +; CHECK: .long .debug_line # DW_AT_stmt_list +; CHECK-NOT: .L +; CHECK: .quad .debug_info+{{[0-9]+}} # DW_AT_type +; CHECK-NOT: .L +; CHECK: .byte 0 # End Of Children Mark +; CHECK-NOT: .L + +source_filename = "test/DebugInfo/X86/sections_as_references.ll" + +%struct.foo = type { i8 } + +@f = global %struct.foo zeroinitializer, align 1, !dbg !0 +@g = global %struct.foo zeroinitializer, align 1, !dbg !6 + +!llvm.dbg.cu = !{!9, !12} +!llvm.module.flags = !{!14, !15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = !DIGlobalVariable(name: "f", scope: null, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true) +!2 = !DIFile(filename: "tu1.cpp", directory: "/dir") +!3 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !4, line: 1, size: 8, align: 8, elements: !5, identifier: "_ZTS3foo") +!4 = !DIFile(filename: "./hdr.h", directory: "/dir") +!5 = !{} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = !DIGlobalVariable(name: "g", scope: null, file: !8, line: 2, type: !3, isLocal: false, isDefinition: true) +!8 = !DIFile(filename: "tu2.cpp", directory: "/dir") +!9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !10, globals: !11, imports: !5) +!10 = !{!3} +!11 = !{!0} +!12 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !8, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !10, globals: !13, imports: !5) +!13 = !{!6} +!14 = !{i32 2, !"Dwarf Version", i32 2} +!15 = !{i32 1, !"Debug Info Version", i32 3} +