@@ -7,7 +7,7 @@ use binaryninja::low_level_il::expression::{
77use binaryninja:: low_level_il:: instruction:: {
88 InstructionHandler , LowLevelILInstructionKind , LowLevelInstructionIndex ,
99} ;
10- use binaryninja:: low_level_il:: LowLevelILRegister ;
10+ use binaryninja:: low_level_il:: { LowLevelILRegister , VisitorAction } ;
1111use rstest:: * ;
1212use std:: path:: PathBuf ;
1313
@@ -168,3 +168,55 @@ fn test_llil_info(_session: &Session) {
168168 _ => panic ! ( "Expected Ret" ) ,
169169 }
170170}
171+
172+ #[ rstest]
173+ fn test_llil_visitor ( _session : & Session ) {
174+ let out_dir = env ! ( "OUT_DIR" ) . parse :: < PathBuf > ( ) . unwrap ( ) ;
175+ let view = binaryninja:: load ( out_dir. join ( "atox.obj" ) ) . expect ( "Failed to create view" ) ;
176+ let platform = view. default_platform ( ) . unwrap ( ) ;
177+
178+ // Sample function: __crt_strtox::c_string_character_source<char>::validate
179+ let sample_function = view. function_at ( & platform, 0x2bd80 ) . unwrap ( ) ;
180+ let llil_function = sample_function. low_level_il ( ) . unwrap ( ) ;
181+ let llil_basic_blocks = llil_function. basic_blocks ( ) ;
182+ let llil_basic_block_iter = llil_basic_blocks. iter ( ) ;
183+
184+ let mut basic_blocks_visited = 0 ;
185+ let mut instructions_visited: Vec < LowLevelInstructionIndex > = vec ! [ ] ;
186+ let mut expressions_visited: Vec < LowLevelExpressionIndex > = vec ! [ ] ;
187+ for basic_block in llil_basic_block_iter {
188+ basic_blocks_visited += 1 ;
189+ for instr in basic_block. iter ( ) {
190+ instructions_visited. push ( instr. index ) ;
191+ expressions_visited. push ( instr. expr_idx ( ) ) ;
192+ instr. visit_tree ( & mut |expr| {
193+ expressions_visited. push ( expr. index ) ;
194+ VisitorAction :: Descend
195+ } ) ;
196+ }
197+ }
198+
199+ assert_eq ! ( basic_blocks_visited, 10 ) ;
200+ // This is a flag instruction removed in LLIL.
201+ instructions_visited. push ( LowLevelInstructionIndex ( 38 ) ) ;
202+ for instr_idx in 0 ..41 {
203+ if instructions_visited. iter ( ) . find ( |x| x. 0 == instr_idx) . is_none ( ) {
204+ panic ! ( "Instruction with index {:?} not visited" , instr_idx) ;
205+ } ;
206+ }
207+ // These are NOP's
208+ expressions_visited. push ( LowLevelExpressionIndex ( 24 ) ) ;
209+ expressions_visited. push ( LowLevelExpressionIndex ( 54 ) ) ;
210+ expressions_visited. push ( LowLevelExpressionIndex ( 62 ) ) ;
211+ expressions_visited. push ( LowLevelExpressionIndex ( 87 ) ) ;
212+ // These are some flag things
213+ expressions_visited. push ( LowLevelExpressionIndex ( 114 ) ) ;
214+ expressions_visited. push ( LowLevelExpressionIndex ( 115 ) ) ;
215+ expressions_visited. push ( LowLevelExpressionIndex ( 116 ) ) ;
216+ expressions_visited. push ( LowLevelExpressionIndex ( 121 ) ) ;
217+ for expr_idx in 0 ..127 {
218+ if expressions_visited. iter ( ) . find ( |x| x. 0 == expr_idx) . is_none ( ) {
219+ panic ! ( "Expression with index {:?} not visited" , expr_idx) ;
220+ } ;
221+ }
222+ }
0 commit comments