From 9af6aa38895d3c1d263c52984666893b9ca22fe1 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 29 Dec 2016 23:28:11 -0500 Subject: [PATCH 1/8] sanitizer support --- src/Cargo.lock | 40 ++++++++++++ src/bootstrap/check.rs | 5 +- src/bootstrap/compile.rs | 12 ++++ src/bootstrap/config.rs | 3 + src/bootstrap/lib.rs | 7 +- src/compiler-rt | 2 +- src/librustc/middle/cstore.rs | 2 + src/librustc/session/config.rs | 25 +++++++- src/librustc_asan/Cargo.toml | 16 +++++ src/librustc_asan/build.rs | 50 +++++++++++++++ src/librustc_asan/lib.rs | 20 ++++++ src/librustc_llvm/ffi.rs | 3 + src/librustc_lsan/Cargo.toml | 16 +++++ src/librustc_lsan/build.rs | 50 +++++++++++++++ src/librustc_lsan/lib.rs | 20 ++++++ src/librustc_metadata/creader.rs | 64 ++++++++++++++++++- src/librustc_metadata/cstore.rs | 5 ++ src/librustc_metadata/cstore_impl.rs | 4 ++ src/librustc_msan/Cargo.toml | 16 +++++ src/librustc_msan/build.rs | 50 +++++++++++++++ src/librustc_msan/lib.rs | 20 ++++++ src/librustc_trans/back/link.rs | 33 ++++++++++ src/librustc_trans/back/write.rs | 18 +++++- src/librustc_trans/declare.rs | 16 +++++ src/librustc_tsan/Cargo.toml | 16 +++++ src/librustc_tsan/build.rs | 50 +++++++++++++++ src/librustc_tsan/lib.rs | 20 ++++++ src/libstd/Cargo.toml | 10 +++ src/libsyntax/feature_gate.rs | 10 +++ src/rustc/std_shim/Cargo.toml | 4 ++ src/rustllvm/RustWrapper.cpp | 6 ++ src/rustllvm/rustllvm.h | 3 + .../feature-gate-sanitizer-runtime.rs | 13 ++++ src/test/run-make/sanitizer-address/Makefile | 21 ++++++ .../run-make/sanitizer-address/overflow.rs | 14 ++++ src/test/run-make/sanitizer-dylib/Makefile | 4 ++ src/test/run-make/sanitizer-dylib/hello.rs | 13 ++++ .../sanitizer-invalid-target/Makefile | 4 ++ .../sanitizer-invalid-target/hello.rs | 13 ++++ src/test/run-make/sanitizer-leak/Makefile | 23 +++++++ src/test/run-make/sanitizer-leak/leak.rs | 16 +++++ src/test/run-make/sanitizer-memory/Makefile | 21 ++++++ src/test/run-make/sanitizer-memory/uninit.rs | 16 +++++ src/test/run-make/sanitizer-thread/Makefile | 21 ++++++ src/test/run-make/sanitizer-thread/racy.rs | 21 ++++++ 45 files changed, 810 insertions(+), 6 deletions(-) create mode 100644 src/librustc_asan/Cargo.toml create mode 100644 src/librustc_asan/build.rs create mode 100644 src/librustc_asan/lib.rs create mode 100644 src/librustc_lsan/Cargo.toml create mode 100644 src/librustc_lsan/build.rs create mode 100644 src/librustc_lsan/lib.rs create mode 100644 src/librustc_msan/Cargo.toml create mode 100644 src/librustc_msan/build.rs create mode 100644 src/librustc_msan/lib.rs create mode 100644 src/librustc_tsan/Cargo.toml create mode 100644 src/librustc_tsan/build.rs create mode 100644 src/librustc_tsan/lib.rs create mode 100644 src/test/compile-fail/feature-gate-sanitizer-runtime.rs create mode 100644 src/test/run-make/sanitizer-address/Makefile create mode 100644 src/test/run-make/sanitizer-address/overflow.rs create mode 100644 src/test/run-make/sanitizer-dylib/Makefile create mode 100644 src/test/run-make/sanitizer-dylib/hello.rs create mode 100644 src/test/run-make/sanitizer-invalid-target/Makefile create mode 100644 src/test/run-make/sanitizer-invalid-target/hello.rs create mode 100644 src/test/run-make/sanitizer-leak/Makefile create mode 100644 src/test/run-make/sanitizer-leak/leak.rs create mode 100644 src/test/run-make/sanitizer-memory/Makefile create mode 100644 src/test/run-make/sanitizer-memory/uninit.rs create mode 100644 src/test/run-make/sanitizer-thread/Makefile create mode 100644 src/test/run-make/sanitizer-thread/racy.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 06cf32ad0f6..8e987ba3b7f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -268,6 +268,15 @@ name = "rustc-serialize" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_asan" +version = "0.0.0" +dependencies = [ + "alloc_system 0.0.0", + "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "core 0.0.0", +] + [[package]] name = "rustc_back" version = "0.0.0" @@ -401,6 +410,15 @@ dependencies = [ "rustc_bitflags 0.0.0", ] +[[package]] +name = "rustc_lsan" +version = "0.0.0" +dependencies = [ + "alloc_system 0.0.0", + "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "core 0.0.0", +] + [[package]] name = "rustc_metadata" version = "0.0.0" @@ -435,6 +453,15 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "rustc_msan" +version = "0.0.0" +dependencies = [ + "alloc_system 0.0.0", + "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "core 0.0.0", +] + [[package]] name = "rustc_passes" version = "0.0.0" @@ -516,6 +543,15 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "rustc_tsan" +version = "0.0.0" +dependencies = [ + "alloc_system 0.0.0", + "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "core 0.0.0", +] + [[package]] name = "rustc_typeck" version = "0.0.0" @@ -577,6 +613,10 @@ dependencies = [ "panic_abort 0.0.0", "panic_unwind 0.0.0", "rand 0.0.0", + "rustc_asan 0.0.0", + "rustc_lsan 0.0.0", + "rustc_msan 0.0.0", + "rustc_tsan 0.0.0", "std_unicode 0.0.0", "unwind 0.0.0", ] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 19aac0f36bb..573d0df0cee 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -332,7 +332,10 @@ pub fn krate(build: &Build, krate: Option<&str>) { let (name, path, features, root) = match mode { Mode::Libstd => { - ("libstd", "src/rustc/std_shim", build.std_features(), "std_shim") + ("libstd", + "src/rustc/std_shim", + build.std_features(), + "std_shim") } Mode::Libtest => { ("libtest", "src/rustc/test_shim", String::new(), "test_shim") diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 776b91028a1..3e29339a75b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -51,6 +51,18 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { features.push_str(" force_alloc_system"); } + + if compiler.stage != 0 && !build.system_llvm(target) { + // 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 don't build the runtimes when compiling against system llvm + // because some distributions ship llvm packages that have a directory + // layout different from the one that the runtime's build system expects + cargo.env("LLVM_CONFIG", build.llvm_config(target)); + } cargo.arg("--features").arg(features) .arg("--manifest-path") .arg(build.src.join("src/rustc/std_shim/Cargo.toml")); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6e077691b3a..b171c89c20a 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -108,6 +108,8 @@ pub struct Config { /// Per-target configuration stored in the global configuration structure. #[derive(Default)] pub struct Target { + // `true` if compiling against system LLVM or a pre-built LLVM + pub system_llvm: bool, pub llvm_config: Option, pub jemalloc: Option, pub cc: Option, @@ -512,6 +514,7 @@ impl Config { .or_insert(Target::default()); let root = parse_configure_path(value); target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); + target.system_llvm = true; } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index df1218752d1..21dd4b1520a 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -599,7 +599,8 @@ impl Build { /// Get the space-separated set of activated features for the standard /// library. fn std_features(&self) -> String { - let mut features = "panic-unwind".to_string(); + let mut features = "panic-unwind asan lsan msan tsan".to_string(); + if self.config.debug_jemalloc { features.push_str(" debug-jemalloc"); } @@ -716,6 +717,10 @@ impl Build { } } + fn system_llvm(&self, target: &str) -> bool { + self.config.target_config.get(target).map(|t| t.system_llvm).unwrap_or(false) + } + /// Returns the path to `FileCheck` binary for the specified target fn llvm_filecheck(&self, target: &str) -> PathBuf { let target_config = self.config.target_config.get(target); diff --git a/src/compiler-rt b/src/compiler-rt index a8fc4c169fa..d30da544a8a 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178 +Subproject commit d30da544a8afc5d78391dee270bdf40e74a215d3 diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 6537cc1adce..2d80fc32c46 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -229,6 +229,7 @@ pub trait CrateStore<'tcx> { fn is_allocator(&self, cnum: CrateNum) -> bool; fn is_panic_runtime(&self, cnum: CrateNum) -> bool; fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; + fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; fn extern_crate(&self, cnum: CrateNum) -> Option; /// The name of the crate as it is referred to in source code of the current @@ -390,6 +391,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") } fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") } fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } + fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") } fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { bug!("panic_strategy") } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d41c2ba93b9..24615f2fa69 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -51,6 +51,14 @@ pub struct Config { pub uint_type: UintTy, } +#[derive(Clone)] +pub enum Sanitizer { + Address, + Leak, + Memory, + Thread, +} + #[derive(Clone, Copy, PartialEq, Hash)] pub enum OptLevel { No, // -O0 @@ -626,11 +634,13 @@ macro_rules! options { Some("a number"); pub const parse_panic_strategy: Option<&'static str> = Some("either `panic` or `abort`"); + pub const parse_sanitizer: Option<&'static str> = + Some("one of: `address`, `leak`, `memory` or `thread`"); } #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, SomePasses, AllPasses}; + use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer}; use rustc_back::PanicStrategy; $( @@ -751,6 +761,17 @@ macro_rules! options { } true } + + fn parse_sanitizer(slote: &mut Option, v: Option<&str>) -> bool { + match v { + Some("address") => *slote = Some(Sanitizer::Address), + Some("leak") => *slote = Some(Sanitizer::Leak), + Some("memory") => *slote = Some(Sanitizer::Memory), + Some("thread") => *slote = Some(Sanitizer::Thread), + _ => return false, + } + true + } } ) } @@ -949,6 +970,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "encode MIR of all functions into the crate metadata"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], "pass `-install_name @rpath/...` to the OSX linker"), + sanitizer: Option = (None, parse_sanitizer, [UNTRACKED], + "Use a sanitizer"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml new file mode 100644 index 00000000000..abbd7cc0966 --- /dev/null +++ b/src/librustc_asan/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The Rust Project Developers"] +build = "build.rs" +name = "rustc_asan" +version = "0.0.0" + +[lib] +name = "rustc_asan" +path = "lib.rs" + +[build-dependencies] +cmake = "0.1.18" + +[dependencies] +alloc_system = { path = "../liballoc_system" } +core = { path = "../libcore" } diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs new file mode 100644 index 00000000000..3e33efcadb8 --- /dev/null +++ b/src/librustc_asan/build.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate cmake; + +use std::path::PathBuf; +use std::env; + +use cmake::Config; + +fn main() { + if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { + let dst = Config::new("../compiler-rt") + .define("COMPILER_RT_BUILD_SANITIZERS", "ON") + .define("COMPILER_RT_BUILD_BUILTINS", "OFF") + .define("COMPILER_RT_BUILD_XRAY", "OFF") + .define("LLVM_CONFIG_PATH", llvm_config) + .build_target("asan") + .build(); + + println!("cargo:rustc-link-search=native={}", + dst.join("build/lib/linux").display()); + println!("cargo:rustc-link-lib=static=clang_rt.asan-x86_64"); + + let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let mut stack = src_dir.join("../compiler-rt") + .read_dir() + .unwrap() + .map(|e| e.unwrap()) + .filter(|e| &*e.file_name() != ".git") + .collect::>(); + while let Some(entry) = stack.pop() { + let path = entry.path(); + if entry.file_type().unwrap().is_dir() { + stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } + } + } + + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs new file mode 100644 index 00000000000..71a166b91eb --- /dev/null +++ b/src/librustc_asan/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(not(stage0), feature(sanitizer_runtime))] +#![cfg_attr(not(stage0), sanitizer_runtime)] +#![feature(alloc_system)] +#![feature(staged_api)] +#![no_std] +#![unstable(feature = "sanitizer_runtime_lib", + reason = "internal implementation detail of sanitizers", + issue = "0")] + +extern crate alloc_system; diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 8510b9f523c..6c9976ca3f8 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -126,6 +126,9 @@ pub enum Attribute { UWTable = 17, ZExt = 18, InReg = 19, + SanitizeThread = 20, + SanitizeAddress = 21, + SanitizeMemory = 22, } /// LLVMIntPredicate diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml new file mode 100644 index 00000000000..ac53f3fe73a --- /dev/null +++ b/src/librustc_lsan/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The Rust Project Developers"] +build = "build.rs" +name = "rustc_lsan" +version = "0.0.0" + +[lib] +name = "rustc_lsan" +path = "lib.rs" + +[build-dependencies] +cmake = "0.1.18" + +[dependencies] +alloc_system = { path = "../liballoc_system" } +core = { path = "../libcore" } diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs new file mode 100644 index 00000000000..f13928d2bd4 --- /dev/null +++ b/src/librustc_lsan/build.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate cmake; + +use std::path::PathBuf; +use std::env; + +use cmake::Config; + +fn main() { + if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { + let dst = Config::new("../compiler-rt") + .define("COMPILER_RT_BUILD_SANITIZERS", "ON") + .define("COMPILER_RT_BUILD_BUILTINS", "OFF") + .define("COMPILER_RT_BUILD_XRAY", "OFF") + .define("LLVM_CONFIG_PATH", llvm_config) + .build_target("lsan") + .build(); + + println!("cargo:rustc-link-search=native={}", + dst.join("build/lib/linux").display()); + println!("cargo:rustc-link-lib=static=clang_rt.lsan-x86_64"); + + let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let mut stack = src_dir.join("../compiler-rt") + .read_dir() + .unwrap() + .map(|e| e.unwrap()) + .filter(|e| &*e.file_name() != ".git") + .collect::>(); + while let Some(entry) = stack.pop() { + let path = entry.path(); + if entry.file_type().unwrap().is_dir() { + stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } + } + } + + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs new file mode 100644 index 00000000000..71a166b91eb --- /dev/null +++ b/src/librustc_lsan/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(not(stage0), feature(sanitizer_runtime))] +#![cfg_attr(not(stage0), sanitizer_runtime)] +#![feature(alloc_system)] +#![feature(staged_api)] +#![no_std] +#![unstable(feature = "sanitizer_runtime_lib", + reason = "internal implementation detail of sanitizers", + issue = "0")] + +extern crate alloc_system; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 81a4f7c93b6..55dc5aa2876 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -17,7 +17,8 @@ use schema::CrateRoot; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; use rustc::middle::cstore::DepKind; -use rustc::session::{config, Session}; +use rustc::session::Session; +use rustc::session::config::{Sanitizer, self}; use rustc_back::PanicStrategy; use rustc::session::search_paths::PathKind; use rustc::middle; @@ -786,6 +787,64 @@ impl<'a> CrateLoader<'a> { &|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 with x86_64 Linux executables linked + // to `std` + if self.sess.target.target.llvm_target != "x86_64-unknown-linux-gnu" { + self.sess.err(&format!("Sanitizers only work with the \ + `x86_64-unknown-linux-gnu` target.")); + return + } + + if !self.sess.crate_types.borrow().iter().all(|ct| { + match *ct { + // Link the runtime + config::CrateTypeExecutable => true, + // This crate will be compiled with the required + // instrumentation pass + config::CrateTypeRlib => 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 == "std" { + uses_std = true; + } + }); + + if uses_std { + let name = match *sanitizer { + Sanitizer::Address => "rustc_asan", + Sanitizer::Leak => "rustc_lsan", + Sanitizer::Memory => "rustc_msan", + Sanitizer::Thread => "rustc_tsan", + }; + info!("loading sanitizer: {}", name); + + let symbol = Symbol::intern(name); + let dep_kind = DepKind::Implicit; + let (_, data) = + self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + PathKind::Crate, dep_kind); + + // 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)); + } + } + } + } + fn inject_allocator_crate(&mut self) { // Make sure that we actually need an allocator, if none of our // dependencies need one then we definitely don't! @@ -982,6 +1041,9 @@ impl<'a> CrateLoader<'a> { impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { fn postprocess(&mut self, krate: &ast::Crate) { + // inject the sanitizer runtime before the allocator runtime because all + // sanitizers force the use of the `alloc_system` allocator + self.inject_sanitizer_runtime(); self.inject_allocator_crate(); self.inject_panic_runtime(krate); diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index beba5faf3d0..4709ca6101c 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -297,6 +297,11 @@ impl CrateMetadata { attr::contains_name(&attrs, "compiler_builtins") } + pub fn is_sanitizer_runtime(&self) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + attr::contains_name(&attrs, "sanitizer_runtime") + } + pub fn is_no_builtins(&self) -> bool { let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "no_builtins") diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 39581a46960..7b0177bfd23 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -297,6 +297,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(cnum).is_compiler_builtins() } + fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { + self.get_crate_data(cnum).is_sanitizer_runtime() + } + fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { self.get_crate_data(cnum).panic_strategy() } diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml new file mode 100644 index 00000000000..628746ac232 --- /dev/null +++ b/src/librustc_msan/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The Rust Project Developers"] +build = "build.rs" +name = "rustc_msan" +version = "0.0.0" + +[lib] +name = "rustc_msan" +path = "lib.rs" + +[build-dependencies] +cmake = "0.1.18" + +[dependencies] +alloc_system = { path = "../liballoc_system" } +core = { path = "../libcore" } diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs new file mode 100644 index 00000000000..bf630c7844a --- /dev/null +++ b/src/librustc_msan/build.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate cmake; + +use std::path::PathBuf; +use std::env; + +use cmake::Config; + +fn main() { + if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { + let dst = Config::new("../compiler-rt") + .define("COMPILER_RT_BUILD_SANITIZERS", "ON") + .define("COMPILER_RT_BUILD_BUILTINS", "OFF") + .define("COMPILER_RT_BUILD_XRAY", "OFF") + .define("LLVM_CONFIG_PATH", llvm_config) + .build_target("msan") + .build(); + + println!("cargo:rustc-link-search=native={}", + dst.join("build/lib/linux").display()); + println!("cargo:rustc-link-lib=static=clang_rt.msan-x86_64"); + + let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let mut stack = src_dir.join("../compiler-rt") + .read_dir() + .unwrap() + .map(|e| e.unwrap()) + .filter(|e| &*e.file_name() != ".git") + .collect::>(); + while let Some(entry) = stack.pop() { + let path = entry.path(); + if entry.file_type().unwrap().is_dir() { + stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } + } + } + + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs new file mode 100644 index 00000000000..71a166b91eb --- /dev/null +++ b/src/librustc_msan/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(not(stage0), feature(sanitizer_runtime))] +#![cfg_attr(not(stage0), sanitizer_runtime)] +#![feature(alloc_system)] +#![feature(staged_api)] +#![no_std] +#![unstable(feature = "sanitizer_runtime_lib", + reason = "internal implementation detail of sanitizers", + issue = "0")] + +extern crate alloc_system; diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 4ddf8a883bc..1cbfa26b705 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -1031,6 +1031,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // symbols from the dylib. let src = sess.cstore.used_crate_source(cnum); match data[cnum.as_usize() - 1] { + _ if sess.cstore.is_sanitizer_runtime(cnum) => { + link_sanitizer_runtime(cmd, sess, tmpdir, cnum); + } // compiler-builtins are always placed last to ensure that they're // linked correctly. _ if sess.cstore.is_compiler_builtins(cnum) => { @@ -1048,6 +1051,8 @@ fn add_upstream_rust_crates(cmd: &mut Linker, } } + // compiler-builtins are always placed last to ensure that they're + // linked correctly. // We must always link the `compiler_builtins` crate statically. Even if it // was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic` // is used) @@ -1064,6 +1069,34 @@ fn add_upstream_rust_crates(cmd: &mut Linker, } } + // 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(cmd: &mut Linker, + sess: &Session, + tmpdir: &Path, + cnum: CrateNum) { + let src = sess.cstore.used_crate_source(cnum); + let cratepath = &src.rlib.unwrap().0; + let dst = tmpdir.join(cratepath.file_name().unwrap()); + let cfg = archive_config(sess, &dst, Some(cratepath)); + let mut archive = ArchiveBuilder::new(cfg); + archive.update_symbols(); + + for f in archive.src_files() { + if f.ends_with("bytecode.deflate") || + f == sess.cstore.metadata_filename() { + archive.remove_file(&f); + continue + } + } + + 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_trans/back/write.rs b/src/librustc_trans/back/write.rs index b3a2d66a07c..8e71c571095 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -12,7 +12,7 @@ use back::lto; use back::link::{get_linker, remove}; use back::symbol_export::ExportedSymbols; use rustc_incremental::{save_trans_partition, in_incr_comp_dir}; -use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses}; +use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses, Sanitizer}; use session::Session; use session::config::{self, OutputType}; use llvm; @@ -678,6 +678,22 @@ pub fn run_passes(sess: &Session, let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone()); let mut metadata_config = ModuleConfig::new(tm, vec![]); + if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer { + match *sanitizer { + Sanitizer::Address => { + modules_config.passes.push("asan".to_owned()); + modules_config.passes.push("asan-module".to_owned()); + } + Sanitizer::Memory => { + modules_config.passes.push("msan".to_owned()) + } + Sanitizer::Thread => { + modules_config.passes.push("tsan".to_owned()) + } + _ => {} + } + } + modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize)); modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize)); diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index bf7a02eb0f1..7ac482459ee 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -23,6 +23,7 @@ use llvm::{self, ValueRef}; use llvm::AttributePlace::Function; use rustc::ty; +use rustc::session::config::Sanitizer; use abi::{Abi, FnType}; use attributes; use context::CrateContext; @@ -72,6 +73,21 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: llvm::Attribute::NoRedZone.apply_llfn(Function, llfn); } + if let Some(ref sanitizer) = ccx.tcx().sess.opts.debugging_opts.sanitizer { + match *sanitizer { + Sanitizer::Address => { + llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn); + }, + Sanitizer::Memory => { + llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn); + }, + Sanitizer::Thread => { + llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn); + }, + _ => {} + } + } + // If we're compiling the compiler-builtins crate, e.g. the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden // visibility as we're going to link this object all over the place but diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml new file mode 100644 index 00000000000..2af0ae3f734 --- /dev/null +++ b/src/librustc_tsan/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The Rust Project Developers"] +build = "build.rs" +name = "rustc_tsan" +version = "0.0.0" + +[lib] +name = "rustc_tsan" +path = "lib.rs" + +[build-dependencies] +cmake = "0.1.18" + +[dependencies] +alloc_system = { path = "../liballoc_system" } +core = { path = "../libcore" } diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs new file mode 100644 index 00000000000..2ba5866ab9d --- /dev/null +++ b/src/librustc_tsan/build.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate cmake; + +use std::path::PathBuf; +use std::env; + +use cmake::Config; + +fn main() { + if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { + let dst = Config::new("../compiler-rt") + .define("COMPILER_RT_BUILD_SANITIZERS", "ON") + .define("COMPILER_RT_BUILD_BUILTINS", "OFF") + .define("COMPILER_RT_BUILD_XRAY", "OFF") + .define("LLVM_CONFIG_PATH", llvm_config) + .build_target("tsan") + .build(); + + println!("cargo:rustc-link-search=native={}", + dst.join("build/lib/linux").display()); + println!("cargo:rustc-link-lib=static=clang_rt.tsan-x86_64"); + + let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let mut stack = src_dir.join("../compiler-rt") + .read_dir() + .unwrap() + .map(|e| e.unwrap()) + .filter(|e| &*e.file_name() != ".git") + .collect::>(); + while let Some(entry) = stack.pop() { + let path = entry.path(); + if entry.file_type().unwrap().is_dir() { + stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } + } + } + + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs new file mode 100644 index 00000000000..71a166b91eb --- /dev/null +++ b/src/librustc_tsan/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(not(stage0), feature(sanitizer_runtime))] +#![cfg_attr(not(stage0), sanitizer_runtime)] +#![feature(alloc_system)] +#![feature(staged_api)] +#![no_std] +#![unstable(feature = "sanitizer_runtime_lib", + reason = "internal implementation detail of sanitizers", + issue = "0")] + +extern crate alloc_system; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 8146e7fb1ed..2ba7517d3d2 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,13 +23,23 @@ compiler_builtins = { path = "../libcompiler_builtins" } std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } +[target.x86_64-unknown-linux-gnu.dependencies] +rustc_asan = { path = "../librustc_asan", optional = true } +rustc_lsan = { path = "../librustc_lsan", optional = true } +rustc_msan = { path = "../librustc_msan", optional = true } +rustc_tsan = { path = "../librustc_tsan", optional = true } + [build-dependencies] build_helper = { path = "../build_helper" } gcc = "0.3.27" [features] +asan = ["rustc_asan"] backtrace = [] debug-jemalloc = ["alloc_jemalloc/debug"] jemalloc = ["alloc_jemalloc"] force_alloc_system = [] +lsan = ["rustc_lsan"] +msan = ["rustc_msan"] panic-unwind = ["panic_unwind"] +tsan = ["rustc_tsan"] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 52ef2a05fcf..6a16a0ef353 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -328,6 +328,10 @@ declare_features! ( // `extern "msp430-interrupt" fn()` (active, abi_msp430_interrupt, "1.16.0", Some(38487)), + + // Used to identify crates that contain sanitizer runtimes + // rustc internal + (active, sanitizer_runtime, "1.17.0", None), ); declare_features! ( @@ -647,6 +651,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG contains compiler-rt intrinsics and will never be \ stable", cfg_fn!(compiler_builtins))), + ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable, + "sanitizer_runtime", + "the `#[sanitizer_runtime]` attribute is used to \ + identify crates that contain the runtime of a \ + sanitizer and will never be stable", + cfg_fn!(sanitizer_runtime))), ("allow_internal_unstable", Normal, Gated(Stability::Unstable, "allow_internal_unstable", diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml index 14c9c5544b1..db96079d3e9 100644 --- a/src/rustc/std_shim/Cargo.toml +++ b/src/rustc/std_shim/Cargo.toml @@ -35,8 +35,12 @@ core = { path = "../../libcore" } # Reexport features from std [features] +asan = ["std/asan"] backtrace = ["std/backtrace"] debug-jemalloc = ["std/debug-jemalloc"] jemalloc = ["std/jemalloc"] force_alloc_system = ["std/force_alloc_system"] +lsan = ["std/lsan"] +msan = ["std/msan"] panic-unwind = ["std/panic-unwind"] +tsan = ["std/tsan"] diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index c7bcd255818..58dfe0a3d38 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -148,6 +148,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::ZExt; case InReg: return Attribute::InReg; + case SanitizeThread: + return Attribute::SanitizeThread; + case SanitizeAddress: + return Attribute::SanitizeAddress; + case SanitizeMemory: + return Attribute::SanitizeMemory; } llvm_unreachable("bad AttributeKind"); } diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index a30fa3133e2..0baf5528e93 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -98,6 +98,9 @@ enum LLVMRustAttribute { UWTable = 17, ZExt = 18, InReg = 19, + SanitizeThread = 20, + SanitizeAddress = 21, + SanitizeMemory = 22, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/src/test/compile-fail/feature-gate-sanitizer-runtime.rs b/src/test/compile-fail/feature-gate-sanitizer-runtime.rs new file mode 100644 index 00000000000..a18641d8246 --- /dev/null +++ b/src/test/compile-fail/feature-gate-sanitizer-runtime.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is + +fn main() {} diff --git a/src/test/run-make/sanitizer-address/Makefile b/src/test/run-make/sanitizer-address/Makefile new file mode 100644 index 00000000000..c490f490cdf --- /dev/null +++ b/src/test/run-make/sanitizer-address/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +# NOTE the address sanitizer only supports x86_64 linux +ifndef IS_WINDOWS +ifeq ($(shell uname),Linux) +ifeq ($(shell uname -m),x86_64) +all: + $(RUSTC) -g -Z sanitizer=address -Z print-link-args overflow.rs | grep -q librustc_asan + $(TMPDIR)/overflow 2>&1 | grep -q stack-buffer-overflow +else +all: + +endif +else +all: + +endif +else +all: + +endif diff --git a/src/test/run-make/sanitizer-address/overflow.rs b/src/test/run-make/sanitizer-address/overflow.rs new file mode 100644 index 00000000000..e35c3873f7e --- /dev/null +++ b/src/test/run-make/sanitizer-address/overflow.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let xs = [0, 1, 2, 3]; + let y = unsafe { *xs.as_ptr().offset(4) }; +} diff --git a/src/test/run-make/sanitizer-dylib/Makefile b/src/test/run-make/sanitizer-dylib/Makefile new file mode 100644 index 00000000000..70a8254a6a6 --- /dev/null +++ b/src/test/run-make/sanitizer-dylib/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) -Z sanitizer=leak --crate-type dylib hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' diff --git a/src/test/run-make/sanitizer-dylib/hello.rs b/src/test/run-make/sanitizer-dylib/hello.rs new file mode 100644 index 00000000000..41782851a1a --- /dev/null +++ b/src/test/run-make/sanitizer-dylib/hello.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/run-make/sanitizer-invalid-target/Makefile b/src/test/run-make/sanitizer-invalid-target/Makefile new file mode 100644 index 00000000000..6a1ce8bab2f --- /dev/null +++ b/src/test/run-make/sanitizer-invalid-target/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | grep -q 'Sanitizers only work with the `x86_64-unknown-linux-gnu` target' diff --git a/src/test/run-make/sanitizer-invalid-target/hello.rs b/src/test/run-make/sanitizer-invalid-target/hello.rs new file mode 100644 index 00000000000..e9e46b7702a --- /dev/null +++ b/src/test/run-make/sanitizer-invalid-target/hello.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/src/test/run-make/sanitizer-leak/Makefile b/src/test/run-make/sanitizer-leak/Makefile new file mode 100644 index 00000000000..492e328fab2 --- /dev/null +++ b/src/test/run-make/sanitizer-leak/Makefile @@ -0,0 +1,23 @@ +-include ../tools.mk + +# NOTE the leak sanitizer only supports x86_64 linux +# Also, this particular sanitizer sometimes doesn't work so we are not going to +# run the binary +ifndef IS_WINDOWS +ifeq ($(shell uname),Linux) +ifeq ($(shell uname -m),x86_64) +all: + $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | grep -q librustc_lsan + $(TMPDIR)/leak 2>&1 | grep -q 'detected memory leaks' +else +all: + +endif +else +all: + +endif +else +all: + +endif diff --git a/src/test/run-make/sanitizer-leak/leak.rs b/src/test/run-make/sanitizer-leak/leak.rs new file mode 100644 index 00000000000..279da6aaae7 --- /dev/null +++ b/src/test/run-make/sanitizer-leak/leak.rs @@ -0,0 +1,16 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::mem; + +fn main() { + let xs = vec![1, 2, 3, 4]; + mem::forget(xs); +} diff --git a/src/test/run-make/sanitizer-memory/Makefile b/src/test/run-make/sanitizer-memory/Makefile new file mode 100644 index 00000000000..f8960992a0d --- /dev/null +++ b/src/test/run-make/sanitizer-memory/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +# NOTE the memory sanitizer only supports x86_64 linux +ifndef IS_WINDOWS +ifeq ($(shell uname),Linux) +ifeq ($(shell uname -m),x86_64) +all: + $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | grep -q librustc_msan + $(TMPDIR)/uninit 2>&1 | grep -q use-of-uninitialized-value +else +all: + +endif +else +all: + +endif +else +all: + +endif diff --git a/src/test/run-make/sanitizer-memory/uninit.rs b/src/test/run-make/sanitizer-memory/uninit.rs new file mode 100644 index 00000000000..8350c7de3ac --- /dev/null +++ b/src/test/run-make/sanitizer-memory/uninit.rs @@ -0,0 +1,16 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::mem; + +fn main() { + let xs: [u8; 4] = unsafe { mem::uninitialized() }; + let y = xs[0] + xs[1]; +} diff --git a/src/test/run-make/sanitizer-thread/Makefile b/src/test/run-make/sanitizer-thread/Makefile new file mode 100644 index 00000000000..e32247c4a9b --- /dev/null +++ b/src/test/run-make/sanitizer-thread/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +# NOTE the leak sanitizer only supports x86_64 linux +ifndef IS_WINDOWS +ifeq ($(shell uname),Linux) +ifeq ($(shell uname -m),x86_64) +all: + $(RUSTC) -g -Z sanitizer=thread -Z print-link-args racy.rs | grep -q librustc_tsan + $(TMPDIR)/racy 2>&1 | grep -q 'data race' +else +all: + +endif +else +all: + +endif +else +all: + +endif diff --git a/src/test/run-make/sanitizer-thread/racy.rs b/src/test/run-make/sanitizer-thread/racy.rs new file mode 100644 index 00000000000..dc929e004a4 --- /dev/null +++ b/src/test/run-make/sanitizer-thread/racy.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::thread; + +static mut ANSWER: i32 = 0; + +fn main() { + let t1 = thread::spawn(|| unsafe { ANSWER = 42 }); + unsafe { + ANSWER = 24; + } + t1.join().ok(); +} From 775a93646cb6db5affff24f2260fb60a7723deba Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 3 Feb 2017 18:58:47 -0500 Subject: [PATCH 2/8] build/test the sanitizers only when --enable-sanitizers is used --- configure | 1 + src/bootstrap/check.rs | 9 +++++---- src/bootstrap/compile.rs | 7 +++---- src/bootstrap/config.rs | 7 ++++--- src/bootstrap/config.toml.example | 3 +++ src/bootstrap/lib.rs | 4 ---- src/librustc_llvm/ffi.rs | 2 +- src/test/run-make/sanitizer-address/Makefile | 12 +----------- src/test/run-make/sanitizer-leak/Makefile | 15 +-------------- src/test/run-make/sanitizer-memory/Makefile | 13 +------------ src/test/run-make/sanitizer-thread/Makefile | 13 +------------ 11 files changed, 21 insertions(+), 65 deletions(-) diff --git a/configure b/configure index 4ce80a5e849..0904143a7b5 100755 --- a/configure +++ b/configure @@ -649,6 +649,7 @@ opt codegen-tests 1 "run the src/test/codegen tests" opt option-checking 1 "complain about unrecognized options in this configure script" opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)" opt vendor 0 "enable usage of vendored Rust crates" +opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)" # Optimization and debugging options. These may be overridden by the release channel, etc. opt_nosave optimize 1 "build optimized rust code" diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 573d0df0cee..32cce45e067 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -236,6 +236,10 @@ pub fn compiletest(build: &Build, cmd.env("RUSTC_BOOTSTRAP", "1"); build.add_rust_test_threads(&mut cmd); + if build.config.sanitizers { + cmd.env("SANITIZER_SUPPORT", "1"); + } + cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); if target.contains("android") { @@ -332,10 +336,7 @@ pub fn krate(build: &Build, krate: Option<&str>) { let (name, path, features, root) = match mode { Mode::Libstd => { - ("libstd", - "src/rustc/std_shim", - build.std_features(), - "std_shim") + ("libstd", "src/rustc/std_shim", build.std_features(), "std_shim") } Mode::Libtest => { ("libtest", "src/rustc/test_shim", String::new(), "test_shim") diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 3e29339a75b..d329f9c0690 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -52,15 +52,14 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { features.push_str(" force_alloc_system"); } - if compiler.stage != 0 && !build.system_llvm(target) { + if compiler.stage != 0 && build.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 don't build the runtimes when compiling against system llvm - // because some distributions ship llvm packages that have a directory - // layout different from the one that the runtime's build system expects + // We also only build the runtimes when --enable-sanitizers (or its + // config.toml equivalent) is used cargo.env("LLVM_CONFIG", build.llvm_config(target)); } cargo.arg("--features").arg(features) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b171c89c20a..a31b202a0ae 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -48,6 +48,7 @@ pub struct Config { pub target_config: HashMap, pub full_bootstrap: bool, pub extended: bool, + pub sanitizers: bool, // llvm codegen options pub llvm_assertions: bool, @@ -108,8 +109,6 @@ pub struct Config { /// Per-target configuration stored in the global configuration structure. #[derive(Default)] pub struct Target { - // `true` if compiling against system LLVM or a pre-built LLVM - pub system_llvm: bool, pub llvm_config: Option, pub jemalloc: Option, pub cc: Option, @@ -150,6 +149,7 @@ struct Build { python: Option, full_bootstrap: Option, extended: Option, + sanitizers: Option, } /// TOML representation of various global install decisions. @@ -294,6 +294,7 @@ impl Config { set(&mut config.vendor, build.vendor); set(&mut config.full_bootstrap, build.full_bootstrap); set(&mut config.extended, build.extended); + set(&mut config.sanitizers, build.sanitizers); if let Some(ref install) = toml.install { config.prefix = install.prefix.clone().map(PathBuf::from); @@ -437,6 +438,7 @@ impl Config { ("VENDOR", self.vendor), ("FULL_BOOTSTRAP", self.full_bootstrap), ("EXTENDED", self.extended), + ("SANITIZERS", self.sanitizers), } match key { @@ -514,7 +516,6 @@ impl Config { .or_insert(Target::default()); let root = parse_configure_path(value); target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); - target.system_llvm = true; } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index a53419ad7fd..025fe990f91 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -124,6 +124,9 @@ # disabled by default. #extended = false +# Build the sanitizer runtimes +#sanitizers = false + # ============================================================================= # General install configuration options # ============================================================================= diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 21dd4b1520a..1d01b8773ce 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -717,10 +717,6 @@ impl Build { } } - fn system_llvm(&self, target: &str) -> bool { - self.config.target_config.get(target).map(|t| t.system_llvm).unwrap_or(false) - } - /// Returns the path to `FileCheck` binary for the specified target fn llvm_filecheck(&self, target: &str) -> PathBuf { let target_config = self.config.target_config.get(target); diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 6c9976ca3f8..bd24f7657e7 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -127,7 +127,7 @@ pub enum Attribute { ZExt = 18, InReg = 19, SanitizeThread = 20, - SanitizeAddress = 21, + SanitizeAddress = 21, SanitizeMemory = 22, } diff --git a/src/test/run-make/sanitizer-address/Makefile b/src/test/run-make/sanitizer-address/Makefile index c490f490cdf..5931145f3a4 100644 --- a/src/test/run-make/sanitizer-address/Makefile +++ b/src/test/run-make/sanitizer-address/Makefile @@ -1,9 +1,7 @@ -include ../tools.mk # NOTE the address sanitizer only supports x86_64 linux -ifndef IS_WINDOWS -ifeq ($(shell uname),Linux) -ifeq ($(shell uname -m),x86_64) +ifdef SANITIZER_SUPPORT all: $(RUSTC) -g -Z sanitizer=address -Z print-link-args overflow.rs | grep -q librustc_asan $(TMPDIR)/overflow 2>&1 | grep -q stack-buffer-overflow @@ -11,11 +9,3 @@ else all: endif -else -all: - -endif -else -all: - -endif diff --git a/src/test/run-make/sanitizer-leak/Makefile b/src/test/run-make/sanitizer-leak/Makefile index 492e328fab2..f02d948fdc8 100644 --- a/src/test/run-make/sanitizer-leak/Makefile +++ b/src/test/run-make/sanitizer-leak/Makefile @@ -1,11 +1,6 @@ -include ../tools.mk -# NOTE the leak sanitizer only supports x86_64 linux -# Also, this particular sanitizer sometimes doesn't work so we are not going to -# run the binary -ifndef IS_WINDOWS -ifeq ($(shell uname),Linux) -ifeq ($(shell uname -m),x86_64) +ifdef SANITIZER_SUPPORT all: $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | grep -q librustc_lsan $(TMPDIR)/leak 2>&1 | grep -q 'detected memory leaks' @@ -13,11 +8,3 @@ else all: endif -else -all: - -endif -else -all: - -endif diff --git a/src/test/run-make/sanitizer-memory/Makefile b/src/test/run-make/sanitizer-memory/Makefile index f8960992a0d..08682e5975e 100644 --- a/src/test/run-make/sanitizer-memory/Makefile +++ b/src/test/run-make/sanitizer-memory/Makefile @@ -1,9 +1,6 @@ -include ../tools.mk -# NOTE the memory sanitizer only supports x86_64 linux -ifndef IS_WINDOWS -ifeq ($(shell uname),Linux) -ifeq ($(shell uname -m),x86_64) +ifdef SANITIZER_SUPPORT all: $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | grep -q librustc_msan $(TMPDIR)/uninit 2>&1 | grep -q use-of-uninitialized-value @@ -11,11 +8,3 @@ else all: endif -else -all: - -endif -else -all: - -endif diff --git a/src/test/run-make/sanitizer-thread/Makefile b/src/test/run-make/sanitizer-thread/Makefile index e32247c4a9b..8bb89a241cb 100644 --- a/src/test/run-make/sanitizer-thread/Makefile +++ b/src/test/run-make/sanitizer-thread/Makefile @@ -1,9 +1,6 @@ -include ../tools.mk -# NOTE the leak sanitizer only supports x86_64 linux -ifndef IS_WINDOWS -ifeq ($(shell uname),Linux) -ifeq ($(shell uname -m),x86_64) +ifdef SANITIZER_SUPPORT all: $(RUSTC) -g -Z sanitizer=thread -Z print-link-args racy.rs | grep -q librustc_tsan $(TMPDIR)/racy 2>&1 | grep -q 'data race' @@ -11,11 +8,3 @@ else all: endif -else -all: - -endif -else -all: - -endif From 22097e6827b726f517e94c31df0728b481f57245 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 4 Feb 2017 20:10:29 -0500 Subject: [PATCH 3/8] use helper function in the rebuild logic of the rustc_*san crates --- src/Cargo.lock | 4 ++++ src/librustc_asan/Cargo.toml | 1 + src/librustc_asan/build.rs | 19 ++++--------------- src/librustc_lsan/Cargo.toml | 1 + src/librustc_lsan/build.rs | 19 ++++--------------- src/librustc_msan/Cargo.toml | 1 + src/librustc_msan/build.rs | 19 ++++--------------- src/librustc_tsan/Cargo.toml | 1 + src/librustc_tsan/build.rs | 19 ++++--------------- 9 files changed, 24 insertions(+), 60 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8e987ba3b7f..c1222dc444a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -273,6 +273,7 @@ name = "rustc_asan" version = "0.0.0" dependencies = [ "alloc_system 0.0.0", + "build_helper 0.1.0", "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -415,6 +416,7 @@ name = "rustc_lsan" version = "0.0.0" dependencies = [ "alloc_system 0.0.0", + "build_helper 0.1.0", "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -458,6 +460,7 @@ name = "rustc_msan" version = "0.0.0" dependencies = [ "alloc_system 0.0.0", + "build_helper 0.1.0", "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -548,6 +551,7 @@ name = "rustc_tsan" version = "0.0.0" dependencies = [ "alloc_system 0.0.0", + "build_helper 0.1.0", "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml index abbd7cc0966..2d4872b1fc9 100644 --- a/src/librustc_asan/Cargo.toml +++ b/src/librustc_asan/Cargo.toml @@ -9,6 +9,7 @@ name = "rustc_asan" path = "lib.rs" [build-dependencies] +build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index 3e33efcadb8..015be14bd49 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate build_helper; extern crate cmake; use std::path::PathBuf; @@ -29,21 +30,9 @@ fn main() { dst.join("build/lib/linux").display()); println!("cargo:rustc-link-lib=static=clang_rt.asan-x86_64"); - let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); - let mut stack = src_dir.join("../compiler-rt") - .read_dir() - .unwrap() - .map(|e| e.unwrap()) - .filter(|e| &*e.file_name() != ".git") - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } - } + build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR") + .unwrap()) + .join("../compiler-rt")); } println!("cargo:rerun-if-changed=build.rs"); diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml index ac53f3fe73a..bc1f2ead768 100644 --- a/src/librustc_lsan/Cargo.toml +++ b/src/librustc_lsan/Cargo.toml @@ -9,6 +9,7 @@ name = "rustc_lsan" path = "lib.rs" [build-dependencies] +build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs index f13928d2bd4..5773777d1f8 100644 --- a/src/librustc_lsan/build.rs +++ b/src/librustc_lsan/build.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate build_helper; extern crate cmake; use std::path::PathBuf; @@ -29,21 +30,9 @@ fn main() { dst.join("build/lib/linux").display()); println!("cargo:rustc-link-lib=static=clang_rt.lsan-x86_64"); - let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); - let mut stack = src_dir.join("../compiler-rt") - .read_dir() - .unwrap() - .map(|e| e.unwrap()) - .filter(|e| &*e.file_name() != ".git") - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } - } + build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR") + .unwrap()) + .join("../compiler-rt")); } println!("cargo:rerun-if-changed=build.rs"); diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml index 628746ac232..45cc6b9839f 100644 --- a/src/librustc_msan/Cargo.toml +++ b/src/librustc_msan/Cargo.toml @@ -9,6 +9,7 @@ name = "rustc_msan" path = "lib.rs" [build-dependencies] +build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs index bf630c7844a..7a4c8f70739 100644 --- a/src/librustc_msan/build.rs +++ b/src/librustc_msan/build.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate build_helper; extern crate cmake; use std::path::PathBuf; @@ -29,21 +30,9 @@ fn main() { dst.join("build/lib/linux").display()); println!("cargo:rustc-link-lib=static=clang_rt.msan-x86_64"); - let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); - let mut stack = src_dir.join("../compiler-rt") - .read_dir() - .unwrap() - .map(|e| e.unwrap()) - .filter(|e| &*e.file_name() != ".git") - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } - } + build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR") + .unwrap()) + .join("../compiler-rt")); } println!("cargo:rerun-if-changed=build.rs"); diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml index 2af0ae3f734..66d6236361e 100644 --- a/src/librustc_tsan/Cargo.toml +++ b/src/librustc_tsan/Cargo.toml @@ -9,6 +9,7 @@ name = "rustc_tsan" path = "lib.rs" [build-dependencies] +build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs index 2ba5866ab9d..84326ae8a71 100644 --- a/src/librustc_tsan/build.rs +++ b/src/librustc_tsan/build.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate build_helper; extern crate cmake; use std::path::PathBuf; @@ -29,21 +30,9 @@ fn main() { dst.join("build/lib/linux").display()); println!("cargo:rustc-link-lib=static=clang_rt.tsan-x86_64"); - let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); - let mut stack = src_dir.join("../compiler-rt") - .read_dir() - .unwrap() - .map(|e| e.unwrap()) - .filter(|e| &*e.file_name() != ".git") - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } - } + build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR") + .unwrap()) + .join("../compiler-rt")); } println!("cargo:rerun-if-changed=build.rs"); From 72058e4f4cff46daf5c60cbd7c7978734ecb13cc Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 4 Feb 2017 20:15:20 -0500 Subject: [PATCH 4/8] enable sanitizers on x86_64-linux releases --- src/ci/docker/dist-x86-linux/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/dist-x86-linux/Dockerfile b/src/ci/docker/dist-x86-linux/Dockerfile index 4e4f5dd6f1e..7238888a4af 100644 --- a/src/ci/docker/dist-x86-linux/Dockerfile +++ b/src/ci/docker/dist-x86-linux/Dockerfile @@ -76,5 +76,5 @@ RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | ENV HOSTS=i686-unknown-linux-gnu ENV HOSTS=$HOSTS,x86_64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended --enable-sanitizers ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS From 47ae2393e63e0d78118262b70245d34b8c8ba929 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 5 Feb 2017 19:09:32 -0500 Subject: [PATCH 5/8] enable sanitizers on build job that tests x86_64 linux --- src/ci/docker/x86_64-gnu/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index 6919487e17c..e903b6ddc64 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -22,5 +22,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu +ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers ENV SCRIPT python2.7 ../x.py test && python2.7 ../x.py dist From 1914c8e0aca19b844b14a8b8032bc9376c6d37f0 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 6 Feb 2017 14:12:56 -0500 Subject: [PATCH 6/8] dist-x86-linux: install newer kernel headers --- src/ci/docker/dist-x86-linux/Dockerfile | 5 ++++ src/ci/docker/dist-x86-linux/build-headers.sh | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100755 src/ci/docker/dist-x86-linux/build-headers.sh diff --git a/src/ci/docker/dist-x86-linux/Dockerfile b/src/ci/docker/dist-x86-linux/Dockerfile index 7238888a4af..a06e47c3bc9 100644 --- a/src/ci/docker/dist-x86-linux/Dockerfile +++ b/src/ci/docker/dist-x86-linux/Dockerfile @@ -63,6 +63,11 @@ RUN ./build-git.sh COPY build-cmake.sh /tmp/ RUN ./build-cmake.sh +# for sanitizers, we need kernel headers files newer than the ones CentOS ships +# with so we install newer ones here +COPY build-headers.sh /tmp/ +RUN ./build-headers.sh + RUN curl -Lo /rustroot/dumb-init \ https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \ chmod +x /rustroot/dumb-init diff --git a/src/ci/docker/dist-x86-linux/build-headers.sh b/src/ci/docker/dist-x86-linux/build-headers.sh new file mode 100755 index 00000000000..4ce38fd9205 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-headers.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright 2017 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +set -ex +source shared.sh + +curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x + +cd linux-3.2.84 +hide_output make mrproper +hide_output make INSTALL_HDR_PATH=dest headers_install + +find dest/include \( -name .install -o -name ..install.cmd \) -delete +yes | cp -fr dest/include/* /usr/include + +cd .. +rm -rf linux-3.2.84 From 78a11f1b97f3ab3fa8c9e225f800489051777bc4 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 7 Feb 2017 22:47:03 -0500 Subject: [PATCH 7/8] fix the sanitizer-dylib test on non x86_64 linux hosts --- src/test/run-make/sanitizer-dylib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make/sanitizer-dylib/Makefile b/src/test/run-make/sanitizer-dylib/Makefile index 70a8254a6a6..34fdf3b9709 100644 --- a/src/test/run-make/sanitizer-dylib/Makefile +++ b/src/test/run-make/sanitizer-dylib/Makefile @@ -1,4 +1,4 @@ -include ../tools.mk all: - $(RUSTC) -Z sanitizer=leak --crate-type dylib hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' + $(RUSTC) -Z sanitizer=leak --crate-type dylib --target x86_64-unknown-linux-gnu hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' From e180dd541a8ae48e4aaf8934765f67955932252f Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 8 Feb 2017 22:58:53 -0500 Subject: [PATCH 8/8] sanitizer-dylib: only run where std for x86_64-linux is available --- src/test/run-make/sanitizer-dylib/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/run-make/sanitizer-dylib/Makefile b/src/test/run-make/sanitizer-dylib/Makefile index 34fdf3b9709..835d5b0d9d8 100644 --- a/src/test/run-make/sanitizer-dylib/Makefile +++ b/src/test/run-make/sanitizer-dylib/Makefile @@ -1,4 +1,8 @@ -include ../tools.mk +ifeq ($(TARGET),x86_64-unknown-linux-gnu) all: - $(RUSTC) -Z sanitizer=leak --crate-type dylib --target x86_64-unknown-linux-gnu hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' + $(RUSTC) -Z sanitizer=leak --crate-type dylib --target $(TARGET) hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`' +else +all: +endif