Skip to content

Commit 3e2f895

Browse files
committed
add realtime sanitizer
1 parent 8448eb2 commit 3e2f895

File tree

31 files changed

+239
-38
lines changed

31 files changed

+239
-38
lines changed

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
1+
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy};
22
use rustc_session::parse::feature_err;
33

44
use super::prelude::*;
@@ -592,7 +592,8 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
592592
r#"memory = "on|off""#,
593593
r#"memtag = "on|off""#,
594594
r#"shadow_call_stack = "on|off""#,
595-
r#"thread = "on|off""#
595+
r#"thread = "on|off""#,
596+
r#"realtime = "nonblocking|blocking|caller""#,
596597
]);
597598

598599
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
@@ -606,6 +607,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
606607

607608
let mut on_set = SanitizerSet::empty();
608609
let mut off_set = SanitizerSet::empty();
610+
let mut rtsan = None;
609611

610612
for item in list.mixed() {
611613
let Some(item) = item.meta_item() else {
@@ -654,6 +656,17 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
654656
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
655657
Some(sym::thread) => apply(SanitizerSet::THREAD),
656658
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
659+
Some(sym::realtime) => match value.value_as_str() {
660+
Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking),
661+
Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking),
662+
Some(sym::caller) => rtsan = Some(RtsanSetting::Caller),
663+
_ => {
664+
cx.expected_specific_argument_strings(
665+
value.value_span,
666+
&[sym::nonblocking, sym::blocking, sym::caller],
667+
);
668+
}
669+
},
657670
_ => {
658671
cx.expected_specific_argument_strings(
659672
item.path().span(),
@@ -666,13 +679,14 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
666679
sym::shadow_call_stack,
667680
sym::thread,
668681
sym::hwaddress,
682+
sym::realtime,
669683
],
670684
);
671685
continue;
672686
}
673687
}
674688
}
675689

676-
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
690+
Some(AttributeKind::Sanitize { on_set, off_set, rtsan, span: cx.attr_span })
677691
}
678692
}

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
//! Set and unset common attributes on LLVM values.
2-
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr};
1+
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSetting};
32
use rustc_hir::def_id::DefId;
43
use rustc_middle::middle::codegen_fn_attrs::{
54
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs,
@@ -101,7 +100,6 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>(
101100
sanitizer_fn_attr: SanitizerFnAttrs,
102101
) -> SmallVec<[&'ll Attribute; 4]> {
103102
let mut attrs = SmallVec::new();
104-
// TODO: add realtim sanitizer
105103
let enabled = tcx.sess.opts.unstable_opts.sanitizer - sanitizer_fn_attr.disabled;
106104
if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) {
107105
attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx));
@@ -132,6 +130,18 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>(
132130
if enabled.contains(SanitizerSet::SAFESTACK) {
133131
attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx));
134132
}
133+
if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::REALTIME) {
134+
match sanitizer_fn_attr.rtsan_setting {
135+
RtsanSetting::Nonblocking => {
136+
attrs.push(llvm::AttributeKind::SanitizeRealtimeNonblocking.create_attr(cx.llcx))
137+
}
138+
RtsanSetting::Blocking => {
139+
attrs.push(llvm::AttributeKind::SanitizeRealtimeBlocking.create_attr(cx.llcx))
140+
}
141+
// caller is the default, so no llvm attribute
142+
RtsanSetting::Caller => (),
143+
}
144+
}
135145
attrs
136146
}
137147

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ pub(crate) unsafe fn llvm_optimize(
646646
sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
647647
sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
648648
sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int,
649+
sanitize_realtime: config.sanitizer.contains(SanitizerSet::REALTIME),
649650
sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD),
650651
sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS),
651652
sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS),

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ pub(crate) enum AttributeKind {
289289
DeadOnUnwind = 43,
290290
DeadOnReturn = 44,
291291
CapturesReadOnly = 45,
292+
SanitizeRealtimeNonblocking = 46,
293+
SanitizeRealtimeBlocking = 47,
292294
}
293295

294296
/// LLVMIntPredicate
@@ -481,6 +483,7 @@ pub(crate) struct SanitizerOptions {
481483
pub sanitize_memory: bool,
482484
pub sanitize_memory_recover: bool,
483485
pub sanitize_memory_track_origins: c_int,
486+
pub sanitize_realtime: bool,
484487
pub sanitize_thread: bool,
485488
pub sanitize_hwaddress: bool,
486489
pub sanitize_hwaddress_recover: bool,

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,9 @@ fn add_sanitizer_libraries(
12511251
if sanitizer.contains(SanitizerSet::SAFESTACK) {
12521252
link_sanitizer_runtime(sess, flavor, linker, "safestack");
12531253
}
1254+
if sanitizer.contains(SanitizerSet::REALTIME) {
1255+
link_sanitizer_runtime(sess, flavor, linker, "rtsan");
1256+
}
12541257
}
12551258

12561259
fn link_sanitizer_runtime(

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::str::FromStr;
33
use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
6-
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy};
6+
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy, RtsanSetting};
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
99
use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
@@ -349,9 +349,12 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
349349
codegen_fn_attrs.alignment =
350350
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);
351351

