Maintain supported sanitizers as a target property
This commit adds an additional target property – `supported_sanitizers`, and replaces the hardcoded allowlists in argument parsing to use this new property. Fixes #81802
This commit is contained in:
parent
64af7eae1e
commit
16c1d0ae06
12 changed files with 49 additions and 66 deletions
|
@ -1517,59 +1517,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
|
// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
|
||||||
"aarch64-apple-darwin",
|
let supported_sanitizers = sess.target.options.supported_sanitizers;
|
||||||
"aarch64-fuchsia",
|
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
|
||||||
"aarch64-unknown-linux-gnu",
|
match unsupported_sanitizers.into_iter().count() {
|
||||||
"x86_64-apple-darwin",
|
0 => {}
|
||||||
"x86_64-fuchsia",
|
1 => sess
|
||||||
"x86_64-unknown-freebsd",
|
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
|
||||||
"x86_64-unknown-linux-gnu",
|
_ => sess.err(&format!(
|
||||||
];
|
"{} sanitizers are not supported for this target",
|
||||||
const LSAN_SUPPORTED_TARGETS: &[&str] = &[
|
unsupported_sanitizers
|
||||||
"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;
|
|
||||||
}
|
}
|
||||||
|
// 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 {
|
pub fn target() -> Target {
|
||||||
let mut base = super::apple_base::opts("macos");
|
let mut base = super::apple_base::opts("macos");
|
||||||
base.cpu = "apple-a12".to_string();
|
base.cpu = "apple-a12".to_string();
|
||||||
base.max_atomic_width = Some(128);
|
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());
|
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
|
||||||
|
|
||||||
// Clang automatically chooses a more specific target based on
|
// 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 {
|
pub fn target() -> Target {
|
||||||
let mut base = super::fuchsia_base::opts();
|
let mut base = super::fuchsia_base::opts();
|
||||||
base.max_atomic_width = Some(128);
|
base.max_atomic_width = Some(128);
|
||||||
|
base.supported_sanitizers = SanitizerSet::ADDRESS;
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "aarch64-fuchsia".to_string(),
|
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
|
// See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
|
||||||
// for target ABI requirements.
|
// for target ABI requirements.
|
||||||
|
@ -9,6 +9,7 @@ pub fn target() -> Target {
|
||||||
// As documented in http://developer.android.com/ndk/guides/cpu-features.html
|
// As documented in http://developer.android.com/ndk/guides/cpu-features.html
|
||||||
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
|
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
|
||||||
base.features = "+neon,+fp-armv8".to_string();
|
base.features = "+neon,+fp-armv8".to_string();
|
||||||
|
base.supported_sanitizers = SanitizerSet::HWADDRESS;
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "aarch64-linux-android".to_string(),
|
llvm_target: "aarch64-linux-android".to_string(),
|
||||||
pointer_width: 64,
|
pointer_width: 64,
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
use crate::spec::{Target, TargetOptions};
|
use crate::spec::{SanitizerSet, Target, TargetOptions};
|
||||||
|
|
||||||
pub fn target() -> Target {
|
pub fn target() -> Target {
|
||||||
let mut base = super::linux_gnu_base::opts();
|
let mut base = super::linux_gnu_base::opts();
|
||||||
base.max_atomic_width = Some(128);
|
base.max_atomic_width = Some(128);
|
||||||
|
base.supported_sanitizers = SanitizerSet::ADDRESS
|
||||||
|
| SanitizerSet::LEAK
|
||||||
|
| SanitizerSet::MEMORY
|
||||||
|
| SanitizerSet::THREAD
|
||||||
|
| SanitizerSet::HWADDRESS;
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "aarch64-unknown-linux-gnu".to_string(),
|
llvm_target: "aarch64-unknown-linux-gnu".to_string(),
|
||||||
|
|
|
@ -614,7 +614,7 @@ impl fmt::Display for SanitizerSet {
|
||||||
_ => panic!("unrecognized sanitizer {:?}", s),
|
_ => panic!("unrecognized sanitizer {:?}", s),
|
||||||
};
|
};
|
||||||
if !first {
|
if !first {
|
||||||
f.write_str(",")?;
|
f.write_str(", ")?;
|
||||||
}
|
}
|
||||||
f.write_str(name)?;
|
f.write_str(name)?;
|
||||||
first = false;
|
first = false;
|
||||||
|
@ -1219,6 +1219,13 @@ pub struct TargetOptions {
|
||||||
/// How to handle split debug information, if at all. Specifying `None` has
|
/// How to handle split debug information, if at all. Specifying `None` has
|
||||||
/// target-specific meaning.
|
/// target-specific meaning.
|
||||||
pub split_debuginfo: SplitDebuginfo,
|
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 {
|
impl Default for TargetOptions {
|
||||||
|
@ -1320,6 +1327,7 @@ impl Default for TargetOptions {
|
||||||
eh_frame_header: true,
|
eh_frame_header: true,
|
||||||
has_thumb_interworking: false,
|
has_thumb_interworking: false,
|
||||||
split_debuginfo: SplitDebuginfo::Off,
|
split_debuginfo: SplitDebuginfo::Off,
|
||||||
|
supported_sanitizers: SanitizerSet::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
|
use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
|
||||||
|
|
||||||
pub fn target() -> Target {
|
pub fn target() -> Target {
|
||||||
let mut base = super::apple_base::opts("macos");
|
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.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.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
|
// Clang automatically chooses a more specific target based on
|
||||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
// 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 {
|
pub fn target() -> Target {
|
||||||
let mut base = super::fuchsia_base::opts();
|
let mut base = super::fuchsia_base::opts();
|
||||||
base.cpu = "x86-64".to_string();
|
base.cpu = "x86-64".to_string();
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||||
|
base.supported_sanitizers = SanitizerSet::ADDRESS;
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "x86_64-fuchsia".to_string(),
|
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 {
|
pub fn target() -> Target {
|
||||||
let mut base = super::freebsd_base::opts();
|
let mut base = super::freebsd_base::opts();
|
||||||
|
@ -6,6 +6,7 @@ pub fn target() -> Target {
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
|
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.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||||
|
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::THREAD;
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "x86_64-unknown-freebsd".to_string(),
|
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 {
|
pub fn target() -> Target {
|
||||||
let mut base = super::linux_gnu_base::opts();
|
let mut base = super::linux_gnu_base::opts();
|
||||||
|
@ -6,6 +6,8 @@ pub fn target() -> Target {
|
||||||
base.max_atomic_width = Some(64);
|
base.max_atomic_width = Some(64);
|
||||||
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
|
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.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
|
||||||
|
base.supported_sanitizers =
|
||||||
|
SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
|
||||||
|
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
|
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
|
// 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)]
|
#![feature(no_core)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
#![no_main]
|
#![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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue