Skip to content

Commit

Permalink
Auto merge of rust-lang#81866 - nagisa:nagisa/sanitizer-support-targe…
Browse files Browse the repository at this point in the history
…t-prop, r=tmiasko

Maintain supported sanitizers as a target property

In an effort to remove a hard-coded allow-list for target-sanitizer support correspondence, this PR moves the configuration to the target options.

Perhaps the one notable change made in this PR is this doc-comment:

```rust
    /// The sanitizers supported by this target
    ///
    /// Note that the support here is at a codegen level. If the machine code with sanitizer
    /// enabled can generated on this target, but the necessary supporting libraries are not
    /// distributed with the target, the sanitizer should still appear in this list for the target.
```

Previously the target would typically be added to the allow-list at the same time as the supporting runtime libraries are shipped for the target. However whether we ship the runtime libraries or not needn't be baked into the compiler; and if we don't users will receive a significantly more directed error about library not being found.

Fixes rust-lang#81802
  • Loading branch information
bors committed Apr 2, 2021
2 parents 138fd56 + 41875c8 commit 9b6c9b6
Show file tree
Hide file tree
Showing 24 changed files with 216 additions and 203 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::config::{OptLevel, SanitizerSet};
use rustc_session::config::OptLevel;
use rustc_session::Session;
use rustc_target::spec::StackProbeType;
use rustc_target::spec::{SanitizerSet, StackProbeType};

use crate::attributes;
use crate::llvm::AttributePlace::Function;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath};
use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath};
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::InnerSpan;
use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo};
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo};
use tracing::debug;

use libc::{c_char, c_int, c_uint, c_void, size_t};
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ use rustc_middle::middle::cstore::EncodedMetadata;
use rustc_middle::middle::exported_symbols;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{DebugInfo, SanitizerSet};
use rustc_session::config::DebugInfo;
use rustc_span::symbol::Symbol;
use rustc_target::spec::SanitizerSet;

use std::ffi::CString;
use std::time::Instant;
Expand Down
40 changes: 16 additions & 24 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_hir::def_id::CrateNum;
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
Expand All @@ -16,7 +16,7 @@ use rustc_session::{filesearch, Session};
use rustc_span::symbol::Symbol;
use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target};
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};

use super::archive::ArchiveBuilder;
use super::command::Command;
Expand Down Expand Up @@ -922,28 +922,20 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
.map(|channel| format!("-{}", channel))
.unwrap_or_default();

match sess.opts.target_triple.triple() {
"aarch64-apple-darwin" | "x86_64-apple-darwin" => {
// On Apple platforms, the sanitizer is always built as a dylib, and
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
// rpath to the library as well (the rpath should be absolute, see
// PR #41352 for details).
let filename = format!("rustc{}_rt.{}", channel, name);
let path = find_sanitizer_runtime(&sess, &filename);
let rpath = path.to_str().expect("non-utf8 component in path");
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
linker.link_dylib(Symbol::intern(&filename));
}
"aarch64-fuchsia"
| "aarch64-unknown-linux-gnu"
| "x86_64-fuchsia"
| "x86_64-unknown-freebsd"
| "x86_64-unknown-linux-gnu" => {
let filename = format!("librustc{}_rt.{}.a", channel, name);
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
linker.link_whole_rlib(&path);
}
_ => {}
if sess.target.is_like_osx {
// On Apple platforms, the sanitizer is always built as a dylib, and
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
// rpath to the library as well (the rpath should be absolute, see
// PR #41352 for details).
let filename = format!("rustc{}_rt.{}", channel, name);
let path = find_sanitizer_runtime(&sess, &filename);
let rpath = path.to_str().expect("non-utf8 component in path");
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
linker.link_dylib(Symbol::intern(&filename));
} else {
let filename = format!("librustc{}_rt.{}.a", channel, name);
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
linker.link_whole_rlib(&path);
}
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::Instance;
use rustc_middle::ty::{SymbolName, TyCtxt};
use rustc_session::config::{CrateType, SanitizerSet};
use rustc_session::config::CrateType;
use rustc_target::spec::SanitizerSet;

pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
crates_export_threshold(&tcx.sess.crate_types())
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel;
use rustc_middle::ty::TyCtxt;
use rustc_session::cgu_reuse_tracker::CguReuseTracker;
use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath};
use rustc_session::config::{Passes, SwitchWithOptPath};
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
use rustc_target::spec::{MergeFunctions, PanicStrategy};
use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet};

use std::any::Any;
use std::fs;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate
use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
use rustc_session::config::{
Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel,
Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel,
};
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
Expand All @@ -18,7 +18,7 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm;
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel};
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel};
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
use std::num::NonZeroUsize;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::mir::mono::Linkage;
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_session::config::SanitizerSet;
use rustc_span::symbol::Symbol;
use rustc_target::spec::SanitizerSet;

#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
pub struct CodegenFnAttrs {
Expand Down
67 changes: 3 additions & 64 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::{early_error, early_warn, Session};

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::impl_stable_hash_via_hash;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

use rustc_target::abi::{Align, TargetDataLayout};
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
Expand All @@ -36,66 +35,6 @@ use std::iter::{self, FromIterator};
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};

