Skip to content

Commit ae23709

Browse files
committed
Add support for panicking in the emulated application when unsupported syscalls are encountered
1 parent 81ee877 commit ae23709

File tree

12 files changed

+64
-6
lines changed

12 files changed

+64
-6
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ environment variable:
228228
This can be used to find which parts of your program are executing slowly under Miri.
229229
The profile is written out to a file with the prefix `<name>`, and can be processed
230230
using the tools in the repository https://github.com/rust-lang/measureme.
231+
* `-Zmiri-panic-on-unsupported` will makes some forms of unsupported functionality,
232+
such as FFI and unsupported syscalls, panic within the context of the emulated
233+
application instead of raising an error within the context of Miri (and halting
234+
execution). Note that code might not expect these operations to ever panic, so
235+
this flag can lead to strange (mis)behavior.
231236
* `-Zmiri-seed=<hex>` configures the seed of the RNG that Miri uses to resolve
232237
non-determinism. This RNG is used to pick base addresses for allocations.
233238
When isolation is enabled (the default), this is also used to emulate system

src/bin/miri.rs

+3
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ fn main() {
296296
"-Zmiri-ignore-leaks" => {
297297
miri_config.ignore_leaks = true;
298298
}
299+
"-Zmiri-panic-on-unsupported" => {
300+
miri_config.panic_on_unsupported = true;
301+
}
299302
"-Zmiri-track-raw-pointers" => {
300303
miri_config.track_raw = true;
301304
}

src/eval.rs

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ pub struct MiriConfig {
5959
/// If `Some`, enable the `measureme` profiler, writing results to a file
6060
/// with the specified prefix.
6161
pub measureme_out: Option<String>,
62+
/// Panic when unsupported functionality is encountered
63+
pub panic_on_unsupported: bool,
6264
}
6365

6466
impl Default for MiriConfig {
@@ -80,6 +82,7 @@ impl Default for MiriConfig {
8082
data_race_detector: true,
8183
cmpxchg_weak_failure_rate: 0.8,
8284
measureme_out: None,
85+
panic_on_unsupported: false,
8386
}
8487
}
8588
}

src/helpers.rs

+17
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
636636
== this.tcx.def_path(start_fn).krate
637637
})
638638
}
639+
640+
/// Handler that should be called when unsupported functionality is encountered.
641+
/// This function will either panic within the context of the emulated application
642+
/// or return an error in the Miri process context
643+
///
644+
/// Return value of `Ok(bool)` indicates whether execution should continue.
645+
fn handle_unsupported<S: AsRef<str>>(&mut self, error_msg: S) -> InterpResult<'tcx, ()> {
646+
let this = self.eval_context_mut();
647+
if this.machine.panic_on_unsupported {
648+
// message is slightly different here to make automated analysis easier
649+
let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
650+
this.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?;
651+
return Ok(());
652+
} else {
653+
throw_unsup_format!("{}", error_msg.as_ref());
654+
}
655+
}
639656
}
640657

641658
/// Check that the number of args is what we expect.

src/machine.rs

+6
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ pub struct Evaluator<'mir, 'tcx> {
297297

298298
/// Cache of `Instance` exported under the given `Symbol` name.
299299
pub(crate) exported_symbols_cache: FxHashMap<Symbol, Instance<'tcx>>,
300+
301+
/// Whether to raise a panic in the context of the evaluated process when unsupported
302+
/// functionality is encountered. If `false`, an error is propagated in the Miri application context
303+
/// instead (default behavior)
304+
pub(crate) panic_on_unsupported: bool,
300305
}
301306

302307
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
@@ -326,6 +331,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
326331
profiler,
327332
string_cache: Default::default(),
328333
exported_symbols_cache: FxHashMap::default(),
334+
panic_on_unsupported: config.panic_on_unsupported,
329335
}
330336
}
331337
}

src/shims/foreign_items.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
259259
if let Some(body) = this.lookup_exported_symbol(link_name_sym)? {
260260
return Ok(Some(body));
261261
}
262-
throw_unsup_format!("can't call (diverging) foreign function: {}", link_name);
262+
this.handle_unsupported(format!(
263+
"can't call (diverging) foreign function: {}",
264+
link_name
265+
))?;
266+
return Ok(None);
263267
}
264268
},
265269
Some(p) => p,
@@ -276,7 +280,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
276280
if let Some(body) = this.lookup_exported_symbol(link_name_sym)? {
277281
return Ok(Some(body));
278282
}
279-
throw_unsup_format!("can't call foreign function: {}", link_name);
283+
284+
this.handle_unsupported(format!("can't call foreign function: {}", link_name))?;
285+
return Ok(None);
280286
}
281287
}
282288

src/shims/panic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
161161
}
162162
}
163163

164-
/// Starta a panic in the interpreter with the given message as payload.
164+
/// Start a panic in the interpreter with the given message as payload.
165165
fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
166166
let this = self.eval_context_mut();
167167

src/shims/posix/linux/foreign_items.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
183183
id if id == sys_futex => {
184184
futex(this, args, dest)?;
185185
}
186-
id => throw_unsup_format!("Miri does not support syscall ID {}", id),
186+
id => {
187+
this.handle_unsupported(format!("can't execute syscall with ID {}", id))?;
188+
return Ok(EmulateByNameResult::NotSupported);
189+
}
187190
}
188191
}
189192

src/shims/windows/foreign_items.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
343343
// Better error for attempts to create a thread
344344
"CreateThread" => {
345345
this.check_abi(abi, Abi::System { unwind: false })?;
346-
throw_unsup_format!("Miri does not support concurrency on Windows");
346+
347+
this.handle_unsupported("can't create threads on Windows")?;
348+
return Ok(EmulateByNameResult::AlreadyJumped);
347349
}
348350

349351
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.

tests/compile-fail/concurrency/thread-spawn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use std::thread;
55

6-
// error-pattern: Miri does not support concurrency on Windows
6+
// error-pattern: can't create threads on Windows
77

88
fn main() {
99
thread::spawn(|| {});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile-flags: -Zmiri-panic-on-unsupported
2+
3+
fn main() {
4+
extern "Rust" {
5+
fn foo();
6+
}
7+
8+
unsafe {
9+
foo();
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
thread 'main' panicked at 'unsupported Miri functionality: can't call foreign function: foo', $DIR/unsupported_foreign_function.rs:9:9
2+
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

0 commit comments

Comments
 (0)