From 9de940b93bdbb0cf032b8337c5390630ba5e1acd Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 28 Feb 2018 15:02:59 +0000 Subject: [PATCH] [DEBUGINFO] Add flag for DWARF2 or less to use sections as references. Summary: Some targets does not support labels inside debug sections, but support references in form `section +|- offset`. Patch adds initial support for this. Also, this patch disables emission of all additional debug sections that may have labels inside of it (like pub sections and string tables). Reviewers: probinson, echristo Subscribers: JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D43627 llvm-svn: 326328 --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 23 ++++++---- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 29 ++++++++++-- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 9 ++++ llvm/test/DebugInfo/X86/sections_as_references.ll | 54 +++++++++++++++++++++++ 4 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 llvm/test/DebugInfo/X86/sections_as_references.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 0b2a046..1dc9d5e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -270,15 +270,20 @@ void DwarfCompileUnit::addRange(RangeSpan Range) { 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::addScopeRangeList(DIE &ScopeDIE, 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 auto &front = Ranges.front(); + const auto &back = Ranges.back(); + attachLowHighPC(Die, front.getStart(), back.getEnd()); } else addScopeRangeList(Die, std::move(Ranges)); } @@ -834,7 +840,7 @@ void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var, 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); } @@ -851,7 +857,8 @@ bool DwarfCompileUnit::hasDwarfPubSections() const { if (CUNode->getGnuPubnames()) return true; - return DD->tuneForGDB() && !includeMinimalInlineScopes(); + return DD->tuneForGDB() && !includeMinimalInlineScopes() && + !DD->useSectionsAsReferences(); } /// addGlobalName - Add a new global name to the compile unit. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 7985908..a9aa00c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -123,6 +123,13 @@ DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, 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 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) // 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 @@ void DwarfDebug::finalizeModuleInfo() { // 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 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, 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 @@ void DwarfDebug::emitDebugARanges() { 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)"); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index f858c96..46d6446 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -258,6 +258,10 @@ class DwarfDebug : public DebugHandlerBase { /// 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; @@ -497,6 +501,11 @@ public: /// 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 diff --git a/llvm/test/DebugInfo/X86/sections_as_references.ll b/llvm/test/DebugInfo/X86/sections_as_references.ll new file mode 100644 index 0000000..30b79b2 --- /dev/null +++ b/llvm/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 | 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} + -- 2.7.4