angr 9.2.158__cp310-abi3-win_amd64.whl → 9.2.159__cp310-abi3-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/ailment/__init__.py +81 -0
- angr/ailment/block.py +81 -0
- angr/ailment/block_walker.py +845 -0
- angr/ailment/constant.py +3 -0
- angr/ailment/converter_common.py +11 -0
- angr/ailment/converter_pcode.py +623 -0
- angr/ailment/converter_vex.py +798 -0
- angr/ailment/expression.py +1639 -0
- angr/ailment/manager.py +33 -0
- angr/ailment/statement.py +978 -0
- angr/ailment/tagged_object.py +61 -0
- angr/ailment/utils.py +114 -0
- angr/analyses/calling_convention/calling_convention.py +6 -2
- angr/analyses/decompiler/ail_simplifier.py +5 -5
- angr/analyses/decompiler/block_io_finder.py +4 -4
- angr/analyses/decompiler/block_similarity.py +2 -2
- angr/analyses/decompiler/block_simplifier.py +4 -4
- angr/analyses/decompiler/callsite_maker.py +2 -2
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +1 -1
- angr/analyses/decompiler/clinic.py +1 -1
- angr/analyses/decompiler/condition_processor.py +1 -1
- angr/analyses/decompiler/counters/boolean_counter.py +4 -4
- angr/analyses/decompiler/counters/call_counter.py +4 -4
- angr/analyses/decompiler/counters/expression_counters.py +5 -5
- angr/analyses/decompiler/counters/seq_cf_structure_counter.py +1 -1
- angr/analyses/decompiler/decompiler.py +5 -3
- angr/analyses/decompiler/dephication/dephication_base.py +12 -1
- angr/analyses/decompiler/dephication/graph_dephication.py +12 -5
- angr/analyses/decompiler/dephication/graph_rewriting.py +6 -10
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +109 -72
- angr/analyses/decompiler/dephication/rewriting_engine.py +32 -9
- angr/analyses/decompiler/dephication/seqnode_dephication.py +32 -10
- angr/analyses/decompiler/empty_node_remover.py +2 -2
- angr/analyses/decompiler/expression_narrower.py +6 -6
- angr/analyses/decompiler/goto_manager.py +2 -2
- angr/analyses/decompiler/jump_target_collector.py +1 -1
- angr/analyses/decompiler/label_collector.py +1 -1
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +25 -25
- angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +1 -1
- angr/analyses/decompiler/optimization_passes/code_motion.py +2 -2
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +3 -3
- angr/analyses/decompiler/optimization_passes/const_derefs.py +3 -3
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +4 -4
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +2 -2
- angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +3 -3
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +4 -4
- angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +1 -1
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +4 -4
- angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +3 -3
- angr/analyses/decompiler/optimization_passes/engine_base.py +1 -1
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +3 -3
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +2 -2
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +3 -3
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +3 -3
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +4 -4
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +25 -1
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +2 -2
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +4 -4
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +2 -2
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +3 -3
- angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +3 -3
- angr/analyses/decompiler/optimization_passes/tag_slicer.py +1 -1
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/base.py +3 -3
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/bswap.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +3 -3
- angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/utils.py +1 -1
- angr/analyses/decompiler/redundant_label_remover.py +1 -1
- angr/analyses/decompiler/region_identifier.py +4 -4
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -1
- angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +1 -1
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +37 -8
- angr/analyses/decompiler/region_simplifiers/goto.py +1 -1
- angr/analyses/decompiler/region_simplifiers/if_.py +1 -1
- angr/analyses/decompiler/region_simplifiers/loop.py +1 -1
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -1
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +14 -2
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +3 -3
- angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +1 -1
- angr/analyses/decompiler/return_maker.py +1 -1
- angr/analyses/decompiler/seq_to_blocks.py +1 -1
- angr/analyses/decompiler/sequence_walker.py +2 -2
- angr/analyses/decompiler/ssailification/rewriting.py +4 -4
- angr/analyses/decompiler/ssailification/rewriting_engine.py +4 -4
- angr/analyses/decompiler/ssailification/rewriting_state.py +3 -3
- angr/analyses/decompiler/ssailification/ssailification.py +2 -2
- angr/analyses/decompiler/ssailification/traversal.py +1 -1
- angr/analyses/decompiler/ssailification/traversal_engine.py +11 -2
- angr/analyses/decompiler/structured_codegen/c.py +3 -3
- angr/analyses/decompiler/structuring/dream.py +1 -1
- angr/analyses/decompiler/structuring/phoenix.py +3 -3
- angr/analyses/decompiler/structuring/structurer_base.py +1 -1
- angr/analyses/decompiler/structuring/structurer_nodes.py +1 -2
- angr/analyses/decompiler/utils.py +1 -1
- angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +1 -1
- angr/analyses/deobfuscator/string_obf_opt_passes.py +3 -3
- angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +2 -2
- angr/analyses/propagator/propagator.py +1 -1
- angr/analyses/proximity_graph.py +2 -2
- angr/analyses/reaching_definitions/engine_ail.py +1 -1
- angr/analyses/reaching_definitions/reaching_definitions.py +1 -1
- angr/analyses/reaching_definitions/subject.py +1 -1
- angr/analyses/s_liveness.py +2 -2
- angr/analyses/s_propagator.py +3 -3
- angr/analyses/s_reaching_definitions/s_rda_model.py +1 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +3 -3
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -3
- angr/analyses/variable_recovery/engine_ail.py +2 -2
- angr/analyses/variable_recovery/engine_base.py +1 -1
- angr/analyses/variable_recovery/variable_recovery_base.py +1 -1
- angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
- angr/engines/light/data.py +1 -1
- angr/engines/light/engine.py +1 -1
- angr/knowledge_plugins/key_definitions/atoms.py +1 -1
- angr/knowledge_plugins/propagations/prop_value.py +1 -1
- angr/knowledge_plugins/propagations/propagation_model.py +1 -1
- angr/knowledge_plugins/propagations/states.py +1 -1
- angr/knowledge_plugins/variables/variable_manager.py +1 -1
- angr/lib/angr_native.dll +0 -0
- angr/rustylib.pyd +0 -0
- angr/utils/ail.py +4 -4
- angr/utils/endness.py +1 -1
- angr/utils/ssa/__init__.py +14 -4
- angr/utils/ssa/tmp_uses_collector.py +4 -4
- angr/utils/ssa/vvar_uses_collector.py +4 -4
- {angr-9.2.158.dist-info → angr-9.2.159.dist-info}/METADATA +6 -6
- {angr-9.2.158.dist-info → angr-9.2.159.dist-info}/RECORD +192 -180
- {angr-9.2.158.dist-info → angr-9.2.159.dist-info}/WHEEL +0 -0
- {angr-9.2.158.dist-info → angr-9.2.159.dist-info}/entry_points.txt +0 -0
- {angr-9.2.158.dist-info → angr-9.2.159.dist-info}/licenses/LICENSE +0 -0
- {angr-9.2.158.dist-info → angr-9.2.159.dist-info}/top_level.txt +0 -0
|
@@ -2,9 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
import logging
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
|
|
5
|
-
from ailment
|
|
6
|
-
from ailment.
|
|
7
|
-
from ailment.
|
|
5
|
+
from angr.ailment import AILBlockWalker
|
|
6
|
+
from angr.ailment.block import Block
|
|
7
|
+
from angr.ailment.expression import Phi, VirtualVariable, VirtualVariableCategory
|
|
8
|
+
from angr.ailment.statement import Assignment, Jump, ConditionalJump, Label
|
|
8
9
|
|
|
9
10
|
from angr.analyses import Analysis
|
|
10
11
|
from angr.analyses.s_reaching_definitions import SRDAModel
|
|
@@ -88,6 +89,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
88
89
|
unresolved_neighbor_map = defaultdict(set)
|
|
89
90
|
|
|
90
91
|
# check for interferences
|
|
92
|
+
candidate_vvar_set_to_phiid: defaultdict[frozenset[int], set[int]] = defaultdict(set)
|
|
91
93
|
for phi_id, src_and_varids in phi_to_srcvarid.items():
|
|
92
94
|
candidate_vvar_set: set[int] = set()
|
|
93
95
|
src_and_varids = list(src_and_varids)
|
|
@@ -135,9 +137,13 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
135
137
|
if not unresolved_neighbor_map[neighbor]:
|
|
136
138
|
del unresolved_neighbor_map[neighbor]
|
|
137
139
|
|
|
140
|
+
if candidate_vvar_set:
|
|
141
|
+
candidate_vvar_set_to_phiid[frozenset(candidate_vvar_set)].add(phi_id)
|
|
142
|
+
|
|
143
|
+
for vvar_set, phi_ids in candidate_vvar_set_to_phiid.items():
|
|
138
144
|
# insert copies of variables as needed
|
|
139
|
-
for varid in
|
|
140
|
-
insertion_type, new_vvar_ids = self._insert_vvar_copy(varid,
|
|
145
|
+
for varid in vvar_set:
|
|
146
|
+
insertion_type, new_vvar_ids = self._insert_vvar_copy(varid, phi_ids)
|
|
141
147
|
|
|
142
148
|
if insertion_type == 0:
|
|
143
149
|
for src, old_vvar_id, new_vvar_id in new_vvar_ids:
|
|
@@ -159,19 +165,20 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
159
165
|
interference.add_edge(new_vvar_id, vvar_id)
|
|
160
166
|
|
|
161
167
|
else: # insertion_type == 1, i.e. the set has only one element
|
|
162
|
-
phi_block_loc, old_phi_varid, new_phi_varid
|
|
163
|
-
|
|
168
|
+
for phi_block_loc, old_phi_varid, new_phi_varid in new_vvar_ids:
|
|
169
|
+
self.copied_vvar_ids.add(new_phi_varid)
|
|
164
170
|
|
|
165
|
-
|
|
171
|
+
phi_congruence_class[new_phi_varid] = {new_phi_varid}
|
|
166
172
|
|
|
167
|
-
|
|
168
|
-
|
|
173
|
+
live_ins[phi_block_loc].discard(old_phi_varid)
|
|
174
|
+
live_ins[phi_block_loc].add(new_phi_varid)
|
|
169
175
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
176
|
+
# update interference graph
|
|
177
|
+
for vvar_id in live_ins[phi_block_loc]:
|
|
178
|
+
interference.add_edge(new_phi_varid, vvar_id)
|
|
173
179
|
|
|
174
|
-
|
|
180
|
+
# update phi_congruence_class
|
|
181
|
+
for phi_id in phi_to_srcvarid:
|
|
175
182
|
(phidef_block_addr, phidef_block_idx), phidef_stmt_idx = self._vvar_defloc[phi_id]
|
|
176
183
|
phi_block = self._blocks[(phidef_block_addr, phidef_block_idx)]
|
|
177
184
|
# phi_stmt is the newly created phi statement with variables replaced
|
|
@@ -199,82 +206,112 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
199
206
|
|
|
200
207
|
return mapping
|
|
201
208
|
|
|
202
|
-
def _insert_vvar_copy(
|
|
203
|
-
|
|
204
|
-
|
|
209
|
+
def _insert_vvar_copy(
|
|
210
|
+
self, varid: int, phi_varids: set[int]
|
|
211
|
+
) -> tuple[int, set[tuple[tuple[int, int | None], int, int]]]:
|
|
212
|
+
new_vvar_info: set[tuple[tuple[int, int | None], int, int]] = set()
|
|
213
|
+
new_vvar_id = self.vvar_id_start
|
|
214
|
+
self.vvar_id_start += 1
|
|
215
|
+
|
|
216
|
+
if varid not in phi_varids:
|
|
205
217
|
# it's one of the source vvars
|
|
206
218
|
|
|
207
|
-
|
|
208
|
-
phi_stmt = phi_block.statements[phidef_stmt_idx]
|
|
219
|
+
stmt_appended_locs: dict[tuple[int, int | None], VirtualVariable] = {}
|
|
209
220
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
221
|
+
# update all phi statements
|
|
222
|
+
for phi_varid in phi_varids:
|
|
223
|
+
(phidef_block_addr, phidef_block_idx), phidef_stmt_idx = self._vvar_defloc[phi_varid]
|
|
224
|
+
phi_block = self._blocks[(phidef_block_addr, phidef_block_idx)]
|
|
225
|
+
phi_stmt = phi_block.statements[phidef_stmt_idx]
|
|
226
|
+
|
|
227
|
+
for src, vvar in list(phi_stmt.src.src_and_vvars):
|
|
228
|
+
if vvar is None or vvar.varid != varid:
|
|
229
|
+
continue
|
|
230
|
+
|
|
231
|
+
if src not in stmt_appended_locs:
|
|
232
|
+
# we have not yet appended a statement to this block
|
|
233
|
+
the_block = self._blocks[src]
|
|
234
|
+
ins_addr = the_block.addr + the_block.original_size - 1
|
|
235
|
+
if vvar.category == VirtualVariableCategory.PARAMETER:
|
|
236
|
+
# it's a parameter, so we copy the variable into a dummy register vvar
|
|
237
|
+
# a parameter vvar should never be assigned to
|
|
238
|
+
new_category = VirtualVariableCategory.REGISTER
|
|
239
|
+
new_oident = DEPHI_VVAR_REG_OFFSET
|
|
240
|
+
else:
|
|
241
|
+
new_category = vvar.category
|
|
242
|
+
new_oident = vvar.oident
|
|
243
|
+
new_vvar = VirtualVariable(
|
|
244
|
+
None, new_vvar_id, vvar.bits, new_category, oident=new_oident, ins_addr=ins_addr
|
|
245
|
+
)
|
|
246
|
+
assignment = Assignment(None, new_vvar, vvar, ins_addr=ins_addr)
|
|
247
|
+
|
|
248
|
+
self._append_stmt(the_block, assignment, old_vvarid=varid, new_vvarid=new_vvar_id)
|
|
249
|
+
|
|
250
|
+
stmt_appended_locs[src] = new_vvar
|
|
236
251
|
|
|
237
|
-
|
|
252
|
+
else:
|
|
253
|
+
new_vvar = stmt_appended_locs[src]
|
|
238
254
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
phi_block.statements[phidef_stmt_idx] = phi_stmt
|
|
255
|
+
replaced_vvars: set[int] = set()
|
|
256
|
+
for _, phi_used_vvar in list(phi_stmt.src.src_and_vvars):
|
|
257
|
+
if phi_used_vvar is not None and phi_used_vvar.varid == varid and varid not in replaced_vvars:
|
|
258
|
+
replaced, phi_stmt = phi_stmt.replace(phi_used_vvar, new_vvar)
|
|
259
|
+
assert replaced
|
|
260
|
+
replaced_vvars.add(varid)
|
|
261
|
+
phi_block.statements[phidef_stmt_idx] = phi_stmt
|
|
247
262
|
|
|
248
|
-
|
|
263
|
+
new_vvar_info.add((src, varid, new_vvar_id))
|
|
249
264
|
|
|
250
|
-
return 0,
|
|
265
|
+
return 0, new_vvar_info
|
|
251
266
|
|
|
252
267
|
# it's the phi assignment destination vvar
|
|
253
268
|
|
|
254
|
-
|
|
255
|
-
|
|
269
|
+
for phi_varid in phi_varids:
|
|
270
|
+
phi_vvar = self._rd.varid_to_vvar[phi_varid]
|
|
271
|
+
(phidef_block_addr, phidef_block_idx), phidef_stmt_idx = self._vvar_defloc[phi_varid]
|
|
272
|
+
the_block = self._blocks[(phidef_block_addr, phidef_block_idx)]
|
|
273
|
+
ins_addr = the_block.addr
|
|
274
|
+
new_vvar = VirtualVariable(
|
|
275
|
+
None, new_vvar_id, phi_vvar.bits, phi_vvar.category, oident=phi_vvar.oident, ins_addr=ins_addr
|
|
276
|
+
)
|
|
277
|
+
assignment = Assignment(None, phi_vvar, new_vvar, ins_addr=ins_addr)
|
|
256
278
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
ins_addr = the_block.addr
|
|
261
|
-
new_vvar = VirtualVariable(
|
|
262
|
-
None, new_vvar_id, phi_vvar.bits, phi_vvar.category, oident=phi_vvar.oident, ins_addr=ins_addr
|
|
263
|
-
)
|
|
264
|
-
assignment = Assignment(None, phi_vvar, new_vvar, ins_addr=ins_addr)
|
|
279
|
+
phi_stmt = the_block.statements[phidef_stmt_idx]
|
|
280
|
+
replaced, phi_stmt = phi_stmt.replace(phi_vvar, new_vvar)
|
|
281
|
+
the_block.statements[phidef_stmt_idx] = phi_stmt
|
|
265
282
|
|
|
266
|
-
|
|
267
|
-
replaced, phi_stmt = phi_stmt.replace(phi_vvar, new_vvar)
|
|
268
|
-
the_block.statements[phidef_stmt_idx] = phi_stmt
|
|
283
|
+
self._record_stmt_for_prepending(the_block, assignment)
|
|
269
284
|
|
|
270
|
-
|
|
285
|
+
new_vvar_info.add(((phidef_block_addr, phidef_block_idx), phi_varid, new_vvar_id))
|
|
271
286
|
|
|
272
|
-
return 1,
|
|
287
|
+
return 1, new_vvar_info
|
|
273
288
|
|
|
274
289
|
@staticmethod
|
|
275
|
-
def _append_stmt(block, stmt):
|
|
290
|
+
def _append_stmt(block, stmt, old_vvarid: int | None = None, new_vvarid: int | None = None):
|
|
291
|
+
|
|
292
|
+
def _handle_VirtualVariable( # pylint:disable=unused-argument
|
|
293
|
+
expr_idx: int, expr: VirtualVariable, stmt_idx: int, stmt, block: Block | None
|
|
294
|
+
):
|
|
295
|
+
assert old_vvarid is not None and new_vvarid is not None
|
|
296
|
+
return (
|
|
297
|
+
None
|
|
298
|
+
if expr.varid != old_vvarid
|
|
299
|
+
else VirtualVariable(
|
|
300
|
+
None, new_vvarid, expr.bits, expr.category, oident=expr.oident, ins_addr=expr.ins_addr
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
|
|
276
304
|
if block.statements and isinstance(block.statements[-1], (Jump, ConditionalJump)):
|
|
277
305
|
block.statements.insert(len(block.statements) - 1, stmt)
|
|
306
|
+
|
|
307
|
+
# replace the vvar usage in the last statement if it's used there
|
|
308
|
+
if old_vvarid is not None and new_vvarid is not None:
|
|
309
|
+
replacer = AILBlockWalker()
|
|
310
|
+
replacer.expr_handlers[VirtualVariable] = _handle_VirtualVariable
|
|
311
|
+
new_stmt = replacer.walk_statement(block.statements[-1])
|
|
312
|
+
if new_stmt is not None and new_stmt is not block.statements[-1]:
|
|
313
|
+
block.statements[-1] = new_stmt
|
|
314
|
+
|
|
278
315
|
else:
|
|
279
316
|
block.statements.append(stmt)
|
|
280
317
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# pylint:disable=unused-argument,no-self-use,too-many-boolean-expressions
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
3
4
|
import logging
|
|
4
5
|
|
|
5
|
-
from ailment.block import Block
|
|
6
|
-
from ailment.statement import (
|
|
6
|
+
from angr.ailment.block import Block
|
|
7
|
+
from angr.ailment.statement import (
|
|
7
8
|
Statement,
|
|
8
9
|
Assignment,
|
|
9
10
|
Store,
|
|
@@ -14,7 +15,7 @@ from ailment.statement import (
|
|
|
14
15
|
DirtyStatement,
|
|
15
16
|
WeakAssignment,
|
|
16
17
|
)
|
|
17
|
-
from ailment.expression import (
|
|
18
|
+
from angr.ailment.expression import (
|
|
18
19
|
Atom,
|
|
19
20
|
Expression,
|
|
20
21
|
VirtualVariable,
|
|
@@ -28,9 +29,11 @@ from ailment.expression import (
|
|
|
28
29
|
DirtyExpression,
|
|
29
30
|
Reinterpret,
|
|
30
31
|
)
|
|
31
|
-
|
|
32
32
|
from angr.engines.light import SimEngineNostmtAIL
|
|
33
33
|
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from angr import KnowledgeBase
|
|
36
|
+
|
|
34
37
|
|
|
35
38
|
_l = logging.getLogger(__name__)
|
|
36
39
|
|
|
@@ -47,11 +50,15 @@ class SimEngineDephiRewriting(SimEngineNostmtAIL[None, Expression | None, Statem
|
|
|
47
50
|
self,
|
|
48
51
|
project,
|
|
49
52
|
vvar_to_vvar: dict[int, int],
|
|
53
|
+
func_addr: int | None = None,
|
|
54
|
+
variable_kb: KnowledgeBase | None = None,
|
|
50
55
|
):
|
|
51
56
|
super().__init__(project)
|
|
52
57
|
|
|
53
58
|
self.vvar_to_vvar = vvar_to_vvar
|
|
54
59
|
self.out_block = None
|
|
60
|
+
self.func_addr = func_addr
|
|
61
|
+
self.variable_kb = variable_kb
|
|
55
62
|
|
|
56
63
|
self._stmt_handlers["IncompleteSwitchCaseHeadStatement"] = self._handle_stmt_IncompleteSwitchCaseHeadStatement
|
|
57
64
|
|
|
@@ -99,13 +106,29 @@ class SimEngineDephiRewriting(SimEngineNostmtAIL[None, Expression | None, Statem
|
|
|
99
106
|
**stmt.dst.tags,
|
|
100
107
|
)
|
|
101
108
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
# ensure we do not generate vvar_A = vvar_A or var_A = var_A (even if lhs and rhs are different vvars, they
|
|
110
|
+
# can be mapped to the same variable)
|
|
111
|
+
dst = stmt.dst if new_dst is None else new_dst
|
|
112
|
+
src = stmt.src if new_src is None else new_src
|
|
113
|
+
if isinstance(dst, VirtualVariable) and isinstance(src, VirtualVariable):
|
|
114
|
+
if dst.varid == src.varid:
|
|
107
115
|
# skip it
|
|
108
116
|
return ()
|
|
117
|
+
if (
|
|
118
|
+
self.func_addr is not None
|
|
119
|
+
and self.variable_kb is not None
|
|
120
|
+
and self.func_addr in self.variable_kb.variables
|
|
121
|
+
):
|
|
122
|
+
dst_var = getattr(dst, "variable", None)
|
|
123
|
+
src_var = getattr(src, "variable", None)
|
|
124
|
+
var_manager = self.variable_kb.variables[self.func_addr]
|
|
125
|
+
if (
|
|
126
|
+
dst_var is not None
|
|
127
|
+
and src_var is not None
|
|
128
|
+
and var_manager.unified_variable(dst_var) is var_manager.unified_variable(src_var)
|
|
129
|
+
):
|
|
130
|
+
# skip it
|
|
131
|
+
return ()
|
|
109
132
|
|
|
110
133
|
return Assignment(stmt.idx, dst, src, **stmt.tags)
|
|
111
134
|
return None
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
import logging
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any, TYPE_CHECKING
|
|
5
5
|
|
|
6
|
-
from ailment.block import Block
|
|
7
|
-
from ailment.statement import Assignment
|
|
8
|
-
from ailment.expression import VirtualVariable, Phi, BinaryOp, UnaryOp
|
|
6
|
+
from angr.ailment.block import Block
|
|
7
|
+
from angr.ailment.statement import Assignment
|
|
8
|
+
from angr.ailment.expression import VirtualVariable, Phi, BinaryOp, UnaryOp
|
|
9
9
|
|
|
10
10
|
import angr
|
|
11
11
|
from angr.utils.ail import is_phi_assignment
|
|
@@ -16,6 +16,9 @@ from angr.analyses.decompiler.sequence_walker import SequenceWalker
|
|
|
16
16
|
from .dephication_base import DephicationBase
|
|
17
17
|
from .rewriting_engine import SimEngineDephiRewriting
|
|
18
18
|
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from angr import KnowledgeBase
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
l = logging.getLogger(__name__)
|
|
21
24
|
|
|
@@ -54,7 +57,14 @@ class SeqNodeRewriter(SequenceWalker):
|
|
|
54
57
|
variables.
|
|
55
58
|
"""
|
|
56
59
|
|
|
57
|
-
def __init__(
|
|
60
|
+
def __init__(
|
|
61
|
+
self,
|
|
62
|
+
seq_node: SequenceNode,
|
|
63
|
+
vvar_to_vvar: dict[int, int],
|
|
64
|
+
project: angr.Project,
|
|
65
|
+
variable_kb: KnowledgeBase | None = None,
|
|
66
|
+
func_addr: int | None = None,
|
|
67
|
+
):
|
|
58
68
|
super().__init__(
|
|
59
69
|
handlers={
|
|
60
70
|
Block: self._handle_Block,
|
|
@@ -67,7 +77,7 @@ class SeqNodeRewriter(SequenceWalker):
|
|
|
67
77
|
)
|
|
68
78
|
|
|
69
79
|
self.vvar_to_vvar = vvar_to_vvar
|
|
70
|
-
self.engine = SimEngineDephiRewriting(project, self.vvar_to_vvar)
|
|
80
|
+
self.engine = SimEngineDephiRewriting(project, self.vvar_to_vvar, func_addr=func_addr, variable_kb=variable_kb)
|
|
71
81
|
|
|
72
82
|
self.output = self.walk(seq_node)
|
|
73
83
|
if self.output is None:
|
|
@@ -109,13 +119,19 @@ class SeqNodeRewriter(SequenceWalker):
|
|
|
109
119
|
|
|
110
120
|
class SeqNodeDephication(DephicationBase):
|
|
111
121
|
"""
|
|
112
|
-
SeqNodeDephication removes phi expressions from
|
|
122
|
+
SeqNodeDephication removes phi expressions from a SequenceNode and its children. It also removes redundant variable
|
|
123
|
+
assignments, e.g., `vvar_2 = vvar_1` where both vvar_1 and vvar_2 are mapped to the same variable.
|
|
113
124
|
"""
|
|
114
125
|
|
|
115
126
|
def __init__(
|
|
116
|
-
self,
|
|
127
|
+
self,
|
|
128
|
+
func: Function | str,
|
|
129
|
+
seq_node,
|
|
130
|
+
vvar_to_vvar_mapping: dict[int, int] | None = None,
|
|
131
|
+
rewrite: bool = False,
|
|
132
|
+
variable_kb: KnowledgeBase | None = None,
|
|
117
133
|
):
|
|
118
|
-
super().__init__(func, vvar_to_vvar_mapping=vvar_to_vvar_mapping, rewrite=rewrite)
|
|
134
|
+
super().__init__(func, vvar_to_vvar_mapping=vvar_to_vvar_mapping, rewrite=rewrite, variable_kb=variable_kb)
|
|
119
135
|
|
|
120
136
|
self._seq_node = seq_node
|
|
121
137
|
|
|
@@ -127,7 +143,13 @@ class SeqNodeDephication(DephicationBase):
|
|
|
127
143
|
return collector.phi_to_src
|
|
128
144
|
|
|
129
145
|
def _rewrite_container(self) -> Any:
|
|
130
|
-
rewriter = SeqNodeRewriter(
|
|
146
|
+
rewriter = SeqNodeRewriter(
|
|
147
|
+
self._seq_node,
|
|
148
|
+
self.vvar_to_vvar_mapping,
|
|
149
|
+
self.project,
|
|
150
|
+
func_addr=self._function.addr,
|
|
151
|
+
variable_kb=self.variable_kb,
|
|
152
|
+
)
|
|
131
153
|
return rewriter.output
|
|
132
154
|
|
|
133
155
|
|
|
@@ -3,8 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from collections import OrderedDict
|
|
4
4
|
|
|
5
5
|
import claripy
|
|
6
|
-
import ailment
|
|
7
|
-
from ailment.expression import negate
|
|
6
|
+
import angr.ailment as ailment
|
|
7
|
+
from angr.ailment.expression import negate
|
|
8
8
|
|
|
9
9
|
from .sequence_walker import SequenceWalker
|
|
10
10
|
from .structuring.structurer_nodes import (
|
|
@@ -3,15 +3,15 @@ from typing import Any, TYPE_CHECKING
|
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import logging
|
|
5
5
|
|
|
6
|
-
from ailment import AILBlockWalkerBase, AILBlockWalker
|
|
7
|
-
from ailment.statement import Assignment, Call
|
|
8
|
-
from ailment.expression import VirtualVariable, Convert, BinaryOp, Phi
|
|
6
|
+
from angr.ailment import AILBlockWalkerBase, AILBlockWalker
|
|
7
|
+
from angr.ailment.statement import Assignment, Call
|
|
8
|
+
from angr.ailment.expression import VirtualVariable, Convert, BinaryOp, Phi
|
|
9
9
|
|
|
10
10
|
from angr.knowledge_plugins.key_definitions import atoms
|
|
11
11
|
from angr.code_location import CodeLocation
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from ailment.expression import (
|
|
14
|
+
from angr.ailment.expression import (
|
|
15
15
|
Expression,
|
|
16
16
|
Load,
|
|
17
17
|
UnaryOp,
|
|
@@ -19,8 +19,8 @@ if TYPE_CHECKING:
|
|
|
19
19
|
DirtyExpression,
|
|
20
20
|
VEXCCallExpression,
|
|
21
21
|
)
|
|
22
|
-
from ailment.statement import Statement
|
|
23
|
-
from ailment.block import Block
|
|
22
|
+
from angr.ailment.statement import Statement
|
|
23
|
+
from angr.ailment.block import Block
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
_l = logging.getLogger(__name__)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
|
-
import ailment
|
|
5
|
+
import angr.ailment as ailment
|
|
6
6
|
|
|
7
7
|
from angr.analyses.decompiler.stack_item import StackItem, StackItemType
|
|
8
8
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
@@ -88,32 +88,32 @@ class BasePointerSaveSimplifier(OptimizationPass):
|
|
|
88
88
|
:rtype: tuple|None
|
|
89
89
|
"""
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
isinstance(stmt, ailment.Stmt.Assignment)
|
|
98
|
-
and isinstance(stmt.dst, ailment.Expr.VirtualVariable)
|
|
99
|
-
and stmt.dst.was_stack
|
|
100
|
-
and stmt.dst.stack_offset < 0
|
|
101
|
-
):
|
|
102
|
-
if (
|
|
103
|
-
isinstance(stmt.src, ailment.Expr.VirtualVariable)
|
|
104
|
-
and stmt.src.was_reg
|
|
105
|
-
and stmt.src.reg_offset == self.project.arch.bp_offset
|
|
106
|
-
):
|
|
107
|
-
return first_block, idx, stmt.dst
|
|
108
|
-
if isinstance(stmt.src, ailment.Expr.StackBaseOffset) and stmt.src.offset == 0:
|
|
109
|
-
return first_block, idx, stmt.dst
|
|
91
|
+
# scan the first N blocks of the function until we find the first baseptr save statement
|
|
92
|
+
max_level = 5
|
|
93
|
+
|
|
94
|
+
for block in self.bfs_nodes(depth=max_level):
|
|
95
|
+
for idx, stmt in enumerate(block.statements):
|
|
110
96
|
if (
|
|
111
|
-
isinstance(stmt
|
|
112
|
-
and isinstance(stmt.
|
|
113
|
-
and stmt.
|
|
114
|
-
and stmt.
|
|
97
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
98
|
+
and isinstance(stmt.dst, ailment.Expr.VirtualVariable)
|
|
99
|
+
and stmt.dst.was_stack
|
|
100
|
+
and stmt.dst.stack_offset < 0
|
|
115
101
|
):
|
|
116
|
-
|
|
102
|
+
if (
|
|
103
|
+
isinstance(stmt.src, ailment.Expr.VirtualVariable)
|
|
104
|
+
and stmt.src.was_reg
|
|
105
|
+
and stmt.src.reg_offset == self.project.arch.bp_offset
|
|
106
|
+
):
|
|
107
|
+
return block, idx, stmt.dst
|
|
108
|
+
if isinstance(stmt.src, ailment.Expr.StackBaseOffset) and stmt.src.offset == 0:
|
|
109
|
+
return block, idx, stmt.dst
|
|
110
|
+
if (
|
|
111
|
+
isinstance(stmt.src, ailment.Expr.UnaryOp)
|
|
112
|
+
and isinstance(stmt.src.operand, ailment.Expr.VirtualVariable)
|
|
113
|
+
and stmt.src.operand.was_stack
|
|
114
|
+
and stmt.src.operand.stack_offset == 0
|
|
115
|
+
):
|
|
116
|
+
return block, idx, stmt.dst
|
|
117
117
|
|
|
118
118
|
# Not found
|
|
119
119
|
return None
|
|
@@ -2,8 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
import itertools
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
|
-
from ailment import Block
|
|
6
|
-
from ailment.statement import Jump, ConditionalJump, Statement, DirtyStatement
|
|
5
|
+
from angr.ailment import Block
|
|
6
|
+
from angr.ailment.statement import Jump, ConditionalJump, Statement, DirtyStatement
|
|
7
7
|
import networkx as nx
|
|
8
8
|
|
|
9
9
|
from angr.analyses.decompiler.optimization_passes.optimization_pass import OptimizationPass, OptimizationPassStage
|
|
@@ -4,9 +4,9 @@ from collections import defaultdict
|
|
|
4
4
|
|
|
5
5
|
import networkx
|
|
6
6
|
|
|
7
|
-
from ailment import AILBlockWalker, Block
|
|
8
|
-
from ailment.statement import ConditionalJump, Statement, Assignment
|
|
9
|
-
from ailment.expression import Const, BinaryOp, VirtualVariable
|
|
7
|
+
from angr.ailment import AILBlockWalker, Block
|
|
8
|
+
from angr.ailment.statement import ConditionalJump, Statement, Assignment
|
|
9
|
+
from angr.ailment.expression import Const, BinaryOp, VirtualVariable
|
|
10
10
|
|
|
11
11
|
from angr.analyses.decompiler.utils import first_nonlabel_nonphi_statement
|
|
12
12
|
from angr.utils.graph import dominates
|
|
@@ -3,9 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
import logging
|
|
5
5
|
|
|
6
|
-
from ailment import Block, AILBlockWalker
|
|
7
|
-
from ailment.expression import Load, Const, BinaryOp, UnaryOp
|
|
8
|
-
from ailment.statement import Statement, Assignment, Call, ConditionalJump
|
|
6
|
+
from angr.ailment import Block, AILBlockWalker
|
|
7
|
+
from angr.ailment.expression import Load, Const, BinaryOp, UnaryOp
|
|
8
|
+
from angr.ailment.statement import Statement, Assignment, Call, ConditionalJump
|
|
9
9
|
|
|
10
10
|
from angr.analyses.decompiler.ailgraph_walker import AILGraphWalker
|
|
11
11
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
@@ -5,10 +5,10 @@ import itertools
|
|
|
5
5
|
|
|
6
6
|
import networkx
|
|
7
7
|
import claripy
|
|
8
|
-
from ailment import Const
|
|
9
|
-
from ailment.block_walker import AILBlockWalkerBase
|
|
10
|
-
from ailment.statement import Call, Statement, ConditionalJump, Assignment, Store, Return
|
|
11
|
-
from ailment.expression import Convert, Register, Expression, Load
|
|
8
|
+
from angr.ailment import Const
|
|
9
|
+
from angr.ailment.block_walker import AILBlockWalkerBase
|
|
10
|
+
from angr.ailment.statement import Call, Statement, ConditionalJump, Assignment, Store, Return
|
|
11
|
+
from angr.ailment.expression import Convert, Register, Expression, Load
|
|
12
12
|
|
|
13
13
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
14
14
|
from angr.analyses.decompiler.structuring import SAILRStructurer, DreamStructurer
|
|
@@ -6,8 +6,8 @@ import networkx
|
|
|
6
6
|
|
|
7
7
|
import claripy
|
|
8
8
|
|
|
9
|
-
from ailment.statement import Jump
|
|
10
|
-
from ailment.expression import Const
|
|
9
|
+
from angr.ailment.statement import Jump
|
|
10
|
+
from angr.ailment.expression import Const
|
|
11
11
|
from angr.utils.graph import to_acyclic_graph
|
|
12
12
|
from angr.analyses.decompiler.condition_processor import ConditionProcessor
|
|
13
13
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
-
from ailment.constant import UNDETERMINED_SIZE
|
|
5
|
-
from ailment.expression import BinaryOp, Load, Const
|
|
6
|
-
from ailment.statement import Assignment, WeakAssignment
|
|
4
|
+
from angr.ailment.constant import UNDETERMINED_SIZE
|
|
5
|
+
from angr.ailment.expression import BinaryOp, Load, Const
|
|
6
|
+
from angr.ailment.statement import Assignment, WeakAssignment
|
|
7
7
|
|
|
8
8
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
9
9
|
|