use std::thread;
use idakit::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let db = std::env::args().nth(1).expect("usage: actor <db.i64>");
Ida::run(move |ida| -> Result<(), Error> {
{
let db = db;
ida.call(move |idb| idb.open(&db).call())??;
}
let n = ida.call(|idb| idb.functions().count())?;
let segs = ida.call(|idb| idb.segments().count())?;
println!("[app] func_count={n} segments={segs}");
let hits = ida.call(|idb| {
let Some(address) = idb.functions().next().map(|f| f.address()) else {
return 0;
};
let sig = idb
.bytes(address, 8)
.iter()
.map(|b| format!("{b:02X}"))
.collect::<Vec<_>>()
.join(" ");
match Pattern::hex(idb, &sig) {
Ok(pat) => idb.search(&pat).count(),
Err(_) => 0,
}
})?;
println!("[app] first function's opening 8 bytes recur {hits} time(s) in the image");
let mut hs = vec![];
for t in 0..4usize {
let ida = ida.clone();
hs.push(thread::spawn(move || {
let idx = t * 1000;
let found = ida
.call(move |idb| idb.functions().nth(idx).map(|f| (f.address(), f.name())))
.expect("kernel call");
let (address, name) = match found {
Some((address, name)) => (format!("{address:#012x}"), String::from(name)),
None => ("<none>".into(), "<unnamed>".into()),
};
println!("[worker {t}] function[{idx}] @ {address} {name}");
}));
}
for h in hs {
h.join().unwrap();
}
ida.call(|idb| idb.close(false))?;
Ok(())
})??;
println!("\nACTOR OK (kernel on its own thread; calls marshaled from app + 4 workers)");
Ok(())
}