use std::{
error::Error,
path::{Path, PathBuf},
};
#[cfg(unix)]
pub mod unix;
#[cfg(windows)]
pub mod windows;
pub unsafe fn objects() -> Result<Objects, Box<dyn Error>> {
unsafe {
objects_with_options(ObjectLookupOptions {
skip_invalid_handles: false,
})
}
}
pub struct ObjectLookupOptions {
pub skip_invalid_handles: bool,
}
pub unsafe fn objects_with_options(
options: ObjectLookupOptions,
) -> Result<Objects, Box<dyn Error>> {
#[cfg(unix)]
unsafe {
unix::objects(options)
}
#[cfg(windows)]
unsafe {
windows::objects(options)
}
}
pub struct Objects {
pub objects: Vec<Object>,
}
pub struct Object {
pub name: Option<String>,
pub path: Option<PathBuf>,
pub addr: usize,
}
impl std::fmt::Display for Object {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut path_str = String::new();
if let Some(path) = &self.path {
path_str = path.display().to_string();
}
let mut name_str = "";
if let Some(name) = &self.name {
name_str = name;
}
write!(
f,
"addr: {:#x} | name: '{}' | path: '{}'",
self.addr, name_str, path_str,
)?;
Ok(())
}
}
pub(crate) fn path_basename(pathbuf: &Path) -> Option<String> {
if let Some(os_str) = pathbuf.file_name() {
if let Some(str_ref) = os_str.to_str() {
return Some(str_ref.to_string());
}
}
None
}
pub struct Symbolizer {
#[cfg(windows)]
dbg: windows::DbgHelpSession,
}
impl Symbolizer {
pub unsafe fn new() -> Result<Self, Box<dyn Error>> {
#[cfg(windows)]
{
let session = unsafe { windows::DbgHelpSession::new(None) }
.map_err(|err| format!("failed to create dbg help session - {err}"))?;
return Ok(Self { dbg: session });
}
#[cfg(unix)]
{
return Ok(Self {});
}
}
pub unsafe fn by_addr(&self, addr: usize) -> Result<SymInfo, Box<dyn Error>> {
#[cfg(unix)]
unsafe {
unix::sym_from_addr(addr)
}
#[cfg(windows)]
unsafe {
self.dbg.sym_from_addr(addr)
}
}
}
pub struct SymInfo {
pub object_name: String,
pub object_base_addr: usize,
pub sym_name: String,
pub sym_addr: usize,
}
impl std::fmt::Display for SymInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "object_name: '{}' | ", self.object_name)?;
write!(
f,
"object_base_addr: 0x{:x?} | ",
self.object_base_addr as usize
)?;
write!(f, "sym_name: '{}' | ", self.sym_name)?;
write!(f, "sym_addr: 0x{:x?}", self.sym_addr as usize)?;
Ok(())
}
}