Skip to content

Commit

Permalink
Auto merge of rust-lang#115120 - icedrocket:ignore-strip-on-msvc, r=m…
Browse files Browse the repository at this point in the history
…ichaelwoerister

Ignore `-C strip` on MSVC

tl;dr - Define `-Cstrip` to only ever affect the binary; no other build artifacts.

This is necessary to improve cross-platform behavior consistency: if someone wanted debug information to be contained only in separate files on all platforms, they would set `-Cstrip=symbols` and `-Csplit-debuginfo=packed`, but this would result in no PDB files on MSVC.

Resolves rust-lang#114215
  • Loading branch information
bors committed Apr 22, 2024
2 parents 290d792 + e82f46a commit 7f2fc33
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 57 deletions.
77 changes: 35 additions & 42 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,52 +902,45 @@ impl<'a> Linker for MsvcLinker<'a> {
}
}

fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
match strip {
Strip::None => {
// This will cause the Microsoft linker to generate a PDB file
// from the CodeView line tables in the object files.
self.cmd.arg("/DEBUG");

// Default to emitting only the file name of the PDB file into
// the binary instead of the full path. Emitting the full path
// may leak private information (such as user names).
// See https://github.com/rust-lang/rust/issues/87825.
//
// This default behavior can be overridden by explicitly passing
// `-Clink-arg=/PDBALTPATH:...` to rustc.
self.cmd.arg("/PDBALTPATH:%_PDB%");

// This will cause the Microsoft linker to embed .natvis info into the PDB file
let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
for entry in natvis_dir {
match entry {
Ok(entry) => {
let path = entry.path();
if path.extension() == Some("natvis".as_ref()) {
let mut arg = OsString::from("/NATVIS:");
arg.push(path);
self.cmd.arg(arg);
}
}
Err(error) => {
self.sess.dcx().emit_warn(errors::NoNatvisDirectory { error });
}
fn debuginfo(&mut self, _strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
// This will cause the Microsoft linker to generate a PDB file
// from the CodeView line tables in the object files.
self.cmd.arg("/DEBUG");

// Default to emitting only the file name of the PDB file into
// the binary instead of the full path. Emitting the full path
// may leak private information (such as user names).
// See https://github.com/rust-lang/rust/issues/87825.
//
// This default behavior can be overridden by explicitly passing
// `-Clink-arg=/PDBALTPATH:...` to rustc.
self.cmd.arg("/PDBALTPATH:%_PDB%");

// This will cause the Microsoft linker to embed .natvis info into the PDB file
let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
for entry in natvis_dir {
match entry {
Ok(entry) => {
let path = entry.path();
if path.extension() == Some("natvis".as_ref()) {
let mut arg = OsString::from("/NATVIS:");
arg.push(path);
self.cmd.arg(arg);
}
}
}

// This will cause the Microsoft linker to embed .natvis info for all crates into the PDB file
for path in natvis_debugger_visualizers {
let mut arg = OsString::from("/NATVIS:");
arg.push(path);
self.cmd.arg(arg);
Err(error) => {
self.sess.dcx().emit_warn(errors::NoNatvisDirectory { error });
}
}
}
Strip::Debuginfo | Strip::Symbols => {
self.cmd.arg("/DEBUG:NONE");
}
}

// This will cause the Microsoft linker to embed .natvis info for all crates into the PDB file
for path in natvis_debugger_visualizers {
let mut arg = OsString::from("/NATVIS:");
arg.push(path);
self.cmd.arg(arg);
}
}

Expand Down
31 changes: 16 additions & 15 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,22 +568,23 @@ data from binaries during linking.

Supported values for this option are:

- `none` - debuginfo and symbols (if they exist) are copied to the produced
binary or separate files depending on the target (e.g. `.pdb` files in case
of MSVC).
- `none` - debuginfo and symbols are not modified.
- `debuginfo` - debuginfo sections and debuginfo symbols from the symbol table
section are stripped at link time and are not copied to the produced binary
or separate files. This should leave backtraces mostly-intact but may make
using a debugger like gdb or lldb ineffectual.
- `symbols` - same as `debuginfo`, but the rest of the symbol table section is stripped as well,
depending on platform support. On platforms which depend on this symbol table for backtraces,
profiling, and similar, this can affect them so negatively as to make the trace incomprehensible.
Programs which may be combined with others, such as CLI pipelines and developer tooling,
or even anything which wants crash-reporting, should usually avoid `-Cstrip=symbols`.

Note that, at any level, removing debuginfo only necessarily impacts "friendly" introspection.
`-Cstrip` cannot be relied on as a meaningful security or obfuscation measure, as disassemblers
and decompilers can extract considerable information even in the absence of symbols.
section are stripped at link time and are not copied to the produced binary.
This should leave backtraces mostly-intact but may make using a debugger like
gdb or lldb ineffectual. Prior to 1.79, this unintentionally disabled the
generation of `*.pdb` files on MSVC, resulting in the absence of symbols.
- `symbols` - same as `debuginfo`, but the rest of the symbol table section is
stripped as well, depending on platform support. On platforms which depend on
this symbol table for backtraces, profiling, and similar, this can affect
them so negatively as to make the trace incomprehensible. Programs which may
be combined with others, such as CLI pipelines and developer tooling, or even
anything which wants crash-reporting, should usually avoid `-Cstrip=symbols`.

Note that, at any level, removing debuginfo only necessarily impacts "friendly"
introspection. `-Cstrip` cannot be relied on as a meaningful security or
obfuscation measure, as disassemblers and decompilers can extract considerable
information even in the absence of symbols.

## symbol-mangling-version

Expand Down
26 changes: 26 additions & 0 deletions tests/ui/debuginfo/msvc-strip-debuginfo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ compile-flags: -C strip=debuginfo
//@ only-msvc
//@ run-pass

use std::path::Path;

pub fn is_related_pdb<P: AsRef<Path>>(path: &P, exe: &P) -> bool {
let (exe, path) = (exe.as_ref(), path.as_ref());

path.extension()
.map(|x| x.to_ascii_lowercase())
.is_some_and(|x| x == "pdb")
&& path.file_stem() == exe.file_stem()
}

pub fn main() {
let curr_exe = std::env::current_exe().unwrap();
let curr_dir = curr_exe.parent().unwrap();

let entries = std::fs::read_dir(curr_dir).unwrap();

assert!(entries
.map_while(|x| x.ok())
.find(|x| is_related_pdb(&x.path(), &curr_exe))
.is_some());
}
26 changes: 26 additions & 0 deletions tests/ui/debuginfo/msvc-strip-symbols.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ compile-flags: -C strip=symbols
//@ only-msvc
//@ run-pass

use std::path::Path;

pub fn is_related_pdb<P: AsRef<Path>>(path: &P, exe: &P) -> bool {
let (exe, path) = (exe.as_ref(), path.as_ref());

path.extension()
.map(|x| x.to_ascii_lowercase())
.is_some_and(|x| x == "pdb")
&& path.file_stem() == exe.file_stem()
}

pub fn main() {
let curr_exe = std::env::current_exe().unwrap();
let curr_dir = curr_exe.parent().unwrap();

let entries = std::fs::read_dir(curr_dir).unwrap();

assert!(entries
.map_while(|x| x.ok())
.find(|x| is_related_pdb(&x.path(), &curr_exe))
.is_some());
}

0 comments on commit 7f2fc33

Please sign in to comment.