use core::ffi::c_void;
use core::fmt;
#[cfg(feature = "std")]
pub fn trace<F: FnMut(&Frame) -> bool>(cb: F) {
let _guard = crate::lock::lock();
unsafe { trace_unsynchronized(cb) }
}
pub unsafe fn trace_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F) {
trace_imp(&mut cb)
}
#[derive(Clone)]
pub struct Frame {
pub(crate) inner: FrameImp,
}
impl Frame {
pub fn ip(&self) -> *mut c_void {
self.inner.ip()
}
pub fn sp(&self) -> *mut c_void {
self.inner.sp()
}
pub fn symbol_address(&self) -> *mut c_void {
self.inner.symbol_address()
}
pub fn module_base_address(&self) -> Option<*mut c_void> {
self.inner.module_base_address()
}
}
impl fmt::Debug for Frame {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Frame")
.field("ip", &self.ip())
.field("symbol_address", &self.symbol_address())
.finish()
}
}
cfg_if::cfg_if! {
if #[cfg(miri)] {
pub(crate) mod miri;
use self::miri::trace as trace_imp;
pub(crate) use self::miri::Frame as FrameImp;
} else if #[cfg(
any(
all(
unix,
not(target_os = "emscripten"),
not(all(target_os = "ios", target_arch = "arm")),
),
all(
target_env = "sgx",
target_vendor = "fortanix",
),
)
)] {
mod libunwind;
use self::libunwind::trace as trace_imp;
pub(crate) use self::libunwind::Frame as FrameImp;
} else if #[cfg(all(windows, not(target_vendor = "uwp")))] {
mod dbghelp;
use self::dbghelp::trace as trace_imp;
pub(crate) use self::dbghelp::Frame as FrameImp;
#[cfg(target_env = "msvc")] pub(crate) use self::dbghelp::StackFrame;
} else {
mod noop;
use self::noop::trace as trace_imp;
pub(crate) use self::noop::Frame as FrameImp;
}
}