Skip to content

Commit e207006

Browse files
committed
Add default sanitizers to TargetOptions
Some sanitizers are part of a system's ABI, like the shadow call stack on Aarch64 and RISC-V Fuchsia. Typically ABI options have other spellings, but LLVM has, for historical reasons, marked this as a sanitizer instead of an alternate ABI option. As a result, Fuchsia targets may not be compiled against the correct ABI unless this option is set. This hasn't caused correctness problems, since the backend reserves the SCS register, and thus preserves its value. But this is an issue for unwinding, as the SCS will not be an array of PCs describing the call complete call chain, and will have gaps from callers that don't use the correct ABI. In the long term, I'd like to see all the sanitizer configs that all frontends copy from clang moved into llvm's libFrontend, and exposed so that frontend consumers can use a small set of simple APIs to use sanitizers in a consistent way across the LLVM ecosystem, but that work is not yet ready today.
1 parent 20383c9 commit e207006

File tree

13 files changed

+43
-31
lines changed

13 files changed

+43
-31
lines changed

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
9696
}
9797
}
9898
}
99-
} else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
99+
} else if cx.tcx.sess.sanitizers().contains(SanitizerSet::MEMORY) {
100100
// If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
101101
// memory sanitizer's behavior.
102102

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>(
101101
no_sanitize: SanitizerSet,
102102
) -> SmallVec<[&'ll Attribute; 4]> {
103103
let mut attrs = SmallVec::new();
104-
let enabled = tcx.sess.opts.unstable_opts.sanitizer - no_sanitize;
104+
let enabled = tcx.sess.sanitizers() - no_sanitize;
105105
if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) {
106106
attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx));
107107
}
@@ -240,13 +240,7 @@ fn probestack_attr<'ll, 'tcx>(cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>) -> Option<&
240240
// Currently stack probes seem somewhat incompatible with the address
241241
// sanitizer and thread sanitizer. With asan we're already protected from
242242
// stack overflow anyway so we don't really need stack probes regardless.
243-
if tcx
244-
.sess
245-
.opts
246-
.unstable_opts
247-
.sanitizer
248-
.intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD)
249-
{
243+
if tcx.sess.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD) {
250244
return None;
251245
}
252246

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,7 +1226,7 @@ fn add_sanitizer_libraries(
12261226
return;
12271227
}
12281228

