Auto merge of #81866 - nagisa:nagisa/sanitizer-support-target-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 #81802
This commit is contained in:
commit
9b6c9b638e
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
@ -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 {
|
||||
@ -2308,8 +2247,8 @@ 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;
|
||||
@ -2317,7 +2256,7 @@ crate mod dep_tracking {
|
||||
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;
|
||||
|
@ -3,8 +3,6 @@
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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.
|
||||
@ -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,
|
||||
|
@ -1,8 +1,13 @@
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::linux_gnu_base::opts();
|
||||
base.max_atomic_width = Some(128);
|
||||
base.supported_sanitizers = SanitizerSet::ADDRESS
|
||||
| SanitizerSet::LEAK
|
||||
| SanitizerSet::MEMORY
|
||||
| SanitizerSet::THREAD
|
||||
| SanitizerSet::HWADDRESS;
|
||||
|
||||
Target {
|
||||
llvm_target: "aarch64-unknown-linux-gnu".to_string(),
|
||||
|
@ -37,6 +37,7 @@
|
||||
use crate::abi::Endian;
|
||||
use crate::spec::abi::{lookup as lookup_abi, Abi};
|
||||
use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_serialize::json::{Json, ToJson};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use std::collections::BTreeMap;
|
||||
@ -511,38 +512,6 @@ impl fmt::Display for SplitDebuginfo {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! supported_targets {
|
||||
( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
|
||||
$(mod $module;)+
|
||||
|
||||
/// List of supported targets
|
||||
pub const TARGETS: &[&str] = &[$($($triple),+),+];
|
||||
|
||||
fn load_builtin(target: &str) -> Option<Target> {
|
||||
let mut t = match target {
|
||||
$( $($triple)|+ => $module::target(), )+
|
||||
_ => return None,
|
||||
};
|
||||
t.is_builtin = true;
|
||||
debug!("got builtin target: {:?}", t);
|
||||
Some(t)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod tests_impl;
|
||||
|
||||
// Cannot put this into a separate file without duplication, make an exception.
|
||||
$(
|
||||
#[test] // `#[test]`
|
||||
fn $module() {
|
||||
tests_impl::test_target(super::$module::target());
|
||||
}
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum StackProbeType {
|
||||
/// Don't emit any stack probes.
|
||||
@ -620,6 +589,117 @@ impl ToJson for StackProbeType {
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::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;
|
||||
}
|
||||
}
|
||||
|
||||
impl SanitizerSet {
|
||||
/// Return sanitizer's name
|
||||
///
|
||||
/// Returns none if the flags is a set of sanitizers numbering not exactly one.
|
||||
fn as_str(self) -> Option<&'static str> {
|
||||
Some(match self {
|
||||
SanitizerSet::ADDRESS => "address",
|
||||
SanitizerSet::LEAK => "leak",
|
||||
SanitizerSet::MEMORY => "memory",
|
||||
SanitizerSet::THREAD => "thread",
|
||||
SanitizerSet::HWADDRESS => "hwaddress",
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 = s.as_str().unwrap_or_else(|| 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);
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for SanitizerSet {
|
||||
fn to_json(&self) -> Json {
|
||||
self.into_iter()
|
||||
.map(|v| Some(v.as_str()?.to_json()))
|
||||
.collect::<Option<Vec<_>>>()
|
||||
.unwrap_or(Vec::new())
|
||||
.to_json()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! supported_targets {
|
||||
( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
|
||||
$(mod $module;)+
|
||||
|
||||
/// List of supported targets
|
||||
pub const TARGETS: &[&str] = &[$($($triple),+),+];
|
||||
|
||||
fn load_builtin(target: &str) -> Option<Target> {
|
||||
let mut t = match target {
|
||||
$( $($triple)|+ => $module::target(), )+
|
||||
_ => return None,
|
||||
};
|
||||
t.is_builtin = true;
|
||||
debug!("got builtin target: {:?}", t);
|
||||
Some(t)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod tests_impl;
|
||||
|
||||
// Cannot put this into a separate file without duplication, make an exception.
|
||||
$(
|
||||
#[test] // `#[test]`
|
||||
fn $module() {
|
||||
tests_impl::test_target(super::$module::target());
|
||||
}
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
supported_targets! {
|
||||
("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
|
||||
("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
|
||||
@ -1164,6 +1244,13 @@ pub struct TargetOptions {
|
||||
/// How to handle split debug information, if at all. Specifying `None` has
|
||||
/// target-specific meaning.
|
||||
pub split_debuginfo: SplitDebuginfo,
|
||||
|
||||
/// 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.
|
||||
pub supported_sanitizers: SanitizerSet,
|
||||
}
|
||||
|
||||
impl Default for TargetOptions {
|
||||
@ -1265,6 +1352,7 @@ impl Default for TargetOptions {
|
||||
eh_frame_header: true,
|
||||
has_thumb_interworking: false,
|
||||
split_debuginfo: SplitDebuginfo::Off,
|
||||
supported_sanitizers: SanitizerSet::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1551,6 +1639,24 @@ impl Target {
|
||||
)),
|
||||
}).unwrap_or(Ok(()))
|
||||
} );
|
||||
($key_name:ident, SanitizerSet) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| {
|
||||
for s in a {
|
||||
base.$key_name |= match s.as_string() {
|
||||
Some("address") => SanitizerSet::ADDRESS,
|
||||
Some("leak") => SanitizerSet::LEAK,
|
||||
Some("memory") => SanitizerSet::MEMORY,
|
||||
Some("thread") => SanitizerSet::THREAD,
|
||||
Some("hwaddress") => SanitizerSet::HWADDRESS,
|
||||
Some(s) => return Some(Err(format!("unknown sanitizer {}", s))),
|
||||
_ => return Some(Err(format!("not a string: {:?}", s))),
|
||||
};
|
||||
}
|
||||
Some(Ok(()))
|
||||
}).unwrap_or(Ok(()))
|
||||
} );
|
||||
|
||||
($key_name:ident, crt_objects_fallback) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
|
||||
@ -1729,6 +1835,7 @@ impl Target {
|
||||
key!(eh_frame_header, bool);
|
||||
key!(has_thumb_interworking, bool);
|
||||
key!(split_debuginfo, SplitDebuginfo)?;
|
||||
key!(supported_sanitizers, SanitizerSet)?;
|
||||
|
||||
// NB: The old name is deprecated, but support for it is retained for
|
||||
// compatibility.
|
||||
@ -1966,6 +2073,7 @@ impl ToJson for Target {
|
||||
target_option_val!(eh_frame_header);
|
||||
target_option_val!(has_thumb_interworking);
|
||||
target_option_val!(split_debuginfo);
|
||||
target_option_val!(supported_sanitizers);
|
||||
|
||||
if default.unsupported_abis != self.unsupported_abis {
|
||||
d.insert(
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
|
||||
use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::apple_base::opts("macos");
|
||||
@ -11,6 +11,7 @@ pub fn target() -> Target {
|
||||
);
|
||||
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
|
||||
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::spec::{StackProbeType, Target};
|
||||
use crate::spec::{SanitizerSet, StackProbeType, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::fuchsia_base::opts();
|
||||
base.cpu = "x86-64".to_string();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||
base.supported_sanitizers = SanitizerSet::ADDRESS;
|
||||
|
||||
Target {
|
||||
llvm_target: "x86_64-fuchsia".to_string(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, StackProbeType, Target};
|
||||
use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::freebsd_base::opts();
|
||||
@ -6,6 +6,7 @@ pub fn target() -> Target {
|
||||
base.max_atomic_width = Some(64);
|
||||
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
|
||||
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::THREAD;
|
||||
|
||||
Target {
|
||||
llvm_target: "x86_64-unknown-freebsd".to_string(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, StackProbeType, Target};
|
||||
use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::linux_gnu_base::opts();
|
||||
@ -6,6 +6,8 @@ pub fn target() -> Target {
|
||||
base.max_atomic_width = Some(64);
|
||||
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
|
||||
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||
base.supported_sanitizers =
|
||||
SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
|
||||
|
||||
Target {
|
||||
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
|
||||
|
@ -43,12 +43,11 @@ use rustc_middle::ty::util::Discr;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
|
||||
use rustc_session::config::SanitizerSet;
|
||||
use rustc_session::lint;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_target::spec::{abi, SanitizerSet};
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
||||
use std::iter;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
|
||||
// error-pattern: error: `-Zsanitizer=leak` only works with targets:
|
||||
|
||||
// error-pattern: error: leak sanitizer is not supported for this target
|
||||
#![feature(no_core)]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: `-Zsanitizer=leak` only works with targets: aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
|
||||
error: leak sanitizer is not supported for this target
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user