Skip to main content

bytesxref/
bytesxref.rs

1//! Bytes + xrefs through the generated cxx bridge: hex-dump a function's head, then who calls it.
2//! Run: cargo run -p idakit-sys --example bytesxref -- path/to/database.i64
3
4use std::env;
5use std::ffi::CString;
6use std::ptr;
7
8use idakit_sys::*;
9
10fn func_label(address: Address) -> String {
11    func_name(address).unwrap_or_default()
12}
13
14/// Every reference targeting `address`, as `(from, type, iscode)`, from the owned xref snapshot.
15fn references_to(address: Address) -> Vec<(Address, i32, bool)> {
16    xrefs_build(address, true)
17        .into_iter()
18        .map(|r| (r.from, r.type_, r.iscode))
19        .collect()
20}
21
22fn main() {
23    let db = env::args()
24        .nth(1)
25        .expect("usage: bytesxref <db.i64>  (a COPY; opened save=false)");
26
27    // SAFETY: the library lifecycle is the raw C ABI; the bridge reads below are safe.
28    unsafe {
29        assert_eq!(init_library(0, ptr::null_mut()), 0, "init_library failed");
30        let cpath = CString::new(db).unwrap();
31        assert_eq!(
32            open_database(cpath.as_ptr(), false, ptr::null()),
33            0,
34            "open_database failed"
35        );
36    }
37
38    let nf = func_qty();
39    assert!(nf > 0, "no functions in db");
40
41    // bytes: hex-dump the first 16 bytes of function[7]'s entry.
42    let address = func_ea(7);
43    let bytes = get_bytes(address, 16).unwrap_or_default();
44    println!("function[7] {address:#012x}  {}", func_label(address));
45    print!("  first {} bytes:", bytes.len());
46    for b in &bytes {
47        print!(" {b:02x}");
48    }
49    println!();
50
51    // xrefs: who references function[7]? If it has no callers, scan forward for a function
52    // that does, so the demo always shows real cross-references.
53    let mut target = address;
54    let mut refs = references_to(target);
55    if refs.is_empty() {
56        for i in 0..nf {
57            let e = func_ea(i);
58            let r = references_to(e);
59            if !r.is_empty() {
60                target = e;
61                refs = r;
62                break;
63            }
64        }
65    }
66
67    println!(
68        "\nxrefs_to {target:#012x}  {}   (total {})",
69        func_label(target),
70        refs.len()
71    );
72    for (from, ty, iscode) in &refs {
73        let kind = if *iscode { "code" } else { "data" };
74        println!(
75            "  from {from:#012x}  {kind} type={ty:<2}  in {}",
76            func_label(*from)
77        );
78    }
79
80    // SAFETY: raw C ABI lifecycle call.
81    unsafe {
82        close_database(false);
83    }
84
85    println!("\nBYTESXREF OK");
86}