Skip to content

Commit 6bd7556

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 1f3cf4d commit 6bd7556

File tree

8 files changed

+58
-15
lines changed

8 files changed

+58
-15
lines changed

src/bin/miri.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ fn main() {
236236
"-Zmiri-track-raw-pointers" => {
237237
miri_config.track_raw = true;
238238
}
239+
"-Zmiri-track-dummy-op" => {
240+
miri_config.dummy_op_visibility = miri::DummyOpVisibility::Track;
241+
}
242+
"-Zmiri-ignore-dummy-op" => {
243+
miri_config.dummy_op_visibility = miri::DummyOpVisibility::Hide;
244+
}
239245
"--" => {
240246
after_dashdash = true;
241247
}

src/diagnostics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub enum NonHaltingDiagnostic {
4040
CreatedCallId(CallId),
4141
CreatedAlloc(AllocId),
4242
FreedAlloc(AllocId),
43+
DummyOpInIsolation(String),
4344
}
4445

4546
/// Emit a custom diagnostic without going through the miri-engine machinery
@@ -279,6 +280,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
279280
CreatedCallId(id) => format!("function call with id {}", id),
280281
CreatedAlloc(AllocId(id)) => format!("created allocation with id {}", id),
281282
FreedAlloc(AllocId(id)) => format!("freed allocation with id {}", id),
283+
DummyOpInIsolation(op) => format!("produced dummy error for `{}`", op),
282284
};
283285
report_msg(
284286
*this.tcx,

src/eval.rs

Lines changed: 14 additions & 1 deletion
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 {
@@ -54,6 +64,8 @@ pub struct MiriConfig {
5464
/// Rate of spurious failures for compare_exchange_weak atomic operations,
5565
/// between 0.0 and 1.0, defaulting to 0.8 (80% chance of failure).
5666
pub cmpxchg_weak_failure_rate: f64,
67+
/// Visibility level of a dummy op performed in isolation mode
68+
pub dummy_op_visibility: DummyOpVisibility,
5769
}
5870

5971
impl Default for MiriConfig {
@@ -73,6 +85,7 @@ impl Default for MiriConfig {
7385
track_raw: false,
7486
data_race_detector: true,
7587
cmpxchg_weak_failure_rate: 0.8,
88+
dummy_op_visibility: DummyOpVisibility::Warn,
7689
}
7790
}
7891
}
@@ -92,7 +105,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
92105
tcx,
93106
rustc_span::source_map::DUMMY_SP,
94107
param_env,
95-
Evaluator::new(config.communicate, config.validate, layout_cx),
108+
Evaluator::new(&config, layout_cx),
96109
MemoryExtra::new(&config),
97110
);
98111
// Complete initialization.

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
@@ -57,7 +57,7 @@ pub use crate::diagnostics::{
5757
register_diagnostic, report_error, EvalContextExt as DiagnosticsEvalContextExt,
5858
NonHaltingDiagnostic, TerminationInfo,
5959
};
60-
pub use crate::eval::{create_ecx, eval_main, AlignmentCheck, MiriConfig};
60+
pub use crate::eval::{create_ecx, eval_main, AlignmentCheck, DummyOpVisibility, MiriConfig};
6161
pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
6262
pub use crate::machine::{
6363
AllocExtra, Evaluator, FrameData, MemoryExtra, MiriEvalContext, MiriEvalContextExt,

src/machine.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ pub struct Evaluator<'mir, 'tcx> {
253253
/// and random number generation is delegated to the host.
254254
pub(crate) communicate: bool,
255255

256+
/// Level of user visibility to dummy ops run in isolation mode.
257+
pub(crate) dummy_op_visibility: DummyOpVisibility,
258+
256259
/// Whether to enforce the validity invariant.
257260
pub(crate) validate: bool,
258261

@@ -274,8 +277,7 @@ pub struct Evaluator<'mir, 'tcx> {
274277

275278
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
276279
pub(crate) fn new(
277-
communicate: bool,
278-
validate: bool,
280+
config: &MiriConfig,
279281
layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
280282
) -> Self {
281283
let layouts =
@@ -288,8 +290,9 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
288290
argv: None,
289291
cmd_line: None,
290292
tls: TlsData::default(),
291-
communicate,
292-
validate,
293+
communicate: config.communicate,
294+
dummy_op_visibility: config.dummy_op_visibility,
295+
validate: config.validate,
293296
file_handler: Default::default(),
294297
dir_handler: Default::default(),
295298
time_anchor: Instant::now(),

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)