use std::collections::BTreeMap; use std::env; use log::debug; use memflow::prelude::v1::*; use serde::{Deserialize, Serialize}; use skidscan_macros::signature; use crate::error::Result; use crate::source_engine::InterfaceReg; pub type InterfaceMap = BTreeMap>; #[derive(Debug, Deserialize, Serialize)] pub struct Interface { pub name: String, pub value: u32, } pub fn interfaces(process: &mut IntoProcessInstanceArcBox<'_>) -> Result { let sig = match env::consts::OS { "linux" => signature!("48 8B 1D ? ? ? ? 48 85 DB 74 ? 49 89 FC"), "windows" => signature!("4C 8B 0D ? ? ? ? 4C 8B D2 4C 8B D9"), _ => panic!("unsupported os"), }; process .module_list()? .iter() .filter(|module| !module.name.starts_with("nvidia")) // Temporary workaround for upstream bug: https://github.com/memflow/memflow-native/blob/1b063fc573957498b88a13b6120120480bc65ea5/src/linux/mem.rs#L168 .filter_map(|module| { let buf = process.read_raw(module.base, module.size as _).ok()?; let list_addr = sig .scan(&buf) .and_then(|ptr| process.read_addr64_rip(module.base + ptr).ok())?; read_interfaces(process, module, list_addr) .ok() .filter(|ifaces| !ifaces.is_empty()) .map(|ifaces| Ok((module.name.to_string(), ifaces))) }) .collect() } fn read_interfaces( process: &mut IntoProcessInstanceArcBox<'_>, module: &ModuleInfo, list_addr: Address, ) -> Result> { let mut ifaces = Vec::new(); let mut reg_ptr = Pointer64::::from(process.read_addr64(list_addr)?); while !reg_ptr.is_null() { let reg = reg_ptr.read(process)?; let name = reg.name.read_string(process)?.to_string(); let value = (reg.create_fn - module.base) as u32; debug!( "found interface: {} at {:#X} ({} + {:#X})", name, value as u64 + module.base.to_umem(), module.name, value ); ifaces.push(Interface { name, value }); reg_ptr = reg.next; } ifaces.sort_unstable_by(|a, b| a.name.cmp(&b.name)); Ok(ifaces) }