Skip to content

Commit af8c2a0

Browse files
committed
Add flags to control user visibility of dummy ops in isolation
For the ops which are not supported in isolation mode (e.g. `getcwd`), miri produces a dummy error. By default, a warning is printed to let the user know about this decision. This change adds a couple of flags to control the level of details in such messages as per user requirement. `-Zmiri-ignore-dummy-op` -- stops generating warnings `-Zmiri-track-dummy-op` -- generates a note with a backtrace per line running dummy op
1 parent e945e0c commit af8c2a0

File tree

8 files changed

+50
-10
lines changed

8 files changed

+50
-10
lines changed

src/bin/miri.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ fn main() {
299299
"-Zmiri-track-raw-pointers" => {
300300
miri_config.track_raw = true;
301301
}
302+
"-Zmiri-track-dummy-op" => {
303+
miri_config.dummy_op_visibility = miri::DummyOpVisibility::Track;
304+
}
305+
"-Zmiri-ignore-dummy-op" => {
306+
miri_config.dummy_op_visibility = miri::DummyOpVisibility::Hide;
307+
}
302308
"--" => {
303309
after_dashdash = true;
304310
}

src/diagnostics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub enum NonHaltingDiagnostic {
5252
CreatedCallId(CallId),
5353
CreatedAlloc(AllocId),
5454
FreedAlloc(AllocId),
55+
DummyOpInIsolation(String),
5556
}
5657

5758
/// Emit a custom diagnostic without going through the miri-engine machinery
@@ -303,6 +304,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
303304
CreatedCallId(id) => format!("function call with id {}", id),
304305
CreatedAlloc(AllocId(id)) => format!("created allocation with id {}", id),
305306
FreedAlloc(AllocId(id)) => format!("freed allocation with id {}", id),
307+
DummyOpInIsolation(op) => format!("produced dummy error for `{}`", op),
306308
};
307309
report_msg(
308310
*this.tcx,

src/eval.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ pub enum AlignmentCheck {
2222
Int,
2323
}
2424

25+
#[derive(Copy, Clone, Debug)]
26+
pub enum DummyOpVisibility {
27+
/// Do not report a dummy op
28+
Hide,
29+
/// Print a warning without a backtrace, once per dummy op
30+
Warn,
31+
/// Print a note with a backtrace, once per line calling dummy op
32+
Track,
33+
}
34+
2535
/// Configuration needed to spawn a Miri instance.
2636
#[derive(Clone)]
2737
pub struct MiriConfig {

src/helpers.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -397,12 +397,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
397397
Ok(())
398398
}
399399

400-
/// Helper function used inside the shims of foreign functions
401-
/// which produce a dummy error when isolation is enabled. It is
402-
/// used to print a warning informing this decision to the user.
403-
fn warn_foreign_in_isolation(&self, name: &str) {
400+
/// Helper function used inside the shims of foreign functions which produce a dummy error
401+
/// when isolation is enabled. It is used to print a warning/backtrace, informing this
402+
/// decision to the user.
403+
fn report_dummy_in_isolation(&self, name: &str) {
404404
let this = self.eval_context_ref();
405-
this.tcx.sess.warn(&format!("`{}` in isolation mode produced a dummy error", name));
405+
match this.machine.dummy_op_visibility {
406+
DummyOpVisibility::Warn => {
407+
let msg = format!("`{}` in isolation mode produced a dummy error", name);
408+
let mut warn = this.tcx.sess.struct_warn(&msg);
409+
warn.note("run with -Zmiri-track-dummy-op to track with a backtrace");
410+
warn.note("run with -Zmiri-ignore-dummy-op to ignore warning");
411+
warn.emit();
412+
}
413+
DummyOpVisibility::Track => {
414+
register_diagnostic(NonHaltingDiagnostic::DummyOpInIsolation(name.to_string()));
415+
}
416+
DummyOpVisibility::Hide => {} // no diagnostics
417+
}
406418
}
407419

408420
/// Helper function used inside the shims of foreign functions to assert that the target OS

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub use crate::diagnostics::{
5959
register_diagnostic, report_error, EvalContextExt as DiagnosticsEvalContextExt,
6060
NonHaltingDiagnostic, TerminationInfo,
6161
};
62-
pub use crate::eval::{create_ecx, eval_main, AlignmentCheck, MiriConfig};
62+
pub use crate::eval::{create_ecx, eval_main, AlignmentCheck, DummyOpVisibility, MiriConfig};
6363
pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
6464
pub use crate::machine::{
6565
AllocExtra, Evaluator, FrameData, MemoryExtra, MiriEvalContext, MiriEvalContextExt,

src/machine.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ pub struct Evaluator<'mir, 'tcx> {
267267
/// and random number generation is delegated to the host.
268268
pub(crate) communicate: bool,
269269

270+
/// Level of user visibility to dummy ops run in isolation mode.
271+
pub(crate) dummy_op_visibility: DummyOpVisibility,
272+
270273
/// Whether to enforce the validity invariant.
271274
pub(crate) validate: bool,
272275

src/shims/env.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
338338
}
339339
} else {
340340
// Return a dummy error in isolation mode, after printing a warning about it.
341-
this.warn_foreign_in_isolation("getcwd");
341+
this.report_dummy_in_isolation("getcwd");
342342
let err = Error::new(ErrorKind::NotFound, "dummy error in isolation mode");
343343
this.set_last_error_from_io_error(err)?;
344344
}
@@ -366,7 +366,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
366366
}
367367
} else {
368368
// Return a dummy error in isolation mode, after printing a warning about it.
369-
this.warn_foreign_in_isolation("GetCurrentDirectoryW");
369+
this.report_dummy_in_isolation("GetCurrentDirectoryW");
370370
let err = Error::new(ErrorKind::NotFound, "dummy error in isolation mode");
371371
this.set_last_error_from_io_error(err)?;
372372
}
@@ -393,7 +393,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
393393
}
394394
} else {
395395
// Return a dummy error in isolation mode, after printing a warning about it.
396-
this.warn_foreign_in_isolation("chdir");
396+
this.report_dummy_in_isolation("chdir");
397397
let err = Error::new(ErrorKind::NotFound, "dummy error in isolation mode");
398398
this.set_last_error_from_io_error(err)?;
399399

@@ -423,7 +423,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
423423
}
424424
} else {
425425
// Return a dummy error in isolation mode, after printing a warning about it.
426-
this.warn_foreign_in_isolation("SetCurrentDirectoryW");
426+
this.report_dummy_in_isolation("SetCurrentDirectoryW");
427427
let err = Error::new(ErrorKind::NotFound, "dummy error in isolation mode");
428428
this.set_last_error_from_io_error(err)?;
429429
Ok(0)

tests/run-pass/current_dir_with_isolation.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,12 @@ fn main() {
55
// Test that current dir operations return the dummy error instead
66
// of stopping the machine in isolation mode
77
assert_eq!(env::current_dir().unwrap_err().kind(), ErrorKind::NotFound);
8+
for _i in 0..3 {
9+
assert_eq!(env::current_dir().unwrap_err().kind(), ErrorKind::NotFound);
10+
}
11+
812
assert_eq!(env::set_current_dir("..").unwrap_err().kind(), ErrorKind::NotFound);
13+
for _i in 0..3 {
14+
assert_eq!(env::set_current_dir("..").unwrap_err().kind(), ErrorKind::NotFound);
15+
}
916
}

0 commit comments

Comments
 (0)