#[cfg(unix)]
use crate::engine::unwind::EXIT_CALLED;
#[cfg(unix)]
use std::sync::atomic::Ordering;
use super::frame_info::{FRAME_INFO, GlobalFrameInfo};
use backtrace::Backtrace;
use wasmer_types::{FrameInfo, TrapCode};
use wasmer_vm::Trap;
pub fn get_trace_and_trapcode(trap: &Trap) -> (Vec<FrameInfo>, Option<TrapCode>) {
#[cfg(unix)]
if EXIT_CALLED.load(Ordering::SeqCst) {
return (Vec::new(), None);
}
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)),
Trap::UncaughtException { backtrace, .. } => (
wasm_trace(&info, None, backtrace),
Some(TrapCode::UncaughtException),
),
}
}
pub fn wasm_trace_from_current_stack() -> Vec<FrameInfo> {
let info = FRAME_INFO.read().unwrap();
let backtrace = Backtrace::new_unresolved();
wasm_trace(&info, None, &backtrace)
}
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<_>>()
}