sanitizer support
This commit is contained in:
parent
c14f87e3b0
commit
9af6aa3889
45 changed files with 810 additions and 6 deletions
40
src/Cargo.lock
generated
40
src/Cargo.lock
generated
|
@ -268,6 +268,15 @@ name = "rustc-serialize"
|
||||||
version = "0.3.19"
|
version = "0.3.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "rustc_back"
|
name = "rustc_back"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -401,6 +410,15 @@ dependencies = [
|
||||||
"rustc_bitflags 0.0.0",
|
"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]]
|
[[package]]
|
||||||
name = "rustc_metadata"
|
name = "rustc_metadata"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -435,6 +453,15 @@ dependencies = [
|
||||||
"syntax_pos 0.0.0",
|
"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]]
|
[[package]]
|
||||||
name = "rustc_passes"
|
name = "rustc_passes"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -516,6 +543,15 @@ dependencies = [
|
||||||
"syntax_pos 0.0.0",
|
"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]]
|
[[package]]
|
||||||
name = "rustc_typeck"
|
name = "rustc_typeck"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -577,6 +613,10 @@ dependencies = [
|
||||||
"panic_abort 0.0.0",
|
"panic_abort 0.0.0",
|
||||||
"panic_unwind 0.0.0",
|
"panic_unwind 0.0.0",
|
||||||
"rand 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",
|
"std_unicode 0.0.0",
|
||||||
"unwind 0.0.0",
|
"unwind 0.0.0",
|
||||||
]
|
]
|
||||||
|
|
|
@ -332,7 +332,10 @@ pub fn krate(build: &Build,
|
||||||
krate: Option<&str>) {
|
krate: Option<&str>) {
|
||||||
let (name, path, features, root) = match mode {
|
let (name, path, features, root) = match mode {
|
||||||
Mode::Libstd => {
|
Mode::Libstd => {
|
||||||
("libstd", "src/rustc/std_shim", build.std_features(), "std_shim")
|
("libstd",
|
||||||
|
"src/rustc/std_shim",
|
||||||
|
build.std_features(),
|
||||||
|
"std_shim")
|
||||||
}
|
}
|
||||||
Mode::Libtest => {
|
Mode::Libtest => {
|
||||||
("libtest", "src/rustc/test_shim", String::new(), "test_shim")
|
("libtest", "src/rustc/test_shim", String::new(), "test_shim")
|
||||||
|
|
|
@ -51,6 +51,18 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
|
||||||
if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
|
if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
|
||||||
features.push_str(" force_alloc_system");
|
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)
|
cargo.arg("--features").arg(features)
|
||||||
.arg("--manifest-path")
|
.arg("--manifest-path")
|
||||||
.arg(build.src.join("src/rustc/std_shim/Cargo.toml"));
|
.arg(build.src.join("src/rustc/std_shim/Cargo.toml"));
|
||||||
|
|
|
@ -108,6 +108,8 @@ pub struct Config {
|
||||||
/// Per-target configuration stored in the global configuration structure.
|
/// Per-target configuration stored in the global configuration structure.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Target {
|
pub struct Target {
|
||||||
|
// `true` if compiling against system LLVM or a pre-built LLVM
|
||||||
|
pub system_llvm: bool,
|
||||||
pub llvm_config: Option<PathBuf>,
|
pub llvm_config: Option<PathBuf>,
|
||||||
pub jemalloc: Option<PathBuf>,
|
pub jemalloc: Option<PathBuf>,
|
||||||
pub cc: Option<PathBuf>,
|
pub cc: Option<PathBuf>,
|
||||||
|
@ -512,6 +514,7 @@ impl Config {
|
||||||
.or_insert(Target::default());
|
.or_insert(Target::default());
|
||||||
let root = parse_configure_path(value);
|
let root = parse_configure_path(value);
|
||||||
target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"]));
|
target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"]));
|
||||||
|
target.system_llvm = true;
|
||||||
}
|
}
|
||||||
"CFG_JEMALLOC_ROOT" if value.len() > 0 => {
|
"CFG_JEMALLOC_ROOT" if value.len() > 0 => {
|
||||||
let target = self.target_config.entry(self.build.clone())
|
let target = self.target_config.entry(self.build.clone())
|
||||||
|
|
|
@ -599,7 +599,8 @@ impl Build {
|
||||||
/// Get the space-separated set of activated features for the standard
|
/// Get the space-separated set of activated features for the standard
|
||||||
/// library.
|
/// library.
|
||||||
fn std_features(&self) -> String {
|
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 {
|
if self.config.debug_jemalloc {
|
||||||
features.push_str(" 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
|
/// Returns the path to `FileCheck` binary for the specified target
|
||||||
fn llvm_filecheck(&self, target: &str) -> PathBuf {
|
fn llvm_filecheck(&self, target: &str) -> PathBuf {
|
||||||
let target_config = self.config.target_config.get(target);
|
let target_config = self.config.target_config.get(target);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
|
Subproject commit d30da544a8afc5d78391dee270bdf40e74a215d3
|
|
@ -229,6 +229,7 @@ pub trait CrateStore<'tcx> {
|
||||||
fn is_allocator(&self, cnum: CrateNum) -> bool;
|
fn is_allocator(&self, cnum: CrateNum) -> bool;
|
||||||
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
|
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
|
||||||
fn is_compiler_builtins(&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 panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
|
||||||
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
|
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
|
||||||
/// The name of the crate as it is referred to in source code of the current
|
/// 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_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
|
||||||
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
|
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_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 {
|
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
|
||||||
bug!("panic_strategy")
|
bug!("panic_strategy")
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,14 @@ pub struct Config {
|
||||||
pub uint_type: UintTy,
|
pub uint_type: UintTy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Sanitizer {
|
||||||
|
Address,
|
||||||
|
Leak,
|
||||||
|
Memory,
|
||||||
|
Thread,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Hash)]
|
||||||
pub enum OptLevel {
|
pub enum OptLevel {
|
||||||
No, // -O0
|
No, // -O0
|
||||||
|
@ -626,11 +634,13 @@ macro_rules! options {
|
||||||
Some("a number");
|
Some("a number");
|
||||||
pub const parse_panic_strategy: Option<&'static str> =
|
pub const parse_panic_strategy: Option<&'static str> =
|
||||||
Some("either `panic` or `abort`");
|
Some("either `panic` or `abort`");
|
||||||
|
pub const parse_sanitizer: Option<&'static str> =
|
||||||
|
Some("one of: `address`, `leak`, `memory` or `thread`");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
mod $mod_set {
|
mod $mod_set {
|
||||||
use super::{$struct_name, Passes, SomePasses, AllPasses};
|
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
|
||||||
use rustc_back::PanicStrategy;
|
use rustc_back::PanicStrategy;
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
@ -751,6 +761,17 @@ macro_rules! options {
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_sanitizer(slote: &mut Option<Sanitizer>, 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"),
|
"encode MIR of all functions into the crate metadata"),
|
||||||
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
|
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
|
||||||
"pass `-install_name @rpath/...` to the OSX linker"),
|
"pass `-install_name @rpath/...` to the OSX linker"),
|
||||||
|
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [UNTRACKED],
|
||||||
|
"Use a sanitizer"),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_lib_output() -> CrateType {
|
pub fn default_lib_output() -> CrateType {
|
||||||
|
|
16
src/librustc_asan/Cargo.toml
Normal file
16
src/librustc_asan/Cargo.toml
Normal file
|
@ -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" }
|
50
src/librustc_asan/build.rs
Normal file
50
src/librustc_asan/build.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Vec<_>>();
|
||||||
|
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");
|
||||||
|
}
|
20
src/librustc_asan/lib.rs
Normal file
20
src/librustc_asan/lib.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
|
|
@ -126,6 +126,9 @@ pub enum Attribute {
|
||||||
UWTable = 17,
|
UWTable = 17,
|
||||||
ZExt = 18,
|
ZExt = 18,
|
||||||
InReg = 19,
|
InReg = 19,
|
||||||
|
SanitizeThread = 20,
|
||||||
|
SanitizeAddress = 21,
|
||||||
|
SanitizeMemory = 22,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LLVMIntPredicate
|
/// LLVMIntPredicate
|
||||||
|
|
16
src/librustc_lsan/Cargo.toml
Normal file
16
src/librustc_lsan/Cargo.toml
Normal file
|
@ -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" }
|
50
src/librustc_lsan/build.rs
Normal file
50
src/librustc_lsan/build.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Vec<_>>();
|
||||||
|
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");
|
||||||
|
}
|
20
src/librustc_lsan/lib.rs
Normal file
20
src/librustc_lsan/lib.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
|
|
@ -17,7 +17,8 @@ use schema::CrateRoot;
|
||||||
use rustc::hir::def_id::{CrateNum, DefIndex};
|
use rustc::hir::def_id::{CrateNum, DefIndex};
|
||||||
use rustc::hir::svh::Svh;
|
use rustc::hir::svh::Svh;
|
||||||
use rustc::middle::cstore::DepKind;
|
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_back::PanicStrategy;
|
||||||
use rustc::session::search_paths::PathKind;
|
use rustc::session::search_paths::PathKind;
|
||||||
use rustc::middle;
|
use rustc::middle;
|
||||||
|
@ -786,6 +787,64 @@ impl<'a> CrateLoader<'a> {
|
||||||
&|data| data.needs_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 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) {
|
fn inject_allocator_crate(&mut self) {
|
||||||
// Make sure that we actually need an allocator, if none of our
|
// Make sure that we actually need an allocator, if none of our
|
||||||
// dependencies need one then we definitely don't!
|
// dependencies need one then we definitely don't!
|
||||||
|
@ -982,6 +1041,9 @@ impl<'a> CrateLoader<'a> {
|
||||||
|
|
||||||
impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
|
impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
|
||||||
fn postprocess(&mut self, krate: &ast::Crate) {
|
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_allocator_crate();
|
||||||
self.inject_panic_runtime(krate);
|
self.inject_panic_runtime(krate);
|
||||||
|
|
||||||
|
|
|
@ -297,6 +297,11 @@ impl CrateMetadata {
|
||||||
attr::contains_name(&attrs, "compiler_builtins")
|
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 {
|
pub fn is_no_builtins(&self) -> bool {
|
||||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||||
attr::contains_name(&attrs, "no_builtins")
|
attr::contains_name(&attrs, "no_builtins")
|
||||||
|
|
|
@ -297,6 +297,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||||
self.get_crate_data(cnum).is_compiler_builtins()
|
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 {
|
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
|
||||||
self.get_crate_data(cnum).panic_strategy()
|
self.get_crate_data(cnum).panic_strategy()
|
||||||
}
|
}
|
||||||
|
|
16
src/librustc_msan/Cargo.toml
Normal file
16
src/librustc_msan/Cargo.toml
Normal file
|
@ -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" }
|
50
src/librustc_msan/build.rs
Normal file
50
src/librustc_msan/build.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Vec<_>>();
|
||||||
|
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");
|
||||||
|
}
|
20
src/librustc_msan/lib.rs
Normal file
20
src/librustc_msan/lib.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
|
|
@ -1031,6 +1031,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// symbols from the dylib.
|
// symbols from the dylib.
|
||||||
let src = sess.cstore.used_crate_source(cnum);
|
let src = sess.cstore.used_crate_source(cnum);
|
||||||
match data[cnum.as_usize() - 1] {
|
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
|
// compiler-builtins are always placed last to ensure that they're
|
||||||
// linked correctly.
|
// linked correctly.
|
||||||
_ if sess.cstore.is_compiler_builtins(cnum) => {
|
_ 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
|
// 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`
|
// was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic`
|
||||||
// is used)
|
// 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.
|
// 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
|
// There's a bit of magic which happens here specifically related to LTO and
|
||||||
// dynamic libraries. Specifically:
|
// dynamic libraries. Specifically:
|
||||||
|
|
|
@ -12,7 +12,7 @@ use back::lto;
|
||||||
use back::link::{get_linker, remove};
|
use back::link::{get_linker, remove};
|
||||||
use back::symbol_export::ExportedSymbols;
|
use back::symbol_export::ExportedSymbols;
|
||||||
use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
|
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::Session;
|
||||||
use session::config::{self, OutputType};
|
use session::config::{self, OutputType};
|
||||||
use llvm;
|
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 modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone());
|
||||||
let mut metadata_config = ModuleConfig::new(tm, vec![]);
|
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_level = Some(get_llvm_opt_level(sess.opts.optimize));
|
||||||
modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));
|
modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
use llvm::{self, ValueRef};
|
use llvm::{self, ValueRef};
|
||||||
use llvm::AttributePlace::Function;
|
use llvm::AttributePlace::Function;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
|
use rustc::session::config::Sanitizer;
|
||||||
use abi::{Abi, FnType};
|
use abi::{Abi, FnType};
|
||||||
use attributes;
|
use attributes;
|
||||||
use context::CrateContext;
|
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);
|
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
|
// If we're compiling the compiler-builtins crate, e.g. the equivalent of
|
||||||
// compiler-rt, then we want to implicitly compile everything with hidden
|
// 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
|
// visibility as we're going to link this object all over the place but
|
||||||
|
|
16
src/librustc_tsan/Cargo.toml
Normal file
16
src/librustc_tsan/Cargo.toml
Normal file
|
@ -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" }
|
50
src/librustc_tsan/build.rs
Normal file
50
src/librustc_tsan/build.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Vec<_>>();
|
||||||
|
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");
|
||||||
|
}
|
20
src/librustc_tsan/lib.rs
Normal file
20
src/librustc_tsan/lib.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
|
|
@ -23,13 +23,23 @@ compiler_builtins = { path = "../libcompiler_builtins" }
|
||||||
std_unicode = { path = "../libstd_unicode" }
|
std_unicode = { path = "../libstd_unicode" }
|
||||||
unwind = { path = "../libunwind" }
|
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-dependencies]
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../build_helper" }
|
||||||
gcc = "0.3.27"
|
gcc = "0.3.27"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
asan = ["rustc_asan"]
|
||||||
backtrace = []
|
backtrace = []
|
||||||
debug-jemalloc = ["alloc_jemalloc/debug"]
|
debug-jemalloc = ["alloc_jemalloc/debug"]
|
||||||
jemalloc = ["alloc_jemalloc"]
|
jemalloc = ["alloc_jemalloc"]
|
||||||
force_alloc_system = []
|
force_alloc_system = []
|
||||||
|
lsan = ["rustc_lsan"]
|
||||||
|
msan = ["rustc_msan"]
|
||||||
panic-unwind = ["panic_unwind"]
|
panic-unwind = ["panic_unwind"]
|
||||||
|
tsan = ["rustc_tsan"]
|
||||||
|
|
|
@ -328,6 +328,10 @@ declare_features! (
|
||||||
|
|
||||||
// `extern "msp430-interrupt" fn()`
|
// `extern "msp430-interrupt" fn()`
|
||||||
(active, abi_msp430_interrupt, "1.16.0", Some(38487)),
|
(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! (
|
declare_features! (
|
||||||
|
@ -647,6 +651,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
||||||
contains compiler-rt intrinsics and will never be \
|
contains compiler-rt intrinsics and will never be \
|
||||||
stable",
|
stable",
|
||||||
cfg_fn!(compiler_builtins))),
|
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", Normal, Gated(Stability::Unstable,
|
||||||
"allow_internal_unstable",
|
"allow_internal_unstable",
|
||||||
|
|
|
@ -35,8 +35,12 @@ core = { path = "../../libcore" }
|
||||||
|
|
||||||
# Reexport features from std
|
# Reexport features from std
|
||||||
[features]
|
[features]
|
||||||
|
asan = ["std/asan"]
|
||||||
backtrace = ["std/backtrace"]
|
backtrace = ["std/backtrace"]
|
||||||
debug-jemalloc = ["std/debug-jemalloc"]
|
debug-jemalloc = ["std/debug-jemalloc"]
|
||||||
jemalloc = ["std/jemalloc"]
|
jemalloc = ["std/jemalloc"]
|
||||||
force_alloc_system = ["std/force_alloc_system"]
|
force_alloc_system = ["std/force_alloc_system"]
|
||||||
|
lsan = ["std/lsan"]
|
||||||
|
msan = ["std/msan"]
|
||||||
panic-unwind = ["std/panic-unwind"]
|
panic-unwind = ["std/panic-unwind"]
|
||||||
|
tsan = ["std/tsan"]
|
||||||
|
|
|
@ -148,6 +148,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
||||||
return Attribute::ZExt;
|
return Attribute::ZExt;
|
||||||
case InReg:
|
case InReg:
|
||||||
return Attribute::InReg;
|
return Attribute::InReg;
|
||||||
|
case SanitizeThread:
|
||||||
|
return Attribute::SanitizeThread;
|
||||||
|
case SanitizeAddress:
|
||||||
|
return Attribute::SanitizeAddress;
|
||||||
|
case SanitizeMemory:
|
||||||
|
return Attribute::SanitizeMemory;
|
||||||
}
|
}
|
||||||
llvm_unreachable("bad AttributeKind");
|
llvm_unreachable("bad AttributeKind");
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,9 @@ enum LLVMRustAttribute {
|
||||||
UWTable = 17,
|
UWTable = 17,
|
||||||
ZExt = 18,
|
ZExt = 18,
|
||||||
InReg = 19,
|
InReg = 19,
|
||||||
|
SanitizeThread = 20,
|
||||||
|
SanitizeAddress = 21,
|
||||||
|
SanitizeMemory = 22,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct OpaqueRustString *RustStringRef;
|
typedef struct OpaqueRustString *RustStringRef;
|
||||||
|
|
13
src/test/compile-fail/feature-gate-sanitizer-runtime.rs
Normal file
13
src/test/compile-fail/feature-gate-sanitizer-runtime.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
|
21
src/test/run-make/sanitizer-address/Makefile
Normal file
21
src/test/run-make/sanitizer-address/Makefile
Normal file
|
@ -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
|
14
src/test/run-make/sanitizer-address/overflow.rs
Normal file
14
src/test/run-make/sanitizer-address/overflow.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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) };
|
||||||
|
}
|
4
src/test/run-make/sanitizer-dylib/Makefile
Normal file
4
src/test/run-make/sanitizer-dylib/Makefile
Normal file
|
@ -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`'
|
13
src/test/run-make/sanitizer-dylib/hello.rs
Normal file
13
src/test/run-make/sanitizer-dylib/hello.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
4
src/test/run-make/sanitizer-invalid-target/Makefile
Normal file
4
src/test/run-make/sanitizer-invalid-target/Makefile
Normal file
|
@ -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'
|
13
src/test/run-make/sanitizer-invalid-target/hello.rs
Normal file
13
src/test/run-make/sanitizer-invalid-target/hello.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(no_core)]
|
||||||
|
#![no_core]
|
||||||
|
#![no_main]
|
23
src/test/run-make/sanitizer-leak/Makefile
Normal file
23
src/test/run-make/sanitizer-leak/Makefile
Normal file
|
@ -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
|
16
src/test/run-make/sanitizer-leak/leak.rs
Normal file
16
src/test/run-make/sanitizer-leak/leak.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
|
||||||
|
}
|
21
src/test/run-make/sanitizer-memory/Makefile
Normal file
21
src/test/run-make/sanitizer-memory/Makefile
Normal file
|
@ -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
|
16
src/test/run-make/sanitizer-memory/uninit.rs
Normal file
16
src/test/run-make/sanitizer-memory/uninit.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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];
|
||||||
|
}
|
21
src/test/run-make/sanitizer-thread/Makefile
Normal file
21
src/test/run-make/sanitizer-thread/Makefile
Normal file
|
@ -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
|
21
src/test/run-make/sanitizer-thread/racy.rs
Normal file
21
src/test/run-make/sanitizer-thread/racy.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue