1+ import functools
12import json
23import math
34
@@ -67,7 +68,14 @@ def assert_llil_eq(old_insn: LowLevelILInstruction, new_insn: LowLevelILInstruct
6768 assert old_op [1 ] == new_op [1 ], err_msg
6869
6970
70- def assert_mlil_eq (old_insn : LowLevelILInstruction , new_insn : LowLevelILInstruction ):
71+ @functools .lru_cache (maxsize = 8 )
72+ def get_mlil_maps (mlil : MediumLevelILFunction , builders : bool ) -> Tuple [LLILSSAToMLILInstructionMapping , LLILSSAToMLILExpressionMapping ]:
73+ instr_map = mlil ._get_llil_ssa_to_mlil_instr_map (builders )
74+ expr_map = mlil ._get_llil_ssa_to_mlil_expr_map (builders )
75+ return instr_map , expr_map
76+
77+
78+ def assert_mlil_eq (old_insn : MediumLevelILInstruction , new_insn : MediumLevelILInstruction ):
7179 """
7280 Make sure that these two instructions are the same (probably correct). Asserts otherwise.
7381
@@ -78,10 +86,23 @@ def assert_mlil_eq(old_insn: LowLevelILInstruction, new_insn: LowLevelILInstruct
7886 """
7987 err_msg = (hex (old_insn .address ), old_insn , new_insn )
8088 assert old_insn .operation == new_insn .operation , err_msg
81- # assert old_insn.attributes == new_insn.attributes, err_msg
89+ assert old_insn .attributes == new_insn .attributes , err_msg
8290 assert old_insn .size == new_insn .size , err_msg
8391 assert old_insn .source_location == new_insn .source_location , err_msg
8492 assert len (old_insn .operands ) == len (new_insn .operands ), err_msg
93+ # Type only applies once we've generated SSA form (probably not consistent)
94+ # assert old_insn.expr_type == new_insn.expr_type, f"{err_msg} {old_insn.expr_type} {new_insn.expr_type}"
95+
96+ instr_map , expr_map = get_mlil_maps (new_insn .function , True )
97+
98+ # Compare that the instruction's LLIL SSA map is the same as the old function
99+ if old_insn .instr_index is not None and old_insn .function .get_expr_index_for_instruction (old_insn .instr_index ) == old_insn .expr_index :
100+ old_llil_ssa = old_insn .function .get_low_level_il_instruction_index (old_insn .instr_index )
101+ if old_llil_ssa is not None :
102+ assert [mlil for (llil , mlil ) in instr_map .items () if llil == old_llil_ssa ] == [new_insn .instr_index ], err_msg
103+ else :
104+ assert [mlil for (llil , mlil ) in instr_map .items () if llil == old_llil_ssa ] == [], err_msg
105+
85106 # Can't compare operands directly since IL expression indices might change when
86107 # copying an instruction to another function
87108 for i , (old_op , new_op ) in enumerate (zip (old_insn .detailed_operands , new_insn .detailed_operands )):
@@ -231,6 +252,11 @@ def translate_instr(
231252 report .append (FlowGraphReport ("new graph" , new_mlil .create_graph_immediate (settings )))
232253 show_report_collection ("copy expr test" , report )
233254
255+ # Check expr mappings are the same
256+ new_map = list (sorted (new_mlil ._get_llil_ssa_to_mlil_expr_map (True ), key = lambda o : (o .lower_index , o .higher_index )))
257+ old_map = list (sorted (old_mlil ._get_llil_ssa_to_mlil_expr_map (False ), key = lambda o : (o .lower_index , o .higher_index )))
258+ assert old_map == new_map
259+
234260 # Check all BBs have all the same instructions
235261 # Technically, this misses any instructions outside a BB, but those are not
236262 # picked up by analysis anyway, and therefore don't matter.
@@ -240,31 +266,52 @@ def translate_instr(
240266 for old_insn , new_insn in zip (old_bb , new_bb ):
241267 assert_mlil_eq (old_insn , new_insn )
242268
269+ # Make sure mappings update correctly following set
270+ new_map = list (sorted (new_mlil ._get_llil_ssa_to_mlil_expr_map (True ), key = lambda o : (o .lower_index , o .higher_index )))
271+ context .mlil = new_mlil
272+ newer_map = list (sorted (context .mlil ._get_llil_ssa_to_mlil_expr_map (False ), key = lambda o : (o .lower_index , o .higher_index )))
273+ assert new_map == newer_map
274+
243275
244- wf = Workflow ("core.function.metaAnalysis" ).clone ("TestCopyExpr " )
276+ wf = Workflow ("core.function.metaAnalysis" ).clone ("core.function.metaAnalysis " )
245277
246278# Define the custom activity configuration
247279wf .register_activity (Activity (
248280 configuration = json .dumps ({
249281 "name" : "extension.test_copy_expr.lil_action" ,
250282 "title" : "Lifted IL copy_expr Test" ,
251- "description" : "Makes sure copy_expr works on Lifted IL functions."
283+ "description" : "Makes sure copy_expr works on Lifted IL functions." ,
284+ "eligibility" : {
285+ "auto" : {
286+ "default" : False
287+ }
288+ }
252289 }),
253290 action = lil_action
254291))
255292wf .register_activity (Activity (
256293 configuration = json .dumps ({
257294 "name" : "extension.test_copy_expr.llil_action" ,
258295 "title" : "Low Level IL copy_expr Test" ,
259- "description" : "Makes sure copy_expr works on Low Level IL functions."
296+ "description" : "Makes sure copy_expr works on Low Level IL functions." ,
297+ "eligibility" : {
298+ "auto" : {
299+ "default" : False
300+ }
301+ }
260302 }),
261303 action = llil_action
262304))
263305wf .register_activity (Activity (
264306 configuration = json .dumps ({
265307 "name" : "extension.test_copy_expr.mlil_action" ,
266308 "title" : "Medium Level IL copy_expr Test" ,
267- "description" : "Makes sure copy_expr works on Medium Level IL functions."
309+ "description" : "Makes sure copy_expr works on Medium Level IL functions." ,
310+ "eligibility" : {
311+ "auto" : {
312+ "default" : False
313+ }
314+ }
268315 }),
269316 action = mlil_action
270317))
0 commit comments