angr 9.2.158__cp310-abi3-macosx_11_0_arm64.whl → 9.2.160__cp310-abi3-macosx_11_0_arm64.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.

Files changed (195) hide show
  1. angr/__init__.py +1 -1
  2. angr/ailment/__init__.py +81 -0
  3. angr/ailment/block.py +81 -0
  4. angr/ailment/block_walker.py +845 -0
  5. angr/ailment/constant.py +3 -0
  6. angr/ailment/converter_common.py +11 -0
  7. angr/ailment/converter_pcode.py +623 -0
  8. angr/ailment/converter_vex.py +798 -0
  9. angr/ailment/expression.py +1639 -0
  10. angr/ailment/manager.py +33 -0
  11. angr/ailment/statement.py +978 -0
  12. angr/ailment/tagged_object.py +61 -0
  13. angr/ailment/utils.py +114 -0
  14. angr/analyses/calling_convention/calling_convention.py +6 -2
  15. angr/analyses/decompiler/ail_simplifier.py +5 -5
  16. angr/analyses/decompiler/block_io_finder.py +4 -4
  17. angr/analyses/decompiler/block_similarity.py +2 -2
  18. angr/analyses/decompiler/block_simplifier.py +4 -4
  19. angr/analyses/decompiler/callsite_maker.py +2 -2
  20. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -1
  21. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
  22. angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +1 -1
  23. angr/analyses/decompiler/clinic.py +5 -2
  24. angr/analyses/decompiler/condition_processor.py +1 -1
  25. angr/analyses/decompiler/counters/boolean_counter.py +4 -4
  26. angr/analyses/decompiler/counters/call_counter.py +4 -4
  27. angr/analyses/decompiler/counters/expression_counters.py +5 -5
  28. angr/analyses/decompiler/counters/seq_cf_structure_counter.py +1 -1
  29. angr/analyses/decompiler/decompiler.py +17 -12
  30. angr/analyses/decompiler/dephication/dephication_base.py +12 -1
  31. angr/analyses/decompiler/dephication/graph_dephication.py +12 -5
  32. angr/analyses/decompiler/dephication/graph_rewriting.py +6 -10
  33. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +109 -72
  34. angr/analyses/decompiler/dephication/rewriting_engine.py +32 -9
  35. angr/analyses/decompiler/dephication/seqnode_dephication.py +32 -10
  36. angr/analyses/decompiler/empty_node_remover.py +2 -2
  37. angr/analyses/decompiler/expression_narrower.py +6 -6
  38. angr/analyses/decompiler/goto_manager.py +2 -2
  39. angr/analyses/decompiler/jump_target_collector.py +1 -1
  40. angr/analyses/decompiler/label_collector.py +1 -1
  41. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +25 -25
  42. angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +1 -1
  43. angr/analyses/decompiler/optimization_passes/code_motion.py +2 -2
  44. angr/analyses/decompiler/optimization_passes/condition_constprop.py +3 -3
  45. angr/analyses/decompiler/optimization_passes/const_derefs.py +3 -3
  46. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +4 -4
  47. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +2 -2
  48. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +3 -3
  49. angr/analyses/decompiler/optimization_passes/div_simplifier.py +1 -1
  50. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
  51. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +4 -4
  52. angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +1 -1
  53. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +4 -4
  54. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +3 -3
  55. angr/analyses/decompiler/optimization_passes/engine_base.py +1 -1
  56. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +3 -3
  57. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
  58. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +2 -2
  59. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +3 -3
  60. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +3 -3
  61. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +4 -4
  62. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +1 -1
  63. angr/analyses/decompiler/optimization_passes/optimization_pass.py +25 -1
  64. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +1 -1
  65. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +1 -1
  66. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +2 -2
  67. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +4 -4
  68. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +2 -2
  69. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
  70. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +3 -3
  71. angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +3 -3
  72. angr/analyses/decompiler/optimization_passes/tag_slicer.py +1 -1
  73. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -1
  74. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +1 -1
  75. angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +1 -1
  76. angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +1 -1
  77. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +1 -1
  78. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +1 -1
  79. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +1 -1
  80. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py +1 -1
  81. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +1 -1
  82. angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +1 -1
  83. angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +1 -1
  84. angr/analyses/decompiler/peephole_optimizations/base.py +3 -3
  85. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +1 -1
  86. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +1 -1
  87. angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +1 -1
  88. angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +1 -1
  89. angr/analyses/decompiler/peephole_optimizations/bswap.py +2 -2
  90. angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +2 -2
  91. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +2 -2
  92. angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +1 -1
  93. angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +2 -2
  94. angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -1
  95. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +1 -1
  96. angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +1 -1
  97. angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +1 -1
  98. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
  99. angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +1 -1
  100. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +2 -2
  101. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +2 -2
  102. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +2 -2
  103. angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +1 -1
  104. angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +1 -1
  105. angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +1 -1
  106. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +2 -2
  107. angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +2 -2
  108. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +1 -1
  109. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +1 -1
  110. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +1 -1
  111. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +1 -1
  112. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +1 -1
  113. angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +1 -1
  114. angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +1 -1
  115. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +1 -1
  116. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +1 -1
  117. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
  118. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +1 -1
  119. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +3 -3
  120. angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +1 -1
  121. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +2 -2
  122. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -1
  123. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +1 -1
  124. angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +1 -1
  125. angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +1 -1
  126. angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +1 -1
  127. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +2 -2
  128. angr/analyses/decompiler/peephole_optimizations/utils.py +1 -1
  129. angr/analyses/decompiler/redundant_label_remover.py +1 -1
  130. angr/analyses/decompiler/region_identifier.py +4 -4
  131. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -1
  132. angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +1 -1
  133. angr/analyses/decompiler/region_simplifiers/expr_folding.py +37 -8
  134. angr/analyses/decompiler/region_simplifiers/goto.py +1 -1
  135. angr/analyses/decompiler/region_simplifiers/if_.py +1 -1
  136. angr/analyses/decompiler/region_simplifiers/loop.py +1 -1
  137. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -1
  138. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +14 -2
  139. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +3 -3
  140. angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +1 -1
  141. angr/analyses/decompiler/return_maker.py +1 -1
  142. angr/analyses/decompiler/seq_to_blocks.py +1 -1
  143. angr/analyses/decompiler/sequence_walker.py +2 -2
  144. angr/analyses/decompiler/ssailification/rewriting.py +4 -4
  145. angr/analyses/decompiler/ssailification/rewriting_engine.py +4 -4
  146. angr/analyses/decompiler/ssailification/rewriting_state.py +3 -3
  147. angr/analyses/decompiler/ssailification/ssailification.py +2 -2
  148. angr/analyses/decompiler/ssailification/traversal.py +1 -1
  149. angr/analyses/decompiler/ssailification/traversal_engine.py +11 -2
  150. angr/analyses/decompiler/structured_codegen/c.py +3 -3
  151. angr/analyses/decompiler/structuring/dream.py +1 -1
  152. angr/analyses/decompiler/structuring/phoenix.py +3 -3
  153. angr/analyses/decompiler/structuring/structurer_base.py +1 -1
  154. angr/analyses/decompiler/structuring/structurer_nodes.py +1 -2
  155. angr/analyses/decompiler/utils.py +1 -1
  156. angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +1 -1
  157. angr/analyses/deobfuscator/string_obf_opt_passes.py +3 -3
  158. angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +2 -2
  159. angr/analyses/propagator/propagator.py +1 -1
  160. angr/analyses/proximity_graph.py +2 -2
  161. angr/analyses/reaching_definitions/engine_ail.py +1 -1
  162. angr/analyses/reaching_definitions/reaching_definitions.py +1 -1
  163. angr/analyses/reaching_definitions/subject.py +1 -1
  164. angr/analyses/s_liveness.py +2 -2
  165. angr/analyses/s_propagator.py +3 -3
  166. angr/analyses/s_reaching_definitions/s_rda_model.py +1 -1
  167. angr/analyses/s_reaching_definitions/s_rda_view.py +3 -3
  168. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -3
  169. angr/analyses/typehoon/simple_solver.py +231 -29
  170. angr/analyses/typehoon/typehoon.py +10 -2
  171. angr/analyses/variable_recovery/engine_ail.py +10 -22
  172. angr/analyses/variable_recovery/engine_base.py +1 -1
  173. angr/analyses/variable_recovery/variable_recovery_base.py +1 -1
  174. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
  175. angr/engines/light/data.py +1 -1
  176. angr/engines/light/engine.py +1 -1
  177. angr/knowledge_plugins/key_definitions/atoms.py +1 -1
  178. angr/knowledge_plugins/propagations/prop_value.py +1 -1
  179. angr/knowledge_plugins/propagations/propagation_model.py +1 -1
  180. angr/knowledge_plugins/propagations/states.py +1 -1
  181. angr/knowledge_plugins/variables/variable_manager.py +1 -1
  182. angr/rustylib.abi3.so +0 -0
  183. angr/state_plugins/unicorn_engine.py +4 -4
  184. angr/{lib/angr_native.dylib → unicornlib.dylib} +0 -0
  185. angr/utils/ail.py +4 -4
  186. angr/utils/endness.py +1 -1
  187. angr/utils/ssa/__init__.py +14 -4
  188. angr/utils/ssa/tmp_uses_collector.py +4 -4
  189. angr/utils/ssa/vvar_uses_collector.py +4 -4
  190. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/METADATA +6 -7
  191. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/RECORD +195 -183
  192. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/WHEEL +0 -0
  193. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/entry_points.txt +0 -0
  194. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/licenses/LICENSE +0 -0
  195. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ UNDETERMINED_SIZE = -0xC0DE
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ class SkipConversionNotice(Exception):
5
+ pass
6
+
7
+
8
+ class Converter:
9
+ @staticmethod
10
+ def convert(thing):
11
+ raise NotImplementedError
@@ -0,0 +1,623 @@
1
+ from __future__ import annotations
2
+ import logging
3
+
4
+ from angr.utils.constants import DEFAULT_STATEMENT
5
+ from angr.engines.pcode.lifter import IRSB
6
+ from pypcode import OpCode, Varnode
7
+ import pypcode
8
+
9
+ from .block import Block
10
+ from .statement import Statement, Assignment, Store, Jump, ConditionalJump, Return, Call
11
+ from .expression import Expression, DirtyExpression, Const, Register, Tmp, UnaryOp, BinaryOp, Load, Convert
12
+
13
+ # FIXME: Convert, ITE
14
+ from .manager import Manager
15
+ from .converter_common import Converter
16
+
17
+
18
+ log = logging.getLogger(name=__name__)
19
+
20
+ # FIXME: Not all ops are mapped to AIL expressions!
21
+ opcode_to_generic_name = {
22
+ # OpCode.MULTIEQUAL : '',
23
+ # OpCode.INDIRECT : '',
24
+ # OpCode.PIECE : '',
25
+ # OpCode.SUBPIECE : '',
26
+ OpCode.INT_EQUAL: "CmpEQ",
27
+ OpCode.INT_NOTEQUAL: "CmpNE",
28
+ OpCode.INT_SLESS: "CmpLTs",
29
+ OpCode.INT_SLESSEQUAL: "CmpLEs",
30
+ OpCode.INT_LESS: "CmpLT",
31
+ OpCode.INT_LESSEQUAL: "CmpLE",
32
+ # OpCode.INT_ZEXT : '',
33
+ # OpCode.INT_SEXT : '',
34
+ OpCode.INT_ADD: "Add",
35
+ OpCode.INT_SUB: "Sub",
36
+ OpCode.INT_CARRY: "Carry",
37
+ OpCode.INT_SCARRY: "SCarry",
38
+ OpCode.INT_SBORROW: "SBorrow",
39
+ # OpCode.INT_2COMP : '',
40
+ OpCode.INT_NEGATE: "Neg",
41
+ OpCode.INT_XOR: "Xor",
42
+ OpCode.INT_AND: "And",
43
+ OpCode.INT_OR: "Or",
44
+ OpCode.INT_LEFT: "Shl",
45
+ OpCode.INT_RIGHT: "Shr",
46
+ OpCode.INT_SRIGHT: "Sar",
47
+ OpCode.INT_MULT: "Mul",
48
+ OpCode.INT_DIV: "Div",
49
+ # OpCode.INT_SDIV : '',
50
+ # OpCode.INT_REM : '',
51
+ # OpCode.INT_SREM : '',
52
+ OpCode.BOOL_NEGATE: "Not",
53
+ OpCode.BOOL_XOR: "LogicalXor",
54
+ OpCode.BOOL_AND: "LogicalAnd",
55
+ OpCode.BOOL_OR: "LogicalOr",
56
+ # OpCode.CAST : '',
57
+ # OpCode.PTRADD : '',
58
+ # OpCode.PTRSUB : '',
59
+ # OpCode.FLOAT_EQUAL : '',
60
+ # OpCode.FLOAT_NOTEQUAL : '',
61
+ # OpCode.FLOAT_LESS : '',
62
+ # OpCode.FLOAT_LESSEQUAL : '',
63
+ # OpCode.FLOAT_NAN : '',
64
+ # OpCode.FLOAT_ADD : '',
65
+ OpCode.FLOAT_DIV: "Div",
66
+ OpCode.FLOAT_MULT: "Mul",
67
+ OpCode.FLOAT_SUB: "Sub",
68
+ # OpCode.FLOAT_NEG : '',
69
+ # OpCode.FLOAT_ABS : '',
70
+ # OpCode.FLOAT_SQRT : '',
71
+ # OpCode.FLOAT_INT2FLOAT : '',
72
+ # OpCode.FLOAT_FLOAT2FLOAT : '',
73
+ # OpCode.FLOAT_TRUNC : '',
74
+ # OpCode.FLOAT_CEIL : '',
75
+ # OpCode.FLOAT_FLOOR : '',
76
+ # OpCode.FLOAT_ROUND : '',
77
+ # OpCode.SEGMENTOP : '',
78
+ # OpCode.CPOOLREF : '',
79
+ # OpCode.NEW : '',
80
+ # OpCode.INSERT : '',
81
+ # OpCode.EXTRACT : '',
82
+ # OpCode.POPCOUNT : '',
83
+ }
84
+
85
+
86
+ class PCodeIRSBConverter(Converter):
87
+ """
88
+ Converts a p-code IRSB to an AIL block
89
+ """
90
+
91
+ @staticmethod
92
+ def convert(irsb: IRSB, manager: Manager): # pylint:disable=arguments-differ
93
+ """
94
+ Convert the given IRSB to an AIL block
95
+
96
+ :param irsb: IRSB to convert
97
+ :param manager: Manager to use
98
+ :return: Converted block
99
+ """
100
+ return PCodeIRSBConverter(irsb, manager)._convert()
101
+
102
+ def __init__(self, irsb: IRSB, manager: Manager):
103
+ self._irsb = irsb
104
+ self._manager = manager
105
+ self._statements = []
106
+ self._current_op = None
107
+ self._next_ins_addr = None
108
+ self._current_behavior = None
109
+ self._statement_idx = 0
110
+
111
+ # Remap all uniques s.t. they are write-once with values starting from 0
112
+ self._unique_tracker: dict[int, tuple[int, int]] = {}
113
+ self._unique_counter = 0
114
+
115
+ self._special_op_handlers = {
116
+ OpCode.COPY: self._convert_copy,
117
+ OpCode.INT_ZEXT: self._convert_zext,
118
+ OpCode.INT_SEXT: self._convert_sext,
119
+ OpCode.LOAD: self._convert_load,
120
+ OpCode.STORE: self._convert_store,
121
+ OpCode.BRANCH: self._convert_branch,
122
+ OpCode.CBRANCH: self._convert_cbranch,
123
+ OpCode.BRANCHIND: self._convert_branchind,
124
+ OpCode.CALL: self._convert_call,
125
+ OpCode.CALLIND: self._convert_callind,
126
+ OpCode.CALLOTHER: self._convert_callother,
127
+ OpCode.RETURN: self._convert_ret,
128
+ OpCode.MULTIEQUAL: self._convert_multiequal,
129
+ OpCode.INDIRECT: self._convert_indirect,
130
+ OpCode.SEGMENTOP: self._convert_segment_op,
131
+ OpCode.CPOOLREF: self._convert_cpool_ref,
132
+ OpCode.NEW: self._convert_new,
133
+ OpCode.FLOAT_INT2FLOAT: self._convert_int2float,
134
+ OpCode.FLOAT_FLOAT2FLOAT: self._convert_float2float,
135
+ }
136
+
137
+ manager.tyenv = None
138
+ manager.block_addr = irsb.addr
139
+ manager.vex_stmt_idx = DEFAULT_STATEMENT # Reset after loop. Necessary?
140
+
141
+ def _convert(self) -> Block:
142
+ """
143
+ Convert the given IRSB to an AIL Block
144
+ """
145
+ self._statement_idx = 0
146
+
147
+ for op in self._irsb._ops:
148
+ self._current_op = op
149
+ if op.opcode == pypcode.OpCode.IMARK:
150
+ self._manager.ins_addr = op.inputs[0].offset
151
+ self._next_ins_addr = op.inputs[-1].offset + op.inputs[-1].size
152
+ else:
153
+ self._current_behavior = self._irsb.behaviors.get_behavior_for_opcode(self._current_op.opcode)
154
+ self._convert_current_op()
155
+ self._statement_idx += 1
156
+
157
+ if (
158
+ "sparc:" in self._irsb.arch.name
159
+ and self._irsb.arch.bits == 32
160
+ and self._current_op.opcode == OpCode.CALL
161
+ ):
162
+ break
163
+
164
+ return Block(self._irsb.addr, self._irsb.size, statements=self._statements)
165
+
166
+ def _convert_current_op(self) -> None:
167
+ """
168
+ Convert the current op to corresponding AIL statement
169
+ """
170
+ assert self._current_behavior is not None
171
+
172
+ is_special = self._current_behavior.opcode in self._special_op_handlers
173
+
174
+ if is_special:
175
+ try:
176
+ self._special_op_handlers[self._current_behavior.opcode]()
177
+ except NotImplementedError as ex:
178
+ log.warning("Unsupported opcode: %s", ex)
179
+ elif self._current_behavior.is_unary:
180
+ self._convert_unary()
181
+ else:
182
+ self._convert_binary()
183
+
184
+ def _convert_unary(self) -> None:
185
+ """
186
+ Convert the current unary op to corresponding AIL statement
187
+ """
188
+ opcode = self._current_op.opcode
189
+
190
+ op = opcode_to_generic_name.get(opcode)
191
+ in1 = self._get_value(self._current_op.inputs[0])
192
+ if op is None:
193
+ log.warning("p-code: Unsupported opcode of type %s", opcode.__name__)
194
+ out = DirtyExpression(self._manager.next_atom(), opcode.__name__, [], bits=self._current_op.output.size * 8)
195
+ else:
196
+ out = UnaryOp(self._manager.next_atom(), op, in1, ins_addr=self._manager.ins_addr)
197
+
198
+ stmt = self._set_value(self._current_op.output, out)
199
+ self._statements.append(stmt)
200
+
201
+ def _convert_binary(self) -> None:
202
+ """
203
+ Convert the current binary op to corresponding AIL statement
204
+ """
205
+ opcode = self._current_op.opcode
206
+ op = opcode_to_generic_name.get(opcode)
207
+ in1 = self._get_value(self._current_op.inputs[0])
208
+ in2 = self._get_value(self._current_op.inputs[1])
209
+ signed = op in {"CmpLEs", "CmpGTs"}
210
+
211
+ if op is None:
212
+ log.warning("p-code: Unsupported opcode of type %s.", opcode.__name__)
213
+ out = DirtyExpression(self._manager.next_atom(), opcode.__name__, [], bits=self._current_op.output.size * 8)
214
+ else:
215
+ out = BinaryOp(self._manager.next_atom(), op, [in1, in2], signed, ins_addr=self._manager.ins_addr)
216
+
217
+ # Zero-extend 1-bit results
218
+ zextend_ops = {
219
+ OpCode.INT_EQUAL,
220
+ OpCode.INT_NOTEQUAL,
221
+ OpCode.INT_SLESS,
222
+ OpCode.INT_SLESSEQUAL,
223
+ OpCode.INT_LESS,
224
+ OpCode.INT_LESSEQUAL,
225
+ }
226
+ if opcode in zextend_ops:
227
+ out = Convert(self._manager.next_atom(), 1, self._current_op.output.size * 8, False, out)
228
+
229
+ stmt = self._set_value(self._current_op.output, out)
230
+ self._statements.append(stmt)
231
+
232
+ def _map_register_name(self, varnode: Varnode) -> int:
233
+ """
234
+ Map SLEIGH register offset to ArchInfo register offset based on name.
235
+
236
+ :param varnode: The varnode to translate
237
+ :return: The register file offset
238
+ """
239
+ # FIXME: Will need performance optimization
240
+ # FIXME: Should not get trans object this way. Moreover, should have a
241
+ # faster mapping method than going through trans
242
+ reg_name = varnode.getRegisterName()
243
+ try:
244
+ reg_offset = self._manager.arch.get_register_offset(reg_name.lower())
245
+ log.debug("Mapped register '%s' to offset %x", reg_name, reg_offset)
246
+ except ValueError:
247
+ reg_offset = varnode.offset + 0x100000
248
+ log.warning("Could not map register '%s' from archinfo. Mapping to %x", reg_name, reg_offset)
249
+ return reg_offset
250
+
251
+ def _remap_temp(self, offset: int, size: int, is_write: bool) -> int | None:
252
+ """
253
+ Remap any unique space addresses such that they are written only once
254
+
255
+ :param offset: The unique space address
256
+ :param is_write: Whether the access is a write or a read
257
+ :return: The remapped temporary register index
258
+ """
259
+ if is_write:
260
+ self._unique_tracker[offset] = self._unique_counter, size
261
+ self._unique_counter += 1
262
+ return self._unique_tracker[offset][0]
263
+ if offset in self._unique_tracker:
264
+ return self._unique_tracker[offset][0]
265
+ # this might be a partial access of an existing temporary variable. return None for now
266
+ return None
267
+
268
+ def _convert_varnode(self, varnode: Varnode, is_write: bool) -> Expression:
269
+ """
270
+ Convert a varnode to a corresponding AIL expression
271
+
272
+ :param varnode: The varnode to remap
273
+ :param is_write: Whether the varnode is being read or written to
274
+ :return: The corresponding AIL expression
275
+ """
276
+ space_name = varnode.space.name
277
+ size = varnode.size * 8
278
+
279
+ if space_name == "const":
280
+ return Const(self._manager.next_atom(), None, varnode.offset, size)
281
+ if space_name == "register":
282
+ offset = self._map_register_name(varnode)
283
+ return Register(self._manager.next_atom(), None, offset, size, reg_name=varnode.getRegisterName())
284
+ if space_name == "unique":
285
+ offset = self._remap_temp(varnode.offset, varnode.size, is_write)
286
+ if offset is None:
287
+ # this might be a partial access of an existing temporary variable
288
+ unique_offset = None
289
+ for delta in range(-1, -8, -1):
290
+ if varnode.offset + delta in self._unique_tracker:
291
+ unique_offset = varnode.offset + delta
292
+ break
293
+ assert unique_offset is not None, "Cannot find the source unique variable"
294
+ # TODO: Check size
295
+ _, ori_tmp_size = self._unique_tracker[unique_offset]
296
+ t = Tmp(self._manager.next_atom(), None, unique_offset, ori_tmp_size * 8)
297
+ # FIXME: Asserting BE
298
+ right_shift_amount = varnode.offset + varnode.size - (unique_offset + ori_tmp_size)
299
+ if right_shift_amount != 0:
300
+ t = BinaryOp(
301
+ self._manager.next_atom(),
302
+ "Shr",
303
+ [t, Const(self._manager.next_atom(), None, right_shift_amount * 8, 8)],
304
+ False,
305
+ ins_addr=self._manager.ins_addr,
306
+ )
307
+ return Convert(self._manager.next_atom(), t.bits, size, False, t, ins_addr=self._manager.ins_addr)
308
+
309
+ return Tmp(self._manager.next_atom(), None, offset, size)
310
+ if space_name in ["ram", "mem"]:
311
+ assert not is_write
312
+ addr = Const(self._manager.next_atom(), None, varnode.offset, self._manager.arch.bits)
313
+ # Note: Load takes bytes, not bits, for size
314
+ return Load(
315
+ self._manager.next_atom(),
316
+ addr,
317
+ varnode.size,
318
+ self._manager.arch.memory_endness,
319
+ ins_addr=self._manager.ins_addr,
320
+ )
321
+ raise NotImplementedError
322
+
323
+ def _set_value(self, varnode: Varnode, value: Expression) -> Statement:
324
+ """
325
+ Create the appropriate assignment statement to store to a varnode
326
+
327
+ This method stores to the appropriate register, or unique space,
328
+ depending on the space indicated by the varnode.
329
+
330
+ :param varnode: Varnode to store into
331
+ :param value: Value to store
332
+ :return: Corresponding AIL statement
333
+ """
334
+ space_name = varnode.space.name
335
+
336
+ if space_name in ["register", "unique"]:
337
+ return Assignment(
338
+ self._statement_idx, self._convert_varnode(varnode, True), value, ins_addr=self._manager.ins_addr
339
+ )
340
+ if space_name in ["ram", "mem"]:
341
+ addr = Const(self._manager.next_atom(), None, varnode.offset, self._manager.arch.bits)
342
+ return Store(
343
+ self._statement_idx,
344
+ addr,
345
+ value,
346
+ varnode.size,
347
+ self._manager.arch.memory_endness,
348
+ ins_addr=self._manager.ins_addr,
349
+ )
350
+ raise NotImplementedError
351
+
352
+ def _get_value(self, varnode: Varnode) -> Expression:
353
+ """
354
+ Create the appropriate expression to load from a varnode
355
+
356
+ This method loads from the appropriate const, register, unique, or RAM
357
+ space, depending on the space indicated by the varnode.
358
+
359
+ :param varnode: Varnode to load from.
360
+ :return: Value loaded
361
+ """
362
+ return self._convert_varnode(varnode, False)
363
+
364
+ def _convert_copy(self) -> None:
365
+ """
366
+ Convert copy operation
367
+ """
368
+ out = self._current_op.output
369
+ inp = self._get_value(self._current_op.inputs[0])
370
+ stmt = self._set_value(out, inp)
371
+ self._statements.append(stmt)
372
+
373
+ def _convert_zext(self) -> None:
374
+ """
375
+ Convert zext operation
376
+ """
377
+ out = self._current_op.output
378
+ inp = Convert(
379
+ self._manager.next_atom(),
380
+ self._current_op.inputs[0].size * 8,
381
+ out.size * 8,
382
+ False,
383
+ self._get_value(self._current_op.inputs[0]),
384
+ )
385
+ stmt = self._set_value(out, inp)
386
+ self._statements.append(stmt)
387
+
388
+ def _convert_sext(self) -> None:
389
+ """
390
+ Convert the signed extension operation
391
+ """
392
+ out = self._current_op.output
393
+ inp = Convert(
394
+ self._manager.next_atom(),
395
+ self._current_op.inputs[0].size * 8,
396
+ out.size * 8,
397
+ False,
398
+ self._get_value(self._current_op.inputs[0]),
399
+ )
400
+ stmt = self._set_value(out, inp)
401
+ self._statements.append(stmt)
402
+
403
+ def _convert_negate(self) -> None:
404
+ """
405
+ Convert bool negate operation
406
+ """
407
+ out = self._current_op.output
408
+ inp = self._get_value(self._current_op.inputs[0])
409
+
410
+ cval = Const(self._manager.next_atom(), None, 0, self._current_op.inputs[0].size * 8)
411
+
412
+ expr = BinaryOp(self._manager.next_atom(), "CmpEQ", [inp, cval], signed=False, ins_addr=self._manager.ins_addr)
413
+
414
+ stmt = self._set_value(out, expr)
415
+ self._statements.append(stmt)
416
+
417
+ def _convert_load(self) -> None:
418
+ """
419
+ Convert a p-code load operation
420
+ """
421
+ spc = self._current_op.inputs[0].getSpaceFromConst()
422
+ out = self._current_op.output
423
+ spc_name = spc.name.lower()
424
+ assert spc_name in {"ram", "mem", "register"}
425
+ if spc_name == "register":
426
+ # load from register
427
+ res = self._get_value(self._current_op.inputs[1])
428
+ stmt = self._set_value(out, res)
429
+ else:
430
+ # load from memory
431
+ off = self._get_value(self._current_op.inputs[1])
432
+ res = Load(
433
+ self._manager.next_atom(),
434
+ off,
435
+ self._current_op.output.size,
436
+ self._manager.arch.memory_endness,
437
+ ins_addr=self._manager.ins_addr,
438
+ )
439
+ stmt = self._set_value(out, res)
440
+ self._statements.append(stmt)
441
+
442
+ def _convert_store(self) -> None:
443
+ """
444
+ Convert a p-code store operation
445
+ """
446
+ spc = self._current_op.inputs[0].getSpaceFromConst()
447
+ spc_name = spc.name.lower()
448
+ assert spc_name in {"ram", "mem", "register"}
449
+ if spc_name == "register":
450
+ # store to register
451
+ out = self._current_op.inputs[2]
452
+ res = self._get_value(self._current_op.inputs[1])
453
+ stmt = self._set_value(out, res)
454
+ else:
455
+ # store to memory
456
+ off = self._get_value(self._current_op.inputs[1])
457
+ data = self._get_value(self._current_op.inputs[2])
458
+ log.debug("Storing %s at offset %s", data, off)
459
+ # self.state.memory.store(off, data, endness=self.project.arch.memory_endness)
460
+ stmt = Store(
461
+ self._statement_idx,
462
+ off,
463
+ data,
464
+ self._current_op.inputs[2].size,
465
+ self._manager.arch.memory_endness,
466
+ ins_addr=self._manager.ins_addr,
467
+ )
468
+ self._statements.append(stmt)
469
+
470
+ def _convert_branch(self) -> None:
471
+ """
472
+ Convert a p-code branch operation
473
+ """
474
+ if self._current_op.inputs[0].space == "const":
475
+ raise NotImplementedError("p-code relative branch not supported yet")
476
+ dest_addr = self._current_op.inputs[0].offset
477
+
478
+ # special handling: if the previous statement is a ConditionalJump with a None destination address, then we
479
+ # back-patch the previous statement
480
+ dest = Const(self._manager.next_atom(), None, dest_addr, self._manager.arch.bits)
481
+ if self._statements:
482
+ last_stmt = self._statements[-1]
483
+ if isinstance(last_stmt, ConditionalJump) and last_stmt.false_target is None:
484
+ last_stmt.false_target = dest
485
+ return
486
+
487
+ stmt = Jump(self._statement_idx, dest, ins_addr=self._manager.ins_addr)
488
+ self._statements.append(stmt)
489
+
490
+ def _convert_cbranch(self) -> None:
491
+ """
492
+ Convert a p-code conditional branch operation
493
+ """
494
+ if self._current_op.inputs[0].space == "const":
495
+ raise NotImplementedError("p-code relative branch not supported yet")
496
+ dest_addr = self._current_op.inputs[0].offset
497
+ cond = self._get_value(self._current_op.inputs[1])
498
+ cval = Const(self._manager.next_atom(), None, 0, cond.bits)
499
+ condition = BinaryOp(self._manager.next_atom(), "CmpNE", [cond, cval], signed=False)
500
+ dest = Const(self._manager.next_atom(), None, dest_addr, self._manager.arch.bits)
501
+ if self._irsb._ops[-1] is self._current_op:
502
+ # if the cbranch op is the last op, then we need to generate a fallthru target
503
+ fallthru = Const(
504
+ self._manager.next_atom(),
505
+ None,
506
+ self._next_ins_addr,
507
+ self._manager.arch.bits,
508
+ )
509
+ else:
510
+ # there will be a Jump statement that follows the cbranch
511
+ fallthru = None
512
+ stmt = ConditionalJump(self._statement_idx, condition, dest, fallthru, ins_addr=self._manager.ins_addr)
513
+ self._statements.append(stmt)
514
+
515
+ def _convert_ret(self) -> None:
516
+ """
517
+ Convert a p-code return operation
518
+ """
519
+ Const(self._manager.next_atom(), None, self._irsb.next, self._manager.arch.bits)
520
+ stmt = Return(
521
+ self._statement_idx,
522
+ [],
523
+ ins_addr=self._manager.ins_addr,
524
+ vex_block_addr=self._manager.block_addr,
525
+ vex_stmt_idx=DEFAULT_STATEMENT,
526
+ )
527
+ self._statements.append(stmt)
528
+
529
+ def _convert_branchind(self) -> None:
530
+ """
531
+ Convert a p-code indirect branch operation
532
+ """
533
+ dest = self._get_value(self._current_op.inputs[0])
534
+ stmt = Jump(self._statement_idx, dest, ins_addr=self._manager.ins_addr)
535
+ self._statements.append(stmt)
536
+
537
+ def _convert_call(self) -> None:
538
+ """
539
+ Convert a p-code call operation
540
+ """
541
+ ret_reg_offset = self._manager.arch.ret_offset
542
+ ret_expr = (
543
+ None if ret_reg_offset is None else Register(None, None, ret_reg_offset, self._manager.arch.bits)
544
+ ) # ???
545
+ dest = Const(self._manager.next_atom(), None, self._irsb.next, self._manager.arch.bits)
546
+ stmt = Call(
547
+ self._manager.next_atom(),
548
+ dest,
549
+ ret_expr=ret_expr,
550
+ ins_addr=self._manager.ins_addr,
551
+ vex_block_addr=self._manager.block_addr,
552
+ vex_stmt_idx=DEFAULT_STATEMENT,
553
+ )
554
+ self._statements.append(stmt)
555
+
556
+ def _convert_callind(self) -> None:
557
+ """
558
+ Convert a p-code indirect call operation
559
+ """
560
+ ret_reg_offset = self._manager.arch.ret_offset
561
+ ret_expr = Register(None, None, ret_reg_offset, self._manager.arch.bits) # ???
562
+ dest = self._get_value(self._current_op.inputs[0])
563
+ stmt = Call(
564
+ self._manager.next_atom(),
565
+ dest,
566
+ ret_expr=ret_expr,
567
+ ins_addr=self._manager.ins_addr,
568
+ vex_block_addr=self._manager.block_addr,
569
+ vex_stmt_idx=DEFAULT_STATEMENT,
570
+ )
571
+ self._statements.append(stmt)
572
+
573
+ def _convert_int2float(self) -> None:
574
+ """
575
+ Convert INT2FLOAT operation.
576
+ """
577
+ out = self._current_op.output
578
+ inp = Convert(
579
+ self._manager.next_atom(),
580
+ self._current_op.inputs[0].size * 8,
581
+ out.size * 8,
582
+ True,
583
+ self._get_value(self._current_op.inputs[0]),
584
+ from_type=Convert.TYPE_INT,
585
+ to_type=Convert.TYPE_FP,
586
+ )
587
+ stmt = self._set_value(out, inp)
588
+ self._statements.append(stmt)
589
+
590
+ def _convert_float2float(self) -> None:
591
+ """
592
+ Convert FLOAT2FLOAT operation.
593
+ """
594
+ out = self._current_op.output
595
+ inp = Convert(
596
+ self._manager.next_atom(),
597
+ self._current_op.inputs[0].size * 8,
598
+ out.size * 8,
599
+ True,
600
+ self._get_value(self._current_op.inputs[0]),
601
+ from_type=Convert.TYPE_FP,
602
+ to_type=Convert.TYPE_FP,
603
+ )
604
+ stmt = self._set_value(out, inp)
605
+ self._statements.append(stmt)
606
+
607
+ def _convert_callother(self) -> None:
608
+ raise NotImplementedError("CALLOTHER emulation not currently supported")
609
+
610
+ def _convert_multiequal(self) -> None:
611
+ raise NotImplementedError("MULTIEQUAL appearing in unheritaged code?")
612
+
613
+ def _convert_indirect(self) -> None:
614
+ raise NotImplementedError("INDIRECT appearing in unheritaged code?")
615
+
616
+ def _convert_segment_op(self) -> None:
617
+ raise NotImplementedError("SEGMENTOP emulation not currently supported")
618
+
619
+ def _convert_cpool_ref(self) -> None:
620
+ raise NotImplementedError("Cannot currently emulate cpool operator")
621
+
622
+ def _convert_new(self) -> None:
623
+ raise NotImplementedError("Cannot currently emulate new operator")