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"
+++ /dev/null
-# rustbuild-only target
+++ /dev/null
-# rustbuild-only target
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",
+ "build_helper 0.1.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"
"rustc_bitflags 0.0.0",
]
+[[package]]
+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",
+]
+
[[package]]
name = "rustc_metadata"
version = "0.0.0"
"syntax_pos 0.0.0",
]
+[[package]]
+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",
+]
+
[[package]]
name = "rustc_passes"
version = "0.0.0"
"syntax_pos 0.0.0",
]
+[[package]]
+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",
+]
+
[[package]]
name = "rustc_typeck"
version = "0.0.0"
"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",
]
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") {
if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
features.push_str(" force_alloc_system");
}
+
+ 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 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)
.arg("--manifest-path")
.arg(build.src.join("src/rustc/std_shim/Cargo.toml"));
pub target_config: HashMap<String, Target>,
pub full_bootstrap: bool,
pub extended: bool,
+ pub sanitizers: bool,
// llvm codegen options
pub llvm_assertions: bool,
python: Option<String>,
full_bootstrap: Option<bool>,
extended: Option<bool>,
+ sanitizers: Option<bool>,
}
/// TOML representation of various global install decisions.
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);
("VENDOR", self.vendor),
("FULL_BOOTSTRAP", self.full_bootstrap),
("EXTENDED", self.extended),
+ ("SANITIZERS", self.sanitizers),
}
match key {
# disabled by default.
#extended = false
+# Build the sanitizer runtimes
+#sanitizers = false
+
# =============================================================================
# General install configuration options
# =============================================================================
let branch = match &build.config.channel[..] {
"stable" |
- "beta" => {
- build.release.split(".").take(2).collect::<Vec<_>>().join(".")
- }
+ "beta" => format!("rust-{}", build.release_num),
_ => "master".to_string(),
};
/// 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");
}
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
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
--- /dev/null
+#!/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 <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.
+
+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
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
-Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
+Subproject commit d30da544a8afc5d78391dee270bdf40e74a215d3
Constant values must not have destructors, and otherwise permit most forms of
data. Constants may refer to the address of other constants, in which case the
-address will have the `static` lifetime. The compiler is, however, still at
-liberty to translate the constant many times, so the address referred to may not
-be stable.
+address will have elided lifetimes where applicable, otherwise – in most cases –
+defaulting to the `static` lifetime. (See below on [static lifetime elision].)
+The compiler is, however, still at liberty to translate the constant many times,
+so the address referred to may not be stable.
+
+[static lifetime elision]: #static-lifetime-elision
Constants must be explicitly typed. The type may be `bool`, `char`, a number, or
a type derived from those primitive types. The derived types are references with
the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs.
-```
+```rust
const BIT1: u32 = 1 << 0;
const BIT2: u32 = 1 << 1;
};
```
+
+
### Static items
A *static item* is similar to a *constant*, except that it represents a precise
Mutable statics are still very useful, however. They can be used with C
libraries and can also be bound from C libraries (in an `extern` block).
-```
+```rust
# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 }
static mut LEVELS: u32 = 0;
Mutable statics have the same restrictions as normal statics, except that the
type of the value is not required to ascribe to `Sync`.
+#### `'static` lifetime elision
+
+[Unstable] Both constant and static declarations of reference types have
+*implicit* `'static` lifetimes unless an explicit lifetime is specified. As
+such, the constant declarations involving `'static` above may be written
+without the lifetimes. Returning to our previous example:
+
+```rust
+# #![feature(static_in_const)]
+const BIT1: u32 = 1 << 0;
+const BIT2: u32 = 1 << 1;
+
+const BITS: [u32; 2] = [BIT1, BIT2];
+const STRING: &str = "bitstring";
+
+struct BitsNStrings<'a> {
+ mybits: [u32; 2],
+ mystring: &'a str,
+}
+
+const BITS_N_STRINGS: BitsNStrings = BitsNStrings {
+ mybits: BITS,
+ mystring: STRING,
+};
+```
+
+Note that if the `static` or `const` items include function or closure
+references, which themselves include references, the compiler will first try the
+standard elision rules ([see discussion in the nomicon][elision-nomicon]). If it
+is unable to resolve the lifetimes by its usual rules, it will default to using
+the `'static` lifetime. By way of example:
+
+[elision-nomicon]: https://doc.rust-lang.org/nomicon/lifetime-elision.html
+
+```rust,ignore
+// Resolved as `fn<'a>(&'a str) -> &'a str`.
+const RESOLVED_SINGLE: fn(&str) -> &str = ..
+
+// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
+const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = ..
+
+// There is insufficient information to bound the return reference lifetime
+// relative to the argument lifetimes, so the signature is resolved as
+// `Fn(&'static Foo, &'static Bar) -> &'static Baz`.
+const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = ..
+```
+
### Traits
A _trait_ describes an abstract interface that types can
### Miscellaneous attributes
-- `deprecated` - mark the item as deprecated; the full attribute is `#[deprecated(since = "crate version", note = "...")`, where both arguments are optional.
+- `deprecated` - mark the item as deprecated; the full attribute is
+ `#[deprecated(since = "crate version", note = "...")`, where both arguments
+ are optional.
- `export_name` - on statics and functions, this determines the name of the
exported symbol.
- `link_section` - on statics and functions, this specifies the section of the
into a Rust program. This capability, especially the signature for the
annotated function, is subject to change.
-* `static_in_const` - Enables lifetime elision with a `'static` default for
- `const` and `static` item declarations.
-
* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
and should be seen as unstable. This attribute is used to
declare a `static` as being unique per-thread leveraging
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<ExternCrate>;
/// The name of the crate as it is referred to in source code of the current
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")
}
pub uint_type: UintTy,
}
+#[derive(Clone)]
+pub enum Sanitizer {
+ Address,
+ Leak,
+ Memory,
+ Thread,
+}
+
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum OptLevel {
No, // -O0
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;
$(
}
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
+ }
}
) }
"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<Sanitizer> = (None, parse_sanitizer, [UNTRACKED],
+ "Use a sanitizer"),
}
pub fn default_lib_output() -> CrateType {
--- /dev/null
+[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]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
--- /dev/null
+// 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 build_helper;
+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");
+
+ 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");
+}
--- /dev/null
+// 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;
UWTable = 17,
ZExt = 18,
InReg = 19,
+ SanitizeThread = 20,
+ SanitizeAddress = 21,
+ SanitizeMemory = 22,
}
/// LLVMIntPredicate
--- /dev/null
+[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]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
--- /dev/null
+// 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 build_helper;
+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");
+
+ 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");
+}
--- /dev/null
+// 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;
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;
&|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!
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);
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")
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()
}
--- /dev/null
+[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]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
--- /dev/null
+// 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 build_helper;
+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");
+
+ 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");
+}
--- /dev/null
+// 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;
// 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) => {
}
}
+ // 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)
}
}
+ // 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:
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;
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));
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;
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
--- /dev/null
+[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]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
--- /dev/null
+// 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 build_helper;
+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");
+
+ 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");
+}
--- /dev/null
+// 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;
}
_ => {
if f.alternate() {
- write!(f, "&{}{}{:#}", lt, m, **ty)
+ write!(f, "&{}{}", lt, m)?;
+ fmt_type(&ty, f, use_absolute)
} else {
- write!(f, "&{}{}{}", lt, m, **ty)
+ write!(f, "&{}{}", lt, m)?;
+ fmt_type(&ty, f, use_absolute)
}
}
}
<ul class='item-list' id='implementors-list'>
")?;
if let Some(implementors) = cache.implementors.get(&it.def_id) {
- let mut implementor_count: FxHashMap<&str, usize> = FxHashMap();
+ // The DefId is for the first Type found with that name. The bool is
+ // if any Types with the same name but different DefId have been found.
+ let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
for implementor in implementors {
- if let clean::Type::ResolvedPath {ref path, ..} = implementor.impl_.for_ {
- *implementor_count.entry(path.last_name()).or_insert(0) += 1;
+ match implementor.impl_.for_ {
+ clean::ResolvedPath { ref path, did, is_generic: false, .. } |
+ clean::BorrowedRef {
+ type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
+ ..
+ } => {
+ let &mut (prev_did, ref mut has_duplicates) =
+ implementor_dups.entry(path.last_name()).or_insert((did, false));
+ if prev_did != did {
+ *has_duplicates = true;
+ }
+ }
+ _ => {}
}
}
write!(w, "<li><code>")?;
// If there's already another implementor that has the same abbridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
- let use_absolute = if let clean::Type::ResolvedPath {
- ref path, ..
- } = implementor.impl_.for_ {
- implementor_count[path.last_name()] > 1
- } else {
- false
+ let use_absolute = match implementor.impl_.for_ {
+ clean::ResolvedPath { ref path, is_generic: false, .. } |
+ clean::BorrowedRef {
+ type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
+ ..
+ } => implementor_dups[path.last_name()].1,
+ _ => false,
};
fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
writeln!(w, "</code></li>")?;
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"]
inner: os_imp::JoinPathsError
}
-/// Joins a collection of `Path`s appropriately for the `PATH`
+/// Joins a collection of [`Path`]s appropriately for the `PATH`
/// environment variable.
///
-/// Returns an `OsString` on success.
+/// Returns an [`OsString`] on success.
///
-/// Returns an `Err` (containing an error message) if one of the input
-/// `Path`s contains an invalid character for constructing the `PATH`
+/// Returns an [`Err`][err] (containing an error message) if one of the input
+/// [`Path`]s contains an invalid character for constructing the `PATH`
/// variable (a double quote on Windows or a colon on Unix).
///
+/// [`Path`]: ../../std/path/struct.Path.html
+/// [`OsString`]: ../../std/ffi/struct.OsString.html
+/// [err]: ../../std/result/enum.Result.html#variant.Err
+///
/// # Examples
///
/// ```
// `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! (
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",
# 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"]
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");
}
UWTable = 17,
ZExt = 18,
InReg = 19,
+ SanitizeThread = 20,
+ SanitizeAddress = 21,
+ SanitizeMemory = 22,
};
typedef struct OpaqueRustString *RustStringRef;
--- /dev/null
+// 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() {}
--- /dev/null
+// 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 foo = 42u32;
+ const FOO : u32 = foo;
+ //~^ ERROR attempt to use a non-constant value in a constant
+}
--- /dev/null
+-include ../tools.mk
+
+# NOTE the address sanitizer only supports x86_64 linux
+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
+else
+all:
+
+endif
--- /dev/null
+// 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) };
+}
--- /dev/null
+-include ../tools.mk
+
+ifeq ($(TARGET),x86_64-unknown-linux-gnu)
+all:
+ $(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
--- /dev/null
+// 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!");
+}
--- /dev/null
+-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'
--- /dev/null
+// 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]
--- /dev/null
+-include ../tools.mk
+
+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'
+else
+all:
+
+endif
--- /dev/null
+// 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);
+}
--- /dev/null
+-include ../tools.mk
+
+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
+else
+all:
+
+endif
--- /dev/null
+// 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];
+}
--- /dev/null
+-include ../tools.mk
+
+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'
+else
+all:
+
+endif
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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.
+
+#![crate_name = "foo"]
+
+pub trait Foo {}
+
+pub struct Bar<T> { field: T }
+
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// "impl Foo for Bar<u8>"
+impl Foo for Bar<u8> {}
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// "impl Foo for Bar<u16>"
+impl Foo for Bar<u16> {}
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// "impl<'a> Foo for &'a Bar<u8>"
+impl<'a> Foo for &'a Bar<u8> {}
+
+pub mod mod1 {
+ pub struct Baz {}
+}
+
+pub mod mod2 {
+ pub enum Baz {}
+}
+
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// "impl Foo for foo::mod1::Baz"
+impl Foo for mod1::Baz {}
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+// "impl<'a> Foo for &'a foo::mod2::Baz"
+impl<'a> Foo for &'a mod2::Baz {}
fn filename(&self, component: &str, target: &str) -> String {
if component == "rust-src" {
format!("rust-src-{}.tar.gz", self.channel)
+ } else if component == "cargo" {
+ format!("cargo-nightly-{}.tar.gz", target)
} else {
format!("{}-{}-{}.tar.gz", component, self.channel, target)
}