@@ -5,10 +5,14 @@ use binaryninjacore_sys::*;
5
5
6
6
use crate :: architecture:: CoreArchitecture ;
7
7
use crate :: basicblock:: BasicBlock ;
8
+ use crate :: disassembly:: DisassemblySettings ;
9
+ use crate :: flowgraph:: FlowGraph ;
8
10
use crate :: function:: { Function , Location } ;
9
11
use crate :: rc:: { Array , CoreArrayProvider , CoreArrayProviderInner , Ref , RefCountable } ;
10
12
use crate :: string:: BnStrCompatible ;
11
- use crate :: types:: { Conf , PossibleValueSet , Type , UserVariableValues , Variable } ;
13
+ use crate :: types:: {
14
+ Conf , PossibleValueSet , RegisterValue , SSAVariable , Type , UserVariableValues , Variable ,
15
+ } ;
12
16
13
17
use super :: { MediumLevelILBlock , MediumLevelILInstruction , MediumLevelILLiftedInstruction } ;
14
18
@@ -371,6 +375,207 @@ impl MediumLevelILFunction {
371
375
assert ! ( !refs. is_null( ) ) ;
372
376
unsafe { Array :: new ( refs, count, self . to_owned ( ) ) }
373
377
}
378
+
379
+ /// Current IL Address
380
+ pub fn current_address ( & self ) -> u64 {
381
+ unsafe { BNMediumLevelILGetCurrentAddress ( self . handle ) }
382
+ }
383
+
384
+ /// Set the current IL Address
385
+ pub fn set_current_address ( & self , value : u64 , arch : Option < CoreArchitecture > ) {
386
+ let arch = arch
387
+ . map ( |x| x. 0 )
388
+ . unwrap_or_else ( || self . get_function ( ) . arch ( ) . 0 ) ;
389
+ unsafe { BNMediumLevelILSetCurrentAddress ( self . handle , arch, value) }
390
+ }
391
+
392
+ /// Returns the BasicBlock at the given MLIL `instruction`.
393
+ pub fn basic_block_containing (
394
+ & self ,
395
+ instruction : & MediumLevelILInstruction ,
396
+ ) -> Option < BasicBlock < MediumLevelILBlock > > {
397
+ let index = instruction. index ;
398
+ let block = unsafe { BNGetMediumLevelILBasicBlockForInstruction ( self . handle , index) } ;
399
+ ( !block. is_null ( ) ) . then ( || unsafe {
400
+ BasicBlock :: from_raw (
401
+ block,
402
+ MediumLevelILBlock {
403
+ function : self . to_owned ( ) ,
404
+ } ,
405
+ )
406
+ } )
407
+ }
408
+ /// ends the function and computes the list of basic blocks.
409
+ pub fn finalize ( & self ) {
410
+ unsafe { BNFinalizeMediumLevelILFunction ( self . handle ) }
411
+ }
412
+
413
+ /// Generate SSA form given the current MLIL
414
+ ///
415
+ /// * `analyze_conditionals` - whether or not to analyze conditionals
416
+ /// * `handle_aliases` - whether or not to handle aliases
417
+ /// * `known_not_aliases` - optional list of variables known to be not aliased
418
+ /// * `known_aliases` - optional list of variables known to be aliased
419
+ pub fn generate_ssa_form (
420
+ & self ,
421
+ analyze_conditionals : bool ,
422
+ handle_aliases : bool ,
423
+ known_not_aliases : impl IntoIterator < Item = Variable > ,
424
+ known_aliases : impl IntoIterator < Item = Variable > ,
425
+ ) {
426
+ let mut known_not_aliases: Box < [ _ ] > =
427
+ known_not_aliases. into_iter ( ) . map ( |x| x. raw ( ) ) . collect ( ) ;
428
+ let mut known_aliases: Box < [ _ ] > = known_aliases. into_iter ( ) . map ( |x| x. raw ( ) ) . collect ( ) ;
429
+ let ( known_not_aliases_ptr, known_not_aliases_len) = if known_not_aliases. is_empty ( ) {
430
+ ( core:: ptr:: null_mut ( ) , 0 )
431
+ } else {
432
+ ( known_not_aliases. as_mut_ptr ( ) , known_not_aliases. len ( ) )
433
+ } ;
434
+ let ( known_aliases_ptr, known_aliases_len) = if known_not_aliases. is_empty ( ) {
435
+ ( core:: ptr:: null_mut ( ) , 0 )
436
+ } else {
437
+ ( known_aliases. as_mut_ptr ( ) , known_aliases. len ( ) )
438
+ } ;
439
+ unsafe {
440
+ BNGenerateMediumLevelILSSAForm (
441
+ self . handle ,
442
+ analyze_conditionals,
443
+ handle_aliases,
444
+ known_not_aliases_ptr,
445
+ known_not_aliases_len,
446
+ known_aliases_ptr,
447
+ known_aliases_len,
448
+ )
449
+ }
450
+ }
451
+
452
+ /// Gets the instruction that contains the given SSA variable's definition.
453
+ ///
454
+ /// Since SSA variables can only be defined once, this will return the single instruction where that occurs.
455
+ /// For SSA variable version 0s, which don't have definitions, this will return None instead.
456
+ pub fn ssa_variable_definition ( & self , var : SSAVariable ) -> Option < MediumLevelILInstruction > {
457
+ let result = unsafe {
458
+ BNGetMediumLevelILSSAVarDefinition ( self . handle , & var. variable . raw ( ) , var. version )
459
+ } ;
460
+ ( result < self . instruction_count ( ) )
461
+ . then ( || MediumLevelILInstruction :: new ( self . to_owned ( ) , result) )
462
+ }
463
+
464
+ pub fn ssa_memory_definition ( & self , version : usize ) -> Option < MediumLevelILInstruction > {
465
+ let result = unsafe { BNGetMediumLevelILSSAMemoryDefinition ( self . handle , version) } ;
466
+ ( result < self . instruction_count ( ) )
467
+ . then ( || MediumLevelILInstruction :: new ( self . to_owned ( ) , result) )
468
+ }
469
+
470
+ ///Gets all the instructions that use the given SSA variable.
471
+ pub fn ssa_variable_uses ( & self , ssa_var : SSAVariable ) -> Array < MediumLevelILInstruction > {
472
+ let mut count = 0 ;
473
+ let uses = unsafe {
474
+ BNGetMediumLevelILSSAVarUses (
475
+ self . handle ,
476
+ & ssa_var. variable . raw ( ) ,
477
+ ssa_var. version ,
478
+ & mut count,
479
+ )
480
+ } ;
481
+ assert ! ( !uses. is_null( ) ) ;
482
+ unsafe { Array :: new ( uses, count, self . to_owned ( ) ) }
483
+ }
484
+
485
+ pub fn ssa_memory_uses ( & self , version : usize ) -> Array < MediumLevelILInstruction > {
486
+ let mut count = 0 ;
487
+ let uses = unsafe { BNGetMediumLevelILSSAMemoryUses ( self . handle , version, & mut count) } ;
488
+ assert ! ( !uses. is_null( ) ) ;
489
+ unsafe { Array :: new ( uses, count, self . to_owned ( ) ) }
490
+ }
491
+
492
+ /// determines if `ssa_var` is live at any point in the function
493
+ pub fn is_ssa_variable_live ( & self , ssa_var : SSAVariable ) -> bool {
494
+ unsafe {
495
+ BNIsMediumLevelILSSAVarLive ( self . handle , & ssa_var. variable . raw ( ) , ssa_var. version )
496
+ }
497
+ }
498
+
499
+ pub fn variable_definitions ( & self , variable : Variable ) -> Array < MediumLevelILInstruction > {
500
+ let mut count = 0 ;
501
+ let defs = unsafe {
502
+ BNGetMediumLevelILVariableDefinitions ( self . handle , & variable. raw ( ) , & mut count)
503
+ } ;
504
+ unsafe { Array :: new ( defs, count, self . to_owned ( ) ) }
505
+ }
506
+
507
+ pub fn variable_uses ( & self , variable : Variable ) -> Array < MediumLevelILInstruction > {
508
+ let mut count = 0 ;
509
+ let uses =
510
+ unsafe { BNGetMediumLevelILVariableUses ( self . handle , & variable. raw ( ) , & mut count) } ;
511
+ unsafe { Array :: new ( uses, count, self . to_owned ( ) ) }
512
+ }
513
+
514
+ /// Computes the list of instructions for which `var` is live.
515
+ /// If `include_last_use` is false, the last use of the variable will not be included in the
516
+ /// list (this allows for easier computation of overlaps in liveness between two variables).
517
+ /// If the variable is never used, this function will return an empty list.
518
+ ///
519
+ /// `var` - the variable to query
520
+ /// `include_last_use` - whether to include the last use of the variable in the list of instructions
521
+ pub fn live_instruction_for_variable (
522
+ & self ,
523
+ variable : Variable ,
524
+ include_last_user : bool ,
525
+ ) -> Array < MediumLevelILInstruction > {
526
+ let mut count = 0 ;
527
+ let uses = unsafe {
528
+ BNGetMediumLevelILLiveInstructionsForVariable (
529
+ self . handle ,
530
+ & variable. raw ( ) ,
531
+ include_last_user,
532
+ & mut count,
533
+ )
534
+ } ;
535
+ unsafe { Array :: new ( uses, count, self . to_owned ( ) ) }
536
+ }
537
+
538
+ pub fn ssa_variable_value ( & self , ssa_var : SSAVariable ) -> RegisterValue {
539
+ unsafe {
540
+ BNGetMediumLevelILSSAVarValue ( self . handle , & ssa_var. variable . raw ( ) , ssa_var. version )
541
+ }
542
+ . into ( )
543
+ }
544
+
545
+ pub fn create_graph ( & self , settings : Option < DisassemblySettings > ) -> FlowGraph {
546
+ let settings = settings. map ( |x| x. handle ) . unwrap_or ( core:: ptr:: null_mut ( ) ) ;
547
+ let graph = unsafe { BNCreateMediumLevelILFunctionGraph ( self . handle , settings) } ;
548
+ unsafe { FlowGraph :: from_raw ( graph) }
549
+ }
550
+
551
+ /// This gets just the MLIL variables - you may be interested in the union
552
+ /// of [MediumLevelIlFunction::aliased_variables] and
553
+ /// [crate::function::Function::parameter_variables] for all the
554
+ /// variables used in the function
555
+ pub fn variables ( & self ) -> Array < Variable > {
556
+ let mut count = 0 ;
557
+ let uses = unsafe { BNGetMediumLevelILVariables ( self . handle , & mut count) } ;
558
+ unsafe { Array :: new ( uses, count, ( ) ) }
559
+ }
560
+
561
+ /// This returns a list of Variables that are taken reference to and used
562
+ /// elsewhere. You may also wish to consider [MediumLevelIlFunction::variables]
563
+ /// and [crate::function::Function::parameter_variables]
564
+ pub fn aliased_variables ( & self ) -> Array < Variable > {
565
+ let mut count = 0 ;
566
+ let uses = unsafe { BNGetMediumLevelILAliasedVariables ( self . handle , & mut count) } ;
567
+ unsafe { Array :: new ( uses, count, ( ) ) }
568
+ }
569
+
570
+ /// This gets just the MLIL SSA variables - you may be interested in the
571
+ /// union of [MediumLevelIlFunction::aliased_variables] and
572
+ /// [crate::function::Function::parameter_variables] for all the
573
+ /// variables used in the function.
574
+ pub fn ssa_variables ( & self ) -> Array < Array < SSAVariable > > {
575
+ let mut count = 0 ;
576
+ let vars = unsafe { BNGetMediumLevelILVariables ( self . handle , & mut count) } ;
577
+ unsafe { Array :: new ( vars, count, self . to_owned ( ) ) }
578
+ }
374
579
}
375
580
376
581
impl ToOwned for MediumLevelILFunction {
0 commit comments