use std::fmt;
use std::os::raw::c_void;
use std::path::Path;
use std::str;
use rustc_demangle::{demangle, Demangle};
pub fn resolve<F: FnMut(&Symbol)>(addr: *mut c_void, mut cb: F) {
resolve_imp(addr, &mut cb)
}
pub struct Symbol {
inner: SymbolImp,
}
impl Symbol {
pub fn name(&self) -> Option<SymbolName> {
self.inner.name()
}
pub fn addr(&self) -> Option<*mut c_void> {
self.inner.addr()
}
pub fn filename(&self) -> Option<&Path> {
self.inner.filename()
}
pub fn lineno(&self) -> Option<u32> {
self.inner.lineno()
}
}
impl fmt::Debug for Symbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut d = f.debug_struct("Symbol");
if let Some(name) = self.name() {
d.field("name", &name);
}
if let Some(addr) = self.addr() {
d.field("addr", &addr);
}
if let Some(filename) = self.filename() {
d.field("filename", &filename);
}
if let Some(lineno) = self.lineno() {
d.field("lineno", &lineno);
}
d.finish()
}
}
pub struct SymbolName<'a> {
bytes: &'a [u8],
demangled: Option<Demangle<'a>>,
}
impl<'a> SymbolName<'a> {
pub fn new(bytes: &'a [u8]) -> SymbolName<'a> {
let demangled = str::from_utf8(bytes).ok().map(demangle);
SymbolName {
bytes: bytes,
demangled: demangled,
}
}
pub fn as_str(&self) -> Option<&'a str> {
self.demangled.as_ref().map(|s| s.as_str())
}
pub fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
}
impl<'a> fmt::Display for SymbolName<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref s) = self.demangled {
s.fmt(f)
} else {
String::from_utf8_lossy(self.bytes).fmt(f)
}
}
}
impl<'a> fmt::Debug for SymbolName<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref s) = self.demangled {
s.fmt(f)
} else {
String::from_utf8_lossy(self.bytes).fmt(f)
}
}
}
cfg_if! {
if #[cfg(all(windows, feature = "dbghelp"))] {
mod dbghelp;
use self::dbghelp::resolve as resolve_imp;
use self::dbghelp::Symbol as SymbolImp;
} else if #[cfg(all(feature = "libbacktrace",
unix,
not(target_os = "emscripten"),
not(target_os = "macos")))] {
mod libbacktrace;
use self::libbacktrace::resolve as resolve_imp;
use self::libbacktrace::Symbol as SymbolImp;
} else if #[cfg(all(feature = "coresymbolication",
target_os = "macos"))] {
mod coresymbolication;
use self::coresymbolication::resolve as resolve_imp;
use self::coresymbolication::Symbol as SymbolImp;
} else if #[cfg(all(unix,
not(target_os = "emscripten"),
feature = "dladdr"))] {
mod dladdr;
use self::dladdr::resolve as resolve_imp;
use self::dladdr::Symbol as SymbolImp;
} else {
mod noop;
use self::noop::resolve as resolve_imp;
use self::noop::Symbol as SymbolImp;
}
}