Skip to content

Conversation

@kees
Copy link
Contributor

@kees kees commented Oct 8, 2025

As fixed in commits 913f7e9, 4a8b124, and 4eef2e3, also fix the stack-depth tracking code to use InstrumentationIRBuilder, and set the Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling

@llvmbot llvmbot added clang Clang issues not falling into any other category compiler-rt:sanitizer llvm:transforms labels Oct 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-clang

Author: Kees Cook (kees)

Changes

As fixed in commits llvm/llvm-project@913f7e9, llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the stack-depth tracking code to use InstrumentationIRBuilder, and set the Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling


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

2 Files Affected:

  • (added) clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c (+40)
  • (modified) llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp (+6-3)
diff --git a/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c b/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c
new file mode 100644
index 0000000000000..33791dabcdca8
--- /dev/null
+++ b/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c
@@ -0,0 +1,40 @@
+// Test that SanitizerCoverage preserves debug locations when inserting stack depth tracking
+// This is a regression test for GitHub issue ClangBuiltLinux/linux#2125
+//
+// The bug was that IRBuilder<> was used instead of InstrumentationIRBuilder in SanitizerCoverage,
+// causing inserted instructions to lack !dbg metadata. This caused LTO builds with debug info
+// to fail verification with:
+// "inlinable function call in a function with debug info must have a !dbg location"
+//
+// Test the lowest-stack tracking path (default stack-depth mode)
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN:   -fsanitize-coverage-type=1 -fsanitize-coverage-stack-depth -debug-info-kind=limited \
+// RUN:   | FileCheck %s --check-prefix=CHECK-STORE
+//
+// Test the callback path (stack-depth with callback-min threshold)
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN:   -fsanitize-coverage-type=1 -mllvm -sanitizer-coverage-stack-depth \
+// RUN:   -mllvm -sanitizer-coverage-stack-depth-callback-min=1 -debug-info-kind=limited \
+// RUN:   | FileCheck %s --check-prefix=CHECK-CALLBACK
+//
+// Verify the store to __sancov_lowest_stack has a debug location
+// CHECK-STORE: store i64 %{{.*}}, ptr @__sancov_lowest_stack, align 8, !dbg !{{[0-9]+}}, {{.*}}!nosanitize
+//
+// Verify the call to __sanitizer_cov_stack_depth has a debug location
+// CHECK-CALLBACK: call void @__sanitizer_cov_stack_depth(){{.*}}, !dbg !{{[0-9]+}}
+
+extern void external_func(void);
+
+// Mark as always_inline to ensure the bug condition is met
+__attribute__((always_inline))
+static inline void inline_helper(void) {
+    external_func();
+}
+
+void foo(int a) {
+    int local[4];  // Stack allocation to trigger stack depth tracking
+    if (a > 0) {
+        inline_helper();
+    }
+    local[0] = a;
+}
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 5b8ea1547ca2f..5dbd0ec2a0e27 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -1084,7 +1084,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     auto ThenTerm = SplitBlockAndInsertIfThen(
         IRB.CreateIsNull(Load), &*IP, false,
         MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
-    IRBuilder<> ThenIRB(ThenTerm);
+    InstrumentationIRBuilder ThenIRB(ThenTerm);
     auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);
     Load->setNoSanitizeMetadata();
     Store->setNoSanitizeMetadata();
