Skip to main content

specter/memory/info/
symbol.rs

1//! Symbol resolution and caching utilities
2
3use dashmap::DashMap;
4use once_cell::sync::Lazy;
5use std::ffi::CString;
6use thiserror::Error;
7
8#[derive(Error, Debug)]
9/// Errors that can occur during symbol resolution
10pub enum SymbolError {
11    /// The specified symbol was not found
12    #[error("Symbol not found: {0}")]
13    NotFound(String),
14    /// Failed to convert the symbol name to a CString
15    #[error("CString error")]
16    StringError,
17}
18
19static CACHE: Lazy<DashMap<String, usize>> = Lazy::new(DashMap::new);
20
21/// Resolves a symbol to its address using dlsym
22///
23/// # Arguments
24/// * `symbol` - The name of the symbol to resolve (e.g., "MGCopyAnswer")
25///
26/// # Returns
27/// * `Result<usize, SymbolError>` - The address of the symbol or an error
28pub fn resolve_symbol(symbol: &str) -> Result<usize, SymbolError> {
29    if let Some(entry) = CACHE.get(symbol) {
30        return Ok(*entry);
31    }
32
33    let c_str = CString::new(symbol).map_err(|_| SymbolError::StringError)?;
34    unsafe {
35        let addr_ptr = libc::dlsym(libc::RTLD_DEFAULT, c_str.as_ptr());
36        if addr_ptr.is_null() {
37            return Err(SymbolError::NotFound(symbol.into()));
38        }
39        let addr = addr_ptr as usize;
40        CACHE.insert(symbol.into(), addr);
41        Ok(addr)
42    }
43}
44
45/// Manually caches a symbol address
46///
47/// Use this if you have resolved a symbol via other means and want to store it for future lookups.
48///
49/// # Arguments
50/// * `s` - The symbol name
51/// * `a` - The symbol address
52pub fn cache_symbol(s: &str, a: usize) {
53    CACHE.insert(s.into(), a);
54}
55
56/// Clears the symbol cache
57pub fn clear_cache() {
58    CACHE.clear();
59}