From 64af7eae1ea25102c8197f9f190ee65ddc4f8a10 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 7 Feb 2021 23:47:03 +0200 Subject: [PATCH 1/4] Move SanitizerSet to rustc_target --- compiler/rustc_codegen_llvm/src/attributes.rs | 4 +- compiler/rustc_codegen_llvm/src/back/write.rs | 4 +- compiler/rustc_codegen_llvm/src/base.rs | 3 +- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +- .../src/back/symbol_export.rs | 3 +- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- compiler/rustc_interface/src/tests.rs | 4 +- .../src/middle/codegen_fn_attrs.rs | 2 +- compiler/rustc_session/src/config.rs | 67 +--------- compiler/rustc_session/src/lib.rs | 2 - compiler/rustc_session/src/options.rs | 2 +- compiler/rustc_session/src/session.rs | 4 +- compiler/rustc_target/src/spec/mod.rs | 119 +++++++++++++----- compiler/rustc_typeck/src/collect.rs | 3 +- 14 files changed, 109 insertions(+), 116 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 64ebe585dd837..594d42c936659 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -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; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 085935b94df50..b3551177323aa 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -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}; diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index db8abdd9b1353..6f6c649bb0b18 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -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; diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 686ebc13ea3fc..9eaabfe04a96f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index abad8281d3a69..b8f277c8ff5e3 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -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()) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7a8d8fb13043b..b03242363735b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -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; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 1653d3bdba16e..2270b2b33e2ba 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -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; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 5f2ffda642cee..bfca6a5f574c4 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -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 { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3692219cb6d44..e39b9b9b33eea 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -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; - - fn into_iter(self) -> Self::IntoIter { - [ - SanitizerSet::ADDRESS, - SanitizerSet::LEAK, - SanitizerSet::MEMORY, - SanitizerSet::THREAD, - SanitizerSet::HWADDRESS, - ] - .iter() - .copied() - .filter(|&s| self.contains(s)) - .collect::>() - .into_iter() - } -} - -impl HashStable 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; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 95d17125a11a9..7971f7ef9efe2 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -3,8 +3,6 @@ #![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] -#[macro_use] -extern crate bitflags; #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index e50972e59a722..623062dd569a1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -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; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 693f427d7afcc..fce34cf724769 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -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; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ddfd82625221f..b68369b44347f 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -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 { - 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,92 @@ 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; + } +} + +/// 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; + + fn into_iter(self) -> Self::IntoIter { + [SanitizerSet::ADDRESS, SanitizerSet::LEAK, SanitizerSet::MEMORY, SanitizerSet::THREAD, SanitizerSet::HWADDRESS] + .iter() + .copied() + .filter(|&s| self.contains(s)) + .collect::>() + .into_iter() + } +} + +impl HashStable for SanitizerSet { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.bits().hash_stable(ctx, hasher); + } +} + +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 { + 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), diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index afe52c977334d..05ba8811cc2df 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -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; From 16c1d0ae0656a5aa929fb0a9ab5c0c740c950ded Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 8 Feb 2021 00:49:00 +0200 Subject: [PATCH 2/4] Maintain supported sanitizers as a target property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds an additional target property – `supported_sanitizers`, and replaces the hardcoded allowlists in argument parsing to use this new property. Fixes #81802 --- compiler/rustc_session/src/session.rs | 69 +++++-------------- .../src/spec/aarch64_apple_darwin.rs | 5 +- .../rustc_target/src/spec/aarch64_fuchsia.rs | 3 +- .../src/spec/aarch64_linux_android.rs | 3 +- .../src/spec/aarch64_unknown_linux_gnu.rs | 7 +- compiler/rustc_target/src/spec/mod.rs | 10 ++- .../src/spec/x86_64_apple_darwin.rs | 3 +- .../rustc_target/src/spec/x86_64_fuchsia.rs | 3 +- .../src/spec/x86_64_unknown_freebsd.rs | 3 +- .../src/spec/x86_64_unknown_linux_gnu.rs | 4 +- src/test/ui/sanitize/unsupported-target.rs | 3 +- .../ui/sanitize/unsupported-target.stderr | 2 +- 12 files changed, 49 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index fce34cf724769..3488efacd1126 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -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)); } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 7de809f76222d..feadd4e891cec 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -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 diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs index 1252741f9797d..c9cb21f1eb1e9 100644 --- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs @@ -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(), diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs index fa6108df206b4..eaf3a2dbcf8c2 100644 --- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs @@ -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, diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs index 58c72af4e769c..a07cd7db8897d 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -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(), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index b68369b44347f..390e5332c0051 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -614,7 +614,7 @@ impl fmt::Display for SanitizerSet { _ => panic!("unrecognized sanitizer {:?}", s), }; if !first { - f.write_str(",")?; + f.write_str(", ")?; } f.write_str(name)?; first = false; @@ -1219,6 +1219,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 { @@ -1320,6 +1327,7 @@ impl Default for TargetOptions { eh_frame_header: true, has_thumb_interworking: false, split_debuginfo: SplitDebuginfo::Off, + supported_sanitizers: SanitizerSet::empty(), } } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index 8c40baccda84a..c82359223da60 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -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 diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs index a39e7f8c34105..99acc7c207bc2 100644 --- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs @@ -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(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs index aac01445917b2..ca3556fc48e50 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs @@ -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(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index dfda49b9c336f..9569e98ed59a8 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -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(), diff --git a/src/test/ui/sanitize/unsupported-target.rs b/src/test/ui/sanitize/unsupported-target.rs index 6ccc9988cdecc..3fb749815f7c3 100644 --- a/src/test/ui/sanitize/unsupported-target.rs +++ b/src/test/ui/sanitize/unsupported-target.rs @@ -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] diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr index 093678707fb99..9bb8405020d73 100644 --- a/src/test/ui/sanitize/unsupported-target.stderr +++ b/src/test/ui/sanitize/unsupported-target.stderr @@ -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 From a3c0f0a3dfccf75bd7df55b2806788489f7831cd Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 13 Feb 2021 22:00:07 +0200 Subject: [PATCH 3/4] (De-)serialize the supported_sanitizers --- compiler/rustc_target/src/spec/mod.rs | 73 ++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 390e5332c0051..89052ef390b8a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -600,19 +600,28 @@ bitflags::bitflags! { } } +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 = match s { - SanitizerSet::ADDRESS => "address", - SanitizerSet::LEAK => "leak", - SanitizerSet::MEMORY => "memory", - SanitizerSet::THREAD => "thread", - SanitizerSet::HWADDRESS => "hwaddress", - _ => panic!("unrecognized sanitizer {:?}", s), - }; + let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s)); if !first { f.write_str(", ")?; } @@ -628,12 +637,18 @@ impl IntoIterator for SanitizerSet { type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { - [SanitizerSet::ADDRESS, SanitizerSet::LEAK, SanitizerSet::MEMORY, SanitizerSet::THREAD, SanitizerSet::HWADDRESS] - .iter() - .copied() - .filter(|&s| self.contains(s)) - .collect::>() - .into_iter() + [ + SanitizerSet::ADDRESS, + SanitizerSet::LEAK, + SanitizerSet::MEMORY, + SanitizerSet::THREAD, + SanitizerSet::HWADDRESS, + ] + .iter() + .copied() + .filter(|&s| self.contains(s)) + .collect::>() + .into_iter() } } @@ -643,6 +658,16 @@ impl HashStable for SanitizerSet { } } +impl ToJson for SanitizerSet { + fn to_json(&self) -> Json { + self.into_iter() + .map(|v| Some(v.as_str()?.to_json())) + .collect::>>() + .unwrap_or(Vec::new()) + .to_json() + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -1614,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| { @@ -1792,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. @@ -2029,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( From 41875c82c7858735b1d028b04156c328715ca454 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 15 Feb 2021 03:17:50 +0200 Subject: [PATCH 4/4] rm target specific logic in link_sanitizer_runtime --- compiler/rustc_codegen_ssa/src/back/link.rs | 36 ++++++++------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 9eaabfe04a96f..217b8f43229a6 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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); } }