diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2019-11-15 00:00:00 +0000 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2019-11-22 19:32:45 +0100 |
| commit | 9b907032891712c21ef9c8ff20c46cd2b20fcf30 (patch) | |
| tree | 356729cea279c0c86f2b3389ed9ca473057d3a0a | |
| parent | 317f68ab10c04719d54265f92784618afed914b6 (diff) | |
| download | rust-9b907032891712c21ef9c8ff20c46cd2b20fcf30.tar.gz rust-9b907032891712c21ef9c8ff20c46cd2b20fcf30.zip | |
Add support for sanitizer recovery
| -rw-r--r-- | src/librustc/session/config.rs | 51 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/back/write.rs | 3 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/back/write.rs | 3 | ||||
| -rw-r--r-- | src/test/codegen/sanitizer-recover.rs | 34 |
4 files changed, 80 insertions, 11 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 50752bac30f..afcbafd8a00 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -43,7 +43,7 @@ pub struct Config { pub usize_ty: UintTy, } -#[derive(Clone, Hash, Debug)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Sanitizer { Address, Leak, @@ -51,6 +51,19 @@ pub enum Sanitizer { Thread, } +impl FromStr for Sanitizer { + type Err = (); + fn from_str(s: &str) -> Result<Sanitizer, ()> { + match s { + "address" => Ok(Sanitizer::Address), + "leak" => Ok(Sanitizer::Leak), + "memory" => Ok(Sanitizer::Memory), + "thread" => Ok(Sanitizer::Thread), + _ => Err(()), + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum OptLevel { No, // -O0 @@ -819,6 +832,8 @@ macro_rules! options { Some("one of: `full`, `partial`, or `off`"); pub const parse_sanitizer: Option<&str> = Some("one of: `address`, `leak`, `memory` or `thread`"); + pub const parse_sanitizer_list: Option<&str> = + Some("comma separated list of sanitizers"); pub const parse_linker_flavor: Option<&str> = Some(::rustc_target::spec::LinkerFlavor::one_of()); pub const parse_optimization_fuel: Option<&str> = @@ -1013,15 +1028,30 @@ macro_rules! options { true } - fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool { - match v { - Some("address") => *slote = Some(Sanitizer::Address), - Some("leak") => *slote = Some(Sanitizer::Leak), - Some("memory") => *slote = Some(Sanitizer::Memory), - Some("thread") => *slote = Some(Sanitizer::Thread), - _ => return false, + fn parse_sanitizer(slot: &mut Option<Sanitizer>, v: Option<&str>) -> bool { + if let Some(Ok(s)) = v.map(str::parse) { + *slot = Some(s); + true + } else { + false + } + } + + fn parse_sanitizer_list(slot: &mut Vec<Sanitizer>, v: Option<&str>) -> bool { + if let Some(v) = v { + for s in v.split(',').map(str::parse) { + if let Ok(s) = s { + if !slot.contains(&s) { + slot.push(s); + } + } else { + return false; + } + } + true + } else { + false } - true } fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool { @@ -1379,6 +1409,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "pass `-install_name @rpath/...` to the macOS linker"), sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED], "use a sanitizer"), + sanitizer_recover: Vec<Sanitizer> = (vec![], parse_sanitizer_list, [TRACKED], + "Enable recovery for selected sanitizers"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], "set the optimization fuel quota for a crate"), print_fuel: Option<String> = (None, parse_opt_string, [TRACKED], @@ -2984,6 +3016,7 @@ mod dep_tracking { Option<cstore::NativeLibraryKind> )); impl_dep_tracking_hash_for_sortable_vec_of!((String, u64)); + impl_dep_tracking_hash_for_sortable_vec_of!(Sanitizer); impl<T1, T2> DepTrackingHash for (T1, T2) where diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 89728245eea..1b94cc605a5 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -364,9 +364,9 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>, } if let Some(sanitizer) = &config.sanitizer { + let recover = config.sanitizer_recover.contains(sanitizer); match sanitizer { Sanitizer::Address => { - let recover = false; extra_passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass( recover)); extra_passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass( @@ -374,7 +374,6 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>, } Sanitizer::Memory => { let track_origins = 0; - let recover = false; extra_passes.push(llvm::LLVMRustCreateMemorySanitizerPass( track_origins, recover)); } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index e11a1ab6ee8..f80869132c0 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -60,6 +60,7 @@ pub struct ModuleConfig { pub pgo_use: Option<PathBuf>, pub sanitizer: Option<Sanitizer>, + pub sanitizer_recover: Vec<Sanitizer>, // Flags indicating which outputs to produce. pub emit_pre_lto_bc: bool, @@ -100,6 +101,7 @@ impl ModuleConfig { pgo_use: None, sanitizer: None, + sanitizer_recover: Default::default(), emit_no_opt_bc: false, emit_pre_lto_bc: false, @@ -356,6 +358,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>( modules_config.pgo_gen = sess.opts.cg.profile_generate.clone(); modules_config.pgo_use = sess.opts.cg.profile_use.clone(); modules_config.sanitizer = sess.opts.debugging_opts.sanitizer.clone(); + modules_config.sanitizer_recover = sess.opts.debugging_opts.sanitizer_recover.clone(); modules_config.opt_level = Some(sess.opts.optimize); modules_config.opt_size = Some(sess.opts.optimize); diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs new file mode 100644 index 00000000000..a292332667b --- /dev/null +++ b/src/test/codegen/sanitizer-recover.rs @@ -0,0 +1,34 @@ +// Verifies that AddressSanitizer and MemorySanitizer +// recovery mode can be enabled with -Zsanitizer-recover. +// +// needs-sanitizer-support +// only-linux +// only-x86_64 +// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER +// +//[ASAN] compile-flags: -Zsanitizer=address +//[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address +//[MSAN] compile-flags: -Zsanitizer=memory +//[MSAN-RECOVER] compile-flags: -Zsanitizer=memory -Zsanitizer-recover=memory + +#![crate_type="lib"] + +// ASAN-LABEL: define i32 @penguin( +// ASAN-RECOVER-LABEL: define i32 @penguin( +// MSAN-LABEL: define i32 @penguin( +// MSAN-RECOVER-LABEL: define i32 @penguin( +#[no_mangle] +pub fn penguin(p: &mut i32) -> i32 { + // ASAN: call void @__asan_report_load4(i64 %0) + // ASAN: unreachable + // + // ASAN-RECOVER: call void @__asan_report_load4_noabort( + // ASAN-RECOVER-NOT: unreachable + // + // MSAN: call void @__msan_warning_noreturn() + // MSAN: unreachable + // + // MSAN-RECOVER: call void @__msan_warning() + // MSAN-RECOVER-NOT: unreachable + *p +} |
