Skip to content

[LLVM][DWARF] Create debug names entry for non-tu top level DIE #121856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 9, 2025

Conversation

ayermolo
Copy link
Contributor

@ayermolo ayermolo commented Jan 6, 2025

When creating a Type Unit (TU), LLVM attempts to do so optimistically. However, if this fails, it discards the TU state and creates the TU within the Compilation Unit (CU). In such cases, an entry for the top-level DIE is not created in the debug names table.
This can cause issues when running llvm-dwarfdump --debug-names --verify, as the missing entry will result in verification failure.
To address this issue, this patch adds a call to the updateAcceleratorTables when TU creation fails. This ensures that the debug names table is updated correctly, even in cases where TU creation fails.

@ayermolo ayermolo requested a review from dwblaikie January 6, 2025 23:34
@llvmbot
Copy link
Member

llvmbot commented Jan 6, 2025

@llvm/pr-subscribers-debuginfo

Author: Alexander Yermolovich (ayermolo)

Changes

When creating a Type Unit (TU), LLVM attempts to do so optimistically. However, if this fails, it discards the TU state and creates the TU within the Compilation Unit (CU). In such cases, an entry for the top-level DIE is not created in the debug names table.
This can cause issues when running llvm-dwarfdump --debug-names --verify, as the missing entry will result in verification failure.
To address this issue, this patch adds a call to the updateAcceleratorTables when TU creation fails. This ensures that the debug names table is updated correctly, even in cases where TU creation fails.


Full diff: https://github.com/llvm/llvm-project/pull/121856.diff

4 Files Affected:

  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+5-4)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h (+2-1)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (+2-1)
  • (added) llvm/test/DebugInfo/X86/dwarf5-debug-names-addr-tu-to-non-tu.ll (+83)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index e1291e2a14a66e..c88ca8c256bb74 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -3704,19 +3704,19 @@ uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
   return Result.high();
 }
 
-void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
+bool DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
                                       StringRef Identifier, DIE &RefDie,
                                       const DICompositeType *CTy) {
   // Fast path if we're building some type units and one has already used the
   // address pool we know we're going to throw away all this work anyway, so
   // don't bother building dependent types.
   if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
-    return;
+    return false;
 
   auto Ins = TypeSignatures.insert(std::make_pair(CTy, 0));
   if (!Ins.second) {
     CU.addDIETypeSignature(RefDie, Ins.first->second);
-    return;
+    return false;
   }
 
   setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
@@ -3789,7 +3789,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
       // they depend on addresses, throwing them out and rebuilding them.
       setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
       CU.constructTypeDIE(RefDie, cast<DICompositeType>(CTy));
-      return;
+      return true;
     }
 
     // If the type wasn't dependent on fission addresses, finish adding the type
@@ -3811,6 +3811,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
     setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
   }
   CU.addDIETypeSignature(RefDie, Signature);
