use idakit::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bin = std::env::args()
.nth(1)
.expect("usage: analyze <path/to/binary>");
Ida::run(move |ida| -> Result<(), Error> {
ida.call(move |idb| -> Result<(), Error> {
idb.open(&bin).run_auto(true).call()?;
let funcs = idb.functions().count();
let segs = idb.segments().count();
println!("analyzed {bin}: {funcs} functions, {segs} segments");
assert!(funcs > 0, "auto-analysis found no functions");
if let Some((address, cfg)) = idb
.functions()
.take(2000)
.filter_map(|f| f.flowchart().ok().map(|c| (f.address(), c)))
.max_by_key(|(_, c)| c.len())
{
let edges: usize = cfg.blocks().map(|(_, b)| b.successors().len()).sum();
let returns = cfg.blocks().filter(|(_, b)| b.kind().is_return()).count();
let entry_insns = idb.instructions_in(cfg.block(cfg.entry()).range()).count();
println!(
"largest CFG @ {address:#x}: {} blocks, {edges} edges, {returns} return block(s); \
entry block has {entry_insns} instruction(s)",
cfg.len()
);
}
idb.close(false);
Ok(())
})?
})??;
Ok(())
}