diff options
Diffstat (limited to 'rust/examples/high_level_il.rs')
| -rw-r--r-- | rust/examples/high_level_il.rs | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/rust/examples/high_level_il.rs b/rust/examples/high_level_il.rs new file mode 100644 index 00000000..d57509da --- /dev/null +++ b/rust/examples/high_level_il.rs @@ -0,0 +1,124 @@ +use binaryninja::binary_view::{BinaryViewBase, BinaryViewExt}; + +fn main() { + println!("Starting session..."); + // This loads all the core architecture, platform, etc plugins + let headless_session = + binaryninja::headless::Session::new().expect("Failed to initialize session"); + + println!("Loading binary..."); + let bv = headless_session + .load("/bin/cat") + .expect("Couldn't open `/bin/cat`"); + + println!("Filename: `{}`", bv.file().filename()); + println!("File size: `{:#x}`", bv.len()); + println!("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"), + } + } + } +} |
