Skip to content

Commit 2d27f83

Browse files
committed
Auto merge of #118521 - dpaoliello:asan, r=<try>
Enable address sanitizer for MSVC targets using INFERASANLIBS linker flag
2 parents 7a34091 + 913f7d5 commit 2d27f83

File tree

5 files changed

+39
-4
lines changed

5 files changed

+39
-4
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,9 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d
11941194
let needs_runtime = !sess.target.is_like_android
11951195
&& match crate_type {
11961196
CrateType::Executable => true,
1197-
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx,
1197+
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
1198+
sess.target.is_like_osx || sess.target.is_like_msvc
1199+
}
11981200
CrateType::Rlib | CrateType::Staticlib => false,
11991201
};
12001202

@@ -1254,6 +1256,10 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
12541256
let rpath = path.to_str().expect("non-utf8 component in path");
12551257
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
12561258
linker.link_dylib(&filename, false, true);
1259+
} else if sess.target.is_like_msvc {
1260+
// MSVC provides the `/INFERASANLIBS` argument to automatically find the
1261+
// compatible ASAN library.
1262+
linker.arg("/INFERASANLIBS");
12571263
} else {
12581264
let filename = format!("librustc{channel}_rt.{name}.a");
12591265
let path = find_sanitizer_runtime(sess, &filename).join(&filename);

compiler/rustc_session/src/session.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1574,7 +1574,10 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
15741574
}
15751575

15761576
// Cannot enable crt-static with sanitizers on Linux
1577-
if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
1577+
if sess.crt_static(None)
1578+
&& !sess.opts.unstable_opts.sanitizer.is_empty()
1579+
&& !sess.target.is_like_msvc
1580+
{
15781581
sess.emit_err(errors::CannotEnableCrtStaticLinux);
15791582
}
15801583

compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use crate::spec::{base, LinkerFlavor, Lld, Target};
1+
use crate::spec::{base, LinkerFlavor, Lld, SanitizerSet, Target};
22

33
pub fn target() -> Target {
44
let mut base = base::windows_msvc::opts();
55
base.cpu = "pentium4".into();
66
base.max_atomic_width = Some(64);
7+
base.supported_sanitizers = SanitizerSet::ADDRESS;
78

89
base.add_pre_link_args(
910
LinkerFlavor::Msvc(Lld::No),

compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use crate::spec::{base, Target};
1+
use crate::spec::{base, SanitizerSet, Target};
22

33
pub fn target() -> Target {
44
let mut base = base::windows_msvc::opts();
55
base.cpu = "x86-64".into();
66
base.plt_by_default = false;
77
base.max_atomic_width = Some(64);
8+
base.supported_sanitizers = SanitizerSet::ADDRESS;
89

910
Target {
1011
llvm_target: "x86_64-pc-windows-msvc".into(),

src/bootstrap/src/core/build_steps/test.rs

+24
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,30 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
19391939
}
19401940
}
19411941

1942+
// Special setup to enable running with sanitizers enabled on MSVC.
1943+
if !builder.config.dry_run()
1944+
&& matches!(suite, "run-make" | "run-make-fulldeps")
1945+
&& target.contains("msvc")
1946+
&& builder.config.sanitizers_enabled(target)
1947+
{
1948+
// Ingore interception failures: not all dlls in the process will have been built with
1949+
// address sanitizer enabled (e.g., ntdll.dll).
1950+
cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
1951+
// Add the address sanitizer runtime to the PATH.
1952+
let asan_runtime_path =
1953+
builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf();
1954+
let old_path = cmd
1955+
.get_envs()
1956+
.find_map(|(k, v)| (k == "PATH").then_some(v))
1957+
.flatten()
1958+
.map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
1959+
let new_path = env::join_paths(
1960+
env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
1961+
)
1962+
.expect("Could not add ASAN runtime path to PATH");
1963+
cmd.env("PATH", new_path);
1964+
}
1965+
19421966
// Some UI tests trigger behavior in rustc where it reads $CARGO and changes behavior if it exists.
19431967
// To make the tests work that rely on it not being set, make sure it is not set.
19441968
cmd.env_remove("CARGO");

0 commit comments

Comments
 (0)