summaryrefslogtreecommitdiff
path: root/rust/examples/high_level_il.rs
blob: 28081a762a7808d057a6f9268a08ecea7904cc30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use binaryninja::binary_view::BinaryViewBase;
use binaryninja::tracing::TracingLogListener;

fn main() {
    tracing_subscriber::fmt::init();
    let _listener = TracingLogListener::new().register();

    // This loads all the core architecture, platform, etc plugins
    let headless_session =
        binaryninja::headless::Session::new().expect("Failed to initialize session");

    tracing::info!("Loading binary...");
    let bv = headless_session
        .load("/bin/cat")
        .expect("Couldn't open `/bin/cat`");

    tracing::info!("File:  `{}`", bv.file());
    tracing::info!("File size: `{:#x}`", bv.len());
    tracing::info!("Function count: {}", bv.functions().len());

    for func in &bv.functions() {
        println!("{:?}:", func.symbol().full_name());

        let Ok(il) = func.high_level_il(true) else {
            continue;
        };

        // Get the SSA form for this function
        let il = il.ssa_form();

        // Loop through all blocks in the function
        for block in il.basic_blocks().iter() {
            // Loop though each instruction in the block
            for instr in block.iter() {
                // Uplift the instruction into a native rust format
                let lifted = instr.lift();
                let address = instr.address;

                // Print the lifted instruction
                println!("{address:08x}: {lifted:#x?}");

                // Generically parse the IL tree and display the parts
                visitor::print_il_expr(&lifted, 2);
            }
        }
    }
}

mod visitor {
    use binaryninja::high_level_il::HighLevelILLiftedOperand::*;
    use binaryninja::high_level_il::{HighLevelILFunction, HighLevelILLiftedInstruction};
    use binaryninja::variable::Variable;

    fn print_indent(indent: usize) {
        print!("{:<indent$}", "")
    }

    fn print_operation(operation: &HighLevelILLiftedInstruction) {
        print!("{}", operation.name());
    }

    fn print_variable(func: &HighLevelILFunction, var: &Variable) {
        print!("{}", func.function().variable_name(var));
    }

    pub(crate) fn print_il_expr(instr: &HighLevelILLiftedInstruction, mut indent: usize) {
        print_indent(indent);
        print_operation(instr);
        println!();

        indent += 1;

        for (_name, operand) in instr.operands() {
            match operand {
                Int(int) => {
                    print_indent(indent);
                    println!("int 0x{:x}", int);
                }
                Float(float) => {
                    print_indent(indent);
                    println!("int {:e}", float);
                }
                Expr(expr) => print_il_expr(&expr, indent),
                Var(var) => {
                    print_indent(indent);
                    print!("var ");
                    print_variable(&instr.function, &var);
                    println!();
                }
                VarSsa(var) => {
                    print_indent(indent);
                    print!("ssa var ");
                    print_variable(&instr.function, &var.variable);
                    println!("#{}", var.version);
                }
                IntList(list) => {
                    print_indent(indent);
                    print!("index list ");
                    for i in list {
                        print!("{i} ");
                    }
                    println!();
                }
                VarSsaList(list) => {
                    print_indent(indent);
                    print!("ssa var list ");
                    for i in list {
                        print_variable(&instr.function, &i.variable);
                        print!("#{} ", i.version);
                    }
                    println!();
                }
                ExprList(list) => {
                    print_indent(indent);
                    println!("expr list");
                    for i in list {
                        print_il_expr(&i, indent + 1);
                    }
                }
                Label(label) => println!("label {}", label.name()),
                MemberIndex(mem_idx) => println!("member_index {:?}", mem_idx),
                ConstantData(_) => println!("constant_data TODO"),
                Intrinsic(_) => println!("intrinsic TODO"),
            }
        }
    }
}