1
Fork 0

Reuse the Backtrace object instead of rolling our own

This commit is contained in:
Oliver Schneider 2017-08-03 12:37:52 +02:00
parent 163821b500
commit f7bc6ab162
2 changed files with 41 additions and 28 deletions

View file

@ -1,6 +1,5 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::path::{PathBuf, Path};
use rustc::mir; use rustc::mir;
use rustc::ty::{FnSig, Ty, layout}; use rustc::ty::{FnSig, Ty, layout};
@ -11,41 +10,23 @@ use super::{
use rustc_const_math::ConstMathErr; use rustc_const_math::ConstMathErr;
use syntax::codemap::Span; use syntax::codemap::Span;
use backtrace::Backtrace;
#[derive(Debug)] #[derive(Debug)]
pub struct EvalError<'tcx> { pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx>, pub kind: EvalErrorKind<'tcx>,
pub backtrace: Vec<Frame>, pub backtrace: Backtrace,
} }
impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> { impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx>) -> Self { fn from(kind: EvalErrorKind<'tcx>) -> Self {
let mut backtrace = Vec::new();
use backtrace::{trace, resolve};
trace(|frame| {
resolve(frame.ip(), |symbol| {
backtrace.push(Frame {
function: symbol.name().map(|s| s.to_string()).unwrap_or(String::new()),
file: symbol.filename().unwrap_or(Path::new("")).to_owned(),
line: symbol.lineno().unwrap_or(0),
});
});
true
});
EvalError { EvalError {
kind, kind,
backtrace, backtrace: Backtrace::new(),
} }
} }
} }
#[derive(Debug)]
pub struct Frame {
pub function: String,
pub file: PathBuf,
pub line: u32,
}
#[derive(Debug)] #[derive(Debug)]
pub enum EvalErrorKind<'tcx> { pub enum EvalErrorKind<'tcx> {
/// This variant is used by machines to signal their own errors that do not /// This variant is used by machines to signal their own errors that do not

View file

@ -1705,13 +1705,45 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
pub fn report(&self, e: &EvalError) { pub fn report(&self, e: &EvalError) {
let mut trace_text = "\n################################\nerror occurred in miri at\n".to_string(); let mut trace_text = "\n################################\nerror occurred in miri at\n".to_string();
for frame in e.backtrace.iter().skip_while(|frame| frame.function.starts_with("backtrace::")) { let mut skip_init = true;
// don't report initialization gibberish 'frames: for (i, frame) in e.backtrace.frames().iter().enumerate() {
if frame.function == "miri::after_analysis" { for symbol in frame.symbols() {
break; if let Some(name) = symbol.name() {
// unmangle the symbol via `to_string`
let name = name.to_string();
if name.starts_with("miri::after_analysis") {
// don't report initialization gibberish
break 'frames;
} else if name.starts_with("backtrace::capture::Backtrace::new")
// debug mode produces funky symbol names
|| name.starts_with("backtrace::capture::{{impl}}::new") {
// don't report backtrace internals
skip_init = false;
continue 'frames;
}
}
}
if skip_init {
continue;
}
write!(trace_text, "{}\n", i).unwrap();
for symbol in frame.symbols() {
if let Some(name) = symbol.name() {
write!(trace_text, "# {}\n", name).unwrap();
} else {
write!(trace_text, "# <unknown>\n").unwrap();
}
if let Some(file_path) = symbol.filename() {
write!(trace_text, "{}", file_path.display()).unwrap();
} else {
write!(trace_text, "<unknown_file>").unwrap();
}
if let Some(line) = symbol.lineno() {
write!(trace_text, ":{}\n", line).unwrap();
} else {
write!(trace_text, "\n").unwrap();
}
} }
write!(trace_text, "# {}\n", frame.function).unwrap();
write!(trace_text, "{}:{}\n", frame.file.display(), frame.line).unwrap();
} }
trace!("{}", trace_text); trace!("{}", trace_text);
if let Some(frame) = self.stack().last() { if let Some(frame) = self.stack().last() {