[clang] [lldb] [clang] Add -fno-debug-record-sysroot (PR #192541)
Keith Smiley via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 27 11:54:24 PDT 2026
https://github.com/keith updated https://github.com/llvm/llvm-project/pull/192541
>From 98fe7f4f44f17d6b813a057862e30283ed582277 Mon Sep 17 00:00:00 2001
From: Keith Smiley <keithbsmiley at gmail.com>
Date: Thu, 16 Apr 2026 14:22:08 -0700
Subject: [PATCH 1/2] [clang] Add -fno-debug-record-sysroot
This enables excluding the absolute path to the sysroot from debug info
for reproducible builds. These fields are used by lldb, which also has
fallbacks since it's possible these paths don't exist on the machine
doing the debugging when built remotely anyways.
This was also possible using `-fdebug-prefix-map=/path/to/Xcode.app=/some/path`
but depending on the environment you might not be able to easily pass
that with the user specific developer directory path.
Assisted by: claude
---
clang/include/clang/Basic/DebugOptions.def | 3 +++
clang/include/clang/Options/Options.td | 7 +++++++
clang/lib/CodeGen/CGDebugInfo.cpp | 15 +++++++++++----
clang/lib/Driver/ToolChains/Clang.cpp | 4 ++++
clang/test/DebugInfo/Generic/sysroot-sdk.c | 9 +++++++++
clang/test/Modules/debug-info-moduleimport.m | 13 +++++++++++++
6 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def
index 604e87e615a69..c9dd3f726e799 100644
--- a/clang/include/clang/Basic/DebugOptions.def
+++ b/clang/include/clang/Basic/DebugOptions.def
@@ -125,6 +125,9 @@ DEBUGOPT(CodeViewCommandLine, 1, 0, Compatible)
/// Whether emit extra debug info for sample pgo profile collection.
DEBUGOPT(DebugInfoForProfiling, 1, 0, Compatible)
+/// Whether to record the sysroot path or scrub it from debug info.
+DEBUGOPT(DebugRecordSysroot, 1, 1, Compatible)
+
/// Whether to emit DW_TAG_template_alias for template aliases.
DEBUGOPT(DebugTemplateAlias, 1, 0, Compatible)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index c16c41ad4057d..03a9e3dd51a8c 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1823,6 +1823,13 @@ defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling",
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option],
"Emit extra debug info to make sample profile more accurate">,
NegFlag<SetFalse, [], [ClangOption, FlangOption]>>;
+defm debug_record_sysroot : BoolFOption<"debug-record-sysroot",
+ CodeGenOpts<"DebugRecordSysroot">, DefaultTrue,
+ PosFlag<SetTrue, [], [ClangOption, CC1Option],
+ "Record the sysroot path in debug info as DW_AT_LLVM_sysroot and in DW_AT_LLVM_include_path "
+ "(used by LLDB to locate the SDK for Clang module imports).">,
+ NegFlag<SetFalse, [], [ClangOption, CC1Option],
+ "Scrub the sysroot path from debug info.">>;
def fprofile_generate_cold_function_coverage : Flag<["-"], "fprofile-generate-cold-function-coverage">,
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
HelpText<"Generate instrumented code to collect coverage info for cold functions into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 641ba32dfc224..2b8773b5b1555 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -852,9 +852,11 @@ void CGDebugInfo::CreateCompileUnit() {
StringRef Sysroot, SDK;
if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB) {
- Sysroot = CGM.getHeaderSearchOpts().Sysroot;
- auto B = llvm::sys::path::rbegin(Sysroot);
- auto E = llvm::sys::path::rend(Sysroot);
+ StringRef FullSysroot = CGM.getHeaderSearchOpts().Sysroot;
+ if (CGM.getCodeGenOpts().DebugRecordSysroot)
+ Sysroot = FullSysroot;
+ auto B = llvm::sys::path::rbegin(FullSysroot);
+ auto E = llvm::sys::path::rend(FullSysroot);
auto It =
std::find_if(B, E, [](auto SDK) { return SDK.ends_with(".sdk"); });
if (It != E)
@@ -3529,7 +3531,12 @@ llvm::DIModule *CGDebugInfo::getOrCreateModuleRef(ASTSourceDescriptor Mod,
IsRootModule ? nullptr
: getOrCreateModuleRef(ASTSourceDescriptor(*M->Parent),
CreateSkeletonCU);
- std::string IncludePath = Mod.getPath().str();
+ StringRef IncludePath = Mod.getPath();
+ if (!CGM.getCodeGenOpts().DebugRecordSysroot) {
+ StringRef Sysroot = CGM.getHeaderSearchOpts().Sysroot;
+ if (!Sysroot.empty() && IncludePath.starts_with(Sysroot))
+ IncludePath = "";
+ }
llvm::DIModule *DIMod =
DBuilder.createModule(Parent, Mod.getModuleName(), ConfigMacros,
RemapPath(IncludePath));
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index cf5a29f19aaff..d5c05f861564b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4460,6 +4460,10 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
addDebugInfoForProfilingArgs(D, TC, Args, CmdArgs);
+ if (!Args.hasFlag(options::OPT_fdebug_record_sysroot,
+ options::OPT_fno_debug_record_sysroot, true))
+ CmdArgs.push_back("-fno-debug-record-sysroot");
+
// The 'g' groups options involve a somewhat intricate sequence of decisions
// about what to pass from the driver to the frontend, but by the time they
// reach cc1 they've been factored into three well-defined orthogonal choices:
diff --git a/clang/test/DebugInfo/Generic/sysroot-sdk.c b/clang/test/DebugInfo/Generic/sysroot-sdk.c
index b52d2e1de9c1d..b424e62f5d3b0 100644
--- a/clang/test/DebugInfo/Generic/sysroot-sdk.c
+++ b/clang/test/DebugInfo/Generic/sysroot-sdk.c
@@ -4,6 +4,10 @@
// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
// RUN: %s -isysroot /CLANG_SYSROOT/MacOSX.sdk -emit-llvm -o - \
// RUN: -debugger-tuning=gdb | FileCheck %s --check-prefix=GDB
+// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
+// RUN: %s -isysroot /CLANG_SYSROOT/MacOSX.sdk -emit-llvm -o - \
+// RUN: -debugger-tuning=lldb -fno-debug-record-sysroot \
+// RUN: | FileCheck %s --check-prefix=NOSYSROOT
void foo(void) {}
@@ -14,3 +18,8 @@ void foo(void) {}
// GDB: distinct !DICompileUnit(
// GDB-NOT: sysroot: "/CLANG_SYSROOT/MacOSX.sdk"
// GDB-NOT: sdk: "MacOSX.sdk"
+
+// -fno-debug-record-sysroot suppresses the sysroot path but keeps the SDK marker.
+// NOSYSROOT: distinct !DICompileUnit(
+// NOSYSROOT-NOT: sysroot: "/CLANG_SYSROOT/MacOSX.sdk"
+// NOSYSROOT-SAME: sdk: "MacOSX.sdk"
diff --git a/clang/test/Modules/debug-info-moduleimport.m b/clang/test/Modules/debug-info-moduleimport.m
index bdeb05bc08a02..b242364e7100e 100644
--- a/clang/test/Modules/debug-info-moduleimport.m
+++ b/clang/test/Modules/debug-info-moduleimport.m
@@ -44,3 +44,16 @@
// SKEL-CHECK: ![[CUFILE]] = !DIFile({{.*}}directory: "[[COMP_DIR:.*]]"
// SKEL-CHECK: distinct !DICompileUnit({{.*}}file: ![[DWOFILE:[0-9]+]]{{.*}}splitDebugFilename: "/MODULE-CACHE{{.*}}dwoId
// SKEL-CHECK: ![[DWOFILE]] = !DIFile({{.*}}directory: "[[COMP_DIR]]"
+
+// With -fno-debug-record-sysroot and a sysroot that covers the module's
+// include path (%S contains %S/Inputs), the DICompileUnit has no sysroot
+// field and the DIModule has no includePath field.
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -debug-info-kind=limited -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/cache %s -I %S/Inputs -isysroot %S -I %t \
+// RUN: -emit-llvm -debugger-tuning=lldb -fno-debug-record-sysroot -o - \
+// RUN: | FileCheck %s --check-prefix=NO-SYSROOT
+
+// NO-SYSROOT-NOT: sysroot:
+// NO-SYSROOT-NOT: includePath:
+// NO-SYSROOT: !DIModule(scope: null, name: "DebugObjC")
>From f5538950d8595e2ce9ff1670bb6d9f34c0da1ddd Mon Sep 17 00:00:00 2001
From: Keith Smiley <keithbsmiley at gmail.com>
Date: Mon, 27 Apr 2026 11:54:09 -0700
Subject: [PATCH 2/2] Add lldb test
---
lldb/test/API/lang/objc/modules-auto-import/Makefile | 2 +-
.../modules-auto-import/TestModulesAutoImport.py | 12 ++++++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/lldb/test/API/lang/objc/modules-auto-import/Makefile b/lldb/test/API/lang/objc/modules-auto-import/Makefile
index 3b2bd504c89d6..5a8aeda2e2506 100644
--- a/lldb/test/API/lang/objc/modules-auto-import/Makefile
+++ b/lldb/test/API/lang/objc/modules-auto-import/Makefile
@@ -1,5 +1,5 @@
OBJC_SOURCES := main.m
-CFLAGS_EXTRAS = $(MANDATORY_MODULE_BUILD_CFLAGS)
+CFLAGS_EXTRAS = $(MANDATORY_MODULE_BUILD_CFLAGS) $(TEST_EXTRA_FLAGS)
include Makefile.rules
diff --git a/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py b/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py
index 9c8ba88bc6d83..bc75e7b7bc02f 100644
--- a/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py
+++ b/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py
@@ -8,6 +8,7 @@
class ObjCModulesAutoImportTestCase(TestBase):
+ SHARED_BUILD_TESTCASE = False
@skipIf(macos_version=["<", "10.12"])
@skipIf(compiler="clang", compiler_version=["<", "19.0"])
@@ -19,3 +20,14 @@ def test_expr(self):
self.runCmd("settings set target.auto-import-clang-modules true")
self.expect_expr("getpid()", result_type="pid_t")
+
+ @skipIf(macos_version=["<", "10.12"])
+ @skipIf(compiler="clang", compiler_version=["<", "19.0"])
+ def test_expr_no_sysroot(self):
+ self.build(dictionary={"TEST_EXTRA_FLAGS": f"-fno-debug-record-sysroot"})
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.m", False)
+ )
+
+ self.runCmd("settings set target.auto-import-clang-modules true")
+ self.expect_expr("getpid()", result_type="pid_t")
More information about the cfe-commits
mailing list