Skip to content

Commit 5768685

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#81802
2 parents 138fd56 + 41875c8 commit 5768685

24 files changed

+216
-203
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1111
use rustc_middle::ty::layout::HasTyCtxt;
1212
use rustc_middle::ty::query::Providers;
1313
use rustc_middle::ty::{self, TyCtxt};
14-
use rustc_session::config::{OptLevel, SanitizerSet};
14+
use rustc_session::config::OptLevel;
1515
use rustc_session::Session;
16-
use rustc_target::spec::StackProbeType;
16+
use rustc_target::spec::{SanitizerSet, StackProbeType};
1717

1818
use crate::attributes;
1919
use crate::llvm::AttributePlace::Function;

compiler/rustc_codegen_llvm/src/back/write.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ use rustc_fs_util::{link_or_copy, path_to_c_string};
2323
use rustc_hir::def_id::LOCAL_CRATE;
2424
use rustc_middle::bug;
2525
use rustc_middle::ty::TyCtxt;
26-
use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath};
26+
use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath};
2727
use rustc_session::Session;
2828
use rustc_span::symbol::sym;
2929
use rustc_span::InnerSpan;
30-
use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo};
30+
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo};
3131
use tracing::debug;
3232

3333
use libc::{c_char, c_int, c_uint, c_void, size_t};

compiler/rustc_codegen_llvm/src/base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ use rustc_middle::middle::cstore::EncodedMetadata;
3232
use rustc_middle::middle::exported_symbols;
3333
use rustc_middle::mir::mono::{Linkage, Visibility};
3434
use rustc_middle::ty::TyCtxt;
35-
use rustc_session::config::{DebugInfo, SanitizerSet};
35+
use rustc_session::config::DebugInfo;
3636
use rustc_span::symbol::Symbol;
37+
use rustc_target::spec::SanitizerSet;
3738

3839
use std::ffi::CString;
3940
use std::time::Instant;

compiler/rustc_codegen_ssa/src/back/link.rs

+16-24
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir::def_id::CrateNum;
66
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
77
use rustc_middle::middle::dependency_format::Linkage;
88
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
9-
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
9+
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
1010
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
1111
use rustc_session::search_paths::PathKind;
1212
use rustc_session::utils::NativeLibKind;
@@ -16,7 +16,7 @@ use rustc_session::{filesearch, Session};
1616
use rustc_span::symbol::Symbol;
1717
use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
1818
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
19-
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target};
19+
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
2020

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

925-
match sess.opts.target_triple.triple() {
926-
"aarch64-apple-darwin" | "x86_64-apple-darwin" => {
927-
// On Apple platforms, the sanitizer is always built as a dylib, and
928-
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
929-
// rpath to the library as well (the rpath should be absolute, see
930-
// PR #41352 for details).
931-
let filename = format!("rustc{}_rt.{}", channel, name);
932-
let path = find_sanitizer_runtime(&sess, &filename);
933-
let rpath = path.to_str().expect("non-utf8 component in path");
934-
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
935-
linker.link_dylib(Symbol::intern(&filename));
936-
}
937-
"aarch64-fuchsia"
938-
| "aarch64-unknown-linux-gnu"
939-
| "x86_64-fuchsia"
940-
| "x86_64-unknown-freebsd"
941-
| "x86_64-unknown-linux-gnu" => {
942-
let filename = format!("librustc{}_rt.{}.a", channel, name);
943-
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
944-
linker.link_whole_rlib(&path);
945-
}
946-
_ => {}
925+
if sess.target.is_like_osx {
926+
// On Apple platforms, the sanitizer is always built as a dylib, and
927+
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
928+
// rpath to the library as well (the rpath should be absolute, see
929+
// PR #41352 for details).
930+
let filename = format!("rustc{}_rt.{}", channel, name);
931+
let path = find_sanitizer_runtime(&sess, &filename);
932+
let rpath = path.to_str().expect("non-utf8 component in path");
933+
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
934+
linker.link_dylib(Symbol::intern(&filename));
935+
} else {
936+
let filename = format!("librustc{}_rt.{}.a", channel, name);
937+
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
938+
linker.link_whole_rlib(&path);
947939
}
948940
}
949941

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use rustc_middle::ty::query::Providers;
1515
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
1616
use rustc_middle::ty::Instance;
1717
use rustc_middle::ty::{SymbolName, TyCtxt};
18-
use rustc_session::config::{CrateType, SanitizerSet};
18+
use rustc_session::config::CrateType;
19+
use rustc_target::spec::SanitizerSet;
1920

2021
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
2122
crates_export_threshold(&tcx.sess.crate_types())

