summaryrefslogtreecommitdiff
path: root/rust/tests
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-05-09 14:00:38 -0400
committerMason Reed <35282038+emesare@users.noreply.github.com>2025-05-12 17:45:24 -0400
commit2a9beeec15d3f32312a0c4f8ad5ddbcfcbc97a89 (patch)
tree5562dd4acafb32f6e9826a4247f910507cec4c8d /rust/tests
parent6617b0afa09f549d0a5c9c53063f3ad8ab82b7e4 (diff)
[Rust] Support SSA form properly in low level IL
Diffstat (limited to 'rust/tests')
-rw-r--r--rust/tests/low_level_il.rs85
1 files changed, 84 insertions, 1 deletions
diff --git a/rust/tests/low_level_il.rs b/rust/tests/low_level_il.rs
index 88d915dc..db8cc549 100644
--- a/rust/tests/low_level_il.rs
+++ b/rust/tests/low_level_il.rs
@@ -7,7 +7,7 @@ use binaryninja::low_level_il::expression::{
use binaryninja::low_level_il::instruction::{
InstructionHandler, LowLevelILInstructionKind, LowLevelInstructionIndex,
};
-use binaryninja::low_level_il::{LowLevelILRegisterKind, VisitorAction};
+use binaryninja::low_level_il::{LowLevelILRegisterKind, LowLevelILSSARegisterKind, VisitorAction};
use std::path::PathBuf;
#[test]
@@ -225,3 +225,86 @@ fn test_llil_visitor() {
};
}
}
+
+#[test]
+fn test_llil_ssa() {
+ let _session = Session::new().expect("Failed to initialize session");
+ let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap();
+ let view = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view");
+ let image_base = view.original_image_base();
+ let platform = view.default_platform().unwrap();
+
+ // Sample function: __crt_strtox::c_string_character_source<char>::validate
+ let sample_function = view.function_at(&platform, image_base + 0x2bd80).unwrap();
+ let llil_function = sample_function.low_level_il().unwrap();
+ let llil_ssa_function = llil_function.ssa_form().expect("Valid SSA form");
+
+ let llil_ssa_basic_blocks = llil_ssa_function.basic_blocks();
+ let mut llil_ssa_basic_block_iter = llil_ssa_basic_blocks.iter();
+ let first_basic_block = llil_ssa_basic_block_iter.next().unwrap();
+ let mut llil_instr_iter = first_basic_block.iter();
+
+ // 0 @ 0002bd80 (LLIL_SET_REG_SSA.d edi#1 = (LLIL_REG_SSA.d edi#0))
+ let ssa_instr_0 = llil_instr_iter.next().unwrap();
+ assert_eq!(ssa_instr_0.index, LowLevelInstructionIndex(0));
+ assert_eq!(ssa_instr_0.address(), image_base + 0x0002bd80);
+ println!("{:?}", ssa_instr_0);
+ println!("{:?}", ssa_instr_0.kind());
+ match ssa_instr_0.kind() {
+ LowLevelILInstructionKind::SetRegSsa(op) => {
+ assert_eq!(op.size(), 4);
+ match op.dest_reg() {
+ LowLevelILSSARegisterKind::Full { kind, version } => {
+ assert_eq!(kind.name(), "edi");
+ assert_eq!(version, 1);
+ }
+ _ => panic!("Expected LowLevelILSSARegisterKind::Full"),
+ }
+ assert_eq!(op.source_expr().index, LowLevelExpressionIndex(0));
+ }
+ _ => panic!("Expected SetRegSsa"),
+ }
+
+ // 1 @ 0002bd82 (LLIL_STORE_SSA.d [(LLIL_SUB.d (LLIL_REG_SSA.d esp#0) - (LLIL_CONST.d 4)) {__saved_ebp}].d = (LLIL_REG_SSA.d ebp#0) @ mem#0 -> mem#1)
+ let ssa_instr_1 = llil_instr_iter.next().unwrap();
+ assert_eq!(ssa_instr_1.index, LowLevelInstructionIndex(1));
+ assert_eq!(ssa_instr_1.address(), image_base + 0x0002bd82);
+ println!("{:?}", ssa_instr_1);
+ println!("{:?}", ssa_instr_1.kind());
+ match ssa_instr_1.kind() {
+ LowLevelILInstructionKind::StoreSsa(op) => {
+ assert_eq!(op.size(), 4);
+ let source_expr = op.source_expr();
+ let source_memory_version = op.source_memory_version();
+ assert_eq!(source_memory_version, 0);
+ assert_eq!(source_expr.index, LowLevelExpressionIndex(5));
+ let dest_expr = op.dest_expr();
+ let dest_memory_version = op.dest_memory_version();
+ assert_eq!(dest_memory_version, 1);
+ assert_eq!(dest_expr.index, LowLevelExpressionIndex(4));
+ }
+ _ => panic!("Expected StoreSsa"),
+ }
+
+ // 34 @ 0002bdc7 (LLIL_CALL_SSA eax#8, edx#5, ecx#6, mem#23 = call((LLIL_EXTERN_PTR.d __CrtDbgReportW), stack = esp#18 @ mem#22))
+ let ssa_instr_34 = llil_ssa_function
+ .instruction_from_index(LowLevelInstructionIndex(34))
+ .expect("Valid instruction");
+ assert_eq!(ssa_instr_34.index, LowLevelInstructionIndex(34));
+ assert_eq!(ssa_instr_34.address(), image_base + 0x0002bdc7);
+ println!("{:?}", ssa_instr_34);
+ println!("{:?}", ssa_instr_34.kind());
+ match ssa_instr_34.kind() {
+ LowLevelILInstructionKind::CallSsa(op) => match op.target().kind() {
+ LowLevelILExpressionKind::ExternPtr(extern_ptr) => {
+ assert_eq!(extern_ptr.size(), 4);
+ let extern_sym = view
+ .symbol_by_address(extern_ptr.value())
+ .expect("Valid symbol");
+ assert_eq!(extern_sym.short_name(), "__CrtDbgReportW".into())
+ }
+ _ => panic!("Expected ExternPtr"),
+ },
+ _ => panic!("Expected CallSsa"),
+ }
+}