Skip to content

Commit 0486354

Browse files
committed
Python: Implement MLIL.copy_expr_to
1 parent 7331610 commit 0486354

File tree

1 file changed

+344
-4
lines changed

1 file changed

+344
-4
lines changed

python/mediumlevelil.py

Lines changed: 344 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)