compiler/rustc_codegen_ssa/src/back/write.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel;
2727
use rustc_middle::ty::TyCtxt;
2828
use rustc_session::cgu_reuse_tracker::CguReuseTracker;
2929
use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
30-
use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath};
30+
use rustc_session::config::{Passes, SwitchWithOptPath};
3131
use rustc_session::Session;
3232
use rustc_span::source_map::SourceMap;
3333
use rustc_span::symbol::{sym, Symbol};
3434
use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
35-
use rustc_target::spec::{MergeFunctions, PanicStrategy};
35+
use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet};
3636

3737
use std::any::Any;
3838
use std::fs;

compiler/rustc_interface/src/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate
88
use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
99
use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
1010
use rustc_session::config::{
11-
Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel,
11+
Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel,
1212
};
1313
use rustc_session::lint::Level;
1414
use rustc_session::search_paths::SearchPath;
@@ -18,7 +18,7 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION};
1818
use rustc_span::symbol::sym;
1919
use rustc_span::SourceFileHashAlgorithm;
2020
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
21-
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel};
21+
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel};
2222
use std::collections::{BTreeMap, BTreeSet};
2323
use std::iter::FromIterator;
2424
use std::num::NonZeroUsize;

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::mir::mono::Linkage;
22
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
3-
use rustc_session::config::SanitizerSet;
43
use rustc_span::symbol::Symbol;
4+
use rustc_target::spec::SanitizerSet;
55

66
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
77
pub struct CodegenFnAttrs {

compiler/rustc_session/src/config.rs

+3-64
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::{early_error, early_warn, Session};
1010

1111
use rustc_data_structures::fx::FxHashSet;
1212
use rustc_data_structures::impl_stable_hash_via_hash;
13-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1413

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

39-
bitflags! {
40-
#[derive(Default, Encodable, Decodable)]
41-
pub struct SanitizerSet: u8 {
42-
const ADDRESS = 1 << 0;
43-
const LEAK = 1 << 1;
44-
const MEMORY = 1 << 2;
45-
const THREAD = 1 << 3;
46-
const HWADDRESS = 1 << 4;
47-
}
48-
}
49-
50-
/// Formats a sanitizer set as a comma separated list of sanitizers' names.
51-
impl fmt::Display for SanitizerSet {
52-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53-
let mut first = true;
54-
for s in *self {
55-
let name = match s {
56-
SanitizerSet::ADDRESS => "address",
57-
SanitizerSet::LEAK => "leak",
58-
SanitizerSet::MEMORY => "memory",
59-
SanitizerSet::THREAD => "thread",
60-
SanitizerSet::HWADDRESS => "hwaddress",
61-
_ => panic!("unrecognized sanitizer {:?}", s),
62-
};
63-
if !first {
64-
f.write_str(",")?;
65-
}
66-
f.write_str(name)?;
67-
first = false;
68-
}
69-
Ok(())
70-
}
71-
}
72-
73-
impl IntoIterator for SanitizerSet {
74-
type Item = SanitizerSet;
75-
type IntoIter = std::vec::IntoIter<SanitizerSet>;
76-
77-
fn into_iter(self) -> Self::IntoIter {
78-
[
79-
SanitizerSet::ADDRESS,
80-
SanitizerSet::LEAK,
81-
SanitizerSet::MEMORY,
82-
SanitizerSet::THREAD,
83-
SanitizerSet::HWADDRESS,
84-
]
85-
.iter()
86-
.copied()
87-
.filter(|&s| self.contains(s))
88-
.collect::<Vec<_>>()
89-
.into_iter()
90-
}
91-
}
92-
93-
impl<CTX> HashStable<CTX> for SanitizerSet {
94-
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
95-
self.bits().hash_stable(ctx, hasher);
96-
}
97-
}
98-
9938
/// The different settings that the `-Z strip` flag can have.
10039
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
10140
pub enum Strip {
@@ -2308,16 +2247,16 @@ impl PpMode {
23082247
crate mod dep_tracking {
23092248
use super::{
23102249
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
2311-
LtoCli, OptLevel, OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm,
2312-
SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
2250+
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
2251+
SymbolManglingVersion, TrimmedDefPaths,
23132252
};
23142253
use crate::lint;
23152254
use crate::options::WasiExecModel;
23162255
use crate::utils::NativeLibKind;
23172256
use rustc_feature::UnstableFeatures;
23182257
use rustc_span::edition::Edition;
23192258
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
2320-
use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
2259+
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel};
23212260
use std::collections::hash_map::DefaultHasher;
23222261
use std::collections::BTreeMap;
23232262
use std::hash::Hash;

compiler/rustc_session/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#![cfg_attr(bootstrap, feature(or_patterns))]
44
#![recursion_limit = "256"]
55

6-
#[macro_use]
7-
extern crate bitflags;
86
#[macro_use]
97
extern crate rustc_macros;
108

compiler/rustc_session/src/options.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::lint;
55
use crate::search_paths::SearchPath;
66
use crate::utils::NativeLibKind;
77

8-
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
8+
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
99
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
1010

1111
use rustc_feature::UnstableFeatures;

compiler/rustc_session/src/session.rs

+18-55
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cgu_reuse_tracker::CguReuseTracker;
22
use crate::code_stats::CodeStats;
33
pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
4-
use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath};
4+
use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
55
use crate::filesearch;
66
use crate::lint::{self, LintId};
77
use crate::parse::ParseSess;
@@ -28,7 +28,7 @@ use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, S
2828
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
2929
use rustc_target::asm::InlineAsmArch;
3030
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
31-
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel};
31+
use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel};
3232