bitflags! {
#[derive(Default, Encodable, Decodable)]
pub struct SanitizerSet: u8 {
const ADDRESS = 1 << 0;
const LEAK = 1 << 1;
const MEMORY = 1 << 2;
const THREAD = 1 << 3;
const HWADDRESS = 1 << 4;
}
}

/// Formats a sanitizer set as a comma separated list of sanitizers' names.
impl fmt::Display for SanitizerSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
for s in *self {
let name = match s {
SanitizerSet::ADDRESS => "address",
SanitizerSet::LEAK => "leak",
SanitizerSet::MEMORY => "memory",
SanitizerSet::THREAD => "thread",
SanitizerSet::HWADDRESS => "hwaddress",
_ => panic!("unrecognized sanitizer {:?}", s),
};
if !first {
f.write_str(",")?;
}
f.write_str(name)?;
first = false;
}
Ok(())
}
}

impl IntoIterator for SanitizerSet {
type Item = SanitizerSet;
type IntoIter = std::vec::IntoIter<SanitizerSet>;

fn into_iter(self) -> Self::IntoIter {
[
SanitizerSet::ADDRESS,
SanitizerSet::LEAK,
SanitizerSet::MEMORY,
SanitizerSet::THREAD,
SanitizerSet::HWADDRESS,
]
.iter()
.copied()
.filter(|&s| self.contains(s))
.collect::<Vec<_>>()
.into_iter()
}
}

impl<CTX> HashStable<CTX> for SanitizerSet {
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
self.bits().hash_stable(ctx, hasher);
}
}

/// The different settings that the `-Z strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
Expand Down Expand Up @@ -2308,16 +2247,16 @@ impl PpMode {
crate mod dep_tracking {
use super::{
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
LtoCli, OptLevel, OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm,
SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
SymbolManglingVersion, TrimmedDefPaths,
};
use crate::lint;
use crate::options::WasiExecModel;
use crate::utils::NativeLibKind;
use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel};
use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeMap;
use std::hash::Hash;
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate rustc_macros;

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::NativeLibKind;

use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};

use rustc_feature::UnstableFeatures;
Expand Down
73 changes: 18 additions & 55 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::cgu_reuse_tracker::CguReuseTracker;
use crate::code_stats::CodeStats;
pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath};
use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
use crate::filesearch;
use crate::lint::{self, LintId};
use crate::parse::ParseSess;
Expand All @@ -28,7 +28,7 @@ use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, S
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel};
use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel};

use std::cell::{self, RefCell};
use std::env;
Expand Down Expand Up @@ -1517,59 +1517,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
);
}

const ASAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-fuchsia",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-fuchsia",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
const LSAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-linux-gnu",
];
const MSAN_SUPPORTED_TARGETS: &[&str] =
&["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
const TSAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
const HWASAN_SUPPORTED_TARGETS: &[&str] =
&["aarch64-linux-android", "aarch64-unknown-linux-gnu"];

// Sanitizers can only be used on some tested platforms.
for s in sess.opts.debugging_opts.sanitizer {
let supported_targets = match s {
SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS,
SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS,
SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS,
SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS,
SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS,
_ => panic!("unrecognized sanitizer {}", s),
};
if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
sess.err(&format!(
"`-Zsanitizer={}` only works with targets: {}",
s,
supported_targets.join(", ")
));
}
let conflicting = sess.opts.debugging_opts.sanitizer - s;
if !conflicting.is_empty() {
sess.err(&format!(
"`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`",
s, conflicting,
));
// Don't report additional errors.
break;
}
// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
let supported_sanitizers = sess.target.options.supported_sanitizers;
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => sess
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
_ => sess.err(&format!(
"{} sanitizers are not supported for this target",
unsupported_sanitizers
)),
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second));
}
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions};
use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};

pub fn target() -> Target {
let mut base = super::apple_base::opts("macos");
base.cpu = "apple-a12".to_string();
base.max_atomic_width = Some(128);
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;

base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());

// Clang automatically chooses a more specific target based on
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/spec/aarch64_fuchsia.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::spec::{Target, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetOptions};

pub fn target() -> Target {
let mut base = super::fuchsia_base::opts();
base.max_atomic_width = Some(128);
base.supported_sanitizers = SanitizerSet::ADDRESS;

Target {
llvm_target: "aarch64-fuchsia".to_string(),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/spec/aarch64_linux_android.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::spec::{Target, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetOptions};

// See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
// for target ABI requirements.
Expand All @@ -9,6 +9,7 @@ pub fn target() -> Target {
// As documented in http://developer.android.com/ndk/guides/cpu-features.html
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
base.features = "+neon,+fp-armv8".to_string();
base.supported_sanitizers = SanitizerSet::HWADDRESS;
Target {
llvm_target: "aarch64-linux-android".to_string(),
pointer_width: 64,
Expand Down
Loading

0 comments on commit 9b6c9b6

Please sign in to comment.