Skip to content

Commit 9b90703

Browse files
committed
Add support for sanitizer recovery
1 parent 317f68a commit 9b90703

File tree

4 files changed

+80
-11
lines changed

4 files changed

+80
-11
lines changed

src/librustc/session/config.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,27 @@ pub struct Config {
4343
pub usize_ty: UintTy,
4444
}
4545

46-
#[derive(Clone, Hash, Debug)]
46+
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
4747
pub enum Sanitizer {
4848
Address,
4949
Leak,
5050
Memory,
5151
Thread,
5252
}
5353

54+
impl FromStr for Sanitizer {
55+
type Err = ();
56+
fn from_str(s: &str) -> Result<Sanitizer, ()> {
57+
match s {
58+
"address" => Ok(Sanitizer::Address),
59+
"leak" => Ok(Sanitizer::Leak),
60+
"memory" => Ok(Sanitizer::Memory),
61+
"thread" => Ok(Sanitizer::Thread),
62+
_ => Err(()),
63+
}
64+
}
65+
}
66+
5467
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
5568
pub enum OptLevel {
5669
No, // -O0
@@ -819,6 +832,8 @@ macro_rules! options {
819832
Some("one of: `full`, `partial`, or `off`");
820833
pub const parse_sanitizer: Option<&str> =
821834
Some("one of: `address`, `leak`, `memory` or `thread`");
835+
pub const parse_sanitizer_list: Option<&str> =
836+
Some("comma separated list of sanitizers");
822837
pub const parse_linker_flavor: Option<&str> =
823838
Some(::rustc_target::spec::LinkerFlavor::one_of());
824839
pub const parse_optimization_fuel: Option<&str> =
@@ -1013,15 +1028,30 @@ macro_rules! options {
10131028
true
10141029
}
10151030

1016-
fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
1017-
match v {
1018-
Some("address") => *slote = Some(Sanitizer::Address),
1019-
Some("leak") => *slote = Some(Sanitizer::Leak),
1020-
Some("memory") => *slote = Some(Sanitizer::Memory),
1021-
Some("thread") => *slote = Some(Sanitizer::Thread),
1022-
_ => return false,
1031+
fn parse_sanitizer(slot: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
1032+
if let Some(Ok(s)) = v.map(str::parse) {
1033+
*slot = Some(s);
1034+
true
1035+
} else {
1036+
false
1037+
}
1038+
}
1039+
1040+
fn parse_sanitizer_list(slot: &mut Vec<Sanitizer>, v: Option<&str>) -> bool {
1041+
if let Some(v) = v {
1042+
for s in v.split(',').map(str::parse) {
1043+
if let Ok(s) = s {
1044+
if !slot.contains(&s) {
1045+
slot.push(s);
1046+
}
1047+
} else {
1048+
return false;
1049+
}
1050+
}
1051+
true
1052+
} else {
1053+
false
10231054
}
1024-
true
10251055
}
10261056

10271057
fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
@@ -1379,6 +1409,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
13791409
"pass `-install_name @rpath/...` to the macOS linker"),
13801410
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
13811411
"use a sanitizer"),
1412+
sanitizer_recover: Vec<Sanitizer> = (vec![], parse_sanitizer_list, [TRACKED],
1413+
"Enable recovery for selected sanitizers"),
13821414
fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
13831415
"set the optimization fuel quota for a crate"),
13841416
print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
@@ -2984,6 +3016,7 @@ mod dep_tracking {
29843016
Option<cstore::NativeLibraryKind>
29853017
));
29863018
impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
3019+
impl_dep_tracking_hash_for_sortable_vec_of!(Sanitizer);
29873020

29883021
impl<T1, T2> DepTrackingHash for (T1, T2)
29893022
where

src/librustc_codegen_llvm/back/write.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,17 +364,16 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
364364
}
365365

366366
if let Some(sanitizer) = &config.sanitizer {
367+
let recover = config.sanitizer_recover.contains(sanitizer);
367368
match sanitizer {
368369
Sanitizer::Address => {
369-
let recover = false;
370370
extra_passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(
371371
recover));
372372
extra_passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(
373373
recover));
374374
}
375375
Sanitizer::Memory => {
376376
let track_origins = 0;
377-
let recover = false;
378377
extra_passes.push(llvm::LLVMRustCreateMemorySanitizerPass(
379378
track_origins, recover));
380379
}

src/librustc_codegen_ssa/back/write.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub struct ModuleConfig {
6060
pub pgo_use: Option<PathBuf>,
6161

6262
pub sanitizer: Option<Sanitizer>,
63+
pub sanitizer_recover: Vec<Sanitizer>,
6364

6465
// Flags indicating which outputs to produce.
6566
pub emit_pre_lto_bc: bool,
@@ -100,6 +101,7 @@ impl ModuleConfig {
100101
pgo_use: None,
101102

102103
sanitizer: None,
104+
sanitizer_recover: Default::default(),
103105

104106
emit_no_opt_bc: false,
105107
emit_pre_lto_bc: false,
@@ -356,6 +358,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
356358
modules_config.pgo_gen = sess.opts.cg.profile_generate.clone();
357359
modules_config.pgo_use = sess.opts.cg.profile_use.clone();
358360
modules_config.sanitizer = sess.opts.debugging_opts.sanitizer.clone();
361+
modules_config.sanitizer_recover = sess.opts.debugging_opts.sanitizer_recover.clone();
359362
modules_config.opt_level = Some(sess.opts.optimize);
360363
modules_config.opt_size = Some(sess.opts.optimize);
361364

src/test/codegen/sanitizer-recover.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Verifies that AddressSanitizer and MemorySanitizer
2+
// recovery mode can be enabled with -Zsanitizer-recover.
3+
//
4+
// needs-sanitizer-support
5+
// only-linux
6+
// only-x86_64
7+
// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER
8+
//
9+
//[ASAN] compile-flags: -Zsanitizer=address
10+
//[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address
11+
//[MSAN] compile-flags: -Zsanitizer=memory
12+
//[MSAN-RECOVER] compile-flags: -Zsanitizer=memory -Zsanitizer-recover=memory
13+
14+
#![crate_type="lib"]
15+
16+
// ASAN-LABEL: define i32 @penguin(
17+
// ASAN-RECOVER-LABEL: define i32 @penguin(
18+
// MSAN-LABEL: define i32 @penguin(
19+
// MSAN-RECOVER-LABEL: define i32 @penguin(
20+
#[no_mangle]
21+
pub fn penguin(p: &mut i32) -> i32 {
22+
// ASAN: call void @__asan_report_load4(i64 %0)
23+
// ASAN: unreachable
24+
//
25+
// ASAN-RECOVER: call void @__asan_report_load4_noabort(
26+
// ASAN-RECOVER-NOT: unreachable
27+
//
28+
// MSAN: call void @__msan_warning_noreturn()
29+
// MSAN: unreachable
30+
//
31+
// MSAN-RECOVER: call void @__msan_warning()
32+
// MSAN-RECOVER-NOT: unreachable
33+
*p
34+
}

0 commit comments

Comments
 (0)