352-
// Compute the disabled sanitizers.
353-
codegen_fn_attrs.sanitizers.disabled |=
354-
tcx.sanitizer_settings_for(did).disabled;
352+
// Per sanitizer override if it's in the default state
353+
let sanitizers = tcx.sanitizer_settings_for(did);
354+
codegen_fn_attrs.sanitizers.disabled |= sanitizers.disabled;
355+
if codegen_fn_attrs.sanitizers.rtsan_setting == RtsanSetting::default() {
356+
codegen_fn_attrs.sanitizers.rtsan_setting = sanitizers.rtsan_setting;
357+
}
355358
// On trait methods, inherit the `#[align]` of the trait's method prototype.
356359
codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));
357360

@@ -587,7 +590,7 @@ fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs
587590
};
588591

589592
// Check for a sanitize annotation directly on this def.
590-
if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
593+
if let Some((on_set, off_set, rtsan)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, rtsan, ..} => (on_set, off_set, rtsan))
591594
{
592595
// the on set is the set of sanitizers explicitly enabled.
593596
// we mask those out since we want the set of disabled sanitizers here
@@ -598,6 +601,11 @@ fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs
598601
// the on set and off set are distjoint since there's a third option: unset.
599602
// a node may not set the sanitizer setting in which case it inherits from parents.
600603
// the code above in this function does this backtracking
604+
605+
// if rtsan was specified here override the parent
606+
if let Some(rtsan) = rtsan {
607+
settings.rtsan_setting = *rtsan;
608+
}
601609
}
602610
settings
603611
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,20 @@ pub struct DebugVisualizer {
382382
pub path: Symbol,
383383
}
384384

385+
#[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)]
386+
#[derive(HashStable_Generic, PrintAttribute)]
387+
pub enum RtsanSetting {
388+
Nonblocking,
389+
Blocking,
390+
Caller,
391+
}
392+
393+
impl RtsanSetting {
394+
pub const fn default() -> Self {
395+
RtsanSetting::Caller
396+
}
397+
}
398+
385399
/// Represents parsed *built-in* inert attributes.
386400
///
387401
/// ## Overview
@@ -683,7 +697,13 @@ pub enum AttributeKind {
683697
///
684698
/// the on set and off set are distjoint since there's a third option: unset.
685699
/// a node may not set the sanitizer setting in which case it inherits from parents.
686-
Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
700+
/// rtsan is unset if None
701+
Sanitize {
702+
on_set: SanitizerSet,
703+
off_set: SanitizerSet,
704+
rtsan: Option<RtsanSetting>,
705+
span: Span,
706+
},
687707

688708
/// Represents `#[should_panic]`
689709
ShouldPanic { reason: Option<Symbol>, span: Span },

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
3939
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
4040
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
41+
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
4142
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
4243
#include "llvm/Transforms/Scalar/AnnotationRemarks.h"
4344
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
@@ -518,6 +519,7 @@ struct LLVMRustSanitizerOptions {
518519
bool SanitizeMemory;
519520
bool SanitizeMemoryRecover;
520521
int SanitizeMemoryTrackOrigins;
522+
bool SanitizerRealtime;
521523
bool SanitizeThread;
522524
bool SanitizeHWAddress;
523525
bool SanitizeHWAddressRecover;
@@ -773,6 +775,17 @@ extern "C" LLVMRustResult LLVMRustOptimize(
773775
MPM.addPass(HWAddressSanitizerPass(opts));
774776
});
775777
}
778+
if (SanitizerOptions->SanitizerRealtime) {
779+
OptimizerLastEPCallbacks.push_back(
780+
#if LLVM_VERSION_GE(20, 0)
781+
[](ModulePassManager &MPM, OptimizationLevel Level,
782+
ThinOrFullLTOPhase phase) {
783+
#else
784+
[](ModulePassManager &MPM, OptimizationLevel Level) {
785+
#endif
786+
MPM.addPass(RealtimeSanitizerPass());
787+
});
788+
}
776789
}
777790

778791
ModulePassManager MPM;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ enum class LLVMRustAttributeKind {
245245
DeadOnUnwind = 43,
246246
DeadOnReturn = 44,
247247
CapturesReadOnly = 45,
248+
SanitizeRealtimeNonblocking = 46,
249+
SanitizeRealtimeBlocking = 47,
248250
};
249251

250252
static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
@@ -340,6 +342,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
340342
case LLVMRustAttributeKind::CapturesAddress:
341343
case LLVMRustAttributeKind::CapturesReadOnly:
342344
report_fatal_error("Should be handled separately");
345+
case LLVMRustAttributeKind::SanitizeRealtimeNonblocking:
346+
return Attribute::SanitizeRealtime;
347+
case LLVMRustAttributeKind::SanitizeRealtimeBlocking:
348+
return Attribute::SanitizeRealtimeBlocking;
343349
}
344350
report_fatal_error("bad LLVMRustAttributeKind");
345351
}

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use rustc_abi::Align;
4-
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
4+
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr, RtsanSetting};
55
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
66
use rustc_span::Symbol;
77
use rustc_target::spec::SanitizerSet;
@@ -245,10 +245,11 @@ impl CodegenFnAttrs {
245245
#[derive(Clone, Copy, Debug, HashStable, TyEncodable, TyDecodable, Eq, PartialEq)]
246246
pub struct SanitizerFnAttrs {
247247
pub disabled: SanitizerSet,
248+
pub rtsan_setting: RtsanSetting,
248249
}
249250

250251
impl SanitizerFnAttrs {
251252
pub const fn default() -> Self {
252-
Self { disabled: SanitizerSet::empty() }
253+
Self { disabled: SanitizerSet::empty(), rtsan_setting: RtsanSetting::default() }
253254
}
254255
}

0 commit comments

Comments
 (0)