From b26932fe03c08052fb8f4a90bab99cb46b18e116 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:13:48 -0400 Subject: [PATCH 1/7] test(trim-paths): consolidate same sysroot path assertions --- tests/testsuite/profile_trim_paths.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index 638c077a72f..44b2cb8f115 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -649,17 +649,16 @@ fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> let bin_path = p.bin("foo"); assert!(bin_path.is_file()); let stdout = run(&bin_path); + + // TODO: re-enable this check when rustc bootstrap disables remapping + // + // assert!(memchr::memmem::find(&stdout, rust_src).is_some()); + // On windows-msvc every debuginfo is in pdb file, so can't find anything here. if cfg!(target_env = "msvc") { - // TODO: re-enable this check when rustc bootstrap disables remapping - // - // assert!(memchr::memmem::find(&stdout, rust_src).is_some()); assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_none()); assert!(memchr::memmem::find(&stdout, pkg_root).is_none()); } else { - // TODO: re-enable this check when rustc bootstrap disables remapping - // - // assert!(memchr::memmem::find(&stdout, rust_src).is_some()); assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_some()); assert!(memchr::memmem::find(&stdout, pkg_root).is_some()); } From f26626a7e4873aa5919ad84fe47fdf8b04b0faeb Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:16:41 -0400 Subject: [PATCH 2/7] test(trim-paths): explain what are inspected --- tests/testsuite/profile_trim_paths.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index 44b2cb8f115..213fa14aeee 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -644,6 +644,7 @@ fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> let pkg_root = p.root(); let pkg_root = pkg_root.as_os_str().as_encoded_bytes(); + // Our baseline of which source roots are discoverable without object trimming. p.cargo("build").run(); let bin_path = p.bin("foo"); @@ -654,7 +655,9 @@ fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> // // assert!(memchr::memmem::find(&stdout, rust_src).is_some()); - // On windows-msvc every debuginfo is in pdb file, so can't find anything here. + // The local package root occurs only in debuginfo in this fixture. + // MSVC puts that debuginfo in the PDB, + // while the other inspectors read embedded debuginfo. if cfg!(target_env = "msvc") { assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_none()); assert!(memchr::memmem::find(&stdout, pkg_root).is_none()); @@ -688,11 +691,17 @@ fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> let bin_path = p.bin("foo"); assert!(bin_path.is_file()); let stdout = run(&bin_path); + + // Original sysroot source root should be trimmed. assert!(memchr::memmem::find(&stdout, rust_src).is_none()); + + // Check line by line so macOS can exempt untrimmable `OSO` symbols. for line in stdout.split(|c| c == &b'\n') { - let registry = memchr::memmem::find(line, registry_src_bytes).is_none(); - let local = memchr::memmem::find(line, pkg_root).is_none(); - if registry && local { + // original registry source root was trimmed. + let registry_is_trimmed = memchr::memmem::find(line, registry_src_bytes).is_none(); + // original project root was trimmed. + let local_is_trimmed = memchr::memmem::find(line, pkg_root).is_none(); + if registry_is_trimmed && local_is_trimmed { continue; } From ab77c3547b582e0417ab0e216bd1345987c9feb1 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:16:41 -0400 Subject: [PATCH 3/7] test(trim-paths): untrimmed registry src root alwasy in executable --- tests/testsuite/profile_trim_paths.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index 213fa14aeee..9309d777c8e 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -655,14 +655,16 @@ fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> // // assert!(memchr::memmem::find(&stdout, rust_src).is_some()); + // `file!()` in `bar()` keeps untrimmed registry source in the executable + // even when debuginfo is separate. + assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_some()); + // The local package root occurs only in debuginfo in this fixture. // MSVC puts that debuginfo in the PDB, // while the other inspectors read embedded debuginfo. if cfg!(target_env = "msvc") { - assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_none()); assert!(memchr::memmem::find(&stdout, pkg_root).is_none()); } else { - assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_some()); assert!(memchr::memmem::find(&stdout, pkg_root).is_some()); } p.cargo("clean").run(); From 0f23cf4592b8a0791336b8d0cc26c1493b2e6406 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:16:41 -0400 Subject: [PATCH 4/7] test(trim-paths): windows backslash paths compatible --- tests/testsuite/profile_trim_paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index 9309d777c8e..d4eea9c1e3c 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -611,7 +611,7 @@ mod object_works { } fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> Vec) { - let registry_src = paths::home().join(".cargo/registry/src"); + let registry_src = paths::home().join(".cargo").join("registry").join("src"); let registry_src_bytes = registry_src.as_os_str().as_encoded_bytes(); let rust_src = "/lib/rustc/src/rust".as_bytes(); From 1df3a22cec47b0b3d883cbeaaf72f01c0515364b Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:15:31 -0400 Subject: [PATCH 5/7] test(trim-paths): re-enable CDB coverage Without the `-lines` flag, CDB disables line information and falls back to symbol matching, which can make a file-and-line breakpoint ambiguous. See --- .github/workflows/main.yml | 3 +++ tests/testsuite/profile_trim_paths.rs | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e0439aca12f..192f832818f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -213,6 +213,9 @@ jobs: shell: pwsh run: Add-Content $env:GITHUB_PATH "C:\Program Files (x86)\Windows Kits\10\Debuggers\arm64" if: matrix.os == 'windows-11-arm' + - name: Check Windows MSVC debugger tool + run: cdb -version + if: matrix.rust == 'nightly-msvc' - name: Configure extra test environment run: echo CARGO_CONTAINER_TESTS=1 >> $GITHUB_ENV if: matrix.os == 'ubuntu-latest' diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index d4eea9c1e3c..e7ab76a4269 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -887,8 +887,6 @@ Hello, Ferris! ); } -// This test is disabled, as it currently doesn't work. -#[cfg(any())] #[cfg(target_env = "msvc")] #[cargo_test( requires = "cdb", @@ -900,7 +898,7 @@ fn cdb_works_after_trimmed() { let run_debugger = |path| { std::process::Command::new("cdb") - .args(["-c", "bp `main.rs:4`;g;g;q"]) + .args(["-lines", "-c", r"bp `src\main.rs:3`;g;g;q"]) .arg(path) .output() .expect("debugger works") From 76dd6a6398ec2f290a4cb1b91ca2a05bab363b4c Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:16:41 -0400 Subject: [PATCH 6/7] test(trim-paths): cover windows-gnu object paths --- .github/workflows/main.yml | 3 +++ tests/testsuite/profile_trim_paths.rs | 32 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 192f832818f..05aeb281126 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -216,6 +216,9 @@ jobs: - name: Check Windows MSVC debugger tool run: cdb -version if: matrix.rust == 'nightly-msvc' + - name: Check Windows GNU object tool + run: objdump --version + if: matrix.os == 'windows-latest' && matrix.rust == 'nightly-gnu' - name: Configure extra test environment run: echo CARGO_CONTAINER_TESTS=1 >> $GITHUB_ENV if: matrix.os == 'ubuntu-latest' diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index e7ab76a4269..45b174fd2c6 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -610,6 +610,38 @@ mod object_works { } } +#[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] +mod object_works { + use super::*; + + fn inspect_debuginfo(path: &std::path::Path) -> Vec { + let parent = path.parent().expect("binary has a parent directory"); + let file_name = path.file_name().expect("binary has a file name"); + let output = std::process::Command::new("objdump") + // Avoid echoing the absolute input path in objdump's file header. + .current_dir(parent) + .arg("--dwarf=info") + .arg(file_name) + .output() + .expect("objdump works"); + assert!( + output.status.success(), + "objdump failed with {}\nstdout:\n{}\nstderr:\n{}", + output.status, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr), + ); + output.stdout + } + + // rustc currently supports only split-debuginfo=off on windows-gnu. + // + #[cargo_test(requires = "objdump")] + fn with_split_debuginfo_off() { + object_works_helper("off", inspect_debuginfo); + } +} + fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> Vec) { let registry_src = paths::home().join(".cargo").join("registry").join("src"); let registry_src_bytes = registry_src.as_os_str().as_encoded_bytes(); From 6596b9adfdb5bd4f3439cfedbc0c922b8a64a8cd Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sun, 12 Jul 2026 12:17:08 -0400 Subject: [PATCH 7/7] test(trim-paths): exercise GDB on windows-gnu --- .github/workflows/main.yml | 3 ++ tests/testsuite/profile_trim_paths.rs | 71 +++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 05aeb281126..45cf3b97092 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -219,6 +219,9 @@ jobs: - name: Check Windows GNU object tool run: objdump --version if: matrix.os == 'windows-latest' && matrix.rust == 'nightly-gnu' + - name: Check Windows GNU debugger tool + run: gdb --version + if: matrix.os == 'windows-latest' && matrix.rust == 'nightly-gnu' - name: Configure extra test environment run: echo CARGO_CONTAINER_TESTS=1 >> $GITHUB_ENV if: matrix.os == 'ubuntu-latest' diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index 45b174fd2c6..d8ae064b210 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -919,6 +919,77 @@ Hello, Ferris! ); } +#[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] +#[cargo_test(requires = "gdb")] +fn gdb_works_after_trimmed() { + use cargo_test_support::compare::assert_e2e; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2015" + + [profile.dev] + trim-paths = "object" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let msg = "Hello, Ferris!"; + println!("{msg}"); + } + "#, + ) + .build(); + + p.cargo("build --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let bin_path = p.bin("foo"); + assert!(bin_path.is_file()); + + // GitHub's Windows runner uses MinGW-builds GDB wrapper, + // which loses the boundary of spaced `-ex` args when forwarding them to `gdborig.exe`. + // Therefore we use a command file instead here. + // + // See + p.change_file( + "gdb.commands", + "break -source src/main.rs -line 4\nrun\nlist\ncontinue\n", + ); + let stdout = String::from_utf8( + p.process("gdb") + .args(&["--batch", "--nx", "--quiet", "--command=gdb.commands"]) + .arg(bin_path.strip_prefix(p.root()).unwrap()) + .run() + .stdout, + ) + .unwrap(); + assert_e2e().eq( + &stdout, + str![[r#" +... +[..]Breakpoint 1,[..] +... +Hello, Ferris! +... + +"#]], + ); +} + #[cfg(target_env = "msvc")] #[cargo_test( requires = "cdb",