@@ -3611,6 +3611,296 @@ def replace_expr(self, original: InstructionOrExpression, new: InstructionOrExpr
36113611
36123612 core .BNReplaceMediumLevelILExpr (self .handle , original , new )
36133613
3614+ def copy_expr_to (
3615+ self ,
3616+ expr : MediumLevelILInstruction ,
3617+ dest : 'MediumLevelILFunction' ,
3618+ sub_expr_handler : Optional [Callable [[MediumLevelILInstruction ], ExpressionIndex ]] = None
3619+ ) -> ExpressionIndex :
3620+ """
3621+ ``copy_expr_to`` deep copies an expression from this function into a target function
3622+ If provided, the function ``sub_expr_handler`` will be called on every copied sub-expression
3623+
3624+ .. warning:: This function should ONLY be called as a part of a lifter or workflow. It will otherwise not do anything useful as analysis will not be running.
3625+
3626+ :param MediumLevelILInstruction expr: Expression in this function to copy
3627+ :param MediumLevelILFunction dest: Function to copy the expression to
3628+ :param sub_expr_handler: Optional function to call on every copied sub-expression
3629+ :return: Index of the copied expression in the target function
3630+ """
3631+
3632+ if sub_expr_handler is None :
3633+ sub_expr_handler = lambda sub_expr : self .copy_expr_to (sub_expr , dest )
3634+
3635+ def do_copy (
3636+ expr : MediumLevelILInstruction ,
3637+ dest : 'MediumLevelILFunction' ,
3638+ sub_expr_handler : Optional [Callable [[MediumLevelILInstruction ], ExpressionIndex ]] = None
3639+ ) -> ExpressionIndex :
3640+ loc = ILSourceLocation .from_instruction (expr )
3641+ if expr .operation == MediumLevelILOperation .MLIL_NOP :
3642+ expr : MediumLevelILNop
3643+ return dest .nop (loc )
3644+ if expr .operation == MediumLevelILOperation .MLIL_SET_VAR :
3645+ expr : MediumLevelILSetVar
3646+ return dest .set_var (expr .size , expr .dest , sub_expr_handler (expr .src ), loc )
3647+ if expr .operation == MediumLevelILOperation .MLIL_SET_VAR_SPLIT :
3648+ expr : MediumLevelILSetVarSplit
3649+ return dest .set_var_split (expr .size , expr .high , expr .low , sub_expr_handler (expr .src ), loc )
3650+ if expr .operation == MediumLevelILOperation .MLIL_SET_VAR_FIELD :
3651+ expr : MediumLevelILSetVarField
3652+ return dest .set_var_field (expr .size , expr .dest , expr .offset , sub_expr_handler (expr .src ), loc )
3653+ if expr .operation == MediumLevelILOperation .MLIL_VAR :
3654+ expr : MediumLevelILVar
3655+ return dest .var (expr .size , expr .src , loc )
3656+ if expr .operation == MediumLevelILOperation .MLIL_VAR_FIELD :
3657+ expr : MediumLevelILVarField
3658+ return dest .var_field (expr .size , expr .src , expr .offset , loc )
3659+ if expr .operation == MediumLevelILOperation .MLIL_VAR_SPLIT :
3660+ expr : MediumLevelILVarSplit
3661+ return dest .var_split (expr .size , expr .high , expr .low , loc )
3662+ if expr .operation == MediumLevelILOperation .MLIL_FORCE_VER :
3663+ expr : MediumLevelILForceVer
3664+ return dest .force_ver (expr .size , expr .dest , expr .src , loc )
3665+ if expr .operation == MediumLevelILOperation .MLIL_ASSERT :
3666+ expr : MediumLevelILAssert
3667+ return dest .assert_expr (expr .size , expr .src , expr .constraint , loc )
3668+ if expr .operation == MediumLevelILOperation .MLIL_ADDRESS_OF :
3669+ expr : MediumLevelILAddressOf
3670+ return dest .address_of (expr .src , loc )
3671+ if expr .operation == MediumLevelILOperation .MLIL_ADDRESS_OF_FIELD :
3672+ expr : MediumLevelILAddressOfField
3673+ return dest .address_of_field (expr .src , expr .offset , loc )
3674+ if expr .operation == MediumLevelILOperation .MLIL_CALL :
3675+ expr : MediumLevelILCall
3676+ params = [sub_expr_handler (param ) for param in expr .params ]
3677+ return dest .call (expr .output , sub_expr_handler (expr .dest ), params , loc )
3678+ if expr .operation == MediumLevelILOperation .MLIL_CALL_UNTYPED :
3679+ expr : MediumLevelILCallUntyped
3680+ params = [sub_expr_handler (param ) for param in expr .params ]
3681+ return dest .call_untyped (
3682+ expr .output ,
3683+ sub_expr_handler (expr .dest ),
3684+ params ,
3685+ sub_expr_handler (expr .stack ),
3686+ loc
3687+ )
3688+ if expr .operation == MediumLevelILOperation .MLIL_SYSCALL :
3689+ expr : MediumLevelILSyscall
3690+ params = [sub_expr_handler (param ) for param in expr .params ]
3691+ return dest .system_call (expr .output , params , loc )
3692+ if expr .operation == MediumLevelILOperation .MLIL_SYSCALL_UNTYPED :
3693+ expr : MediumLevelILSyscallUntyped
3694+ params = [sub_expr_handler (param ) for param in expr .params ]
3695+ return dest .system_call_untyped (
3696+ expr .output ,
3697+ params ,
3698+ sub_expr_handler (expr .stack ),
3699+ loc
3700+ )
3701+ if expr .operation == MediumLevelILOperation .MLIL_TAILCALL :
3702+ expr : MediumLevelILTailcall
3703+ params = [sub_expr_handler (param ) for param in expr .params ]
3704+ return dest .tailcall (expr .output , sub_expr_handler (expr .dest ), params , loc )
3705+ if expr .operation == MediumLevelILOperation .MLIL_TAILCALL_UNTYPED :
3706+ expr : MediumLevelILTailcallUntyped
3707+ params = [sub_expr_handler (param ) for param in expr .params ]
3708+ return dest .tailcall_untyped (
3709+ expr .output ,
3710+ sub_expr_handler (expr .dest ),
3711+ params ,
3712+ sub_expr_handler (expr .stack ),
3713+ loc
3714+ )
3715+ # if expr.operation == MediumLevelILOperation.MLIL_SEPARATE_PARAM_LIST:
3716+ # expr: MediumLevelILSeparateParamList
3717+ # params = [sub_expr_handler(param) for param in expr.params]
3718+ # return dest.separate_param_list(params, loc)
3719+ # if expr.operation == MediumLevelILOperation.MLIL_SHARED_PARAM_SLOT:
3720+ # expr: MediumLevelILSharedParamSlot
3721+ # params = [sub_expr_handler(param) for param in expr.params]
3722+ # return dest.shared_param_slot(params, loc)
3723+ if expr .operation == MediumLevelILOperation .MLIL_RET :
3724+ expr : MediumLevelILRet
3725+ params = [sub_expr_handler (src ) for src in expr .src ]
3726+ return dest .ret (params , loc )
3727+ if expr .operation == MediumLevelILOperation .MLIL_NORET :
3728+ expr : MediumLevelILNoret
3729+ return dest .no_ret (loc )
3730+ if expr .operation == MediumLevelILOperation .MLIL_STORE :
3731+ expr : MediumLevelILStore
3732+ return dest .store (expr .size , sub_expr_handler (expr .dest ), sub_expr_handler (expr .src ), loc )
3733+ if expr .operation == MediumLevelILOperation .MLIL_STORE_STRUCT :
3734+ expr : MediumLevelILStoreStruct
3735+ return dest .store_struct (expr .size , sub_expr_handler (expr .dest ), expr .offset , sub_expr_handler (expr .src ), loc )
3736+ if expr .operation == MediumLevelILOperation .MLIL_LOAD :
3737+ expr : MediumLevelILLoad
3738+ return dest .load (expr .size , sub_expr_handler (expr .src ), loc )
3739+ if expr .operation == MediumLevelILOperation .MLIL_LOAD_STRUCT :
3740+ expr : MediumLevelILLoadStruct
3741+ return dest .load_struct (expr .size , sub_expr_handler (expr .src ), expr .offset , loc )
3742+ if expr .operation == MediumLevelILOperation .MLIL_JUMP :
3743+ expr : MediumLevelILJump
3744+ return dest .jump (sub_expr_handler (expr .dest ), loc )
3745+ if expr .operation in [
3746+ MediumLevelILOperation .MLIL_NEG ,
3747+ MediumLevelILOperation .MLIL_NOT ,
3748+ MediumLevelILOperation .MLIL_SX ,
3749+ MediumLevelILOperation .MLIL_ZX ,
3750+ MediumLevelILOperation .MLIL_LOW_PART ,
3751+ MediumLevelILOperation .MLIL_BOOL_TO_INT ,
3752+ MediumLevelILOperation .MLIL_RET_HINT ,
3753+ MediumLevelILOperation .MLIL_UNIMPL_MEM ,
3754+ MediumLevelILOperation .MLIL_FSQRT ,
3755+ MediumLevelILOperation .MLIL_FNEG ,
3756+ MediumLevelILOperation .MLIL_FABS ,
3757+ MediumLevelILOperation .MLIL_FLOAT_TO_INT ,
3758+ MediumLevelILOperation .MLIL_INT_TO_FLOAT ,
3759+ MediumLevelILOperation .MLIL_FLOAT_CONV ,
3760+ MediumLevelILOperation .MLIL_ROUND_TO_INT ,
3761+ MediumLevelILOperation .MLIL_FLOOR ,
3762+ MediumLevelILOperation .MLIL_CEIL ,
3763+ MediumLevelILOperation .MLIL_FTRUNC
3764+ ]:
3765+ expr : MediumLevelILUnaryBase
3766+ return dest .expr (expr .operation , sub_expr_handler (expr .src ), size = expr .size , source_location = loc )
3767+ if expr .operation in [
3768+ MediumLevelILOperation .MLIL_ADD ,
3769+ MediumLevelILOperation .MLIL_SUB ,
3770+ MediumLevelILOperation .MLIL_AND ,
3771+ MediumLevelILOperation .MLIL_OR ,
3772+ MediumLevelILOperation .MLIL_XOR ,
3773+ MediumLevelILOperation .MLIL_LSL ,
3774+ MediumLevelILOperation .MLIL_LSR ,
3775+ MediumLevelILOperation .MLIL_ASR ,
3776+ MediumLevelILOperation .MLIL_ROL ,
3777+ MediumLevelILOperation .MLIL_ROR ,
3778+ MediumLevelILOperation .MLIL_MUL ,
3779+ MediumLevelILOperation .MLIL_MULU_DP ,
3780+ MediumLevelILOperation .MLIL_MULS_DP ,
3781+ MediumLevelILOperation .MLIL_DIVU ,
3782+ MediumLevelILOperation .MLIL_DIVS ,
3783+ MediumLevelILOperation .MLIL_MODU ,
3784+ MediumLevelILOperation .MLIL_MODS ,
3785+ MediumLevelILOperation .MLIL_DIVU_DP ,
3786+ MediumLevelILOperation .MLIL_DIVS_DP ,
3787+ MediumLevelILOperation .MLIL_MODU_DP ,
3788+ MediumLevelILOperation .MLIL_MODS_DP ,
3789+ MediumLevelILOperation .MLIL_CMP_E ,
3790+ MediumLevelILOperation .MLIL_CMP_NE ,
3791+ MediumLevelILOperation .MLIL_CMP_SLT ,
3792+ MediumLevelILOperation .MLIL_CMP_ULT ,
3793+ MediumLevelILOperation .MLIL_CMP_SLE ,
3794+ MediumLevelILOperation .MLIL_CMP_ULE ,
3795+ MediumLevelILOperation .MLIL_CMP_SGE ,
3796+ MediumLevelILOperation .MLIL_CMP_UGE ,
3797+ MediumLevelILOperation .MLIL_CMP_SGT ,
3798+ MediumLevelILOperation .MLIL_CMP_UGT ,
3799+ MediumLevelILOperation .MLIL_TEST_BIT ,
3800+ MediumLevelILOperation .MLIL_ADD_OVERFLOW ,
3801+ MediumLevelILOperation .MLIL_FADD ,
3802+ MediumLevelILOperation .MLIL_FSUB ,
3803+ MediumLevelILOperation .MLIL_FMUL ,
3804+ MediumLevelILOperation .MLIL_FDIV ,
3805+ MediumLevelILOperation .MLIL_FCMP_E ,
3806+ MediumLevelILOperation .MLIL_FCMP_NE ,
3807+ MediumLevelILOperation .MLIL_FCMP_LT ,
3808+ MediumLevelILOperation .MLIL_FCMP_LE ,
3809+ MediumLevelILOperation .MLIL_FCMP_GE ,
3810+ MediumLevelILOperation .MLIL_FCMP_GT ,
3811+ MediumLevelILOperation .MLIL_FCMP_O ,
3812+ MediumLevelILOperation .MLIL_FCMP_UO
3813+ ]:
3814+ expr : MediumLevelILBinaryBase
3815+ return dest .expr (
3816+ expr .operation ,
3817+ sub_expr_handler (expr .left ),
3818+ sub_expr_handler (expr .right ),
3819+ size = expr .size ,
3820+ source_location = loc
3821+ )
3822+ if expr .operation in [
3823+ MediumLevelILOperation .MLIL_ADC ,
3824+ MediumLevelILOperation .MLIL_SBB ,
3825+ MediumLevelILOperation .MLIL_RLC ,
3826+ MediumLevelILOperation .MLIL_RRC
3827+ ]:
3828+ expr : MediumLevelILCarryBase
3829+ return dest .expr (
3830+ expr .operation ,
3831+ sub_expr_handler (expr .left ),
3832+ sub_expr_handler (expr .right ),
3833+ sub_expr_handler (expr .carry ),
3834+ size = expr .size ,
3835+ source_location = loc
3836+ )
3837+ if expr .operation == MediumLevelILOperation .MLIL_JUMP_TO :
3838+ expr : MediumLevelILJumpTo
3839+ label_list = {}
3840+ for a , b in expr .targets .items ():
3841+ label_a = dest .get_label_for_source_instruction (b )
3842+ if label_a is None :
3843+ return dest .jump (sub_expr_handler (expr .dest ), loc )
3844+ label_list [a ] = label_a
3845+ return dest .jump_to (sub_expr_handler (expr .dest ), label_list , loc )
3846+ if expr .operation == MediumLevelILOperation .MLIL_GOTO :
3847+ expr : MediumLevelILGoto
3848+ label_a = dest .get_label_for_source_instruction (expr .dest )
3849+ if label_a is None :
3850+ return dest .jump (dest .const_pointer (expr .function .arch .address_size , expr .function [expr .dest ].address ), loc )
3851+ return dest .goto (label_a , loc )
3852+ if expr .operation == MediumLevelILOperation .MLIL_IF :
3853+ expr : MediumLevelILIf
3854+ label_a = dest .get_label_for_source_instruction (expr .true )
3855+ label_b = dest .get_label_for_source_instruction (expr .false )
3856+ if label_a is None or label_b is None :
3857+ return dest .undefined (loc )
3858+ return dest .if_expr (sub_expr_handler (expr .condition ), label_a , label_b , loc )
3859+ if expr .operation == MediumLevelILOperation .MLIL_CONST :
3860+ expr : MediumLevelILConst
3861+ return dest .const (expr .size , expr .constant , loc )
3862+ if expr .operation == MediumLevelILOperation .MLIL_CONST_PTR :
3863+ expr : MediumLevelILConstPtr
3864+ return dest .const_pointer (expr .size , expr .constant , loc )
3865+ if expr .operation == MediumLevelILOperation .MLIL_EXTERN_PTR :
3866+ expr : MediumLevelILExternPtr
3867+ return dest .extern_pointer (expr .size , expr .constant , expr .offset , loc )
3868+ if expr .operation == MediumLevelILOperation .MLIL_FLOAT_CONST :
3869+ expr : MediumLevelILFloatConst
3870+ return dest .float_const_raw (expr .size , expr .raw_operands [0 ], loc )
3871+ if expr .operation == MediumLevelILOperation .MLIL_IMPORT :
3872+ expr : MediumLevelILImport
3873+ return dest .imported_address (expr .size , expr .constant , loc )
3874+ if expr .operation == MediumLevelILOperation .MLIL_CONST_DATA :
3875+ expr : MediumLevelILConstData
3876+ return dest .const_data (expr .size , expr .constant_data , loc )
3877+ if expr .operation == MediumLevelILOperation .MLIL_BP :
3878+ expr : MediumLevelILBp
3879+ return dest .breakpoint (loc )
3880+ if expr .operation == MediumLevelILOperation .MLIL_TRAP :
3881+ expr : MediumLevelILTrap
3882+ return dest .trap (expr .vector , loc )
3883+ if expr .operation == MediumLevelILOperation .MLIL_INTRINSIC :
3884+ expr : MediumLevelILIntrinsic
3885+ params = [sub_expr_handler (param ) for param in expr .params ]
3886+ return dest .intrinsic (expr .output , expr .intrinsic , params , loc )
3887+ if expr .operation == MediumLevelILOperation .MLIL_FREE_VAR_SLOT :
3888+ expr : MediumLevelILFreeVarSlot
3889+ return dest .free_var_slot (expr .dest , loc )
3890+ if expr .operation == MediumLevelILOperation .MLIL_UNDEF :
3891+ expr : MediumLevelILUndef
3892+ return dest .undefined (loc )
3893+ if expr .operation == MediumLevelILOperation .MLIL_UNIMPL :
3894+ expr : MediumLevelILUnimpl
3895+ return dest .unimplemented (loc )
3896+ raise NotImplementedError (f"unknown expr operation { expr .operation } in copy_expr_to" )
3897+
3898+ new_index = do_copy (expr , dest , sub_expr_handler )
3899+ # Copy expression metadata as well
3900+ dest .set_expr_attributes (new_index , expr .attributes )
3901+ dest .set_expr_type (new_index , self .get_expr_type (expr .expr_index ))
3902+ return new_index
3903+
36143904 def set_expr_attributes (self , expr : InstructionOrExpression , value : ILInstructionAttributeSet ):
36153905 """
36163906 ``set_expr_attributes`` allows modification of instruction attributes but ONLY during lifting.
@@ -4890,6 +5180,20 @@ def intrinsic(
48905180 source_location = loc
48915181 )
48925182
5183+ def free_var_slot (
5184+ self ,
5185+ var : 'variable.Variable' ,
5186+ loc : Optional ['ILSourceLocation' ] = None
5187+ ) -> ExpressionIndex :
5188+ """
5189+ ``free_var_slot`` return an expression that clears the slot of the variable ``var`` which is in a register stack
5190+
5191+ :param Variable var: variable to free
5192+ :param ILSourceLocation loc: location of returned expression
5193+ :return: the expression ``free_var_slot(var)``
5194+ """
5195+ return self .expr (MediumLevelILOperation .MLIL_FREE_VAR_SLOT , var .identifier , source_location = loc )
5196+
48935197 def undefined (self , loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
48945198 """
48955199 ``undefined`` returns the undefined expression. This should be used for instructions which perform functions but
@@ -5384,6 +5688,37 @@ def generate_ssa_form(self, analyze_conditionals : bool = True, handle_aliases :
53845688 known_alias_list [i ] = known_aliases [i ].to_BNVariable ()
53855689 core .BNGenerateMediumLevelILSSAForm (self .handle , analyze_conditionals , handle_aliases , known_not_alias_list , len (known_not_alias_list ), known_alias_list , len (known_alias_list ))
53865690
5691+ def prepare_to_copy_function (self , src : 'MediumLevelILFunction' ):
5692+ """
5693+ ``prepare_to_copy_function`` sets up state in this MLIL function in preparation
5694+ of copying instructions from ``src``
5695+
5696+ :param MediumLevelILFunction src: function about to be copied from
5697+ """
5698+ core .BNPrepareToCopyMediumLevelILFunction (self .handle , src .handle )
5699+
5700+ def prepare_to_copy_block (self , src : 'MediumLevelILBasicBlock' ):
5701+ """
5702+ ``prepare_to_copy_block`` sets up state when copying a function in preparation
5703+ of copying the instructions from the block ``src``
5704+
5705+ :param MediumLevelILBasicBlock src: block about to be copied from
5706+ """
5707+ core .BNPrepareToCopyMediumLevelILBasicBlock (self .handle , src .handle )
5708+
5709+ def get_label_for_source_instruction (self , i : InstructionIndex ) -> Optional ['MediumLevelILLabel' ]:
5710+ """
5711+ Get the MediumLevelILLabel for a given source instruction. The returned label is to an internal object with
5712+ the same lifetime as the containing MediumLevelILFunction.
5713+
5714+ :param i: The source instruction index
5715+ :return: The MediumLevelILLabel for the source instruction
5716+ """
5717+ label = core .BNGetLabelForMediumLevelILSourceInstruction (self .handle , i )
5718+ if not label :
5719+ return None
5720+ return MediumLevelILLabel (handle = label )
5721+
53875722 def get_ssa_instruction_index (self , instr : InstructionIndex ) -> InstructionIndex :
53885723 return InstructionIndex (core .BNGetMediumLevelILSSAInstructionIndex (self .handle , instr ))
53895724
@@ -5742,7 +6077,7 @@ def get_expr_type(self, expr_index: int) -> Optional['types.Type']:
57426077 )
57436078 return None
57446079
5745- def set_expr_type (self , expr_index : int , expr_type : StringOrType ) -> None :
6080+ def set_expr_type (self , expr_index : int , expr_type : Optional [ StringOrType ] ) -> None :
57466081 """
57476082 Set type of expression
57486083
@@ -5754,9 +6089,14 @@ def set_expr_type(self, expr_index: int, expr_type: StringOrType) -> None:
57546089 :param int expr_index: index of the expression to set
57556090 :param StringOrType: new type of the expression
57566091 """
5757- if isinstance (expr_type , str ):
5758- (expr_type , _ ) = self .view .parse_type_string (expr_type )
5759- tc = expr_type ._to_core_struct ()
6092+ if expr_type is not None :
6093+ if isinstance (expr_type , str ):
6094+ (expr_type , _ ) = self .view .parse_type_string (expr_type )
6095+ tc = expr_type ._to_core_struct ()
6096+ else :
6097+ tc = core .BNTypeWithConfidence ()
6098+ tc .type = None
6099+ tc .confidence = 0
57606100 core .BNSetMediumLevelILExprType (self .handle , expr_index , tc )
57616101
57626102
0 commit comments