Skip to content

Prevent a crash when a global variable has debug metadata #145918

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

Conversation

gbMattN
Copy link
Contributor

@gbMattN gbMattN commented Jun 26, 2025

This patch fixes a crash I found when trying to compile some codebases with -fsanitize=type and -g

@llvmbot
Copy link
Member

llvmbot commented Jun 26, 2025

@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-llvm-ir

Author: None (gbMattN)

Changes

This patch fixes a crash I found when trying to compile some codebases with -fsanitize=type and -g


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

2 Files Affected:

  • (modified) llvm/lib/IR/DebugInfo.cpp (+2-2)
  • (modified) llvm/unittests/IR/DebugInfoTest.cpp (+38)
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 5c645ffe3f3f7..c0ca896247ff3 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -50,7 +50,7 @@ TinyPtrVector<DbgDeclareInst *> llvm::findDbgDeclares(Value *V) {
   // DenseMap lookup. This check is a bitfield datamember lookup.
   if (!V->isUsedByMetadata())
     return {};
-  auto *L = LocalAsMetadata::getIfExists(V);
+  auto *L = ValueAsMetadata::getIfExists(V);
   if (!L)
     return {};
   auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L);
@@ -69,7 +69,7 @@ TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) {
   // DenseMap lookup. This check is a bitfield datamember lookup.
   if (!V->isUsedByMetadata())
     return {};
-  auto *L = LocalAsMetadata::getIfExists(V);
+  auto *L = ValueAsMetadata::getIfExists(V);
   if (!L)
     return {};
 
diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp
index 35bdbf8cc8321..1f88f249789f8 100644
--- a/llvm/unittests/IR/DebugInfoTest.cpp
+++ b/llvm/unittests/IR/DebugInfoTest.cpp
@@ -195,6 +195,44 @@ TEST(MetadataTest, DeleteInstUsedByDbgRecord) {
   EXPECT_TRUE(isa<UndefValue>(DVRs[0]->getValue(0)));
 }
 
+TEST(MetadataTest, GlobalConstantMetadataUsedByDbgRecord) {
+    LLVMContext C;
+  std::unique_ptr<Module> M = parseIR(C, R"(
+    @x = dso_local global i32 0, align 4
+    define i16 @f(i16 %a) !dbg !6 {
+      %b = add i16 %a, 1, !dbg !11
+      call void @llvm.dbg.declare(metadata ptr @x, metadata !9, metadata !DIExpression()), !dbg !11
+      ret i16 0, !dbg !11
+    }
+    declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+    attributes #0 = { nounwind readnone speculatable willreturn }
+
+    !llvm.dbg.cu = !{!0}
+    !llvm.module.flags = !{!5}
+
+    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+    !1 = !DIFile(filename: "t.ll", directory: "/")
+    !2 = !{}
+    !5 = !{i32 2, !"Debug Info Version", i32 3}
+    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+    !7 = !DISubroutineType(types: !2)
+    !8 = !{!9}
+    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
+    !11 = !DILocation(line: 1, column: 1, scope: !6)
+)");
+
+  // Find the global @x
+  Value* V = M->getNamedValue("x");
+
+  // Find the dbg.value
+  auto DVIs = findDbgDeclares(V);
+  auto DVRs = findDVRDeclares(V);
+
+  EXPECT_EQ(DVRs[0]->getNumVariableLocationOps(), 1u);
+  EXPECT_FALSE(isa<UndefValue>(DVRs[0]->getValue(0)));
+}
+
 TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) {
   LLVMContext Ctx;
   std::unique_ptr<Module> M = parseIR(Ctx, R"(

Copy link

github-actions bot commented Jun 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes, that's a pain -- so 'C' s being looked up from somewhere else and is wrong/bad? Any idea where the 'C' variable is coming from here? (Possibly we should do something else to ensure this isn't an error latent in other unit tests).

@jmorse
Copy link
Member

jmorse commented Jun 27, 2025

Hmmmph, got my wires crossed on reviews and patches there, lemmie try again...

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Urgh. Discussed slightly offline, the fix is correct but it indicates that we've never been able to lookup debug-users of global variables in LLVM, ever, because of the VAM/LocalAsMetadata differences you're fixing here. Which is horrible, but I imagine it's not a common access pattern -- usually we look up the debug-users of a local instruction that's being fiddled with.

Would you be able to repeat the fix/unit-test for findDVRValues please, as it looks like that's vulnerable to the same issue.

@gbMattN
Copy link
Contributor Author

gbMattN commented Jun 27, 2025

Done so!

@gbMattN gbMattN force-pushed the users/nagym/prevent-global-metadata-crash branch from 4e75e08 to ecbf511 Compare June 27, 2025 10:41
Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; ship it!

@gbMattN gbMattN merged commit 0158ca2 into llvm:main Jun 27, 2025
4 checks passed
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
This patch fixes a crash I found when trying to compile some codebases
with -fsanitize=type and -g
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