1229-
let sanitizer = sess.opts.unstable_opts.sanitizer;
1229+
let sanitizer = sess.sanitizers();
12301230
if sanitizer.contains(SanitizerSet::ADDRESS) {
12311231
link_sanitizer_runtime(sess, flavor, linker, "asan");
12321232
}
@@ -2496,11 +2496,7 @@ fn add_order_independent_options(
24962496
&& crate_type == CrateType::Executable
24972497
&& !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
24982498
{
2499-
let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
2500-
"asan/"
2501-
} else {
2502-
""
2503-
};
2499+
let prefix = if sess.sanitizers().contains(SanitizerSet::ADDRESS) { "asan/" } else { "" };
25042500
cmd.link_arg(format!("--dynamic-linker={prefix}ld.so.1"));
25052501
}
25062502

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl ModuleConfig {
176176
debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling,
177177
instrument_coverage: if_regular!(sess.instrument_coverage(), false),
178178

179-
sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
179+
sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()),
180180
sanitizer_dataflow_abilist: if_regular!(
181181
sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(),
182182
Vec::new()

compiler/rustc_metadata/src/creader.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl CStore {
412412
match (&left_name_val, &right_name_val) {
413413
(Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
414414
cmp::Ordering::Equal => {
415-
if !l.1.consistent(&tcx.sess.opts, Some(&r.1)) {
415+
if !l.1.consistent(&tcx.sess, Some(&r.1)) {
416416
report_diff(
417417
&l.0.prefix,
418418
&l.0.name,
@@ -424,26 +424,26 @@ impl CStore {
424424
right_name_val = None;
425425
}
426426
cmp::Ordering::Greater => {
427-
if !r.1.consistent(&tcx.sess.opts, None) {
427+
if !r.1.consistent(&tcx.sess, None) {
428428
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
429429
}
430430
right_name_val = None;
431431
}
432432
cmp::Ordering::Less => {
433-
if !l.1.consistent(&tcx.sess.opts, None) {
433+
if !l.1.consistent(&tcx.sess, None) {
434434
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
435435
}
436436
left_name_val = None;
437437
}
438438
},
439439
(Some(l), None) => {
440-
if !l.1.consistent(&tcx.sess.opts, None) {
440+
if !l.1.consistent(&tcx.sess, None) {
441441
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
442442
}
443443
left_name_val = None;
444444
}
445445
(None, Some(r)) => {
446-
if !r.1.consistent(&tcx.sess.opts, None) {
446+
if !r.1.consistent(&tcx.sess, None) {
447447
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
448448
}
449449
right_name_val = None;

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub fn walk_native_lib_search_dirs<R>(
7171
|| sess.target.os == "linux"
7272
|| sess.target.os == "fuchsia"
7373
|| sess.target.is_like_aix
74-
|| sess.target.is_like_darwin && !sess.opts.unstable_opts.sanitizer.is_empty()
74+
|| sess.target.is_like_darwin && !sess.sanitizers().is_empty()
7575
{
7676
f(&sess.target_tlib_path.dir, false)?;
7777
}

compiler/rustc_session/src/config/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
224224
ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol());
225225
}
226226

227-
for mut s in sess.opts.unstable_opts.sanitizer {
227+
for mut s in sess.sanitizers() {
228228
// KASAN is still ASAN under the hood, so it uses the same attribute.
229229
if s == SanitizerSet::KERNELADDRESS {
230230
s = SanitizerSet::ADDRESS;

compiler/rustc_session/src/options.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_target::spec::{
2222
use crate::config::*;
2323
use crate::search_paths::SearchPath;
2424
use crate::utils::NativeLib;
25-
use crate::{EarlyDiagCtxt, lint};
25+
use crate::{EarlyDiagCtxt, Session, lint};
2626

2727
macro_rules! insert {
2828
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
@@ -111,12 +111,12 @@ mod target_modifier_consistency_check {
111111
lparsed & tmod_sanitizers == rparsed & tmod_sanitizers
112112
}
113113
pub(super) fn sanitizer_cfi_normalize_integers(
114-
opts: &Options,
114+
sess: &Session,
115115
l: &TargetModifier,
116116
r: Option<&TargetModifier>,
117117
) -> bool {
118118
// For kCFI, the helper flag -Zsanitizer-cfi-normalize-integers should also be a target modifier
119-
if opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) {
119+
if sess.sanitizers().contains(SanitizerSet::KCFI) {
120120
if let Some(r) = r {
121121
return l.extend().tech_value == r.extend().tech_value;
122122
} else {
@@ -133,7 +133,7 @@ impl TargetModifier {
133133
}
134134
// Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`)
135135
// When other is None, consistency with default value is checked
136-
pub fn consistent(&self, opts: &Options, other: Option<&TargetModifier>) -> bool {
136+
pub fn consistent(&self, sess: &Session, other: Option<&TargetModifier>) -> bool {
137137
assert!(other.is_none() || self.opt == other.unwrap().opt);
138138
match self.opt {
139139
OptionsTargetModifiers::UnstableOptions(unstable) => match unstable {
@@ -142,7 +142,7 @@ impl TargetModifier {
142142
}
143143
UnstableOptionsTargetModifiers::sanitizer_cfi_normalize_integers => {
144144
return target_modifier_consistency_check::sanitizer_cfi_normalize_integers(
145-
opts, self, other,
145+
sess, self, other,
146146
);
147147
}
148148
_ => {}
@@ -2575,6 +2575,7 @@ written to standard error output)"),
25752575
retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
25762576
"enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \
25772577
target features (default: no)"),
2578+
#[rustc_lint_opt_deny_field_access("use `Session::sanitizers()` instead of this field")]
25782579
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED TARGET_MODIFIER],
25792580
"use a sanitizer"),
25802581
sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],

compiler/rustc_session/src/session.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ impl Session {
323323
}
324324

325325
pub fn is_sanitizer_cfi_enabled(&self) -> bool {
326-
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
326+
self.sanitizers().contains(SanitizerSet::CFI)
327327
}
328328

329329
pub fn is_sanitizer_cfi_canonical_jump_tables_disabled(&self) -> bool {
@@ -347,7 +347,7 @@ impl Session {
347347
}
348348

349349
pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
350-
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
350+
self.sanitizers().contains(SanitizerSet::KCFI)
351351
}
352352

353353
pub fn is_split_lto_unit_enabled(&self) -> bool {
@@ -527,7 +527,7 @@ impl Session {
527527
// AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs.
528528
// MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
529529
// HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
530-
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
530+
|| self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
531531
}
532532

533533
pub fn diagnostic_width(&self) -> usize {
@@ -922,6 +922,10 @@ impl Session {
922922
min
923923
}
924924
}
925+
926+
pub fn sanitizers(&self) -> SanitizerSet {
927+
return self.opts.unstable_opts.sanitizer | self.target.options.default_sanitizers;
928+
}
925929
}
926930

927931
// JUSTIFICATION: part of session construction

compiler/rustc_target/src/spec/json.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ impl Target {
214214
supported_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b);
215215
}
216216

217+
if let Some(default_sanitizers) = json.default_sanitizers {
218+
base.default_sanitizers =
219+
default_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b);
220+
}
221+
217222
forward!(generate_arange_section);
218223
forward!(supports_stack_protector);
219224
forward!(small_data_threshold_support);
@@ -392,6 +397,7 @@ impl ToJson for Target {
392397
target_option_val!(split_debuginfo);
393398
target_option_val!(supported_split_debuginfo);
394399
target_option_val!(supported_sanitizers);
400+
target_option_val!(default_sanitizers);
395401
target_option_val!(c_enum_min_bits);
396402
target_option_val!(generate_arange_section);
397403
target_option_val!(supports_stack_protector);
@@ -612,6 +618,7 @@ struct TargetSpecJson {
612618
split_debuginfo: Option<SplitDebuginfo>,
613619
supported_split_debuginfo: Option<StaticCow<[SplitDebuginfo]>>,
614620
supported_sanitizers: Option<Vec<SanitizerSet>>,
621+
default_sanitizers: Option<Vec<SanitizerSet>>,
615622
generate_arange_section: Option<bool>,
616623
supports_stack_protector: Option<bool>,
617624
small_data_threshold_support: Option<SmallDataThresholdSupport>,

0 commit comments

Comments
 (0)