Add support for panicking in the emulated application when unsupported syscalls are encountered
This commit is contained in:
parent
81ee877f71
commit
ae237098f8
@ -228,6 +228,11 @@ environment variable:
|
||||
This can be used to find which parts of your program are executing slowly under Miri.
|
||||
The profile is written out to a file with the prefix `<name>`, and can be processed
|
||||
using the tools in the repository https://github.com/rust-lang/measureme.
|
||||
* `-Zmiri-panic-on-unsupported` will makes some forms of unsupported functionality,
|
||||
such as FFI and unsupported syscalls, panic within the context of the emulated
|
||||
application instead of raising an error within the context of Miri (and halting
|
||||
execution). Note that code might not expect these operations to ever panic, so
|
||||
this flag can lead to strange (mis)behavior.
|
||||
* `-Zmiri-seed=<hex>` configures the seed of the RNG that Miri uses to resolve
|
||||
non-determinism. This RNG is used to pick base addresses for allocations.
|
||||
When isolation is enabled (the default), this is also used to emulate system
|
||||
|
@ -296,6 +296,9 @@ fn main() {
|
||||
"-Zmiri-ignore-leaks" => {
|
||||
miri_config.ignore_leaks = true;
|
||||
}
|
||||
"-Zmiri-panic-on-unsupported" => {
|
||||
miri_config.panic_on_unsupported = true;
|
||||
}
|
||||
"-Zmiri-track-raw-pointers" => {
|
||||
miri_config.track_raw = true;
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ pub struct MiriConfig {
|
||||
/// If `Some`, enable the `measureme` profiler, writing results to a file
|
||||
/// with the specified prefix.
|
||||
pub measureme_out: Option<String>,
|
||||
/// Panic when unsupported functionality is encountered
|
||||
pub panic_on_unsupported: bool,
|
||||
}
|
||||
|
||||
impl Default for MiriConfig {
|
||||
@ -80,6 +82,7 @@ impl Default for MiriConfig {
|
||||
data_race_detector: true,
|
||||
cmpxchg_weak_failure_rate: 0.8,
|
||||
measureme_out: None,
|
||||
panic_on_unsupported: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -636,6 +636,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
== this.tcx.def_path(start_fn).krate
|
||||
})
|
||||
}
|
||||
|
||||
/// Handler that should be called when unsupported functionality is encountered.
|
||||
/// This function will either panic within the context of the emulated application
|
||||
/// or return an error in the Miri process context
|
||||
///
|
||||
/// Return value of `Ok(bool)` indicates whether execution should continue.
|
||||
fn handle_unsupported<S: AsRef<str>>(&mut self, error_msg: S) -> InterpResult<'tcx, ()> {
|
||||
let this = self.eval_context_mut();
|
||||
if this.machine.panic_on_unsupported {
|
||||
// message is slightly different here to make automated analysis easier
|
||||
let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
|
||||
this.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?;
|
||||
return Ok(());
|
||||
} else {
|
||||
throw_unsup_format!("{}", error_msg.as_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the number of args is what we expect.
|
||||
|
@ -297,6 +297,11 @@ pub struct Evaluator<'mir, 'tcx> {
|
||||
|
||||
/// Cache of `Instance` exported under the given `Symbol` name.
|
||||
pub(crate) exported_symbols_cache: FxHashMap<Symbol, Instance<'tcx>>,
|
||||
|
||||
/// Whether to raise a panic in the context of the evaluated process when unsupported
|
||||
/// functionality is encountered. If `false`, an error is propagated in the Miri application context
|
||||
/// instead (default behavior)
|
||||
pub(crate) panic_on_unsupported: bool,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
|
||||
@ -326,6 +331,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
|
||||
profiler,
|
||||
string_cache: Default::default(),
|
||||
exported_symbols_cache: FxHashMap::default(),
|
||||
panic_on_unsupported: config.panic_on_unsupported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +259,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
if let Some(body) = this.lookup_exported_symbol(link_name_sym)? {
|
||||
return Ok(Some(body));
|
||||
}
|
||||
throw_unsup_format!("can't call (diverging) foreign function: {}", link_name);
|
||||
this.handle_unsupported(format!(
|
||||
"can't call (diverging) foreign function: {}",
|
||||
link_name
|
||||
))?;
|
||||
return Ok(None);
|
||||
}
|
||||
},
|
||||
Some(p) => p,
|
||||
@ -276,7 +280,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
if let Some(body) = this.lookup_exported_symbol(link_name_sym)? {
|
||||
return Ok(Some(body));
|
||||
}
|
||||
throw_unsup_format!("can't call foreign function: {}", link_name);
|
||||
|
||||
this.handle_unsupported(format!("can't call foreign function: {}", link_name))?;
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
}
|
||||
}
|
||||
|
||||
/// Starta a panic in the interpreter with the given message as payload.
|
||||
/// Start a panic in the interpreter with the given message as payload.
|
||||
fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
@ -183,7 +183,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
id if id == sys_futex => {
|
||||
futex(this, args, dest)?;
|
||||
}
|
||||
id => throw_unsup_format!("Miri does not support syscall ID {}", id),
|
||||
id => {
|
||||
this.handle_unsupported(format!("can't execute syscall with ID {}", id))?;
|
||||
return Ok(EmulateByNameResult::NotSupported);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,7 +343,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
// Better error for attempts to create a thread
|
||||
"CreateThread" => {
|
||||
this.check_abi(abi, Abi::System { unwind: false })?;
|
||||
throw_unsup_format!("Miri does not support concurrency on Windows");
|
||||
|
||||
this.handle_unsupported("can't create threads on Windows")?;
|
||||
return Ok(EmulateByNameResult::AlreadyJumped);
|
||||
}
|
||||
|
||||
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
// error-pattern: Miri does not support concurrency on Windows
|
||||
// error-pattern: can't create threads on Windows
|
||||
|
||||
fn main() {
|
||||
thread::spawn(|| {});
|
||||
|
11
tests/run-pass/panic/unsupported_foreign_function.rs
Normal file
11
tests/run-pass/panic/unsupported_foreign_function.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// compile-flags: -Zmiri-panic-on-unsupported
|
||||
|
||||
fn main() {
|
||||
extern "Rust" {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
foo();
|
||||
}
|
||||
}
|
2
tests/run-pass/panic/unsupported_foreign_function.stderr
Normal file
2
tests/run-pass/panic/unsupported_foreign_function.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
thread 'main' panicked at 'unsupported Miri functionality: can't call foreign function: foo', $DIR/unsupported_foreign_function.rs:9:9
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
Loading…
x
Reference in New Issue
Block a user