2020
2121import ctypes
2222import struct
23- from typing import Generator , List , Optional , Dict , Union , Tuple , NewType , ClassVar , Set , Callable , Any , Iterator , overload
23+ from typing import Generator , List , Optional , Dict , Union , Tuple , NewType , ClassVar , Set , \
24+ Callable , Any , Iterator , overload , Mapping
2425from dataclasses import dataclass
2526
2627# Binary Ninja components
@@ -511,6 +512,22 @@ def create(
511512 core_inst = CoreLowLevelILInstruction .from_BNLowLevelILInstruction (inst )
512513 return ILInstruction [core_inst .operation ](func , expr_index , core_inst , instr_index ) # type: ignore
513514
515+ def copy_to (
516+ self , dest : 'LowLevelILFunction' ,
517+ sub_expr_handler : Optional [Callable [['LowLevelILInstruction' ], ExpressionIndex ]] = None
518+ ) -> ExpressionIndex :
519+ """
520+ ``copy_to`` deep copies an expression into a new IL function.
521+ If provided, the function ``sub_expr_handler`` will be called on every copied sub-expression
522+
523+ .. 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.
524+
525+ :param LowLevelILFunction dest: Function to copy the expression to
526+ :param sub_expr_handler: Optional function to call on every copied sub-expression
527+ :return: Index of the copied expression in the target function
528+ """
529+ return self .function .copy_expr_to (self , dest , sub_expr_handler )
530+
514531 def __str__ (self ):
515532 tokens = self .tokens
516533 if tokens is None :
@@ -3853,6 +3870,8 @@ def copy_expr(self, original: LowLevelILInstruction) -> ExpressionIndex:
38533870 """
38543871 ``copy_expr`` adds an expression to the function which is equivalent to the given expression
38553872
3873+ .. 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.
3874+
38563875 :param LowLevelILInstruction original: the original IL Instruction you want to copy
38573876 :return: The index of the newly copied expression
38583877 """
@@ -3871,7 +3890,7 @@ def replace_expr(self, original: InstructionOrExpression, new: InstructionOrExpr
38713890 """
38723891 ``replace_expr`` allows modification of expressions but ONLY during lifting.
38733892
3874- .. warning:: This function should ONLY be called as a part of a lifter. It will otherwise not do anything useful as there's no way to trigger re- analysis of IL levels at this time .
3893+ .. 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 .
38753894
38763895 :param ExpressionIndex original: the ExpressionIndex to replace (may also be an expression index)
38773896 :param ExpressionIndex new: the ExpressionIndex to add to the current LowLevelILFunction (may also be an expression index)
@@ -3889,11 +3908,229 @@ def replace_expr(self, original: InstructionOrExpression, new: InstructionOrExpr
38893908
38903909 core .BNReplaceLowLevelILExpr (self .handle , original , new )
38913910
3911+ def copy_expr_to (
3912+ self , expr : LowLevelILInstruction , dest : 'LowLevelILFunction' ,
3913+ sub_expr_handler : Optional [Callable [[LowLevelILInstruction ], ExpressionIndex ]] = None
3914+ ) -> ExpressionIndex :
3915+ """
3916+ ``copy_expr_to`` deep copies an expression from this function into a target function
3917+ If provided, the function ``sub_expr_handler`` will be called on every copied sub-expression
3918+
3919+ .. 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.
3920+
3921+ :param LowLevelILInstruction expr: Expression in this function to copy
3922+ :param LowLevelILFunction dest: Function to copy the expression to
3923+ :param sub_expr_handler: Optional function to call on every copied sub-expression
3924+ :return: Index of the copied expression in the target function
3925+ """
3926+
3927+ if sub_expr_handler is None :
3928+ sub_expr_handler = lambda sub_expr : self .copy_expr_to (sub_expr , dest )
3929+ loc = ILSourceLocation .from_instruction (expr )
3930+
3931+ if expr .operation == LowLevelILOperation .LLIL_NOP :
3932+ expr : LowLevelILNop
3933+ return dest .nop (loc )
3934+ if expr .operation == LowLevelILOperation .LLIL_SET_REG :
3935+ expr : LowLevelILSetReg
3936+ return dest .set_reg (expr .size , expr .dest , sub_expr_handler (expr .src ), expr .flags , loc )
3937+ if expr .operation == LowLevelILOperation .LLIL_SET_REG_SPLIT :
3938+ expr : LowLevelILSetRegSplit
3939+ return dest .set_reg_split (expr .size , expr .hi , expr .lo , sub_expr_handler (expr .src ), expr .flags , loc )
3940+ if expr .operation == LowLevelILOperation .LLIL_SET_REG_STACK_REL :
3941+ expr : LowLevelILSetRegStackRel
3942+ return dest .set_reg_stack_top_relative (expr .size , expr .stack , sub_expr_handler (expr .dest ), sub_expr_handler (expr .src ), expr .flags , loc )
3943+ if expr .operation == LowLevelILOperation .LLIL_REG_STACK_PUSH :
3944+ expr : LowLevelILRegStackPush
3945+ return dest .reg_stack_push (expr .size , expr .stack , sub_expr_handler (expr .src ), expr .flags , loc )
3946+ if expr .operation == LowLevelILOperation .LLIL_SET_FLAG :
3947+ expr : LowLevelILSetFlag
3948+ return dest .set_flag (expr .dest .name , sub_expr_handler (expr .src ), loc )
3949+ if expr .operation == LowLevelILOperation .LLIL_LOAD :
3950+ expr : LowLevelILLoad
3951+ return dest .load (expr .size , sub_expr_handler (expr .src ), expr .flags , loc )
3952+ if expr .operation == LowLevelILOperation .LLIL_STORE :
3953+ expr : LowLevelILStore
3954+ return dest .store (expr .size , sub_expr_handler (expr .dest ), sub_expr_handler (expr .src ), expr .flags , loc )
3955+ if expr .operation == LowLevelILOperation .LLIL_REG :
3956+ expr : LowLevelILReg
3957+ return dest .reg (expr .size , expr .src , loc )
3958+ if expr .operation == LowLevelILOperation .LLIL_REG_SPLIT :
3959+ expr : LowLevelILRegSplit
3960+ return dest .reg_split (expr .size , expr .hi , expr .lo , loc )
3961+ if expr .operation == LowLevelILOperation .LLIL_REG_STACK_REL :
3962+ expr : LowLevelILRegStackRel
3963+ return dest .reg_stack_top_relative (expr .size , expr .stack , sub_expr_handler (expr .src ), loc )
3964+ if expr .operation == LowLevelILOperation .LLIL_REG_STACK_POP :
3965+ expr : LowLevelILRegStackPop
3966+ return dest .reg_stack_pop (expr .size , expr .stack , loc )
3967+ if expr .operation == LowLevelILOperation .LLIL_FLAG :
3968+ expr : LowLevelILFlag
3969+ return dest .flag (expr .src .name , loc )
3970+ if expr .operation == LowLevelILOperation .LLIL_FLAG_BIT :
3971+ expr : LowLevelILFlagBit
3972+ return dest .flag_bit (expr .size , expr .src .name , expr .bit , loc )
3973+ if expr .operation == LowLevelILOperation .LLIL_JUMP :
3974+ expr : LowLevelILJump
3975+ return dest .jump (sub_expr_handler (expr .dest ), loc )
3976+ if expr .operation == LowLevelILOperation .LLIL_CALL :
3977+ expr : LowLevelILCall
3978+ return dest .call (sub_expr_handler (expr .dest ), loc )
3979+ if expr .operation == LowLevelILOperation .LLIL_CALL_STACK_ADJUST :
3980+ expr : LowLevelILCallStackAdjust
3981+ return dest .call_stack_adjust (sub_expr_handler (expr .dest ), expr .stack_adjustment , loc )
3982+ if expr .operation == LowLevelILOperation .LLIL_TAILCALL :
3983+ expr : LowLevelILTailcall
3984+ return dest .tailcall (sub_expr_handler (expr .dest ), loc )
3985+ if expr .operation == LowLevelILOperation .LLIL_RET :
3986+ expr : LowLevelILRet
3987+ return dest .ret (sub_expr_handler (expr .dest ), loc )
3988+ if expr .operation == LowLevelILOperation .LLIL_JUMP_TO :
3989+ expr : LowLevelILJumpTo
3990+ label_list = {}
3991+ for a , b in expr .targets .items ():
3992+ label_a = dest .get_label_for_source_instruction (b )
3993+ if label_a is None :
3994+ return dest .jump (sub_expr_handler (expr .dest ), loc )
3995+ label_list [a ] = label_a
3996+ return dest .jump_to (sub_expr_handler (expr .dest ), label_list , loc )
3997+ if expr .operation == LowLevelILOperation .LLIL_GOTO :
3998+ expr : LowLevelILGoto
3999+ label_a = dest .get_label_for_source_instruction (expr .dest )
4000+ if label_a is None :
4001+ return dest .jump (dest .const_pointer (expr .function .arch .address_size , expr .function [expr .dest ].address ))
4002+ return dest .goto (label_a , loc )
4003+ if expr .operation == LowLevelILOperation .LLIL_IF :
4004+ expr : LowLevelILIf
4005+ label_a = dest .get_label_for_source_instruction (expr .true )
4006+ label_b = dest .get_label_for_source_instruction (expr .false )
4007+ if label_a is None or label_b is None :
4008+ return dest .undefined (loc )
4009+ return dest .if_expr (sub_expr_handler (expr .condition ), label_a , label_b , loc )
4010+ if expr .operation == LowLevelILOperation .LLIL_FLAG_COND :
4011+ expr : LowLevelILFlagCond
4012+ return dest .flag_condition (expr .condition , expr .semantic_class , loc )
4013+ if expr .operation == LowLevelILOperation .LLIL_FLAG_GROUP :
4014+ expr : LowLevelILFlagGroup
4015+ return dest .flag_group (expr .semantic_group .name , loc )
4016+ if expr .operation == LowLevelILOperation .LLIL_TRAP :
4017+ expr : LowLevelILTrap
4018+ return dest .trap (expr .vector , loc )
4019+ if expr .operation == LowLevelILOperation .LLIL_CONST :
4020+ expr : LowLevelILConst
4021+ return dest .const (expr .size , expr .constant , loc )
4022+ if expr .operation == LowLevelILOperation .LLIL_CONST_PTR :
4023+ expr : LowLevelILConstPtr
4024+ return dest .const_pointer (expr .size , expr .constant , loc )
4025+ if expr .operation == LowLevelILOperation .LLIL_EXTERN_PTR :
4026+ expr : LowLevelILExternPtr
4027+ return dest .extern_pointer (expr .size , expr .constant , expr .offset , loc )
4028+ if expr .operation == LowLevelILOperation .LLIL_FLOAT_CONST :
4029+ expr : LowLevelILFloatConst
4030+ return dest .float_const_raw (expr .size , expr .constant , loc )
4031+ if expr .operation in [
4032+ LowLevelILOperation .LLIL_POP ,
4033+ LowLevelILOperation .LLIL_NORET ,
4034+ LowLevelILOperation .LLIL_SYSCALL ,
4035+ LowLevelILOperation .LLIL_BP ,
4036+ LowLevelILOperation .LLIL_UNDEF ,
4037+ LowLevelILOperation .LLIL_UNIMPL
4038+ ]:
4039+ expr :Y
4040+ return dest .expr (expr .operation , size = expr .size , flags = expr .flags , source_location = loc )
4041+ if expr .operation in [
4042+ LowLevelILOperation .LLIL_PUSH ,
4043+ LowLevelILOperation .LLIL_NEG ,
4044+ LowLevelILOperation .LLIL_NOT ,
4045+ LowLevelILOperation .LLIL_SX ,
4046+ LowLevelILOperation .LLIL_ZX ,
4047+ LowLevelILOperation .LLIL_LOW_PART ,
4048+ LowLevelILOperation .LLIL_BOOL_TO_INT ,
4049+ LowLevelILOperation .LLIL_UNIMPL_MEM ,
4050+ LowLevelILOperation .LLIL_FSQRT ,
4051+ LowLevelILOperation .LLIL_FNEG ,
4052+ LowLevelILOperation .LLIL_FABS ,
4053+ LowLevelILOperation .LLIL_FLOAT_TO_INT ,
4054+ LowLevelILOperation .LLIL_INT_TO_FLOAT ,
4055+ LowLevelILOperation .LLIL_FLOAT_CONV ,
4056+ LowLevelILOperation .LLIL_ROUND_TO_INT ,
4057+ LowLevelILOperation .LLIL_FLOOR ,
4058+ LowLevelILOperation .LLIL_CEIL ,
4059+ LowLevelILOperation .LLIL_FTRUNC ,
4060+ ]:
4061+ expr : LowLevelILUnaryBase
4062+ return dest .expr (expr .operation , sub_expr_handler (expr .src ), size = expr .size , flags = expr .flags , source_location = loc )
4063+ if expr .operation in [
4064+ LowLevelILOperation .LLIL_ADD ,
4065+ LowLevelILOperation .LLIL_SUB ,
4066+ LowLevelILOperation .LLIL_AND ,
4067+ LowLevelILOperation .LLIL_OR ,
4068+ LowLevelILOperation .LLIL_XOR ,
4069+ LowLevelILOperation .LLIL_LSL ,
4070+ LowLevelILOperation .LLIL_LSR ,
4071+ LowLevelILOperation .LLIL_ASR ,
4072+ LowLevelILOperation .LLIL_ROL ,
4073+ LowLevelILOperation .LLIL_ROR ,
4074+ LowLevelILOperation .LLIL_MUL ,
4075+ LowLevelILOperation .LLIL_MULU_DP ,
4076+ LowLevelILOperation .LLIL_MULS_DP ,
4077+ LowLevelILOperation .LLIL_DIVU ,
4078+ LowLevelILOperation .LLIL_DIVS ,
4079+ LowLevelILOperation .LLIL_MODU ,
4080+ LowLevelILOperation .LLIL_MODS ,
4081+ LowLevelILOperation .LLIL_DIVU_DP ,
4082+ LowLevelILOperation .LLIL_DIVS_DP ,
4083+ LowLevelILOperation .LLIL_MODU_DP ,
4084+ LowLevelILOperation .LLIL_MODS_DP ,
4085+ LowLevelILOperation .LLIL_CMP_E ,
4086+ LowLevelILOperation .LLIL_CMP_NE ,
4087+ LowLevelILOperation .LLIL_CMP_SLT ,
4088+ LowLevelILOperation .LLIL_CMP_ULT ,
4089+ LowLevelILOperation .LLIL_CMP_SLE ,
4090+ LowLevelILOperation .LLIL_CMP_ULE ,
4091+ LowLevelILOperation .LLIL_CMP_SGE ,
4092+ LowLevelILOperation .LLIL_CMP_UGE ,
4093+ LowLevelILOperation .LLIL_CMP_SGT ,
4094+ LowLevelILOperation .LLIL_CMP_UGT ,
4095+ LowLevelILOperation .LLIL_TEST_BIT ,
4096+ LowLevelILOperation .LLIL_ADD_OVERFLOW ,
4097+ LowLevelILOperation .LLIL_FADD ,
4098+ LowLevelILOperation .LLIL_FSUB ,
4099+ LowLevelILOperation .LLIL_FMUL ,
4100+ LowLevelILOperation .LLIL_FDIV ,
4101+ LowLevelILOperation .LLIL_FCMP_E ,
4102+ LowLevelILOperation .LLIL_FCMP_NE ,
4103+ LowLevelILOperation .LLIL_FCMP_LT ,
4104+ LowLevelILOperation .LLIL_FCMP_LE ,
4105+ LowLevelILOperation .LLIL_FCMP_GE ,
4106+ LowLevelILOperation .LLIL_FCMP_GT ,
4107+ LowLevelILOperation .LLIL_FCMP_O ,
4108+ LowLevelILOperation .LLIL_FCMP_UO ,
4109+ ]:
4110+ expr : LowLevelILBinaryBase
4111+ return dest .expr (expr .operation , sub_expr_handler (expr .left ), sub_expr_handler (expr .right ), size = expr .size , flags = expr .flags , source_location = loc )
4112+ if expr .operation in [
4113+ LowLevelILOperation .LLIL_ADC ,
4114+ LowLevelILOperation .LLIL_SBB ,
4115+ LowLevelILOperation .LLIL_RLC ,
4116+ LowLevelILOperation .LLIL_RRC ,
4117+ ]:
4118+ expr : LowLevelILCarryBase
4119+ return dest .expr (expr .operation , sub_expr_handler (expr .left ), sub_expr_handler (expr .right ), sub_expr_handler (expr .carry ), size = expr .size , flags = expr .flags , source_location = loc )
4120+ if expr .operation == LowLevelILOperation .LLIL_INTRINSIC :
4121+ expr : LowLevelILIntrinsic
4122+ params = []
4123+ for param in expr .params :
4124+ params .append (sub_expr_handler (param ))
4125+ return dest .intrinsic (expr .output , expr .intrinsic , params , expr .flags , loc )
4126+
4127+ raise NotImplementedError (f"unknown expr operation { expr .operation } in copy_expr_to" )
4128+
38924129 def set_expr_attributes (self , expr : InstructionOrExpression , value : ILInstructionAttributeSet ):
38934130 """
38944131 ``set_expr_attributes`` allows modification of instruction attributes but ONLY during lifting.
38954132
3896- .. warning:: This function should ONLY be called as a part of a lifter. It will otherwise not do anything useful as there's no way to trigger re- analysis of IL levels at this time .
4133+ .. 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 .
38974134
38984135 :param ExpressionIndex expr: the ExpressionIndex to replace (may also be an expression index)
38994136 :param set(ILInstructionAttribute) value: the set of attributes to place on the instruction
@@ -4030,17 +4267,21 @@ def set_flag(
40304267 """
40314268 return self .expr (LowLevelILOperation .LLIL_SET_FLAG , ExpressionIndex (self .arch .get_flag_by_name (flag )), value , source_location = loc )
40324269
4033- def load (self , size : int , addr : ExpressionIndex , loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
4270+ def load (
4271+ self , size : int , addr : ExpressionIndex , flags : Optional ['architecture.FlagName' ] = None ,
4272+ loc : Optional ['ILSourceLocation' ] = None
4273+ ) -> ExpressionIndex :
40344274 """
40354275 ``load`` Reads ``size`` bytes from the expression ``addr``
40364276
40374277 :param int size: number of bytes to read
40384278 :param ExpressionIndex addr: the expression to read memory from
4279+ :param FlagName flags: which flags are set by this operation
40394280 :param ILSourceLocation loc: location of returned expression
40404281 :return: The expression ``[addr].size``
40414282 :rtype: ExpressionIndex
40424283 """
4043- return self .expr (LowLevelILOperation .LLIL_LOAD , addr , size = size , source_location = loc )
4284+ return self .expr (LowLevelILOperation .LLIL_LOAD , addr , size = size , flags = flags , source_location = loc )
40444285
40454286 def store (
40464287 self , size : int , addr : ExpressionIndex , value : ExpressionIndex , flags : Optional ['architecture.FlagName' ] = None ,
@@ -4172,17 +4413,18 @@ def const_pointer(self, size: int, value: int, loc: Optional['ILSourceLocation']
41724413 """
41734414 return self .expr (LowLevelILOperation .LLIL_CONST_PTR , value , size = size , source_location = loc )
41744415
4175- def reloc_pointer (self , size : int , value : int , loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
4416+ def extern_pointer (self , size : int , value : int , offset : int , loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
41764417 """
4177- ``reloc_pointer `` returns an expression for the constant relocated pointer ``value`` with size ``size``
4418+ ``extern_pointer `` returns an expression for the constant external pointer ``value`` with size ``size`` at offset ``offset ``
41784419
41794420 :param int size: the size of the pointer in bytes
41804421 :param int value: address referenced by pointer
4422+ :param int offset: offset into external pointer
41814423 :param ILSourceLocation loc: location of returned expression
41824424 :return: A constant expression of given value and size
41834425 :rtype: ExpressionIndex
41844426 """
4185- return self .expr (LowLevelILOperation .LLIL_EXTERN_PTR , value , size = size , source_location = loc )
4427+ return self .expr (LowLevelILOperation .LLIL_EXTERN_PTR , value , offset , size = size , source_location = loc )
41864428
41874429 def float_const_raw (self , size : int , value : int , loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
41884430 """
@@ -4792,6 +5034,19 @@ def jump(self, dest: ExpressionIndex, loc: Optional['ILSourceLocation'] = None)
47925034 """
47935035 return self .expr (LowLevelILOperation .LLIL_JUMP , dest , source_location = loc )
47945036
5037+ def jump_to (self , dest : ExpressionIndex , targets : Dict [int , 'LowLevelILLabel' ], loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
5038+ """
5039+ ``jump_to`` returns an expression which jumps (branches) various targets in ``targets``
5040+ choosing the target in ``targets`` based on the value calculated by ``dest``
5041+
5042+ :param ExpressionIndex dest: the expression choosing which jump target to use
5043+ :param Mapping[int, MediumLevelILLabel] targets: the list of targets for jump locations
5044+ :param ILSourceLocation loc: location of returned expression
5045+ :return: The expression ``jump(dest)``
5046+ :rtype: ExpressionIndex
5047+ """
5048+ return self .expr (LowLevelILOperation .LLIL_JUMP_TO , dest , len (targets ) * 2 , self .add_label_map (targets ), size = 0 , source_location = loc )
5049+
47955050 def call (self , dest : ExpressionIndex , loc : Optional ['ILSourceLocation' ] = None ) -> ExpressionIndex :
47965051 """
47975052 ``call`` returns an expression which first pushes the address of the next instruction onto the stack then jumps
@@ -5637,6 +5892,37 @@ def generate_ssa_form(self) -> None:
56375892 """
56385893 core .BNGenerateLowLevelILSSAForm (self .handle )
56395894
5895+ def prepare_to_copy_function (self , src : 'LowLevelILFunction' ):
5896+ """
5897+ ``prepare_to_copy_function`` sets up state in this LLIL function in preparation
5898+ of copying instructions from ``src``
5899+
5900+ :param LowLevelILFunction src: function about to be copied from
5901+ """
5902+ core .BNPrepareToCopyLowLevelILFunction (self .handle , src .handle )
5903+
5904+ def prepare_to_copy_block (self , src : 'LowLevelILBasicBlock' ):
5905+ """
5906+ ``prepare_to_copy_block`` sets up state when copying a function in preparation
5907+ of copying the instructions from the block ``src``
5908+
5909+ :param LowLevelILBasicBlock src: block about to be copied from
5910+ """
5911+ core .BNPrepareToCopyLowLevelILBasicBlock (self .handle , src .handle )
5912+
5913+ def get_label_for_source_instruction (self , i : InstructionIndex ) -> Optional ['LowLevelILLabel' ]:
5914+ """
5915+ Get the LowLevelILLabel for a given source instruction. The returned label is to an internal object with
5916+ the same lifetime as the containing LowLevelILFunction.
5917+
5918+ :param i: The source instruction index
5919+ :return: The LowLevelILLabel for the source instruction
5920+ """
5921+ label = core .BNGetLabelForLowLevelILSourceInstruction (self .handle , i )
5922+ if not label :
5923+ return None
5924+ return LowLevelILLabel (handle = label )
5925+
56405926 def add_label_for_address (self , arch : 'architecture.Architecture' , addr : int ) -> None :
56415927 """
56425928 ``add_label_for_address`` adds a low-level IL label for the given architecture ``arch`` at the given virtual
0 commit comments