Skip to content

Commit e8095d0

Browse files
committed
Auto merge of #2390 - RalfJung:debug, r=RalfJung
fix some debugging papercuts - detect when Miri got locally installed and is being run with the wrong toolchain - when an ICE occurs, print a backtrace of where the interpreter was at the time
2 parents 8757d86 + 5cf7ed1 commit e8095d0

File tree

4 files changed

+61
-17
lines changed

4 files changed

+61
-17
lines changed

cargo-miri/bin.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,15 @@ fn setup(subcommand: MiriCommand) {
374374
}
375375
None => {
376376
// Check for `rust-src` rustup component.
377-
let sysroot = miri()
378-
.args(&["--print", "sysroot"])
379-
.output()
380-
.expect("failed to determine sysroot")
381-
.stdout;
382-
let sysroot = std::str::from_utf8(&sysroot).unwrap();
377+
let output =
378+
miri().args(&["--print", "sysroot"]).output().expect("failed to determine sysroot");
379+
if !output.status.success() {
380+
show_error(format!(
381+
"Failed to determine sysroot; Miri said:\n{}",
382+
String::from_utf8_lossy(&output.stderr).trim_end()
383+
));
384+
}
385+
let sysroot = std::str::from_utf8(&output.stdout).unwrap();
383386
let sysroot = Path::new(sysroot.trim_end_matches('\n'));
384387
// Check for `$SYSROOT/lib/rustlib/src/rust/library`; test if that contains `std/Cargo.toml`.
385388
let rustup_src =

src/bin/miri.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![feature(rustc_private, stmt_expr_attributes)]
2-
#![allow(clippy::manual_range_contains)]
2+
#![allow(clippy::manual_range_contains, clippy::useless_format)]
33

44
extern crate rustc_data_structures;
55
extern crate rustc_driver;
@@ -143,6 +143,11 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
143143
}
144144
}
145145

146+
fn show_error(msg: String) -> ! {
147+
eprintln!("fatal error: {}", msg);
148+
std::process::exit(1)
149+
}
150+
146151
fn init_early_loggers() {
147152
// Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
148153
// initialize them both, and we always initialize `miri`'s first.
@@ -214,13 +219,26 @@ fn compile_time_sysroot() -> Option<String> {
214219
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
215220
let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
216221
Some(match (home, toolchain) {
217-
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
218-
_ =>
219-
option_env!("RUST_SYSROOT")
220-
.expect(
222+
(Some(home), Some(toolchain)) => {
223+
// Check that at runtime, we are still in this toolchain.
224+
let toolchain_runtime =
225+
env::var_os("RUSTUP_TOOLCHAIN").or_else(|| env::var_os("MULTIRUST_TOOLCHAIN"));
226+
if !matches!(toolchain_runtime, Some(r) if r == toolchain) {
227+
show_error(format!(
228+
"This Miri got built with local toolchain `{toolchain}`, but now is being run under a different toolchain. \n\
229+
Make sure to run Miri in the toolchain it got built with, e.g. via `cargo +{toolchain} miri`."
230+
));
231+
}
232+
233+
format!("{}/toolchains/{}", home, toolchain)
234+
}
235+
_ => option_env!("RUST_SYSROOT")
236+
.unwrap_or_else(|| {
237+
show_error(format!(
221238
"To build Miri without rustup, set the `RUST_SYSROOT` env var at build time",
222-
)
223-
.to_owned(),
239+
))
240+
})
241+
.to_owned(),
224242
})
225243
}
226244

src/diagnostics.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,4 +505,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
505505
}
506506
});
507507
}
508+
509+
/// We had a panic in Miri itself, try to print something useful.
510+
fn handle_ice(&self) {
511+
eprintln!();
512+
eprintln!(
513+
"Miri caused an ICE during evaluation. Here's the interpreter backtrace at the time of the panic:"
514+
);
515+
let this = self.eval_context_ref();
516+
let stacktrace = this.generate_stacktrace();
517+
report_msg(
518+
this,
519+
DiagLevel::Note,
520+
"the place in the program where the ICE was triggered",
521+
vec![],
522+
vec![],
523+
&stacktrace,
524+
);
525+
}
508526
}

src/eval.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
//! Main evaluator loop and setting up the initial stack frame.
22
3+
use std::collections::HashSet;
34
use std::ffi::OsStr;
45
use std::iter;
6+
use std::panic::{self, AssertUnwindSafe};
7+
use std::thread;
58

69
use log::info;
710

@@ -15,8 +18,6 @@ use rustc_target::spec::abi::Abi;
1518

1619
use rustc_session::config::EntryFnType;
1720

18-
use std::collections::HashSet;
19-
2021
use crate::*;
2122

2223
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -326,7 +327,7 @@ pub fn eval_entry<'tcx>(
326327
};
327328

328329
// Perform the main execution.
329-
let res: InterpResult<'_, i64> = (|| {
330+
let res: thread::Result<InterpResult<'_, i64>> = panic::catch_unwind(AssertUnwindSafe(|| {
330331
// Main loop.
331332
loop {
332333
let info = ecx.preprocess_diagnostics();
@@ -356,7 +357,11 @@ pub fn eval_entry<'tcx>(
356357
}
357358
let return_code = ecx.read_scalar(&ret_place.into())?.to_machine_isize(&ecx)?;
358359
Ok(return_code)
359-
})();
360+
}));
361+
let res = res.unwrap_or_else(|panic_payload| {
362+
ecx.handle_ice();
363+
panic::resume_unwind(panic_payload)
364+
});
360365

361366
// Machine cleanup.
362367
// Execution of the program has halted so any memory access we do here

0 commit comments

Comments
 (0)