Skip to main content

probe_argloc/
probe_argloc.rs

1//! Tally decompiled-local `LocalLocation` variants across a database, printing the histogram and
2//! a few example scattered/pair locations. Verifies which argloc variants a fixture exercises.
3//!
4//!   `cargo run -p idakit --example probe_argloc -- <db.i64> [max-funcs]`
5
6use 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}