@@ -1131,7 +1131,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
           EstimatedStackSize >= Options.StackDepthCallbackMin) {
         if (InsertBefore)
           IRB.SetInsertPoint(InsertBefore);
-        IRB.CreateCall(SanCovStackDepthCallback)->setCannotMerge();
+        auto Call = IRB.CreateCall(SanCovStackDepthCallback);
+        if (EntryLoc)
+          Call->setDebugLoc(EntryLoc);
+        Call->setCannotMerge();
       }
     } else {
       // Check stack depth.  If it's the deepest so far, record it.
@@ -1144,7 +1147,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
       auto ThenTerm = SplitBlockAndInsertIfThen(
           IsStackLower, &*IP, false,
           MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
-      IRBuilder<> ThenIRB(ThenTerm);
+      InstrumentationIRBuilder ThenIRB(ThenTerm);
       auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);
       LowestStack->setNoSanitizeMetadata();
       Store->setNoSanitizeMetadata();

@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Kees Cook (kees)

Changes

As fixed in commits llvm/llvm-project@913f7e9, llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the stack-depth tracking code to use InstrumentationIRBuilder, and set the Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling


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

2 Files Affected:

  • (added) clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c (+40)
  • (modified) llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp (+6-3)
diff --git a/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c b/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c
new file mode 100644
index 0000000000000..33791dabcdca8
--- /dev/null
+++ b/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c
@@ -0,0 +1,40 @@
+// Test that SanitizerCoverage preserves debug locations when inserting stack depth tracking
+// This is a regression test for GitHub issue ClangBuiltLinux/linux#2125
+//
+// The bug was that IRBuilder<> was used instead of InstrumentationIRBuilder in SanitizerCoverage,
+// causing inserted instructions to lack !dbg metadata. This caused LTO builds with debug info
+// to fail verification with:
+// "inlinable function call in a function with debug info must have a !dbg location"
+//
+// Test the lowest-stack tracking path (default stack-depth mode)
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN:   -fsanitize-coverage-type=1 -fsanitize-coverage-stack-depth -debug-info-kind=limited \
+// RUN:   | FileCheck %s --check-prefix=CHECK-STORE
+//
+// Test the callback path (stack-depth with callback-min threshold)
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN:   -fsanitize-coverage-type=1 -mllvm -sanitizer-coverage-stack-depth \
+// RUN:   -mllvm -sanitizer-coverage-stack-depth-callback-min=1 -debug-info-kind=limited \
+// RUN:   | FileCheck %s --check-prefix=CHECK-CALLBACK
+//
+// Verify the store to __sancov_lowest_stack has a debug location
+// CHECK-STORE: store i64 %{{.*}}, ptr @__sancov_lowest_stack, align 8, !dbg !{{[0-9]+}}, {{.*}}!nosanitize
+//
+// Verify the call to __sanitizer_cov_stack_depth has a debug location
+// CHECK-CALLBACK: call void @__sanitizer_cov_stack_depth(){{.*}}, !dbg !{{[0-9]+}}
+
+extern void external_func(void);
+
+// Mark as always_inline to ensure the bug condition is met
+__attribute__((always_inline))
+static inline void inline_helper(void) {
+    external_func();
+}
+
+void foo(int a) {
+    int local[4];  // Stack allocation to trigger stack depth tracking
+    if (a > 0) {
+        inline_helper();
+    }
+    local[0] = a;
+}
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 5b8ea1547ca2f..5dbd0ec2a0e27 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -1084,7 +1084,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     auto ThenTerm = SplitBlockAndInsertIfThen(
         IRB.CreateIsNull(Load), &*IP, false,
         MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
-    IRBuilder<> ThenIRB(ThenTerm);
+    InstrumentationIRBuilder ThenIRB(ThenTerm);
     auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);
     Load->setNoSanitizeMetadata();
     Store->setNoSanitizeMetadata();
@@ -1131,7 +1131,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
           EstimatedStackSize >= Options.StackDepthCallbackMin) {
         if (InsertBefore)
           IRB.SetInsertPoint(InsertBefore);
-        IRB.CreateCall(SanCovStackDepthCallback)->setCannotMerge();
+        auto Call = IRB.CreateCall(SanCovStackDepthCallback);
+        if (EntryLoc)
+          Call->setDebugLoc(EntryLoc);
+        Call->setCannotMerge();
       }
     } else {
       // Check stack depth.  If it's the deepest so far, record it.
@@ -1144,7 +1147,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
       auto ThenTerm = SplitBlockAndInsertIfThen(
           IsStackLower, &*IP, false,
           MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
-      IRBuilder<> ThenIRB(ThenTerm);
+      InstrumentationIRBuilder ThenIRB(ThenTerm);
       auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);
       LowestStack->setNoSanitizeMetadata();
       Store->setNoSanitizeMetadata();

@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Kees Cook (kees)

Changes

As fixed in commits llvm/llvm-project@913f7e9, llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the stack-depth tracking code to use InstrumentationIRBuilder, and set the Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling


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

2 Files Affected:

  • (added) clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c (+40)
  • (modified) llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp (+6-3)
diff --git a/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c b/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c
new file mode 100644
index 0000000000000..33791dabcdca8
--- /dev/null
+++ b/clang/test/CodeGen/sanitizer-coverage-stack-depth-debug-loc.c
@@ -0,0 +1,40 @@
+// Test that SanitizerCoverage preserves debug locations when inserting stack depth tracking
+// This is a regression test for GitHub issue ClangBuiltLinux/linux#2125
+//
+// The bug was that IRBuilder<> was used instead of InstrumentationIRBuilder in SanitizerCoverage,
+// causing inserted instructions to lack !dbg metadata. This caused LTO builds with debug info
+// to fail verification with:
+// "inlinable function call in a function with debug info must have a !dbg location"
+//
+// Test the lowest-stack tracking path (default stack-depth mode)
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN:   -fsanitize-coverage-type=1 -fsanitize-coverage-stack-depth -debug-info-kind=limited \
+// RUN:   | FileCheck %s --check-prefix=CHECK-STORE
+//
+// Test the callback path (stack-depth with callback-min threshold)
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
+// RUN:   -fsanitize-coverage-type=1 -mllvm -sanitizer-coverage-stack-depth \
+// RUN:   -mllvm -sanitizer-coverage-stack-depth-callback-min=1 -debug-info-kind=limited \
+// RUN:   | FileCheck %s --check-prefix=CHECK-CALLBACK
+//
+// Verify the store to __sancov_lowest_stack has a debug location
+// CHECK-STORE: store i64 %{{.*}}, ptr @__sancov_lowest_stack, align 8, !dbg !{{[0-9]+}}, {{.*}}!nosanitize
+//
+// Verify the call to __sanitizer_cov_stack_depth has a debug location
+// CHECK-CALLBACK: call void @__sanitizer_cov_stack_depth(){{.*}}, !dbg !{{[0-9]+}}
+
+extern void external_func(void);
+
+// Mark as always_inline to ensure the bug condition is met
+__attribute__((always_inline))
+static inline void inline_helper(void) {
+    external_func();
+}
+
+void foo(int a) {
+    int local[4];  // Stack allocation to trigger stack depth tracking
+    if (a > 0) {
+        inline_helper();
+    }
+    local[0] = a;
+}
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 5b8ea1547ca2f..5dbd0ec2a0e27 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -1084,7 +1084,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
     auto ThenTerm = SplitBlockAndInsertIfThen(
         IRB.CreateIsNull(Load), &*IP, false,
         MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
-    IRBuilder<> ThenIRB(ThenTerm);
+    InstrumentationIRBuilder ThenIRB(ThenTerm);
     auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);
     Load->setNoSanitizeMetadata();
     Store->setNoSanitizeMetadata();
@@ -1131,7 +1131,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
           EstimatedStackSize >= Options.StackDepthCallbackMin) {
         if (InsertBefore)
           IRB.SetInsertPoint(InsertBefore);
-        IRB.CreateCall(SanCovStackDepthCallback)->setCannotMerge();
+        auto Call = IRB.CreateCall(SanCovStackDepthCallback);
+        if (EntryLoc)
+          Call->setDebugLoc(EntryLoc);
+        Call->setCannotMerge();
       }
     } else {
       // Check stack depth.  If it's the deepest so far, record it.
@@ -1144,7 +1147,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
       auto ThenTerm = SplitBlockAndInsertIfThen(
           IsStackLower, &*IP, false,
           MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
-      IRBuilder<> ThenIRB(ThenTerm);
+      InstrumentationIRBuilder ThenIRB(ThenTerm);
       auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);
       LowestStack->setNoSanitizeMetadata();
       Store->setNoSanitizeMetadata();

@kees kees requested a review from melver October 8, 2025 05:54
As fixed in commits llvm/llvm-project@913f7e9, llvm/llvm-project@4a8b124,
and llvm/llvm-project@4eef2e3, also fix the stack-depth tracking code
to use InstrumentationIRBuilder, set the Store and Call's Debug location
to EntryLoc, and update the tests to include stack-depth tests.

ClangBuiltLinux/linux#2125
@kees kees requested a review from melver October 8, 2025 20:38
@kees
Copy link
Contributor Author

kees commented Oct 8, 2025

CI appears to be broken? "cp" failed? O_o

@JustinStitt
Copy link
Contributor

CI appears to be broken? "cp" failed? O_o

Actual error seems to be:

  CMake Error at /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/unittests/CMakeLists.txt:25 (message):
    The LLDBBreakpointTests are not allowed to link liblldb.
  Call Stack (most recent call first):
    /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/unittests/Breakpoint/CMakeLists.txt:1 (add_lldb_unittest)

which then causes the cp failure when the build artifact isn't there to be copied.

@JustinStitt
Copy link
Contributor

JustinStitt commented Oct 8, 2025

It seems the test failure is introduced by a combination of 02572c6 and f3e2c20 and not by @kees patch.

tracking here: #162566

edit: the fix is probably just this #162571

@kees kees merged commit 28b7f66 into llvm:main Oct 9, 2025
9 checks passed
@kees kees deleted the fix-irbuilder branch October 9, 2025 07:50
@nathanchance nathanchance added this to the LLVM 21.x Release milestone Oct 9, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Oct 9, 2025
@nathanchance
Copy link
Member

/cherry-pick 28b7f66

@llvmbot
Copy link
Member

llvmbot commented Oct 9, 2025

/pull-request #162697

@llvmbot llvmbot moved this from Needs Triage to Done in LLVM Release Status Oct 9, 2025
svkeerthy pushed a commit that referenced this pull request Oct 9, 2025
As fixed in commits 913f7e9,
4a8b124, and 4eef2e3, also fix the
stack-depth tracking code to use InstrumentationIRBuilder, and set the
Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling
clingfei pushed a commit to clingfei/llvm-project that referenced this pull request Oct 10, 2025
As fixed in commits llvm/llvm-project@913f7e9,
llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the
stack-depth tracking code to use InstrumentationIRBuilder, and set the
Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling
DharuniRAcharya pushed a commit to DharuniRAcharya/llvm-project that referenced this pull request Oct 13, 2025
As fixed in commits llvm/llvm-project@913f7e9,
llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the
stack-depth tracking code to use InstrumentationIRBuilder, and set the
Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling
akadutta pushed a commit to akadutta/llvm-project that referenced this pull request Oct 14, 2025
As fixed in commits llvm/llvm-project@913f7e9,
llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the
stack-depth tracking code to use InstrumentationIRBuilder, and set the
Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling
c-rhodes pushed a commit to llvmbot/llvm-project that referenced this pull request Oct 27, 2025
As fixed in commits llvm/llvm-project@913f7e9,
llvm/llvm-project@4a8b124, and llvm/llvm-project@4eef2e3, also fix the
stack-depth tracking code to use InstrumentationIRBuilder, and set the
Call's Debug location to EntryLoc.

ClangBuiltLinux/linux#2125

cc @nathanchance @melver @JustinStitt @bwendling

(cherry picked from commit 28b7f66)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category compiler-rt:sanitizer llvm:transforms

Projects

Development

Successfully merging this pull request may close these issues.

6 participants