3333
use std::cell::{self, RefCell};
3434
use std::env;
@@ -1517,59 +1517,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
15171517
);
15181518
}
15191519

1520-
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
1521-
"aarch64-apple-darwin",
1522-
"aarch64-fuchsia",
1523-
"aarch64-unknown-linux-gnu",
1524-
"x86_64-apple-darwin",
1525-
"x86_64-fuchsia",
1526-
"x86_64-unknown-freebsd",
1527-
"x86_64-unknown-linux-gnu",
1528-
];
1529-
const LSAN_SUPPORTED_TARGETS: &[&str] = &[
1530-
"aarch64-apple-darwin",
1531-
"aarch64-unknown-linux-gnu",
1532-
"x86_64-apple-darwin",
1533-
"x86_64-unknown-linux-gnu",
1534-
];
1535-
const MSAN_SUPPORTED_TARGETS: &[&str] =
1536-
&["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
1537-
const TSAN_SUPPORTED_TARGETS: &[&str] = &[
1538-
"aarch64-apple-darwin",
1539-
"aarch64-unknown-linux-gnu",
1540-
"x86_64-apple-darwin",
1541-
"x86_64-unknown-freebsd",
1542-
"x86_64-unknown-linux-gnu",
1543-
];
1544-
const HWASAN_SUPPORTED_TARGETS: &[&str] =
1545-
&["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
1546-
1547-
// Sanitizers can only be used on some tested platforms.
1548-
for s in sess.opts.debugging_opts.sanitizer {
1549-
let supported_targets = match s {
1550-
SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS,
1551-
SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS,
1552-
SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS,
1553-
SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS,
1554-
SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS,
1555-
_ => panic!("unrecognized sanitizer {}", s),
1556-
};
1557-
if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
1558-
sess.err(&format!(
1559-
"`-Zsanitizer={}` only works with targets: {}",
1560-
s,
1561-
supported_targets.join(", ")
1562-
));
1563-
}
1564-
let conflicting = sess.opts.debugging_opts.sanitizer - s;
1565-
if !conflicting.is_empty() {
1566-
sess.err(&format!(
1567-
"`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`",
1568-
s, conflicting,
1569-
));
1570-
// Don't report additional errors.
1571-
break;
1572-
}
1520+
// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
1521+
let supported_sanitizers = sess.target.options.supported_sanitizers;
1522+
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
1523+
match unsupported_sanitizers.into_iter().count() {
1524+
0 => {}
1525+
1 => sess
1526+
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
1527+
_ => sess.err(&format!(
1528+
"{} sanitizers are not supported for this target",
1529+
unsupported_sanitizers
1530+
)),
1531+
}
1532+
// Cannot mix and match sanitizers.
1533+
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
1534+
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
1535+
sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second));
15731536
}
15741537
}
15751538

compiler/rustc_target/src/spec/aarch64_apple_darwin.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use crate::spec::{LinkerFlavor, Target, TargetOptions};
1+
use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
22

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

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

1112
// Clang automatically chooses a more specific target based on

compiler/rustc_target/src/spec/aarch64_fuchsia.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
use crate::spec::{Target, TargetOptions};
1+
use crate::spec::{SanitizerSet, Target, TargetOptions};
22

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

78
Target {
89
llvm_target: "aarch64-fuchsia".to_string(),

compiler/rustc_target/src/spec/aarch64_linux_android.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{Target, TargetOptions};
1+
use crate::spec::{SanitizerSet, Target, TargetOptions};
22

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

0 commit comments

Comments
 (0)