use super::{
ExportCallback, ExportInfo, ImportCallback, ImportInfo, ModuleAddressInfo, ModuleInfo,
ModuleInfoCallback, SectionCallback, SectionInfo,
};
use crate::cglue::*;
use crate::prelude::v1::{Result, *};
use std::prelude::v1::*;
pub type Pid = u32;
pub type ExitCode = i32;
#[repr(C)]
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub enum ProcessState {
Unknown,
Alive,
Dead(ExitCode),
}
impl ProcessState {
pub fn is_alive(&self) -> bool {
matches!(*self, ProcessState::Alive)
}
pub fn is_dead(&self) -> bool {
matches!(*self, ProcessState::Dead(_))
}
pub fn is_unknown(&self) -> bool {
matches!(*self, ProcessState::Unknown)
}
}
#[cfg_attr(feature = "plugins", cglue_trait)]
#[int_result]
pub trait Process: Send {
fn state(&mut self) -> ProcessState;
fn set_dtb(&mut self, dtb1: Address, dtb2: Address) -> Result<()>;
fn module_address_list_callback(
&mut self,
target_arch: Option<&ArchitectureIdent>,
callback: ModuleAddressCallback,
) -> Result<()>;
fn module_list_callback(
&mut self,
target_arch: Option<&ArchitectureIdent>,
mut callback: ModuleInfoCallback,
) -> Result<()> {
let sptr = self as *mut Self;
let inner_callback = &mut |ModuleAddressInfo { address, arch }| match unsafe { &mut *sptr }
.module_by_address(address, arch)
{
Ok(info) => callback.call(info),
Err(e) => {
log::trace!("Error when reading module {:x} {:?}", address, e);
true }
};
unsafe { sptr.as_mut().unwrap() }
.module_address_list_callback(target_arch, inner_callback.into())
}
fn module_by_address(
&mut self,
address: Address,
architecture: ArchitectureIdent,
) -> Result<ModuleInfo>;
fn module_by_name_arch(
&mut self,
name: &str,
architecture: Option<&ArchitectureIdent>,
) -> Result<ModuleInfo> {
let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ModuleNotFound));
let callback = &mut |data: ModuleInfo| {
if data.name.as_ref() == name {
ret = Ok(data);
false
} else {
true
}
};
self.module_list_callback(architecture, callback.into())?;
ret
}
fn module_by_name(&mut self, name: &str) -> Result<ModuleInfo> {
self.module_by_name_arch(name, None)
}
#[skip_func]
fn module_list_arch(
&mut self,
target_arch: Option<&ArchitectureIdent>,
) -> Result<Vec<ModuleInfo>> {
let mut ret = vec![];
self.module_list_callback(target_arch, (&mut ret).into())?;
Ok(ret)
}
#[skip_func]
fn module_list(&mut self) -> Result<Vec<ModuleInfo>> {
self.module_list_arch(None)
}
fn primary_module_address(&mut self) -> Result<Address>;
fn primary_module(&mut self) -> Result<ModuleInfo> {
let addr = self.primary_module_address()?;
self.module_by_address(addr, self.info().proc_arch)
}
fn module_import_list_callback(
&mut self,
info: &ModuleInfo,
callback: ImportCallback,
) -> Result<()>;
fn module_export_list_callback(
&mut self,
info: &ModuleInfo,
callback: ExportCallback,
) -> Result<()>;
fn module_section_list_callback(
&mut self,
info: &ModuleInfo,
callback: SectionCallback,
) -> Result<()>;
#[skip_func]
fn module_import_list(&mut self, info: &ModuleInfo) -> Result<Vec<ImportInfo>> {
let mut ret = vec![];
self.module_import_list_callback(info, (&mut ret).into())?;
Ok(ret)
}
#[skip_func]
fn module_export_list(&mut self, info: &ModuleInfo) -> Result<Vec<ExportInfo>> {
let mut ret = vec![];
self.module_export_list_callback(info, (&mut ret).into())?;
Ok(ret)
}
#[skip_func]
fn module_section_list(&mut self, info: &ModuleInfo) -> Result<Vec<SectionInfo>> {
let mut ret = vec![];
self.module_section_list_callback(info, (&mut ret).into())?;
Ok(ret)
}
fn module_import_by_name(&mut self, info: &ModuleInfo, name: &str) -> Result<ImportInfo> {
let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ImportNotFound));
let callback = &mut |data: ImportInfo| {
if data.name.as_ref() == name {
ret = Ok(data);
false
} else {
true
}
};
self.module_import_list_callback(info, callback.into())?;
ret
}
fn module_export_by_name(&mut self, info: &ModuleInfo, name: &str) -> Result<ExportInfo> {
let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ImportNotFound));
let callback = &mut |data: ExportInfo| {
if data.name.as_ref() == name {
ret = Ok(data);
false
} else {
true
}
};
self.module_export_list_callback(info, callback.into())?;
ret
}
fn module_section_by_name(&mut self, info: &ModuleInfo, name: &str) -> Result<SectionInfo> {
let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ImportNotFound));
let callback = &mut |data: SectionInfo| {
if data.name.as_ref() == name {
ret = Ok(data);
false
} else {
true
}
};
self.module_section_list_callback(info, callback.into())?;
ret
}
fn info(&self) -> &ProcessInfo;
fn mapped_mem_range(
&mut self,
gap_size: imem,
start: Address,
end: Address,
out: MemoryRangeCallback,
);
#[skip_func]
fn mapped_mem_range_vec(
&mut self,
gap_size: imem,
start: Address,
end: Address,
) -> Vec<MemoryRange> {
let mut out = vec![];
self.mapped_mem_range(gap_size, start, end, (&mut out).into());
out
}
fn mapped_mem(&mut self, gap_size: imem, out: MemoryRangeCallback) {
self.mapped_mem_range(gap_size, Address::null(), Address::invalid(), out)
}
#[skip_func]
fn mapped_mem_vec(&mut self, gap_size: imem) -> Vec<MemoryRange> {
let mut out = vec![];
self.mapped_mem(gap_size, (&mut out).into());
out
}
}
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct ProcessInfo {
pub address: Address,
pub pid: Pid,
pub state: ProcessState,
pub name: ReprCString,
pub path: ReprCString,
pub command_line: ReprCString,
pub sys_arch: ArchitectureIdent,
pub proc_arch: ArchitectureIdent,
pub dtb1: Address,
pub dtb2: Address,
}
pub type ProcessInfoCallback<'a> = OpaqueCallback<'a, ProcessInfo>;