use std::sync::Arc;
use std::sync::RwLock;
use crate::dbg_backend::DebugBackend;
use crate::error::Result;
use crate::gdb::BreakpointManager;
use crate::symbols::{SymbolIndex, SymbolStore};
use crate::target::{DriverObjectInfo, Target, ThreadInfo};
use crate::types::{Dtb, VirtAddr};
#[derive(Clone, Copy)]
pub enum CompletionStrategy {
None,
Symbol,
Type,
Process,
Thread,
Vcpu,
Breakpoint,
Driver,
}
impl CompletionStrategy {
pub fn from_kebab(s: &str) -> Option<Self> {
Some(match s {
"none" | "" => Self::None,
"symbol" => Self::Symbol,
"type" => Self::Type,
"process" => Self::Process,
"thread" => Self::Thread,
"vcpu" => Self::Vcpu,
"breakpoint" => Self::Breakpoint,
"driver" => Self::Driver,
_ => return None,
})
}
}
pub type ProcessCache = Vec<(String, u64)>;
pub type VcpuCache = Vec<String>;
pub type ThreadCache = Vec<ThreadInfo>;
pub type BreakpointCache = Vec<(u32, bool, VirtAddr, Option<String>)>;
pub type DriverObjectCache = Vec<DriverObjectInfo>;
pub type UserCommandCache = Vec<(String, String, Vec<CompletionStrategy>)>;
#[derive(Clone)]
pub struct ReplCaches {
pub symbols: Arc<RwLock<SymbolIndex>>,
pub types: Arc<RwLock<SymbolIndex>>,
pub symbol_store: Arc<SymbolStore>,
pub dtb: Arc<RwLock<Dtb>>,
pub processes: Arc<RwLock<ProcessCache>>,
pub threads: Arc<RwLock<ThreadCache>>,
pub vcpus: Arc<RwLock<VcpuCache>>,
pub breakpoints: Arc<RwLock<BreakpointCache>>,
pub drivers: Arc<RwLock<DriverObjectCache>>,
pub user_commands: Arc<RwLock<UserCommandCache>>,
}
impl ReplCaches {
pub fn refresh_processes(&self, debugger: &Target) -> Result<()> {
let processes = debugger.guest.enumerate_processes()?;
*self.processes.write().unwrap() = processes.into_iter().map(|p| (p.name, p.pid)).collect();
Ok(())
}
pub fn refresh_vcpus(&self, client: &mut dyn DebugBackend) {
if let Ok(vcpus) = client.thread_list() {
*self.vcpus.write().unwrap() = vcpus;
}
}
pub fn clear_threads(&self) {
self.threads.write().unwrap().clear();
}
pub fn refresh_breakpoints(&self, breakpoints: &BreakpointManager) {
*self.breakpoints.write().unwrap() = breakpoints
.list()
.iter()
.map(|bp| (bp.id, bp.enabled, bp.address, bp.symbol.clone()))
.collect();
}
pub fn refresh_symbol_context(&self, debugger: &Target) {
let new_dtb = debugger.current_dtb();
if *self.dtb.read().unwrap() == new_dtb {
return;
}
*self.symbols.write().unwrap() = debugger.current_symbol_index();
*self.types.write().unwrap() = debugger.current_types_index();
*self.dtb.write().unwrap() = new_dtb;
}
pub fn refresh_drivers(&self, debugger: &Target) {
if let Ok(drivers) = debugger.enumerate_driver_objects() {
*self.drivers.write().unwrap() = drivers;
}
}
}