use super::frame_info::{GlobalFrameInfo, FRAME_INFO};
use backtrace::Backtrace;
use wasmer_types::{FrameInfo, TrapCode};
use wasmer_vm::Trap;
pub fn get_trace_and_trapcode(trap: &Trap) -> (Vec<FrameInfo>, Option<TrapCode>) {
let info = FRAME_INFO.read().unwrap();
match &trap {
Trap::User(_err) => (wasm_trace(&info, None, &Backtrace::new_unresolved()), None),
Trap::OOM { backtrace } => (wasm_trace(&info, None, backtrace), None),
Trap::Wasm {
pc,
signal_trap,
backtrace,
} => {
let trap_code = info
.lookup_trap_info(*pc)
.map_or(signal_trap.unwrap_or(TrapCode::StackOverflow), |info| {
info.trap_code
});
(wasm_trace(&info, Some(*pc), backtrace), Some(trap_code))
}
Trap::Lib {
trap_code,
backtrace,
} => (wasm_trace(&info, None, backtrace), Some(*trap_code)),
}
}
fn wasm_trace(
info: &GlobalFrameInfo,
trap_pc: Option<usize>,
backtrace: &Backtrace,
) -> Vec<FrameInfo> {
backtrace
.frames()
.iter()
.filter_map(|frame| {
let pc = frame.ip() as usize;
if pc == 0 {
None
} else {
let pc_to_lookup = if Some(pc) == trap_pc { pc } else { pc - 1 };
Some(pc_to_lookup)
}
})
.filter_map(|pc| info.lookup_frame_info(pc))
.collect::<Vec<_>>()
}