Skip to content

Commit ab9186c

Browse files
committed
Add support for panicking in the emulated application when unsupported syscalls are encountered
1 parent 28717a0 commit ab9186c

12 files changed

+79
-6
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ 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).
231235
* `-Zmiri-seed=<hex>` configures the seed of the RNG that Miri uses to resolve
232236
non-determinism. This RNG is used to pick base addresses for allocations.
233237
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

+16
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
628628
}
629629
Ok(())
630630
}
631+
632+
/// Handler that should be called when unsupported functionality is encountered.
633+
/// This function will either panic within the context of the emulated application
634+
/// or return an error in the Miri process context
635+
///
636+
/// Return value of `Ok(bool)` indicates whether execution should continue.
637+
fn handle_unsupported<S: AsRef<str>>(&mut self, error_msg: S) -> InterpResult<'tcx, ()> {
638+
if self.eval_context_ref().machine.panic_on_unsupported {
639+
// message is slightly different here to make automated analysis easier
640+
let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
641+
self.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?;
642+
return Ok(());
643+
} else {
644+
throw_unsup_format!("{}", error_msg);
645+
}
646+
}
631647
}
632648

633649
/// 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

+18-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,24 @@ 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+
/// Handler that should be called when unsupported functionality is encountered.
165+
/// This function will either panic within the context of the emulated application
166+
/// or return an error in the Miri process context
167+
///
168+
/// Return value of `Ok(bool)` indicates whether execution should continue.
169+
fn handle_unsupported<S: AsRef<str>>(&mut self, error_msg: S) -> InterpResult<'tcx, ()> {
170+
let error = format!("unsupported Miri functionality: {}", error_msg.as_ref());
171+
172+
if self.eval_context_ref().machine.panic_on_unsupported {
173+
// message is slightly different here to make automated analysis easier
174+
self.start_panic(error.as_ref(), StackPopUnwind::Skip)?;
175+
return Ok(());
176+
} else {
177+
throw_unsup_format!("{}", error);
178+
}
179+
}
180+
181+
/// Start a panic in the interpreter with the given message as payload.
165182
fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
166183
let this = self.eval_context_mut();
167184

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(false);
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("concurrency is not supported on Windows")?;
348+
return Ok(false);
347349
}
348350

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

tests/compile-fail/unsupported_foreign_function.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ fn main() {
44
}
55

66
unsafe {
7-
foo(); //~ ERROR unsupported operation: can't call foreign function: foo
7+
foo(); //~ ERROR unsupported operation: can't call foreign function "foo"
88
}
99
}
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)