+  return false;
 }
 
 // Add the Name along with its companion DIE to the appropriate accelerator
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 9662c617d730ee..2bbd0805b1c4d1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -744,7 +744,8 @@ class DwarfDebug : public DebugHandlerBase {
 
   /// Add a DIE to the set of types that we're going to pull into
   /// type units.
-  void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
+  /// Returns true if TU creation fails, and type was emitted in the CU.
+  bool addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
                             DIE &Die, const DICompositeType *CTy);
 
   /// Add a label so that arange data can be generated for it.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 0a8a1ad38c959f..90ee8b21cb87fa 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -589,7 +589,8 @@ DIE *DwarfUnit::createTypeDIE(const DIScope *Context, DIE &ContextDIE,
       // Skip updating the accelerator tables since this is not the full type.
       if (MDString *TypeId = CTy->getRawIdentifier()) {
         addGlobalType(Ty, TyDIE, Context);
-        DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
+        if (DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy))
+          updateAcceleratorTables(Context, Ty, TyDIE);
       } else {
         updateAcceleratorTables(Context, Ty, TyDIE);
         finishNonUnitTypeDIE(TyDIE, CTy);
diff --git a/llvm/test/DebugInfo/X86/dwarf5-debug-names-addr-tu-to-non-tu.ll b/llvm/test/DebugInfo/X86/dwarf5-debug-names-addr-tu-to-non-tu.ll
new file mode 100644
index 00000000000000..a1a5b073f2a91c
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/dwarf5-debug-names-addr-tu-to-non-tu.ll
@@ -0,0 +1,83 @@
+; RUN: llc -filetype=obj -O0 -generate-type-units -mtriple=x86_64-unknown-linux-gnu < %s \
+; RUN:     | llvm-dwarfdump -debug-info -debug-names - \
+; RUN:     | FileCheck %s
+
+;; Test that an entry in the debug names table gets created for a top level DIE when the creation of TU is aborted.
+
+; CHECK: [[OFFSET:0x[0-9a-f]*]]:   DW_TAG_structure_type
+; CHECK: [[OFFSET1:0x[0-9a-f]*]]:   DW_TAG_structure_type
+
+; CHECK:        Bucket 0 [
+; CHECK-NEXT:    Name 1 {
+; CHECK-NEXT:      Hash: {{.+}}
+; CHECK-NEXT:      String: {{.+}} "t3"
+; CHECK-NEXT:      Entry @ {{.+}} {
+; CHECK-NEXT:        Abbrev: 0x1
+; CHECK-NEXT:        Tag: DW_TAG_structure_type
+; CHECK-NEXT:        DW_IDX_die_offset: [[OFFSET]]
+; CHECK-NEXT:        DW_IDX_parent: <parent not indexed>
+
+; CHECK:        Name 5 {
+; CHECK-NEXT:      Hash: {{.+}}
+; CHECK-NEXT:      String: {{.+}} "t2<&foo>"
+; CHECK-NEXT:      Entry @ 0xe1 {
+; CHECK-NEXT:        Abbrev: 0x1
+; CHECK-NEXT:        Tag: DW_TAG_structure_type
+; CHECK-NEXT:        DW_IDX_die_offset: [[OFFSET1]]
+; CHECK-NEXT:        DW_IDX_parent: <parent not indexed>
+
+;; clang++ -O0 main.cpp -gdwarf-5 -fdebug-types-section -gpubnames -S -emit-llvm -glldb -o main.ll
+;; int foo;
+;; namespace {
+;; struct t1 {};
+;; } // namespace
+;; template <int *> struct t2 {
+;;   t1 v1;
+;; };
+;; struct t3 {
+;;   t2<&foo> v1;
+;; };
+;; t3 v1;
+
+; ModuleID = 'main.cpp'
+source_filename = "main.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.t3 = type { i8 }
+
+@foo = dso_local global i32 0, align 4, !dbg !0
+@v1 = dso_local global %struct.t3 zeroinitializer, align 1, !dbg !5
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!20, !21, !22, !23, !24, !25, !26}
+!llvm.ident = !{!27}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, line: 1, type: !19, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 20.0.0git ([email protected]:llvm/llvm-project.git ba373096e8ac83a7136fc44bc4e71a7bc53417a6)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, sysroot: "/")
+!3 = !DIFile(filename: "main.cpp", directory: "/StructuredType", checksumkind: CSK_MD5, checksum: "f91f8d905197b1c0309da9526bc4776e")
+!4 = !{!0, !5}
+!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
+!6 = distinct !DIGlobalVariable(name: "v1", scope: !2, file: !3, line: 11, type: !7, isLocal: false, isDefinition: true)
+!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t3", file: !3, line: 8, size: 8, flags: DIFlagTypePassByValue, elements: !8, identifier: "_ZTS2t3")
+!8 = !{!9}
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "v1", scope: !7, file: !3, line: 9, baseType: !10, size: 8)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2<&foo>", file: !3, line: 5, size: 8, flags: DIFlagTypePassByValue, elements: !11, templateParams: !16, identifier: "_ZTS2t2IXadL_Z3fooEEE")
+!11 = !{!12}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "v1", scope: !10, file: !3, line: 6, baseType: !13, size: 8)
+!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", scope: !14, file: !3, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !15)
+!14 = !DINamespace(scope: null)
+!15 = !{}
+!16 = !{!17}
+!17 = !DITemplateValueParameter(type: !18, value: ptr @foo)
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!20 = !{i32 7, !"Dwarf Version", i32 5}
+!21 = !{i32 2, !"Debug Info Version", i32 3}
+!22 = !{i32 1, !"wchar_size", i32 4}
+!23 = !{i32 8, !"PIC Level", i32 2}
+!24 = !{i32 7, !"PIE Level", i32 2}
+!25 = !{i32 7, !"uwtable", i32 2}
+!26 = !{i32 7, !"frame-pointer", i32 2}
+!27 = !{!"clang version 20.0.0git ([email protected]:llvm/llvm-project.git ba373096e8ac83a7136fc44bc4e71a7bc53417a6)"}

@ayermolo ayermolo force-pushed the DebugNamesTuNonTUFix branch from ff5c90f to dda4a8a Compare January 7, 2025 22:03
LLVM tries to create TU optimistically. If that fails it discards the TU
state and creates TU wihin the CU. When this happens the entry in debug
names table for top level DIE is not created. This causes
llvm-dwarfdumjp --debug-names --verify to fail because an entry is
missing. This patch adds a call to updateAcceleratorTables, when TU
creation fails.
@ayermolo ayermolo force-pushed the DebugNamesTuNonTUFix branch from 8e9cbfb to dda7d6d Compare January 8, 2025 22:48
@ayermolo ayermolo merged commit fce0314 into llvm:main Jan 9, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants