Skip to content

Commit

Permalink
Enable address sanitizer for MSVC targets using INFERASANLIBS linker …
Browse files Browse the repository at this point in the history
…flag
  • Loading branch information
dpaoliello committed Dec 1, 2023
1 parent 87e1447 commit 913f7d5
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 4 deletions.
8 changes: 7 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,9 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d
let needs_runtime = !sess.target.is_like_android
&& match crate_type {
CrateType::Executable => true,
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx,
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
sess.target.is_like_osx || sess.target.is_like_msvc
}
CrateType::Rlib | CrateType::Staticlib => false,
};

Expand Down Expand Up @@ -1249,6 +1251,10 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
let rpath = path.to_str().expect("non-utf8 component in path");
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
linker.link_dylib(&filename, false, true);
} else if sess.target.is_like_msvc {
// MSVC provides the `/INFERASANLIBS` argument to automatically find the
// compatible ASAN library.
linker.arg("/INFERASANLIBS");
} else {
let filename = format!("librustc{channel}_rt.{name}.a");
let path = find_sanitizer_runtime(sess, &filename).join(&filename);
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1579,7 +1579,10 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}

// Cannot enable crt-static with sanitizers on Linux
if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
if sess.crt_static(None)
&& !sess.opts.unstable_opts.sanitizer.is_empty()
&& !sess.target.is_like_msvc
{
sess.emit_err(errors::CannotEnableCrtStaticLinux);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::spec::{base, LinkerFlavor, Lld, Target};
use crate::spec::{base, LinkerFlavor, Lld, SanitizerSet, Target};

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

base.add_pre_link_args(
LinkerFlavor::Msvc(Lld::No),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::spec::{base, Target};
use crate::spec::{base, SanitizerSet, Target};

pub fn target() -> Target {
let mut base = base::windows_msvc::opts();
base.cpu = "x86-64".into();
base.plt_by_default = false;
base.max_atomic_width = Some(64);
base.supported_sanitizers = SanitizerSet::ADDRESS;

Target {
llvm_target: "x86_64-pc-windows-msvc".into(),
Expand Down
24 changes: 24 additions & 0 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,30 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
}
}

// Special setup to enable running with sanitizers enabled on MSVC.
if !builder.config.dry_run()
&& matches!(suite, "run-make" | "run-make-fulldeps")
&& target.contains("msvc")
&& builder.config.sanitizers_enabled(target)
{
// Ingore interception failures: not all dlls in the process will have been built with
// address sanitizer enabled (e.g., ntdll.dll).
cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
// Add the address sanitizer runtime to the PATH.
let asan_runtime_path =
builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf();
let old_path = cmd
.get_envs()
.find_map(|(k, v)| (k == "PATH").then_some(v))
.flatten()
.map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
let new_path = env::join_paths(
env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
)
.expect("Could not add ASAN runtime path to PATH");
cmd.env("PATH", new_path);
}

// Some UI tests trigger behavior in rustc where it reads $CARGO and changes behavior if it exists.
// To make the tests work that rely on it not being set, make sure it is not set.
cmd.env_remove("CARGO");
Expand Down

0 comments on commit 913f7d5

Please sign in to comment.