From 78e7eeeaa1f93f40fa96c36194b1afdfbfdb7364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 6 Oct 2019 00:00:00 +0000 Subject: [PATCH 1/5] Remove sanitizer runtime crates --- Cargo.lock | 48 ---------------- src/bootstrap/dist.rs | 4 -- src/build_helper/lib.rs | 104 ----------------------------------- src/librustc_asan/Cargo.toml | 20 ------- src/librustc_asan/build.rs | 30 ---------- src/librustc_asan/lib.rs | 10 ---- src/librustc_lsan/Cargo.toml | 20 ------- src/librustc_lsan/build.rs | 29 ---------- src/librustc_lsan/lib.rs | 10 ---- src/librustc_msan/Cargo.toml | 20 ------- src/librustc_msan/build.rs | 29 ---------- src/librustc_msan/lib.rs | 10 ---- src/librustc_tsan/Cargo.toml | 20 ------- src/librustc_tsan/build.rs | 30 ---------- src/librustc_tsan/lib.rs | 10 ---- src/libstd/Cargo.toml | 10 ---- 16 files changed, 404 deletions(-) delete mode 100644 src/librustc_asan/Cargo.toml delete mode 100644 src/librustc_asan/build.rs delete mode 100644 src/librustc_asan/lib.rs delete mode 100644 src/librustc_lsan/Cargo.toml delete mode 100644 src/librustc_lsan/build.rs delete mode 100644 src/librustc_lsan/lib.rs delete mode 100644 src/librustc_msan/Cargo.toml delete mode 100644 src/librustc_msan/build.rs delete mode 100644 src/librustc_msan/lib.rs delete mode 100644 src/librustc_tsan/Cargo.toml delete mode 100644 src/librustc_tsan/build.rs delete mode 100644 src/librustc_tsan/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 4f60ea305196..1470e2be75df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3348,17 +3348,6 @@ dependencies = [ "smallvec 1.0.0", ] -[[package]] -name = "rustc_asan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_ast_lowering" version = "0.0.0" @@ -3680,17 +3669,6 @@ dependencies = [ "libc", ] -[[package]] -name = "rustc_lsan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_macros" version = "0.1.0" @@ -3752,17 +3730,6 @@ dependencies = [ "syntax", ] -[[package]] -name = "rustc_msan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_parse" version = "0.0.0" @@ -3935,17 +3902,6 @@ dependencies = [ "syntax", ] -[[package]] -name = "rustc_tsan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_typeck" version = "0.0.0" @@ -4307,10 +4263,6 @@ dependencies = [ "panic_unwind", "profiler_builtins", "rand 0.7.0", - "rustc_asan", - "rustc_lsan", - "rustc_msan", - "rustc_tsan", "unwind", "wasi 0.9.0+wasi-snapshot-preview1", ] diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e64d4c8637d5..8d13df3ee21a 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -984,10 +984,6 @@ impl Step for Src { "src/libcore", "src/libpanic_abort", "src/libpanic_unwind", - "src/librustc_asan", - "src/librustc_lsan", - "src/librustc_msan", - "src/librustc_tsan", "src/libstd", "src/libunwind", "src/libtest", diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 3f42533238a8..43c3c5773ce5 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -1,7 +1,5 @@ -use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use std::thread; use std::time::{SystemTime, UNIX_EPOCH}; use std::{env, fs}; @@ -181,108 +179,6 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool { } } -#[must_use] -pub struct NativeLibBoilerplate { - pub src_dir: PathBuf, - pub out_dir: PathBuf, -} - -impl NativeLibBoilerplate { - /// On macOS we don't want to ship the exact filename that compiler-rt builds. - /// This conflicts with the system and ours is likely a wildly different - /// version, so they can't be substituted. - /// - /// As a result, we rename it here but we need to also use - /// `install_name_tool` on macOS to rename the commands listed inside of it to - /// ensure it's linked against correctly. - pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) { - if env::var("TARGET").unwrap() != "x86_64-apple-darwin" { - return; - } - - let dir = self.out_dir.join("build/lib/darwin"); - let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name); - let src = dir.join(&format!("lib{}.dylib", name)); - let new_name = format!("lib__rustc__{}.dylib", name); - let dst = dir.join(&new_name); - - println!("{} => {}", src.display(), dst.display()); - fs::rename(&src, &dst).unwrap(); - let status = Command::new("install_name_tool") - .arg("-id") - .arg(format!("@rpath/{}", new_name)) - .arg(&dst) - .status() - .expect("failed to execute `install_name_tool`"); - assert!(status.success()); - } -} - -impl Drop for NativeLibBoilerplate { - fn drop(&mut self) { - if !thread::panicking() { - t!(File::create(self.out_dir.join("rustbuild.timestamp"))); - } - } -} - -// Perform standard preparations for native libraries that are build only once for all stages. -// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are -// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler. -// If Err is returned, then everything is up-to-date and further build actions can be skipped. -// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out -// of scope, so all the build actions should be completed until then. -pub fn native_lib_boilerplate( - src_dir: &Path, - out_name: &str, - link_name: &str, - search_subdir: &str, -) -> Result { - rerun_if_changed_anything_in_dir(src_dir); - - let out_dir = - env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| env::var_os("OUT_DIR").unwrap()); - let out_dir = PathBuf::from(out_dir).join(out_name); - t!(fs::create_dir_all(&out_dir)); - if link_name.contains('=') { - println!("cargo:rustc-link-lib={}", link_name); - } else { - println!("cargo:rustc-link-lib=static={}", link_name); - } - println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display()); - - let timestamp = out_dir.join("rustbuild.timestamp"); - if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(src_dir, ×tamp) { - Ok(NativeLibBoilerplate { src_dir: src_dir.to_path_buf(), out_dir }) - } else { - Err(()) - } -} - -pub fn sanitizer_lib_boilerplate( - sanitizer_name: &str, -) -> Result<(NativeLibBoilerplate, String), ()> { - let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() { - "x86_64-unknown-linux-gnu" => { - (format!("clang_rt.{}-x86_64", sanitizer_name), "build/lib/linux", false) - } - "x86_64-apple-darwin" => { - (format!("clang_rt.{}_osx_dynamic", sanitizer_name), "build/lib/darwin", true) - } - _ => return Err(()), - }; - let to_link = if apple { - format!("dylib=__rustc__{}", link_name) - } else { - format!("static={}", link_name) - }; - // This env var is provided by rustbuild to tell us where `compiler-rt` - // lives. - let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); - let lib = native_lib_boilerplate(dir.as_ref(), sanitizer_name, &to_link, search_path)?; - Ok((lib, link_name)) -} - fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { let meta = t!(e.metadata()); diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml deleted file mode 100644 index df117de8720e..000000000000 --- a/src/librustc_asan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_asan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_asan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs deleted file mode 100644 index e276dc16c35e..000000000000 --- a/src/librustc_asan/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -use build_helper::sanitizer_lib_boilerplate; -use std::env; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("asan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - native.fixup_sanitizer_lib_name("asan"); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs deleted file mode 100644 index bdbc154f4e86..000000000000 --- a/src/librustc_asan/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable( - feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "none" -)] diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml deleted file mode 100644 index 9a24361f44e6..000000000000 --- a/src/librustc_lsan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_lsan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_lsan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs deleted file mode 100644 index 6201bc9356dc..000000000000 --- a/src/librustc_lsan/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use build_helper::sanitizer_lib_boilerplate; -use std::env; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("lsan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs deleted file mode 100644 index bdbc154f4e86..000000000000 --- a/src/librustc_lsan/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable( - feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "none" -)] diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml deleted file mode 100644 index bda407857250..000000000000 --- a/src/librustc_msan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_msan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_msan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs deleted file mode 100644 index dc08d51b51cb..000000000000 --- a/src/librustc_msan/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use build_helper::sanitizer_lib_boilerplate; -use std::env; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("msan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs deleted file mode 100644 index bdbc154f4e86..000000000000 --- a/src/librustc_msan/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable( - feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "none" -)] diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml deleted file mode 100644 index 82045dd0cddc..000000000000 --- a/src/librustc_tsan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_tsan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_tsan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs deleted file mode 100644 index 570642a2eaa7..000000000000 --- a/src/librustc_tsan/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -use build_helper::sanitizer_lib_boilerplate; -use std::env; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("tsan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - native.fixup_sanitizer_lib_name("tsan"); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs deleted file mode 100644 index bdbc154f4e86..000000000000 --- a/src/librustc_tsan/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable( - feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "none" -)] diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index a22e162bbff4..c9ff93eac029 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -34,16 +34,6 @@ features = [ "rustc-dep-of-std" ] # enable build support for integrating into li [dev-dependencies] rand = "0.7" -[target.x86_64-apple-darwin.dependencies] -rustc_asan = { path = "../librustc_asan" } -rustc_tsan = { path = "../librustc_tsan" } - -[target.x86_64-unknown-linux-gnu.dependencies] -rustc_asan = { path = "../librustc_asan" } -rustc_lsan = { path = "../librustc_lsan" } -rustc_msan = { path = "../librustc_msan" } -rustc_tsan = { path = "../librustc_tsan" } - [target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } From 36d08125705598aa12ceb092f34c332fbba12c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 7 Oct 2019 00:00:00 +0000 Subject: [PATCH 2/5] Remove sanitizer_runtime attribute --- .../src/library-features/sanitizer-runtime-lib.md | 5 ----- src/librustc/query/mod.rs | 4 ---- src/librustc_codegen_ssa/base.rs | 4 ---- src/librustc_codegen_ssa/lib.rs | 1 - src/librustc_feature/active.rs | 3 --- src/librustc_feature/builtin_attrs.rs | 5 ----- src/librustc_feature/removed.rs | 2 ++ src/librustc_metadata/rmeta/decoder.rs | 4 ---- src/librustc_metadata/rmeta/decoder/cstore_impl.rs | 1 - src/librustc_metadata/rmeta/encoder.rs | 1 - src/librustc_metadata/rmeta/mod.rs | 1 - .../feature-gates/feature-gate-sanitizer-runtime.rs | 3 --- .../feature-gate-sanitizer-runtime.stderr | 11 ----------- 13 files changed, 2 insertions(+), 43 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md delete mode 100644 src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr diff --git a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md deleted file mode 100644 index 82ae67fc05ac..000000000000 --- a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md +++ /dev/null @@ -1,5 +0,0 @@ -# `sanitizer_runtime_lib` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 4a2ec9b9687f..9de46f86200e 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -686,10 +686,6 @@ rustc_queries! { fatal_cycle desc { "checking if the crate has_panic_handler" } } - query is_sanitizer_runtime(_: CrateNum) -> bool { - fatal_cycle - desc { "query a crate is `#![sanitizer_runtime]`" } - } query is_profiler_runtime(_: CrateNum) -> bool { fatal_cycle desc { "query a crate is `#![profiler_runtime]`" } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index ededb36c7127..cb094079d645 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -723,7 +723,6 @@ impl CrateInfo { panic_runtime: None, compiler_builtins: None, profiler_runtime: None, - sanitizer_runtime: None, is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE), @@ -759,9 +758,6 @@ impl CrateInfo { if tcx.is_profiler_runtime(cnum) { info.profiler_runtime = Some(cnum); } - if tcx.is_sanitizer_runtime(cnum) { - info.sanitizer_runtime = Some(cnum); - } if tcx.is_no_builtins(cnum) { info.is_no_builtins.insert(cnum); } diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index a8d051db8b47..ee527ecb509b 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -122,7 +122,6 @@ pub struct CrateInfo { pub panic_runtime: Option, pub compiler_builtins: Option, pub profiler_runtime: Option, - pub sanitizer_runtime: Option, pub is_no_builtins: FxHashSet, pub native_libraries: FxHashMap>>, pub crate_name: FxHashMap, diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 8cb1684491bb..3b894775e697 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -192,9 +192,6 @@ declare_features! ( /// Allows using the `unadjusted` ABI; perma-unstable. (active, abi_unadjusted, "1.16.0", None, None), - /// Allows identifying crates that contain sanitizer runtimes. - (active, sanitizer_runtime, "1.17.0", None, None), - /// Used to identify crates that contain the profiler runtime. (active, profiler_runtime, "1.18.0", None, None), diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index 3cbf96b6d29a..a38726e3de81 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -409,11 +409,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), - gated!( - sanitizer_runtime, Whitelisted, template!(Word), - "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \ - of a sanitizer and will never be stable", - ), gated!( profiler_runtime, Whitelisted, template!(Word), "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs index 1eeedd772141..d5b6fe81c7be 100644 --- a/src/librustc_feature/removed.rs +++ b/src/librustc_feature/removed.rs @@ -74,6 +74,8 @@ declare_features! ( (removed, pushpop_unsafe, "1.2.0", None, None, None), (removed, needs_allocator, "1.4.0", Some(27389), None, Some("subsumed by `#![feature(allocator_internals)]`")), + /// Allows identifying crates that contain sanitizer runtimes. + (removed, sanitizer_runtime, "1.17.0", None, None, None), (removed, proc_macro_mod, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 77d143643b59..4d3be00debaf 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1587,10 +1587,6 @@ impl<'a, 'tcx> CrateMetadata { self.root.panic_runtime } - crate fn is_sanitizer_runtime(&self) -> bool { - self.root.sanitizer_runtime - } - crate fn is_profiler_runtime(&self) -> bool { self.root.profiler_runtime } diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index ba3c4e4aff44..b61ab8cc450f 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -161,7 +161,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } has_panic_handler => { cdata.root.has_panic_handler } - is_sanitizer_runtime => { cdata.root.sanitizer_runtime } is_profiler_runtime => { cdata.root.profiler_runtime } panic_strategy => { cdata.root.panic_strategy } extern_crate => { diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 952d3bb85827..7f8791d0c34d 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -514,7 +514,6 @@ impl<'tcx> EncodeContext<'tcx> { no_builtins: attr::contains_name(&attrs, sym::no_builtins), panic_runtime: attr::contains_name(&attrs, sym::panic_runtime), profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime), - sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime), symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version, crate_deps, diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 6309f1c260e1..426ea62b8cd4 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -209,7 +209,6 @@ crate struct CrateRoot<'tcx> { no_builtins: bool, panic_runtime: bool, profiler_runtime: bool, - sanitizer_runtime: bool, symbol_mangling_version: SymbolManglingVersion, } diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs deleted file mode 100644 index 3b972c117a6f..000000000000 --- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr deleted file mode 100644 index b13ec215f8c0..000000000000 --- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable - --> $DIR/feature-gate-sanitizer-runtime.rs:1:1 - | -LL | #![sanitizer_runtime] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(sanitizer_runtime)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From 0c6b1a7e3c54ff3a5ef6744073281b00368749c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 7 Nov 2019 00:00:00 +0000 Subject: [PATCH 3/5] Link sanitizer runtimes instead of injecting crate dependencies --- src/librustc_codegen_ssa/back/link.rs | 89 +++++++-------- src/librustc_metadata/creader.rs | 105 +----------------- src/librustc_session/session.rs | 26 +++++ .../sanitizer-address/Makefile | 2 +- .../sanitizer-invalid-cratetype/Makefile | 16 --- .../sanitizer-invalid-cratetype/hello.rs | 3 - .../sanitizer-invalid-target/Makefile | 2 +- .../run-make-fulldeps/sanitizer-leak/Makefile | 2 +- .../sanitizer-memory/Makefile | 4 +- 9 files changed, 74 insertions(+), 175 deletions(-) delete mode 100644 src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile delete mode 100644 src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index a53402ebb5c7..c91491fa5486 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -531,6 +531,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( { let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu); + link_sanitizer_runtime(sess, crate_type, &mut *linker); link_args::( &mut *linker, flavor, @@ -735,6 +736,47 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( } } +fn link_sanitizer_runtime(sess: &Session, crate_type: config::CrateType, linker: &mut dyn Linker) { + let sanitizer = match &sess.opts.debugging_opts.sanitizer { + Some(s) => s, + None => return, + }; + + if crate_type != config::CrateType::Executable { + return; + } + + let name = match sanitizer { + Sanitizer::Address => "asan", + Sanitizer::Leak => "lsan", + Sanitizer::Memory => "msan", + Sanitizer::Thread => "tsan", + }; + + let default_sysroot = filesearch::get_or_default_sysroot(); + let default_tlib = + filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple()); + + match sess.opts.target_triple.triple() { + "x86_64-apple-darwin" => { + // On Apple platforms, the sanitizer is always built as a dylib, and + // LLVM will link to `@rpath/*.dylib`, so we need to specify an + // rpath to the library as well (the rpath should be absolute, see + // PR #41352 for details). + let libname = format!("rustc_rt.{}", name); + let rpath = default_tlib.to_str().expect("non-utf8 component in path"); + linker.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]); + linker.link_dylib(Symbol::intern(&libname)); + } + "x86_64-unknown-linux-gnu" => { + let filename = format!("librustc_rt.{}.a", name); + let path = default_tlib.join(&filename); + linker.link_whole_rlib(&path); + } + _ => {} + } +} + /// Returns a boolean indicating whether the specified crate should be ignored /// during LTO. /// @@ -1415,12 +1457,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { add_static_crate::(cmd, sess, codegen_results, tmpdir, crate_type, cnum); } - _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) - && crate_type == config::CrateType::Executable => - { - // Link the sanitizer runtimes only if we are actually producing an executable - link_sanitizer_runtime::(cmd, sess, codegen_results, tmpdir, cnum); - } // compiler-builtins are always placed last to ensure that they're // linked correctly. _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => { @@ -1457,47 +1493,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( } } - // We must link the sanitizer runtime using -Wl,--whole-archive but since - // it's packed in a .rlib, it contains stuff that are not objects that will - // make the linker error. So we must remove those bits from the .rlib before - // linking it. - fn link_sanitizer_runtime<'a, B: ArchiveBuilder<'a>>( - cmd: &mut dyn Linker, - sess: &'a Session, - codegen_results: &CodegenResults, - tmpdir: &Path, - cnum: CrateNum, - ) { - let src = &codegen_results.crate_info.used_crate_source[&cnum]; - let cratepath = &src.rlib.as_ref().unwrap().0; - - if sess.target.target.options.is_like_osx { - // On Apple platforms, the sanitizer is always built as a dylib, and - // LLVM will link to `@rpath/*.dylib`, so we need to specify an - // rpath to the library as well (the rpath should be absolute, see - // PR #41352 for details). - // - // FIXME: Remove this logic into librustc_*san once Cargo supports it - let rpath = cratepath.parent().unwrap(); - let rpath = rpath.to_str().expect("non-utf8 component in path"); - cmd.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]); - } - - let dst = tmpdir.join(cratepath.file_name().unwrap()); - let mut archive = ::new(sess, &dst, Some(cratepath)); - archive.update_symbols(); - - for f in archive.src_files() { - if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME { - archive.remove_file(&f); - } - } - - archive.build(); - - cmd.link_whole_rlib(&dst); - } - // Adds the static "rlib" versions of all crates to the command line. // There's a bit of magic which happens here specifically related to LTO and // dynamic libraries. Specifically: diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index b21715fadfe6..7ccc367be256 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -6,7 +6,7 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob use rustc::hir::map::Definitions; use rustc::middle::cstore::DepKind; use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; -use rustc::session::config::{self, Sanitizer}; +use rustc::session::config; use rustc::session::search_paths::PathKind; use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::TyCtxt; @@ -674,108 +674,6 @@ impl<'a> CrateLoader<'a> { self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime()); } - fn inject_sanitizer_runtime(&mut self) { - if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer { - // Sanitizers can only be used on some tested platforms with - // executables linked to `std` - const ASAN_SUPPORTED_TARGETS: &[&str] = - &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; - const TSAN_SUPPORTED_TARGETS: &[&str] = - &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; - const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - - let supported_targets = match *sanitizer { - Sanitizer::Address => ASAN_SUPPORTED_TARGETS, - Sanitizer::Thread => TSAN_SUPPORTED_TARGETS, - Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, - Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, - }; - if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) { - self.sess.err(&format!( - "{:?}Sanitizer only works with the `{}` target", - sanitizer, - supported_targets.join("` or `") - )); - return; - } - - // firstyear 2017 - during testing I was unable to access an OSX machine - // to make this work on different crate types. As a result, today I have - // only been able to test and support linux as a target. - if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" { - if !self.sess.crate_types.borrow().iter().all(|ct| { - match *ct { - // Link the runtime - config::CrateType::Executable => true, - // This crate will be compiled with the required - // instrumentation pass - config::CrateType::Staticlib - | config::CrateType::Rlib - | config::CrateType::Dylib - | config::CrateType::Cdylib => false, - _ => { - self.sess.err(&format!( - "Only executables, staticlibs, \ - cdylibs, dylibs and rlibs can be compiled with \ - `-Z sanitizer`" - )); - false - } - } - }) { - return; - } - } else { - if !self.sess.crate_types.borrow().iter().all(|ct| { - match *ct { - // Link the runtime - config::CrateType::Executable => true, - // This crate will be compiled with the required - // instrumentation pass - config::CrateType::Rlib => false, - _ => { - self.sess.err(&format!( - "Only executables and rlibs can be \ - compiled with `-Z sanitizer`" - )); - false - } - } - }) { - return; - } - } - - let mut uses_std = false; - self.cstore.iter_crate_data(|_, data| { - if data.name() == sym::std { - uses_std = true; - } - }); - - if uses_std { - let name = Symbol::intern(match sanitizer { - Sanitizer::Address => "rustc_asan", - Sanitizer::Leak => "rustc_lsan", - Sanitizer::Memory => "rustc_msan", - Sanitizer::Thread => "rustc_tsan", - }); - info!("loading sanitizer: {}", name); - - let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None); - let data = self.cstore.get_crate_data(cnum); - - // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime - if !data.is_sanitizer_runtime() { - self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", name)); - } - } else { - self.sess.err("Must link std to be compiled with `-Z sanitizer`"); - } - } - } - fn inject_profiler_runtime(&mut self) { if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() { info!("loading profiler"); @@ -927,7 +825,6 @@ impl<'a> CrateLoader<'a> { } pub fn postprocess(&mut self, krate: &ast::Crate) { - self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); self.inject_panic_runtime(krate); diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index dba5b9f3f14c..d979247b46d3 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -1124,6 +1124,32 @@ fn validate_commandline_args_with_session_available(sess: &Session) { See https://github.com/rust-lang/rust/issues/61002 for details.", ); } + + // Sanitizers can only be used on some tested platforms. + if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer { + const ASAN_SUPPORTED_TARGETS: &[&str] = + &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; + const TSAN_SUPPORTED_TARGETS: &[&str] = + &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; + const LSAN_SUPPORTED_TARGETS: &[&str] = + &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; + const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; + + let supported_targets = match *sanitizer { + Sanitizer::Address => ASAN_SUPPORTED_TARGETS, + Sanitizer::Thread => TSAN_SUPPORTED_TARGETS, + Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, + Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, + }; + + if !supported_targets.contains(&&*sess.opts.target_triple.triple()) { + sess.err(&format!( + "{:?}Sanitizer only works with the `{}` target", + sanitizer, + supported_targets.join("` or `") + )); + } + } } /// Hash value constructed out of all the `-C metadata` arguments passed to the diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile index 3a377c32993d..7f5e9049b2f7 100644 --- a/src/test/run-make-fulldeps/sanitizer-address/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile @@ -23,7 +23,7 @@ endif endif all: - $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan + $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) rustc_rt.asan # Verify that stack buffer overflow is detected: $(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow # Verify that variable name is included in address sanitizer report: diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile deleted file mode 100644 index 9581ac565ea0..000000000000 --- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# needs-sanitizer-support - --include ../tools.mk - -# NOTE the address sanitizer only supports x86_64 linux and macOS - -ifeq ($(TARGET),x86_64-apple-darwin) -EXTRA_RUSTFLAG=-C rpath -else -ifeq ($(TARGET),x86_64-unknown-linux-gnu) -EXTRA_RUSTFLAG= -endif -endif - -all: - $(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | $(CGREP) '-Z sanitizer' diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs deleted file mode 100644 index e7a11a969c03..000000000000 --- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile index df8afee15ce0..2a23f0fe3d4e 100644 --- a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile @@ -2,4 +2,4 @@ all: $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \ - $(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` target' + $(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target' diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile index 101e8272ab91..d8598b8ac93f 100644 --- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile @@ -7,5 +7,5 @@ # FIXME(#46126) ThinLTO for libstd broke this test all: - $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_lsan + $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) rustc_rt.lsan $(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks' diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile index f5787903a2b5..8bc9df1b4bae 100644 --- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-memory/Makefile @@ -5,7 +5,7 @@ # only-x86_64 all: - $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan + $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) rustc_rt.msan $(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value - $(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) librustc_msan + $(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) rustc_rt.msan $(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value From ae57259403957ce31760b1fe83ec55343155696f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 7 Nov 2019 00:00:00 +0000 Subject: [PATCH 4/5] Add bootstrap step for building sanitizer runtimes --- src/bootstrap/builder.rs | 1 + src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 80 +++++++++++++-------------- src/bootstrap/doc.rs | 2 +- src/bootstrap/native.rs | 115 +++++++++++++++++++++++++++++++++++++++ src/bootstrap/test.rs | 2 +- 6 files changed, 159 insertions(+), 43 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 3a14b3e71c47..00c8e72a8f68 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -343,6 +343,7 @@ impl<'a> Builder<'a> { tool::Rustdoc, tool::Clippy, native::Llvm, + native::Sanitizers, tool::Rustfmt, tool::Miri, native::Lld diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index d4016f16fa9d..b76515763fbd 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -45,7 +45,7 @@ impl Step for Std { let compiler = builder.compiler(0, builder.config.build); let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind)); - std_cargo(builder, &compiler, target, &mut cargo); + std_cargo(builder, target, &mut cargo); builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7f0bb5813a4a..eced03506ab9 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -87,7 +87,7 @@ impl Step for Std { target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); - std_cargo(builder, &compiler, target, &mut cargo); + std_cargo(builder, target, &mut cargo); builder.info(&format!( "Building stage{} std artifacts ({} -> {})", @@ -153,17 +153,18 @@ fn copy_third_party_objects( copy_and_stamp(Path::new(&src), "libunwind.a"); } + if builder.config.sanitizers && compiler.stage != 0 { + // The sanitizers are only copied in stage1 or above, + // to avoid creating dependency on LLVM. + target_deps.extend(copy_sanitizers(builder, &compiler, target)); + } + target_deps } /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. -pub fn std_cargo( - builder: &Builder<'_>, - compiler: &Compiler, - target: Interned, - cargo: &mut Cargo, -) { +pub fn std_cargo(builder: &Builder<'_>, target: Interned, cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -206,19 +207,6 @@ pub fn std_cargo( let mut features = builder.std_features(); features.push_str(&compiler_builtins_c_feature); - if compiler.stage != 0 && builder.config.sanitizers { - // This variable is used by the sanitizer runtime crates, e.g. - // rustc_lsan, to build the sanitizer runtime from C code - // When this variable is missing, those crates won't compile the C code, - // so we don't set this variable during stage0 where llvm-config is - // missing - // We also only build the runtimes when --enable-sanitizers (or its - // config.toml equivalent) is used - let llvm_config = builder.ensure(native::Llvm { target: builder.config.build }); - cargo.env("LLVM_CONFIG", llvm_config); - cargo.env("RUSTC_BUILD_SANITIZERS", "1"); - } - cargo .arg("--features") .arg(features) @@ -276,31 +264,43 @@ impl Step for StdLink { let libdir = builder.sysroot_libdir(target_compiler, target); let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); - - if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { - // The sanitizers are only built in stage1 or above, so the dylibs will - // be missing in stage0 and causes panic. See the `std()` function above - // for reason why the sanitizers are not built in stage0. - copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); - } } } -fn copy_apple_sanitizer_dylibs( +/// Copies sanitizer runtime libraries into target libdir. +fn copy_sanitizers( builder: &Builder<'_>, - native_dir: &Path, - platform: &str, - into: &Path, -) { - for &sanitizer in &["asan", "tsan"] { - let filename = format!("lib__rustc__clang_rt.{}_{}_dynamic.dylib", sanitizer, platform); - let mut src_path = native_dir.join(sanitizer); - src_path.push("build"); - src_path.push("lib"); - src_path.push("darwin"); - src_path.push(&filename); - builder.copy(&src_path, &into.join(filename)); + compiler: &Compiler, + target: Interned, +) -> Vec { + let runtimes: Vec = builder.ensure(native::Sanitizers { target }); + + if builder.config.dry_run { + return Vec::new(); + } + + let mut target_deps = Vec::new(); + let libdir = builder.sysroot_libdir(*compiler, target); + + for runtime in &runtimes { + let dst = libdir.join(&runtime.name); + builder.copy(&runtime.path, &dst); + + if target == "x86_64-apple-darwin" { + // Update the library install name reflect the fact it has been renamed. + let status = Command::new("install_name_tool") + .arg("-id") + .arg(format!("@rpath/{}", runtime.name)) + .arg(&dst) + .status() + .expect("failed to execute `install_name_tool`"); + assert!(status.success()); + } + + target_deps.push(dst); } + + target_deps } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 8cd7fc2c1725..4d18199dc8ac 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -449,7 +449,7 @@ impl Step for Std { let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc"); - compile::std_cargo(builder, &compiler, target, &mut cargo); + compile::std_cargo(builder, target, &mut cargo); // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 2a4e9903e552..ce977f1bbc44 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -546,3 +546,118 @@ impl Step for TestHelpers { .compile("rust_test_helpers"); } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Sanitizers { + pub target: Interned, +} + +impl Step for Sanitizers { + type Output = Vec; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/llvm-project/compiler-rt").path("src/sanitizers") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Sanitizers { target: run.target }); + } + + /// Builds sanitizer runtime libraries. + fn run(self, builder: &Builder<'_>) -> Self::Output { + let compiler_rt_dir = builder.src.join("src/llvm-project/compiler-rt"); + if !compiler_rt_dir.exists() { + return Vec::new(); + } + + let out_dir = builder.native_dir(self.target).join("sanitizers"); + let runtimes = supported_sanitizers(&out_dir, self.target); + if runtimes.is_empty() { + return runtimes; + } + + let llvm_config = builder.ensure(Llvm { target: builder.config.build }); + if builder.config.dry_run { + return runtimes; + } + + let done_stamp = out_dir.join("sanitizers-finished-building"); + if done_stamp.exists() { + builder.info(&format!( + "Assuming that sanitizers rebuild is not necessary. \ + To force a rebuild, remove the file `{}`", + done_stamp.display() + )); + return runtimes; + } + + builder.info(&format!("Building sanitizers for {}", self.target)); + let _time = util::timeit(&builder); + + let mut cfg = cmake::Config::new(&compiler_rt_dir); + cfg.target(&self.target); + cfg.host(&builder.config.build); + cfg.profile("Release"); + + cfg.define("CMAKE_C_COMPILER_TARGET", self.target); + cfg.define("COMPILER_RT_BUILD_BUILTINS", "OFF"); + cfg.define("COMPILER_RT_BUILD_CRT", "OFF"); + cfg.define("COMPILER_RT_BUILD_LIBFUZZER", "OFF"); + cfg.define("COMPILER_RT_BUILD_PROFILE", "OFF"); + cfg.define("COMPILER_RT_BUILD_SANITIZERS", "ON"); + cfg.define("COMPILER_RT_BUILD_XRAY", "OFF"); + cfg.define("COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"); + cfg.define("COMPILER_RT_USE_LIBCXX", "OFF"); + cfg.define("LLVM_CONFIG_PATH", &llvm_config); + + t!(fs::create_dir_all(&out_dir)); + cfg.out_dir(out_dir); + + for runtime in &runtimes { + cfg.build_target(&runtime.cmake_target); + cfg.build(); + } + + t!(fs::write(&done_stamp, b"")); + + runtimes + } +} + +#[derive(Clone, Debug)] +pub struct SanitizerRuntime { + /// CMake target used to build the runtime. + pub cmake_target: String, + /// Path to the built runtime library. + pub path: PathBuf, + /// Library filename that will be used rustc. + pub name: String, +} + +/// Returns sanitizers available on a given target. +fn supported_sanitizers(out_dir: &Path, target: Interned) -> Vec { + let mut result = Vec::new(); + match &*target { + "x86_64-apple-darwin" => { + for s in &["asan", "lsan", "tsan"] { + result.push(SanitizerRuntime { + cmake_target: format!("clang_rt.{}_osx_dynamic", s), + path: out_dir + .join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)), + name: format!("librustc_rt.{}.dylib", s), + }); + } + } + "x86_64-unknown-linux-gnu" => { + for s in &["asan", "lsan", "msan", "tsan"] { + result.push(SanitizerRuntime { + cmake_target: format!("clang_rt.{}-x86_64", s), + path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)), + name: format!("librustc_rt.{}.a", s), + }); + } + } + _ => {} + } + result +} diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b5c8de057d01..10e07489e121 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1659,7 +1659,7 @@ impl Step for Crate { let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand()); match mode { Mode::Std => { - compile::std_cargo(builder, &compiler, target, &mut cargo); + compile::std_cargo(builder, target, &mut cargo); } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); From e88f071ed373f1eb572dee6bc6898508425126e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 16 Oct 2019 00:00:00 +0000 Subject: [PATCH 5/5] Document sanitizers in unstable-book --- .../src/compiler-flags/sanitizer.md | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/sanitizer.md diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md new file mode 100644 index 000000000000..cbb90bd3bb33 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -0,0 +1,163 @@ +# `sanitizer` + +The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699). + +------------------------ + +This feature allows for use of one of following sanitizers: + +* [AddressSanitizer][clang-asan] a faster memory error detector. Can + detect out-of-bounds access to heap, stack, and globals, use after free, use + after return, double free, invalid free, memory leaks. +* [LeakSanitizer][clang-lsan] a run-time memory leak detector. +* [MemorySanitizer][clang-msan] a detector of uninitialized reads. +* [ThreadSanitizer][clang-tsan] a fast data race detector. + +To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one +of `address`, `leak`, `memory` or `thread`. + +# Examples + +This sections show various issues that can be detected with sanitizers. For +simplicity, the examples are prepared under assumption that optimization level +used is zero. + +## AddressSanitizer + +Stack buffer overflow: + +```shell +$ cat a.rs +fn main() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} +$ rustc -Zsanitizer=address a.rs +$ ./a +================================================================= +==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388 +READ of size 4 at 0x7ffcc15f43d0 thread T0 + #0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4) + #1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb) + #2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12 + #3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39 + #4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7 + #5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12 + #6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8 + #7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24 + #8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61) + #9 0x55f77dc0163a in main (/tmp/a+0xa63a) + #10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba) + #11 0x55f77dc01289 in _start (/tmp/a+0xa289) + +Address 0x7ffcc15f43d0 is located in stack of thread T0 at offset 48 in frame + #0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f) + + This frame has 1 object(s): + [32, 48) 'xs' <== Memory access at offset 48 overflows this variable +HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) +SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4) in a::main::hab3bd2a745c2d0ac +Shadow bytes around the buggy address: + 0x1000182b6820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6860: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +=>0x1000182b6870: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00 + 0x1000182b6880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b68a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b68b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b68c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb + Shadow gap: cc +==10029==ABORTING +``` + +## MemorySanitizer + +Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument +standard library, and passing `-msan-track-origins=2` to the LLVM to track +origins of uninitialized memory: + +```shell +$ cat src/main.rs +use std::mem::MaybeUninit; + +fn main() { + unsafe { + let a = MaybeUninit::<[usize; 4]>::uninit(); + let a = a.assume_init(); + println!("{}", a[2]); + } +} + +$ env RUSTFLAGS="-Zsanitizer=memory -Cllvm-args=-msan-track-origins=2" cargo -Zbuild-std run --target x86_64-unknown-linux-gnu +==9416==WARNING: MemorySanitizer: use-of-uninitialized-value + #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16 +... + Uninitialized value was stored to memory at + #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3 + #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16 + + Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E' + #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3 +``` + + +# Instrumentation of external dependencies and std + +The sanitizers to varying degrees work correctly with partially instrumented +code. On the one extreme is LeakSanitizer that doesn't use any compile time +instrumentation, on the other is MemorySanitizer that requires that all program +code to be instrumented (failing to achieve that will inevitably result in +false positives). + +It is strongly recommended to combine sanitizers with recompiled and +instrumented standard library, for example using [cargo `-Zbuild-std` +functionality][build-std]. + +[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std + +# Build scripts and procedural macros + +Use of sanitizers together with build scripts and procedural macros is +technically possible, but in almost all cases it would be best avoided. This +is especially true for procedural macros which would require an instrumented +version of rustc. + +In more practical terms when using cargo always remember to pass `--target` +flag, so that rustflags will not be applied to build scripts and procedural +macros. + +# Additional Information + +* [Sanitizers project page](https://github.com/google/sanitizers/wiki/) +* [AddressSanitizer in Clang][clang-asan] +* [LeakSanitizer in Clang][clang-lsan] +* [MemorySanitizer in Clang][clang-msan] +* [ThreadSanitizer in Clang][clang-tsan] + +[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html +[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html +[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html +[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html