[llvm] CodeGen: Fix CodeView crashes with empty llvm.dbg.cu (PR #163286)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 30 21:22:59 PDT 2025
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/163286
>From fb0e512d7837c61f4305fe608b4645bf8dd6af3b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 14 Oct 2025 07:48:32 +0900
Subject: [PATCH 1/2] CodeGen: Fix CodeView crashes with empty llvm.dbg.cu
---
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 21 +++++++++----
.../X86/codeview-empty-dbg-cu-crash.ll | 30 +++++++++++++++++++
2 files changed, 45 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index e57ed24a45065..6cbed50e14ea9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -625,10 +625,13 @@ void CodeViewDebug::beginModule(Module *M) {
if (Asm->hasDebugInfo()) {
Node = *M->debug_compile_units_begin();
} else {
+ auto DebugCompileUnits = MMI->getModule()->debug_compile_units();
+ if (DebugCompileUnits.empty())
+ return;
+
// When emitting only compiler information, we may have only NoDebug CUs,
// which would be skipped by debug_compile_units_begin.
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- Node = *CUs->operands().begin();
+ Node = *DebugCompileUnits.begin();
}
const auto *CU = cast<DICompileUnit>(Node);
DISourceLanguageName Lang = CU->getSourceLanguage();
@@ -900,8 +903,11 @@ void CodeViewDebug::emitCompilerInformation() {
OS.AddComment("CPUType");
OS.emitInt16(static_cast<uint64_t>(TheCPU));
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- const MDNode *Node = *CUs->operands().begin();
+ auto CUs = MMI->getModule()->debug_compile_units();
+ if (CUs.empty())
+ return;
+
+ const MDNode *Node = *CUs.begin();
const auto *CU = cast<DICompileUnit>(Node);
StringRef CompilerVersion = CU->getProducer();
@@ -948,8 +954,11 @@ void CodeViewDebug::emitBuildInfo() {
// not clear if the compiler path should refer to the executable for the
// frontend or the backend. Leave it blank for now.
TypeIndex BuildInfoArgs[BuildInfoRecord::MaxArgs] = {};
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs.
+ auto CUs = MMI->getModule()->debug_compile_units();
+ if (CUs.empty())
+ return;
+
+ const MDNode *Node = *CUs.begin(); // FIXME: Multiple CUs.
const auto *CU = cast<DICompileUnit>(Node);
const DIFile *MainSourceFile = CU->getFile();
BuildInfoArgs[BuildInfoRecord::CurrentDirectory] =
diff --git a/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll b/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll
new file mode 100644
index 0000000000000..395b99e7f90b6
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll
@@ -0,0 +1,30 @@
+; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s
+
+; CHECK: .file "<stdin>"
+; CHECK-NEXT: .section .debug$S,"dr"
+; CHECK-NEXT: .p2align 2, 0x0
+; CHECK-NEXT: .long 4 # Debug section magic
+; CHECK-NEXT: .long 241
+; CHECK-NEXT: .long .Ltmp1-.Ltmp0 # Subsection size
+; CHECK-NEXT: .Ltmp0:
+; CHECK-NEXT: .short .Ltmp3-.Ltmp2 # Record length
+; CHECK-NEXT: .Ltmp2:
+; CHECK-NEXT: .short 4353 # Record kind: S_OBJNAME
+; CHECK-NEXT: .long 0 # Signature
+; CHECK-NEXT: .byte 0 # Object name
+; CHECK-NEXT: .p2align 2, 0x0
+; CHECK-NEXT: .Ltmp3:
+; CHECK-NEXT: .short .Ltmp5-.Ltmp4 # Record length
+; CHECK-NEXT: .Ltmp4:
+; CHECK-NEXT: .short 4412 # Record kind: S_COMPILE3
+; CHECK-NEXT: .long 3 # Flags and language
+; CHECK-NEXT: .short 208 # CPUType
+; CHECK-NEXT: .Ltmp1:
+; CHECK-NEXT: .p2align 2, 0x0
+; CHECK-NEXT: .cv_filechecksums # File index to string table offset subsection
+; CHECK-NEXT: .cv_stringtable # String table
+
+!llvm.dbg.cu = !{}
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
>From fddd3683c6431f1fe19ae7cedd20e5cf2021621c Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 30 Oct 2025 21:22:42 -0700
Subject: [PATCH 2/2] Emit 0 instead of incomplete information
---
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 20 +++++++++----------
.../X86/codeview-empty-dbg-cu-crash.ll | 7 +++++++
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 6cbed50e14ea9..e64ad6a5aa4cc 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -903,18 +903,18 @@ void CodeViewDebug::emitCompilerInformation() {
OS.AddComment("CPUType");
OS.emitInt16(static_cast<uint64_t>(TheCPU));
+ StringRef CompilerVersion = "0";
auto CUs = MMI->getModule()->debug_compile_units();
- if (CUs.empty())
- return;
-
- const MDNode *Node = *CUs.begin();
- const auto *CU = cast<DICompileUnit>(Node);
+ if (!CUs.empty()) {
+ const MDNode *Node = *CUs.begin();
+ const auto *CU = cast<DICompileUnit>(Node);
- StringRef CompilerVersion = CU->getProducer();
- Version FrontVer = parseVersion(CompilerVersion);
- OS.AddComment("Frontend version");
- for (int N : FrontVer.Part) {
- OS.emitInt16(N);
+ CompilerVersion = CU->getProducer();
+ Version FrontVer = parseVersion(CompilerVersion);
+ OS.AddComment("Frontend version");
+ for (int N : FrontVer.Part) {
+ OS.emitInt16(N);
+ }
}
// Some Microsoft tools, like Binscope, expect a backend version number of at
diff --git a/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll b/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll
index 395b99e7f90b6..b40b48cb0bd40 100644
--- a/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll
+++ b/llvm/test/DebugInfo/X86/codeview-empty-dbg-cu-crash.ll
@@ -19,6 +19,13 @@
; CHECK-NEXT: .short 4412 # Record kind: S_COMPILE3
; CHECK-NEXT: .long 3 # Flags and language
; CHECK-NEXT: .short 208 # CPUType
+; CHECK-NEXT: .short 22000 # Backend version
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .asciz "0" # Null-terminated compiler version string
+; CHECK-NEXT: .p2align 2, 0x0
+; CHECK-NEXT: .Ltmp5:
; CHECK-NEXT: .Ltmp1:
; CHECK-NEXT: .p2align 2, 0x0
; CHECK-NEXT: .cv_filechecksums # File index to string table offset subsection
More information about the llvm-commits
mailing list