From b3cee2fb42e9117d6ec2e291e9e99cb4eb99c18d Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 25 May 2017 18:50:28 +0000 Subject: [PATCH] DebugInfo: Produce debug_{gnu_}pub{names,types} entries when explicitly requested, even in -gmlt or when empty Turns out gold doesn't use the DW_AT_GNU_pubnames to decide whether to parse the rest of the DIEs when building gdb-index. This causes gold to trip over LLVM's output when there are DW_FORM_ref_addr present. Gold does use the presence of a debug_gnu_pub{names,types} entry for the CU to skip parsing the debug_info portion, so make sure that's included even when empty (technically, when empty there couldn't be any ref_addr anyway - it only came up when gmlt didn't produce any (even non-empty) pubnames - but given what that reveals about gold's implementation, this seems like a good thing to do for consistency). llvm-svn: 303894 --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 8 +-- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 4 +- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 28 ++++++---- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 7 +-- llvm/test/DebugInfo/Generic/empty.ll | 8 ++- llvm/test/DebugInfo/X86/empty.ll | 9 ++- llvm/test/DebugInfo/X86/gnu-public-names-empty.ll | 5 ++ llvm/test/DebugInfo/X86/gnu-public-names-gmlt.ll | 68 +++++++++++++++++++++++ 8 files changed, 113 insertions(+), 24 deletions(-) create mode 100644 llvm/test/DebugInfo/X86/gnu-public-names-gmlt.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index e172712..04073b3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -760,7 +760,7 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) { /// addGlobalName - Add a new global name to the compile unit. void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die, const DIScope *Context) { - if (includeMinimalInlineScopes()) + if (!DD->hasDwarfPubSections(includeMinimalInlineScopes())) return; std::string FullName = getParentContextString(Context) + Name.str(); GlobalNames[FullName] = &Die; @@ -768,7 +768,7 @@ void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die, void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name, const DIScope *Context) { - if (includeMinimalInlineScopes()) + if (!DD->hasDwarfPubSections(includeMinimalInlineScopes())) return; std::string FullName = getParentContextString(Context) + Name.str(); // Insert, allowing the entry to remain as-is if it's already present @@ -781,7 +781,7 @@ void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name, /// Add a new global type to the unit. void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die, const DIScope *Context) { - if (includeMinimalInlineScopes()) + if (!DD->hasDwarfPubSections(includeMinimalInlineScopes())) return; std::string FullName = getParentContextString(Context) + Ty->getName().str(); GlobalTypes[FullName] = &Die; @@ -789,7 +789,7 @@ void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die, void DwarfCompileUnit::addGlobalTypeUnitType(const DIType *Ty, const DIScope *Context) { - if (includeMinimalInlineScopes()) + if (!DD->hasDwarfPubSections(includeMinimalInlineScopes())) return; std::string FullName = getParentContextString(Context) + Ty->getName().str(); // Insert, allowing the entry to remain as-is if it's already present diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 77e9e67..b8f5747 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -77,8 +77,6 @@ class DwarfCompileUnit final : public DwarfUnit { bool isDwoUnit() const override; - bool includeMinimalInlineScopes() const; - DenseMap &getAbstractSPDies() { if (isDwoUnit() && !DD->shareAcrossDWOCUs()) return AbstractSPDies; @@ -101,6 +99,8 @@ public: return Skeleton; } + bool includeMinimalInlineScopes() const; + void initStmtList(); /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 8fb3db2..fa59307 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -252,12 +252,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) // Handle split DWARF. HasSplitDwarf = !Asm->TM.Options.MCOptions.SplitDwarfFile.empty(); - // Pubnames/pubtypes on by default for GDB. - if (DwarfPubSections == Default) - HasDwarfPubSections = tuneForGDB(); - else - HasDwarfPubSections = DwarfPubSections == Enable; - // SCE defaults to linkage names only for abstract subprograms. if (DwarfLinkageNames == DefaultLinkageNames) UseAllLinkageNames = !tuneForSCE(); @@ -391,8 +385,20 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, } } -void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { - if (!GenerateGnuPubSections) +bool DwarfDebug::hasDwarfPubSections(bool includeMinimalInlineScopes) const { + // Opting in to GNU Pubnames/types overrides the default to ensure these are + // generated for things like Gold's gdb_index generation. + if (GenerateGnuPubSections) + return true; + + if (DwarfPubSections == Default) + return tuneForGDB() && !includeMinimalInlineScopes; + + return DwarfPubSections == Enable; +} + +void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { + if (!hasDwarfPubSections(U.includeMinimalInlineScopes())) return; U.addFlag(D, dwarf::DW_AT_GNU_pubnames); @@ -718,7 +724,9 @@ void DwarfDebug::endModule() { } // Emit the pubnames and pubtypes sections if requested. - if (HasDwarfPubSections) { + // The condition is optimistically correct - any CU not using GMLT (& + // implicit/default pubnames state) might still have pubnames. + if (hasDwarfPubSections(/* gmlt */ false)) { emitDebugPubNames(GenerateGnuPubSections); emitDebugPubTypes(GenerateGnuPubSections); } @@ -1395,7 +1403,7 @@ void DwarfDebug::emitDebugPubSection( const auto &Globals = (TheU->*Accessor)(); - if (Globals.empty()) + if (!hasDwarfPubSections(TheU->includeMinimalInlineScopes())) continue; if (auto *Skeleton = TheU->getSkeleton()) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index b9c5aa9..97b96dd 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -246,9 +246,6 @@ class DwarfDebug : public DebugHandlerBase { std::pair, const DICompositeType *>, 1> TypeUnitsUnderConstruction; - /// Whether to emit the pubnames/pubtypes sections. - bool HasDwarfPubSections; - /// Whether to use the GNU TLS opcode (instead of the standard opcode). bool UseGNUTLSOpcode; @@ -415,7 +412,7 @@ class DwarfDebug : public DebugHandlerBase { /// Flags to let the linker know we have emitted new style pubnames. Only /// emit it here if we don't have a skeleton CU for split dwarf. - void addGnuPubAttributes(DwarfUnit &U, DIE &D) const; + void addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const; /// Create new DwarfCompileUnit for the given metadata node with tag /// DW_TAG_compile_unit. @@ -556,6 +553,8 @@ public: /// A helper function to check whether the DIE for a given Scope is /// going to be null. bool isLexicalScopeDIENull(LexicalScope *Scope); + + bool hasDwarfPubSections(bool includeMinimalInlineScopes) const; }; } // End of namespace llvm diff --git a/llvm/test/DebugInfo/Generic/empty.ll b/llvm/test/DebugInfo/Generic/empty.ll index d5f738f..f8bc2c0 100644 --- a/llvm/test/DebugInfo/Generic/empty.ll +++ b/llvm/test/DebugInfo/Generic/empty.ll @@ -13,10 +13,14 @@ ; CHECK-NOT: file_names[ ; CHECK: .debug_pubnames contents: -; CHECK-NOT: Offset +; CHECK-NEXT: length = 0x0000000e +; CHECK-NEXT: Offset +; CHECK-NEXT: {{^$}} ; CHECK: .debug_pubtypes contents: -; CHECK-NOT: Offset +; CHECK-NEXT: length = 0x0000000e +; CHECK-NEXT: Offset +; CHECK-NEXT: {{^$}} ; Don't emit DW_AT_addr_base when there are no addresses. ; FISSION-NOT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] diff --git a/llvm/test/DebugInfo/X86/empty.ll b/llvm/test/DebugInfo/X86/empty.ll index 774b908..a91e0d5 100644 --- a/llvm/test/DebugInfo/X86/empty.ll +++ b/llvm/test/DebugInfo/X86/empty.ll @@ -8,10 +8,15 @@ ; CHECK-NOT: file_names[ ; CHECK: .debug_pubnames contents: -; CHECK-NOT: Offset +; CHECK-NEXT: length = 0x0000000e +; CHECK-NEXT: Offset +; CHECK-NEXT: {{^$}} ; CHECK: .debug_pubtypes contents: -; CHECK-NOT: Offset +; CHECK-NEXT: length = 0x0000000e +; CHECK-NEXT: Offset +; CHECK-NEXT: {{^$}} + ; Don't emit DW_AT_addr_base when there are no addresses. ; FISSION-NOT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] diff --git a/llvm/test/DebugInfo/X86/gnu-public-names-empty.ll b/llvm/test/DebugInfo/X86/gnu-public-names-empty.ll index b04f7af..069674c 100644 --- a/llvm/test/DebugInfo/X86/gnu-public-names-empty.ll +++ b/llvm/test/DebugInfo/X86/gnu-public-names-empty.ll @@ -9,6 +9,11 @@ ; CHECK: DW_AT_GNU_pubnames [DW_FORM_flag_present] (true) ; CHECK-NOT: DW_AT_GNU_pubtypes [ +; CHECK: .debug_gnu_pubnames contents: +; CHECK-NEXT: length = 0x0000000e +; CHECK-NEXT: Offset +; CHECK-NEXT: {{^$}} + !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} diff --git a/llvm/test/DebugInfo/X86/gnu-public-names-gmlt.ll b/llvm/test/DebugInfo/X86/gnu-public-names-gmlt.ll new file mode 100644 index 0000000..569f56a --- /dev/null +++ b/llvm/test/DebugInfo/X86/gnu-public-names-gmlt.ll @@ -0,0 +1,68 @@ +; RUN: llc -mtriple=x86_64-pc-linux-gnu -filetype=obj < %s -generate-gnu-dwarf-pub-sections | llvm-dwarfdump - | FileCheck --check-prefix=GPUB --check-prefix=CHECK %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -filetype=obj < %s -generate-dwarf-pub-sections=Enable | llvm-dwarfdump - | FileCheck --check-prefix=PUB --check-prefix=CHECK %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -filetype=obj < %s | llvm-dwarfdump - | FileCheck --check-prefix=NONE %s + +; Generated from: +; void f1(); +; inline __attribute__((always_inline)) void f2() { +; f1(); +; } +; void f3() { +; f2(); +; } +; $ clang++ -gmlt %s -emit-llvm -S + +; GPUB: Compile Unit +; GPUB: DW_AT_GNU_pubnames + +; GPUB: .debug_gnu_pubnames contents: +; PUB: .debug_pubnames contents: +; CHECK-NEXT: unit_offset = 0x00000000 +; CHECK-NEXT: Name +; CHECK-NEXT: "f2" +; CHECK-NEXT: "f3" + +; GPUB: .debug_gnu_pubtypes contents: +; PUB: .debug_pubtypes contents: +; CHECK-NEXT: length = 0x0000000e version = 0x0002 unit_offset = 0x00000000 +; CHECK-NEXT: Name + +; NONE: .debug_pubnames contents: +; NONE: {{^$}} +; NONE: .debug_pubtypes contents: +; NONE: {{^$}} +; NONE: .debug_gnu_pubnames contents: +; NONE: {{^$}} +; NONE: .debug_gnu_pubtypes contents: +; NONE: {{^$}} + + +; Function Attrs: noinline uwtable +define void @_Z2f3v() #0 !dbg !7 { +entry: + call void @_Z2f1v(), !dbg !9 + ret void, !dbg !12 +} + +declare void @_Z2f1v() #1 + +attributes #0 = { noinline uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 303768) (llvm/trunk 303774)", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "gnu-public-names-gmlt.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 5.0.0 (trunk 303768) (llvm/trunk 303774)"} +!7 = distinct !DISubprogram(name: "f3", scope: !1, file: !1, line: 5, type: !8, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !2) +!9 = !DILocation(line: 3, column: 3, scope: !10, inlinedAt: !11) +!10 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!11 = distinct !DILocation(line: 6, column: 3, scope: !7) +!12 = !DILocation(line: 7, column: 1, scope: !7) -- 2.7.4