probe_argloc/
probe_argloc.rs1use idakit::prelude::*;
7
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 use idakit::decompiler::ctree::LocalLocation as L;
10 let mut args = std::env::args().skip(1);
11 let bin = args
12 .next()
13 .expect("usage: probe_argloc <db.i64> [max-funcs]");
14 let max: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(2000);
15
16 Ida::run(move |ida| -> Result<(), Error> {
17 ida.call(move |idb| -> Result<(), Error> {
18 idb.open(&bin).run_auto(false).call()?;
19
20 let mut n = [0usize; 8];
21 let mut decompiled = 0usize;
22 let mut examples: Vec<String> = Vec::new();
23 let eas: Vec<_> = idb.functions().take(max).map(|f| f.address()).collect();
24 for ea in eas {
25 let Ok(cf) = idb.decompile(ea) else { continue };
26 let Ok(tree) = cf.ctree() else { continue };
27 decompiled += 1;
28 for lv in tree.locals() {
29 let i = match &lv.location {
30 L::Register(_) => 0,
31 L::RegisterPair { .. } => 1,
32 L::Stack(_) => 2,
33 L::RegisterRelative { .. } => 3,
34 L::Static(_) => 4,
35 L::Scattered(_) => 5,
36 L::Custom => 6,
37 L::Unallocated => 7,
38 };
39 n[i] += 1;
40 if matches!(lv.location, L::Scattered(_) | L::RegisterPair { .. } | L::RegisterRelative { .. })
41 && examples.len() < 12
42 {
43 examples.push(format!(" {} {:?} = {:?}", lv.name, lv.width, lv.location));
44 }
45 }
46 }
47 println!(
48 "{decompiled} fns | reg={} pair={} stack={} rrel={} static={} scatter={} custom={} none={}",
49 n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]
50 );
51 if !examples.is_empty() {
52 println!("rich-variant examples:");
53 for e in &examples {
54 println!("{e}");
55 }
56 }
57 idb.close(false);
58 Ok(())
59 })?
60 })??;
61 Ok(())
62}