angr 9.2.131__py3-none-manylinux2014_aarch64.whl → 9.2.133__py3-none-manylinux2014_aarch64.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 +128 -128
- angr/analyses/__init__.py +38 -38
- angr/analyses/analysis.py +6 -2
- angr/analyses/backward_slice.py +3 -4
- angr/analyses/binary_optimizer.py +5 -12
- angr/analyses/bindiff.py +3 -6
- angr/analyses/calling_convention.py +3 -4
- angr/analyses/cfg/__init__.py +3 -3
- angr/analyses/cfg/cfg_base.py +1 -1
- angr/analyses/cfg/cfg_emulated.py +5 -5
- angr/analyses/cfg/cfg_fast.py +19 -17
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +5 -5
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +148 -101
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
- angr/analyses/data_dep/__init__.py +4 -4
- angr/analyses/datagraph_meta.py +1 -1
- angr/analyses/ddg.py +16 -17
- angr/analyses/decompiler/__init__.py +12 -12
- angr/analyses/decompiler/ail_simplifier.py +24 -12
- angr/analyses/decompiler/block_similarity.py +2 -4
- angr/analyses/decompiler/block_simplifier.py +10 -21
- angr/analyses/decompiler/callsite_maker.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
- angr/analyses/decompiler/clinic.py +122 -41
- angr/analyses/decompiler/condition_processor.py +57 -39
- angr/analyses/decompiler/counters/__init__.py +3 -3
- angr/analyses/decompiler/decompilation_cache.py +7 -7
- angr/analyses/decompiler/dephication/__init__.py +1 -1
- angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +11 -3
- angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
- angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/graph_region.py +8 -8
- angr/analyses/decompiler/optimization_passes/__init__.py +20 -20
- angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +1 -2
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +1 -3
- angr/analyses/decompiler/optimization_passes/engine_base.py +262 -84
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +175 -39
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +2 -5
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +5 -5
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +12 -3
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +42 -19
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +9 -5
- angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/base.py +6 -6
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +2 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
- angr/analyses/decompiler/presets/__init__.py +1 -1
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +3 -3
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +8 -12
- angr/analyses/decompiler/ssailification/rewriting.py +1 -2
- angr/analyses/decompiler/ssailification/rewriting_engine.py +139 -56
- angr/analyses/decompiler/ssailification/ssailification.py +2 -1
- angr/analyses/decompiler/ssailification/traversal.py +4 -6
- angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
- angr/analyses/decompiler/structured_codegen/__init__.py +5 -5
- angr/analyses/decompiler/structured_codegen/base.py +3 -3
- angr/analyses/decompiler/structured_codegen/c.py +39 -40
- angr/analyses/decompiler/structuring/__init__.py +3 -3
- angr/analyses/decompiler/structuring/phoenix.py +45 -29
- angr/analyses/decompiler/structuring/structurer_base.py +2 -2
- angr/analyses/decompiler/structuring/structurer_nodes.py +23 -14
- angr/analyses/deobfuscator/__init__.py +3 -3
- angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
- angr/analyses/deobfuscator/string_obf_finder.py +2 -2
- angr/analyses/deobfuscator/string_obf_opt_passes.py +1 -1
- angr/analyses/disassembly.py +4 -4
- angr/analyses/forward_analysis/__init__.py +1 -1
- angr/analyses/forward_analysis/visitors/graph.py +6 -6
- angr/analyses/init_finder.py +47 -22
- angr/analyses/loop_analysis.py +1 -1
- angr/analyses/loopfinder.py +1 -1
- angr/analyses/propagator/engine_base.py +21 -14
- angr/analyses/propagator/engine_vex.py +149 -179
- angr/analyses/propagator/outdated_definition_walker.py +12 -6
- angr/analyses/propagator/propagator.py +10 -28
- angr/analyses/propagator/top_checker_mixin.py +211 -5
- angr/analyses/propagator/vex_vars.py +4 -4
- angr/analyses/reaching_definitions/__init__.py +9 -9
- angr/analyses/reaching_definitions/call_trace.py +2 -2
- angr/analyses/reaching_definitions/dep_graph.py +1 -1
- angr/analyses/reaching_definitions/engine_ail.py +304 -329
- angr/analyses/reaching_definitions/engine_vex.py +243 -229
- angr/analyses/reaching_definitions/function_handler.py +3 -3
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +1 -1
- angr/analyses/reaching_definitions/rd_state.py +47 -42
- angr/analyses/reassembler.py +26 -31
- angr/analyses/s_liveness.py +8 -0
- angr/analyses/s_propagator.py +18 -3
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -5
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
- angr/analyses/stack_pointer_tracker.py +4 -4
- angr/analyses/typehoon/simple_solver.py +14 -14
- angr/analyses/typehoon/translator.py +10 -2
- angr/analyses/typehoon/typeconsts.py +11 -3
- angr/analyses/typehoon/typevars.py +26 -26
- angr/analyses/unpacker/__init__.py +1 -1
- angr/analyses/variable_recovery/engine_ail.py +299 -259
- angr/analyses/variable_recovery/engine_base.py +138 -121
- angr/analyses/variable_recovery/engine_vex.py +175 -185
- angr/analyses/variable_recovery/irsb_scanner.py +49 -38
- angr/analyses/variable_recovery/variable_recovery.py +28 -5
- angr/analyses/variable_recovery/variable_recovery_base.py +33 -34
- angr/analyses/variable_recovery/variable_recovery_fast.py +4 -8
- angr/analyses/veritesting.py +2 -2
- angr/analyses/vfg.py +5 -5
- angr/analyses/xrefs.py +46 -19
- angr/angrdb/serializers/__init__.py +1 -1
- angr/annocfg.py +20 -15
- angr/blade.py +2 -2
- angr/block.py +20 -25
- angr/calling_conventions.py +12 -14
- angr/code_location.py +6 -10
- angr/codenode.py +3 -3
- angr/engines/__init__.py +12 -14
- angr/engines/engine.py +24 -61
- angr/engines/light/__init__.py +13 -5
- angr/engines/light/data.py +1 -1
- angr/engines/light/engine.py +1003 -1185
- angr/engines/pcode/__init__.py +1 -1
- angr/engines/pcode/behavior.py +1 -1
- angr/engines/pcode/cc.py +2 -0
- angr/engines/pcode/lifter.py +13 -15
- angr/engines/soot/expressions/__init__.py +12 -12
- angr/engines/soot/statements/__init__.py +6 -6
- angr/engines/soot/values/__init__.py +6 -6
- angr/engines/soot/values/arrayref.py +2 -2
- angr/engines/soot/values/constants.py +1 -1
- angr/engines/soot/values/instancefieldref.py +1 -1
- angr/engines/soot/values/paramref.py +1 -1
- angr/engines/soot/values/staticfieldref.py +1 -1
- angr/engines/successors.py +15 -14
- angr/engines/vex/__init__.py +5 -5
- angr/engines/vex/claripy/ccall.py +2 -2
- angr/engines/vex/claripy/datalayer.py +1 -1
- angr/engines/vex/claripy/irop.py +19 -19
- angr/engines/vex/heavy/__init__.py +2 -2
- angr/engines/vex/heavy/actions.py +1 -3
- angr/engines/vex/heavy/heavy.py +4 -6
- angr/engines/vex/lifter.py +2 -4
- angr/engines/vex/light/light.py +0 -2
- angr/engines/vex/light/slicing.py +5 -5
- angr/exploration_techniques/__init__.py +19 -142
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +1 -1
- angr/exploration_techniques/dfs.py +3 -1
- angr/exploration_techniques/director.py +2 -3
- angr/exploration_techniques/driller_core.py +1 -1
- angr/exploration_techniques/explorer.py +4 -2
- angr/exploration_techniques/lengthlimiter.py +2 -1
- angr/exploration_techniques/local_loop_seer.py +2 -1
- angr/exploration_techniques/loop_seer.py +5 -5
- angr/exploration_techniques/manual_mergepoint.py +2 -1
- angr/exploration_techniques/memory_watcher.py +3 -1
- angr/exploration_techniques/oppologist.py +4 -5
- angr/exploration_techniques/slicecutor.py +4 -2
- angr/exploration_techniques/spiller.py +1 -1
- angr/exploration_techniques/stochastic.py +2 -1
- angr/exploration_techniques/stub_stasher.py +2 -1
- angr/exploration_techniques/suggestions.py +3 -1
- angr/exploration_techniques/symbion.py +3 -1
- angr/exploration_techniques/tech_builder.py +2 -1
- angr/exploration_techniques/threading.py +2 -11
- angr/exploration_techniques/timeout.py +4 -2
- angr/exploration_techniques/tracer.py +4 -3
- angr/exploration_techniques/unique.py +3 -2
- angr/exploration_techniques/veritesting.py +1 -1
- angr/factory.py +36 -6
- angr/keyed_region.py +4 -4
- angr/knowledge_base.py +1 -1
- angr/knowledge_plugins/__init__.py +11 -11
- angr/knowledge_plugins/cfg/__init__.py +5 -5
- angr/knowledge_plugins/cfg/cfg_manager.py +2 -2
- angr/knowledge_plugins/cfg/cfg_model.py +8 -8
- angr/knowledge_plugins/cfg/cfg_node.py +19 -19
- angr/knowledge_plugins/cfg/indirect_jump.py +6 -6
- angr/knowledge_plugins/cfg/memory_data.py +5 -7
- angr/knowledge_plugins/functions/function.py +48 -52
- angr/knowledge_plugins/functions/function_parser.py +4 -4
- angr/knowledge_plugins/key_definitions/__init__.py +3 -3
- angr/knowledge_plugins/key_definitions/atoms.py +8 -8
- angr/knowledge_plugins/key_definitions/definition.py +1 -1
- angr/knowledge_plugins/key_definitions/live_definitions.py +30 -27
- angr/knowledge_plugins/labels.py +1 -1
- angr/knowledge_plugins/propagations/__init__.py +1 -1
- angr/knowledge_plugins/propagations/prop_value.py +2 -2
- angr/knowledge_plugins/propagations/propagation_model.py +7 -8
- angr/knowledge_plugins/propagations/states.py +44 -39
- angr/knowledge_plugins/variables/variable_access.py +2 -2
- angr/knowledge_plugins/variables/variable_manager.py +24 -10
- angr/knowledge_plugins/xrefs/xref.py +5 -8
- angr/misc/__init__.py +4 -4
- angr/misc/hookset.py +4 -5
- angr/misc/loggers.py +2 -2
- angr/misc/telemetry.py +1 -1
- angr/procedures/__init__.py +1 -1
- angr/procedures/cgc/fdwait.py +2 -2
- angr/procedures/definitions/__init__.py +2 -2
- angr/procedures/definitions/linux_kernel.py +0 -1
- angr/procedures/definitions/parse_syscalls_from_local_system.py +1 -1
- angr/procedures/definitions/parse_win32json.py +0 -1
- angr/procedures/ntdll/exceptions.py +1 -1
- angr/procedures/stubs/format_parser.py +3 -3
- angr/procedures/win32/dynamic_loading.py +1 -1
- angr/protos/__init__.py +3 -3
- angr/sim_manager.py +3 -5
- angr/sim_state.py +40 -42
- angr/sim_state_options.py +3 -3
- angr/sim_type.py +15 -14
- angr/sim_variable.py +42 -45
- angr/simos/__init__.py +4 -4
- angr/simos/cgc.py +1 -1
- angr/simos/simos.py +1 -1
- angr/simos/userland.py +1 -1
- angr/slicer.py +4 -7
- angr/state_plugins/__init__.py +34 -34
- angr/state_plugins/callstack.py +5 -12
- angr/state_plugins/heap/__init__.py +2 -2
- angr/state_plugins/heap/heap_brk.py +2 -4
- angr/state_plugins/heap/heap_ptmalloc.py +1 -1
- angr/state_plugins/jni_references.py +3 -2
- angr/state_plugins/scratch.py +1 -1
- angr/state_plugins/sim_action.py +1 -4
- angr/state_plugins/sim_event.py +1 -1
- angr/state_plugins/solver.py +7 -9
- angr/state_plugins/uc_manager.py +1 -1
- angr/state_plugins/view.py +2 -2
- angr/storage/__init__.py +1 -1
- angr/storage/file.py +10 -10
- angr/storage/memory_mixins/__init__.py +46 -46
- angr/storage/memory_mixins/default_filler_mixin.py +1 -3
- angr/storage/memory_mixins/javavm_memory_mixin.py +2 -2
- angr/storage/memory_mixins/name_resolution_mixin.py +2 -2
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -3
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +6 -6
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
- angr/storage/memory_mixins/regioned_memory/__init__.py +3 -3
- angr/storage/memory_mixins/regioned_memory/region_data.py +5 -5
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +7 -9
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +4 -4
- angr/storage/memory_object.py +4 -4
- angr/utils/__init__.py +3 -3
- angr/utils/bits.py +12 -0
- angr/utils/dynamic_dictlist.py +1 -1
- angr/utils/graph.py +1 -1
- angr/utils/orderedset.py +4 -1
- angr/utils/segment_list.py +2 -2
- angr/utils/ssa/__init__.py +33 -8
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/METADATA +6 -6
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/RECORD +262 -263
- angr/analyses/propagator/engine_ail.py +0 -1562
- angr/storage/memory_mixins/__init__.pyi +0 -48
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/LICENSE +0 -0
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/WHEEL +0 -0
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/entry_points.txt +0 -0
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/top_level.txt +0 -0
angr/engines/light/engine.py
CHANGED
|
@@ -1,54 +1,100 @@
|
|
|
1
|
-
# pylint:disable=no-self-use,
|
|
1
|
+
# pylint:disable=no-self-use,unused-argument
|
|
2
2
|
from __future__ import annotations
|
|
3
|
-
from typing import Any
|
|
4
|
-
import
|
|
3
|
+
from typing import Any, Protocol, cast, TypeVar, Generic
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from abc import abstractmethod
|
|
5
6
|
import re
|
|
6
7
|
import logging
|
|
7
8
|
|
|
8
9
|
import ailment
|
|
9
10
|
import pyvex
|
|
10
11
|
import claripy
|
|
11
|
-
import
|
|
12
|
+
from pyvex.expr import IRExpr
|
|
12
13
|
|
|
13
14
|
from angr.misc.ux import once
|
|
14
|
-
from angr.engines.vex.claripy.datalayer import value as claripy_value
|
|
15
15
|
from angr.engines.vex.claripy.irop import UnsupportedIROpError, SimOperationError, vexop_to_simop
|
|
16
16
|
from angr.code_location import CodeLocation
|
|
17
|
-
from angr.
|
|
18
|
-
from angr.engines.engine import SimEngine
|
|
19
|
-
import
|
|
17
|
+
from angr.project import Project
|
|
18
|
+
from angr.engines.engine import DataType_co, SimEngine, StateType
|
|
19
|
+
from angr.block import Block
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class
|
|
22
|
+
class BlockProtocol(Protocol):
|
|
23
23
|
"""
|
|
24
|
-
|
|
24
|
+
The minimum protocol that a block an engine can process should adhere to.
|
|
25
|
+
Requires just an addr attribute.
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
self.arch: archinfo.Arch | None = None
|
|
29
|
-
self.l = logger
|
|
30
|
-
super().__init__(*args, **kwargs)
|
|
28
|
+
addr: int
|
|
31
29
|
|
|
32
|
-
def _is_top(self, expr) -> bool:
|
|
33
|
-
"""
|
|
34
|
-
Check if a given expression is a TOP value.
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return False
|
|
31
|
+
BlockType = TypeVar("BlockType", bound=BlockProtocol)
|
|
32
|
+
ResultType = TypeVar("ResultType")
|
|
33
|
+
StmtDataType = TypeVar("StmtDataType")
|
|
40
34
|
|
|
41
|
-
def _top(self, size: int):
|
|
42
|
-
"""
|
|
43
|
-
Return a TOP value. It will only be called if _is_top() has been implemented.
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
class IRTop(pyvex.expr.IRExpr):
|
|
37
|
+
"""
|
|
38
|
+
A dummy IRExpr used for intra-engine communication and code-reuse.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, ty: str):
|
|
42
|
+
super().__init__()
|
|
43
|
+
self.ty = ty
|
|
44
|
+
|
|
45
|
+
def result_type(self, tyenv):
|
|
46
|
+
return self.ty
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class SimEngineLight(Generic[StateType, DataType_co, BlockType, ResultType], SimEngine[StateType, ResultType]):
|
|
50
|
+
"""
|
|
51
|
+
A full-featured engine base class, suitable for static analysis
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
# local variables
|
|
55
|
+
block: BlockType
|
|
56
|
+
_call_stack: list[Any]
|
|
57
|
+
state: StateType
|
|
58
|
+
|
|
59
|
+
stmt_idx: int
|
|
60
|
+
ins_addr: int
|
|
61
|
+
tmps: dict[int, DataType_co]
|
|
62
|
+
|
|
63
|
+
def __init__(self, project: Project, logger=None):
|
|
64
|
+
self.l = logger or logging.getLogger(self.__module__ + "." + self.__class__.__name__)
|
|
65
|
+
super().__init__(project)
|
|
66
|
+
|
|
67
|
+
# there's two of these to support the mixin pattern - mixins can override process while there must be some base
|
|
68
|
+
# class that provides _process
|
|
69
|
+
def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType:
|
|
70
|
+
return self._process(state, block=block, **kwargs)
|
|
71
|
+
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def _process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType: ...
|
|
74
|
+
|
|
75
|
+
def lift(self, state: StateType) -> BlockType:
|
|
76
|
+
raise TypeError(f"{type(self)} requires `block` to be passed to `process`")
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Helper methods
|
|
80
|
+
#
|
|
81
|
+
|
|
82
|
+
def _codeloc(self, block_only=False, context=None):
|
|
83
|
+
return CodeLocation(
|
|
84
|
+
self.block.addr,
|
|
85
|
+
None if block_only else self.stmt_idx,
|
|
86
|
+
ins_addr=None if block_only else self.ins_addr,
|
|
87
|
+
context=context,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def _top(self, bits: int) -> DataType_co: ...
|
|
92
|
+
|
|
93
|
+
@abstractmethod
|
|
94
|
+
def _is_top(self, expr: Any) -> bool: ...
|
|
49
95
|
|
|
50
96
|
@staticmethod
|
|
51
|
-
def sp_offset(bits: int, offset: int):
|
|
97
|
+
def sp_offset(bits: int, offset: int) -> claripy.ast.BV:
|
|
52
98
|
base = claripy.BVS("SpOffset", bits, explicit_name=True)
|
|
53
99
|
if offset:
|
|
54
100
|
base += offset
|
|
@@ -73,92 +119,180 @@ class SimEngineLightMixin:
|
|
|
73
119
|
# Unexpected but fine
|
|
74
120
|
return 0
|
|
75
121
|
if isinstance(spoffset_expr.args[1], claripy.ast.Base) and spoffset_expr.args[1].op == "BVV":
|
|
76
|
-
return spoffset_expr.args[1].args[0]
|
|
122
|
+
return cast(int, spoffset_expr.args[1].args[0])
|
|
77
123
|
elif spoffset_expr.op == "__sub__":
|
|
78
124
|
if len(spoffset_expr.args) == 1:
|
|
79
125
|
# Unexpected but fine
|
|
80
126
|
return 0
|
|
81
127
|
if isinstance(spoffset_expr.args[1], claripy.ast.Base) and spoffset_expr.args[1].op == "BVV":
|
|
82
|
-
return -spoffset_expr.args[1].args[0] & (
|
|
128
|
+
return -cast(int, spoffset_expr.args[1].args[0]) & (
|
|
129
|
+
(1 << cast(claripy.ast.BV, spoffset_expr).size()) - 1
|
|
130
|
+
)
|
|
83
131
|
return None
|
|
84
132
|
|
|
85
133
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
134
|
+
T = TypeVar("T")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def longest_prefix_lookup(haystack: str, mapping: dict[str, T]) -> T | None:
|
|
138
|
+
for l in reversed(range(len(haystack))):
|
|
139
|
+
handler = mapping.get(haystack[:l], None)
|
|
140
|
+
if handler is not None:
|
|
141
|
+
return handler
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# noinspection PyPep8Naming
|
|
146
|
+
class SimEngineLightVEX(
|
|
147
|
+
Generic[StateType, DataType_co, ResultType, StmtDataType], SimEngineLight[StateType, DataType_co, Block, ResultType]
|
|
89
148
|
):
|
|
90
149
|
"""
|
|
91
|
-
A
|
|
150
|
+
A mixin for doing static analysis on VEX
|
|
92
151
|
"""
|
|
93
152
|
|
|
94
|
-
|
|
95
|
-
logger = logging.getLogger(self.__module__ + "." + self.__class__.__name__)
|
|
96
|
-
super().__init__(logger=logger)
|
|
153
|
+
tyenv: pyvex.IRTypeEnv
|
|
97
154
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
self._call_stack = None
|
|
103
|
-
|
|
104
|
-
self.stmt_idx = None
|
|
105
|
-
self.ins_addr = None
|
|
106
|
-
self.tmps = None
|
|
155
|
+
@staticmethod
|
|
156
|
+
def unop_handler(f: Callable[[T, pyvex.expr.Unop], DataType_co]) -> Callable[[T, pyvex.expr.Unop], DataType_co]:
|
|
157
|
+
f.unop_handler = True
|
|
158
|
+
return f
|
|
107
159
|
|
|
108
|
-
|
|
109
|
-
|
|
160
|
+
@staticmethod
|
|
161
|
+
def binop_handler(f: Callable[[T, pyvex.expr.Binop], DataType_co]) -> Callable[[T, pyvex.expr.Binop], DataType_co]:
|
|
162
|
+
f.binop_handler = True
|
|
163
|
+
return f
|
|
110
164
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
165
|
+
@staticmethod
|
|
166
|
+
def binopv_handler(
|
|
167
|
+
f: Callable[[T, int, int, pyvex.expr.Binop], DataType_co]
|
|
168
|
+
) -> Callable[[T, int, int, pyvex.expr.Binop], DataType_co]:
|
|
169
|
+
f.binopv_handler = True
|
|
170
|
+
return f
|
|
115
171
|
|
|
116
|
-
|
|
117
|
-
|
|
172
|
+
@staticmethod
|
|
173
|
+
def triop_handler(f: Callable[[T, pyvex.expr.Triop], DataType_co]) -> Callable[[T, pyvex.expr.Triop], DataType_co]:
|
|
174
|
+
f.triop_handler = True
|
|
175
|
+
return f
|
|
118
176
|
|
|
119
|
-
|
|
120
|
-
|
|
177
|
+
@staticmethod
|
|
178
|
+
def qop_handler(f: Callable[[T, pyvex.expr.Qop], DataType_co]) -> Callable[[T, pyvex.expr.Qop], DataType_co]:
|
|
179
|
+
f.qop_handler = True
|
|
180
|
+
return f
|
|
121
181
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
182
|
+
@staticmethod
|
|
183
|
+
def ccall_handler(f: Callable[[T, pyvex.expr.CCall], DataType_co]) -> Callable[[T, pyvex.expr.CCall], DataType_co]:
|
|
184
|
+
f.ccall_handler = True
|
|
185
|
+
return f
|
|
125
186
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
)
|
|
187
|
+
@staticmethod
|
|
188
|
+
def dirty_handler(
|
|
189
|
+
f: Callable[[T, pyvex.stmt.Dirty], StmtDataType]
|
|
190
|
+
) -> Callable[[T, pyvex.stmt.Dirty], StmtDataType]:
|
|
191
|
+
f.dirty_handler = True
|
|
192
|
+
return f
|
|
133
193
|
|
|
194
|
+
def __init__(self, *args, **kwargs):
|
|
195
|
+
super().__init__(*args, **kwargs)
|
|
134
196
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
197
|
+
def checked(h: T, attr: str) -> T:
|
|
198
|
+
if not getattr(h, attr, False):
|
|
199
|
+
raise TypeError(f"Handle {h} is not validated for {attr}")
|
|
200
|
+
return h
|
|
201
|
+
|
|
202
|
+
self._stmt_handlers: dict[str, Callable[[Any], StmtDataType]] = {
|
|
203
|
+
"Ist_WrTmp": self._handle_stmt_WrTmp,
|
|
204
|
+
"Ist_Put": self._handle_stmt_Put,
|
|
205
|
+
"Ist_PutI": self._handle_stmt_PutI,
|
|
206
|
+
"Ist_Store": self._handle_stmt_Store,
|
|
207
|
+
"Ist_StoreG": self._handle_stmt_StoreG,
|
|
208
|
+
"Ist_LoadG": self._handle_stmt_LoadG,
|
|
209
|
+
"Ist_CAS": self._handle_stmt_CAS,
|
|
210
|
+
"Ist_LLSC": self._handle_stmt_LLSC,
|
|
211
|
+
"Ist_MBE": self._handle_stmt_MBE,
|
|
212
|
+
"Ist_Exit": self._handle_stmt_Exit,
|
|
213
|
+
"Ist_NoOp": self._handle_stmt_NoOp,
|
|
214
|
+
"Ist_IMark": self._handle_stmt_IMark,
|
|
215
|
+
"Ist_AbiHint": self._handle_stmt_AbiHint,
|
|
216
|
+
"Ist_Dirty": self._handle_stmt_Dirty,
|
|
217
|
+
}
|
|
218
|
+
self._expr_handlers: dict[str, Callable[[Any], DataType_co]] = {
|
|
219
|
+
"IRTop": self._handle_expr_IRTop,
|
|
220
|
+
"VECRET": self._handle_expr_VECRET,
|
|
221
|
+
"GSPTR": self._handle_expr_GSPTR,
|
|
222
|
+
"RdTmp": self._handle_expr_RdTmp,
|
|
223
|
+
"Get": self._handle_expr_Get,
|
|
224
|
+
"GetI": self._handle_expr_GetI,
|
|
225
|
+
"Load": self._handle_expr_Load,
|
|
226
|
+
"ITE": self._handle_expr_ITE,
|
|
227
|
+
"Unop": self._handle_expr_Unop,
|
|
228
|
+
"Binop": self._handle_expr_Binop,
|
|
229
|
+
"Triop": self._handle_expr_Triop,
|
|
230
|
+
"Qop": self._handle_expr_Qop,
|
|
231
|
+
"CCall": self._handle_expr_CCall,
|
|
232
|
+
"Const": self._handle_expr_Const,
|
|
233
|
+
}
|
|
234
|
+
self._unop_handlers: dict[str, Callable[[pyvex.expr.Unop], DataType_co]] = {
|
|
235
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "unop_handler")
|
|
236
|
+
for name in dir(self)
|
|
237
|
+
if name.startswith("_handle_unop_")
|
|
238
|
+
}
|
|
239
|
+
self._binop_handlers: dict[str, Callable[[pyvex.expr.Binop], DataType_co]] = {
|
|
240
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "binop_handler")
|
|
241
|
+
for name in dir(self)
|
|
242
|
+
if name.startswith("_handle_binop_")
|
|
243
|
+
}
|
|
244
|
+
self._binopv_handlers: dict[str, Callable[[int, int, pyvex.expr.Binop], DataType_co]] = {
|
|
245
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "binopv_handler")
|
|
246
|
+
for name in dir(self)
|
|
247
|
+
if name.startswith("_handle_binopv_")
|
|
248
|
+
}
|
|
249
|
+
self._triop_handlers: dict[str, Callable[[pyvex.expr.Triop], DataType_co]] = {
|
|
250
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "triop_handler")
|
|
251
|
+
for name in dir(self)
|
|
252
|
+
if name.startswith("_handle_triop_")
|
|
253
|
+
}
|
|
254
|
+
self._qop_handlers: dict[str, Callable[[pyvex.expr.Qop], DataType_co]] = {
|
|
255
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "qop_handler")
|
|
256
|
+
for name in dir(self)
|
|
257
|
+
if name.startswith("_handle_qop_")
|
|
258
|
+
}
|
|
259
|
+
self._ccall_handlers: dict[str, Callable[[pyvex.expr.CCall], DataType_co]] = {
|
|
260
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "ccall_handler")
|
|
261
|
+
for name in dir(self)
|
|
262
|
+
if name.startswith("_handle_ccall_")
|
|
263
|
+
}
|
|
264
|
+
self._dirty_handlers: dict[str, Callable[[pyvex.stmt.Dirty], StmtDataType]] = {
|
|
265
|
+
name.split("_", 3)[-1]: checked(getattr(self, name), "dirty_handler")
|
|
266
|
+
for name in dir(self)
|
|
267
|
+
if name.startswith("_handle_dirty_")
|
|
268
|
+
}
|
|
140
269
|
|
|
141
|
-
def _process(
|
|
270
|
+
def _process(
|
|
271
|
+
self, state: StateType, *, block: Block | None = None, whitelist: set[int] | None = None, **kwargs
|
|
272
|
+
) -> ResultType:
|
|
142
273
|
# initialize local variables
|
|
143
274
|
self.tmps = {}
|
|
275
|
+
|
|
276
|
+
if block is None:
|
|
277
|
+
block = self.lift(state)
|
|
144
278
|
self.block = block
|
|
145
279
|
self.state = state
|
|
146
|
-
|
|
147
|
-
if state is not None:
|
|
148
|
-
self.arch: archinfo.Arch = state.arch
|
|
149
|
-
|
|
280
|
+
self.arch = self.project.arch
|
|
150
281
|
self.tyenv = block.vex.tyenv
|
|
151
|
-
|
|
152
|
-
self.
|
|
153
|
-
|
|
154
|
-
self.
|
|
155
|
-
self.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
282
|
+
self.stmt_idx = -1
|
|
283
|
+
self.ins_addr = -1
|
|
284
|
+
|
|
285
|
+
result = self._process_block(whitelist=whitelist)
|
|
286
|
+
del self.stmt_idx
|
|
287
|
+
del self.ins_addr
|
|
288
|
+
del self.tmps
|
|
289
|
+
del self.block
|
|
290
|
+
del self.state
|
|
291
|
+
del self.tyenv
|
|
292
|
+
return result
|
|
293
|
+
|
|
294
|
+
def _process_block(self, whitelist: set[int] | None = None) -> ResultType:
|
|
295
|
+
result = []
|
|
162
296
|
for stmt_idx, stmt in enumerate(self.block.vex.statements):
|
|
163
297
|
if whitelist is not None and stmt_idx not in whitelist:
|
|
164
298
|
continue
|
|
@@ -169,1290 +303,974 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
|
|
|
169
303
|
# The bug caused by skipping IMarks is reported at https://github.com/angr/angr/pull/1150
|
|
170
304
|
self.ins_addr = stmt.addr + stmt.delta
|
|
171
305
|
|
|
172
|
-
self.
|
|
173
|
-
|
|
174
|
-
self._process_block_end()
|
|
175
|
-
|
|
176
|
-
def
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if self.block.vex.jumpkind == "Ijk_Call":
|
|
182
|
-
self.stmt_idx = DEFAULT_STATEMENT
|
|
183
|
-
handler = "_handle_function"
|
|
184
|
-
if hasattr(self, handler):
|
|
185
|
-
func_addr = (
|
|
186
|
-
self.block.vex.next if isinstance(self.block.vex.next, int) else self._expr(self.block.vex.next)
|
|
187
|
-
)
|
|
188
|
-
if func_addr is None and self.l is not None:
|
|
189
|
-
self.l.debug("Cannot determine the callee address at %#x.", self.block.addr)
|
|
190
|
-
getattr(self, handler)(func_addr)
|
|
191
|
-
else:
|
|
192
|
-
if self.l is not None:
|
|
193
|
-
self.l.warning("Function handler not implemented.")
|
|
306
|
+
result.append(self._stmt(stmt))
|
|
307
|
+
|
|
308
|
+
return self._process_block_end(result, whitelist)
|
|
309
|
+
|
|
310
|
+
def _stmt(self, stmt: pyvex.stmt.IRStmt) -> StmtDataType:
|
|
311
|
+
return self._stmt_handlers[stmt.tag](stmt)
|
|
312
|
+
|
|
313
|
+
@abstractmethod
|
|
314
|
+
def _process_block_end(self, stmt_result: list[StmtDataType], whitelist: set[int] | None) -> ResultType: ...
|
|
194
315
|
|
|
195
316
|
#
|
|
196
317
|
# Statement handlers
|
|
197
318
|
#
|
|
198
319
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
320
|
+
@abstractmethod
|
|
321
|
+
def _handle_stmt_WrTmp(self, stmt: pyvex.stmt.WrTmp) -> StmtDataType: ...
|
|
322
|
+
|
|
323
|
+
@abstractmethod
|
|
324
|
+
def _handle_stmt_Put(self, stmt: pyvex.stmt.Put) -> StmtDataType: ...
|
|
325
|
+
|
|
326
|
+
@abstractmethod
|
|
327
|
+
def _handle_stmt_PutI(self, stmt: pyvex.stmt.PutI) -> StmtDataType: ...
|
|
205
328
|
|
|
206
|
-
|
|
207
|
-
def
|
|
208
|
-
data = self._expr(stmt.data)
|
|
209
|
-
if data is None:
|
|
210
|
-
return
|
|
329
|
+
@abstractmethod
|
|
330
|
+
def _handle_stmt_Store(self, stmt: pyvex.stmt.Store) -> StmtDataType: ...
|
|
211
331
|
|
|
212
|
-
|
|
332
|
+
@abstractmethod
|
|
333
|
+
def _handle_stmt_StoreG(self, stmt: pyvex.stmt.StoreG) -> StmtDataType: ...
|
|
213
334
|
|
|
214
|
-
|
|
215
|
-
def
|
|
216
|
-
if data is None:
|
|
217
|
-
return
|
|
218
|
-
self.tmps[tmp] = data
|
|
335
|
+
@abstractmethod
|
|
336
|
+
def _handle_stmt_LoadG(self, stmt: pyvex.stmt.LoadG) -> StmtDataType: ...
|
|
219
337
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
self.l.error("Unimplemented Dirty node for current architecture.")
|
|
338
|
+
@abstractmethod
|
|
339
|
+
def _handle_stmt_CAS(self, stmt: pyvex.stmt.CAS) -> StmtDataType: ...
|
|
223
340
|
|
|
224
|
-
|
|
225
|
-
|
|
341
|
+
@abstractmethod
|
|
342
|
+
def _handle_stmt_LLSC(self, stmt: pyvex.stmt.LLSC) -> StmtDataType: ...
|
|
226
343
|
|
|
227
|
-
|
|
228
|
-
|
|
344
|
+
@abstractmethod
|
|
345
|
+
def _handle_stmt_MBE(self, stmt: pyvex.stmt.MBE) -> StmtDataType: ...
|
|
229
346
|
|
|
230
|
-
|
|
231
|
-
|
|
347
|
+
@abstractmethod
|
|
348
|
+
def _handle_stmt_Exit(self, stmt: pyvex.stmt.Exit) -> StmtDataType: ...
|
|
232
349
|
|
|
233
|
-
|
|
234
|
-
|
|
350
|
+
@abstractmethod
|
|
351
|
+
def _handle_stmt_NoOp(self, stmt: pyvex.stmt.NoOp) -> StmtDataType: ...
|
|
352
|
+
|
|
353
|
+
@abstractmethod
|
|
354
|
+
def _handle_stmt_IMark(self, stmt: pyvex.stmt.IMark) -> StmtDataType: ...
|
|
355
|
+
|
|
356
|
+
@abstractmethod
|
|
357
|
+
def _handle_stmt_AbiHint(self, stmt: pyvex.stmt.AbiHint) -> StmtDataType: ...
|
|
358
|
+
|
|
359
|
+
def _handle_stmt_Dirty(self, stmt: pyvex.stmt.Dirty) -> StmtDataType:
|
|
360
|
+
handler = longest_prefix_lookup(stmt.cee.name, self._dirty_handlers)
|
|
361
|
+
if handler is not None:
|
|
362
|
+
return handler(stmt)
|
|
363
|
+
|
|
364
|
+
if once(stmt.cee.name) and self.l is not None:
|
|
365
|
+
self.l.error("Unsupported Dirty %s.", stmt.cee.name)
|
|
366
|
+
if stmt.tmp in (-1, 0xFFFFFFFF):
|
|
367
|
+
return self._handle_stmt_NoOp(pyvex.stmt.NoOp())
|
|
368
|
+
return self._handle_stmt_WrTmp(pyvex.stmt.WrTmp(stmt.tmp, IRTop(self.tyenv.lookup(stmt.tmp))))
|
|
235
369
|
|
|
236
370
|
#
|
|
237
371
|
# Expression handlers
|
|
238
372
|
#
|
|
239
373
|
|
|
240
|
-
def _expr(self, expr):
|
|
241
|
-
handler =
|
|
242
|
-
|
|
243
|
-
return getattr(self, handler)(expr)
|
|
244
|
-
if self.l is not None:
|
|
245
|
-
self.l.error("Unsupported expression type %s.", type(expr).__name__)
|
|
246
|
-
return None
|
|
374
|
+
def _expr(self, expr: IRExpr) -> DataType_co:
|
|
375
|
+
handler = type(expr).__name__
|
|
376
|
+
return self._expr_handlers[handler](expr)
|
|
247
377
|
|
|
248
|
-
|
|
378
|
+
# not generated by vex
|
|
379
|
+
def _handle_expr_IRTop(self, expr: IRTop) -> DataType_co:
|
|
380
|
+
return self._top(pyvex.get_type_size(expr.result_type(self.tyenv)))
|
|
381
|
+
|
|
382
|
+
@abstractmethod
|
|
383
|
+
def _handle_expr_VECRET(self, expr: pyvex.expr.VECRET) -> DataType_co: ...
|
|
384
|
+
|
|
385
|
+
@abstractmethod
|
|
386
|
+
def _handle_expr_GSPTR(self, expr: pyvex.expr.GSPTR) -> DataType_co: ...
|
|
387
|
+
|
|
388
|
+
@abstractmethod
|
|
389
|
+
def _handle_expr_RdTmp(self, expr: pyvex.expr.RdTmp) -> DataType_co: ...
|
|
390
|
+
|
|
391
|
+
@abstractmethod
|
|
392
|
+
def _handle_expr_Get(self, expr: pyvex.expr.Get) -> DataType_co: ...
|
|
393
|
+
|
|
394
|
+
@abstractmethod
|
|
395
|
+
def _handle_expr_GetI(self, expr: pyvex.expr.GetI) -> DataType_co: ...
|
|
396
|
+
|
|
397
|
+
@abstractmethod
|
|
398
|
+
def _handle_expr_Load(self, expr: pyvex.expr.Load) -> DataType_co: ...
|
|
399
|
+
|
|
400
|
+
@abstractmethod
|
|
401
|
+
def _handle_expr_ITE(self, expr: pyvex.expr.ITE) -> DataType_co: ...
|
|
402
|
+
|
|
403
|
+
def _handle_expr_Unop(self, expr: pyvex.expr.Unop) -> DataType_co:
|
|
249
404
|
handler = None
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
handler
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if
|
|
262
|
-
return
|
|
405
|
+
assert expr.op.startswith("Iop_")
|
|
406
|
+
handler = longest_prefix_lookup(expr.op[4:], self._unop_handlers)
|
|
407
|
+
if handler is not None:
|
|
408
|
+
return handler(expr)
|
|
409
|
+
|
|
410
|
+
# All conversions are handled by the Conversion handler
|
|
411
|
+
try:
|
|
412
|
+
simop = vexop_to_simop(expr.op)
|
|
413
|
+
except (UnsupportedIROpError, SimOperationError):
|
|
414
|
+
simop = None
|
|
415
|
+
|
|
416
|
+
if simop is not None and "Reinterp" not in expr.op and simop.op_attrs.get("conversion", None):
|
|
417
|
+
return self._handle_conversion(simop._from_size, simop._to_size, simop.is_signed, expr.args[0])
|
|
418
|
+
|
|
419
|
+
if once(expr.op) and self.l is not None:
|
|
420
|
+
self.l.error("Unsupported Unop %s.", expr.op)
|
|
421
|
+
return self._top(pyvex.get_type_size(expr.result_type(self.tyenv)))
|
|
422
|
+
|
|
423
|
+
@abstractmethod
|
|
424
|
+
def _handle_conversion(self, from_size: int, to_size: int, signed: bool, operand: IRExpr) -> DataType_co: ...
|
|
425
|
+
|
|
426
|
+
def _handle_expr_Binop(self, expr: pyvex.expr.Binop) -> DataType_co:
|
|
427
|
+
assert expr.op.startswith("Iop_")
|
|
428
|
+
|
|
429
|
+
# vector information
|
|
430
|
+
m = re.match(r"Iop_[^\d]+(\d+)[SU]{0,1}x(\d+)", expr.op)
|
|
431
|
+
if m is not None:
|
|
432
|
+
vector_size = int(m.group(1))
|
|
433
|
+
vector_count = int(m.group(2))
|
|
434
|
+
handler_v = longest_prefix_lookup(expr.op[4:], self._binopv_handlers)
|
|
435
|
+
if handler_v is not None:
|
|
436
|
+
return handler_v(vector_size, vector_count, expr)
|
|
437
|
+
|
|
438
|
+
handler = longest_prefix_lookup(expr.op[4:], self._binop_handlers)
|
|
439
|
+
if handler is not None:
|
|
440
|
+
return handler(expr)
|
|
441
|
+
|
|
442
|
+
if once(expr.op) and self.l is not None:
|
|
443
|
+
self.l.warning("Unsupported Binop %s.", expr.op)
|
|
444
|
+
return self._top(pyvex.get_type_size(expr.result_type(self.tyenv)))
|
|
445
|
+
|
|
446
|
+
def _handle_expr_Triop(self, expr: pyvex.expr.Triop) -> DataType_co:
|
|
447
|
+
assert expr.op.startswith("Iop_")
|
|
448
|
+
handler = longest_prefix_lookup(expr.op[4:], self._triop_handlers)
|
|
449
|
+
if handler is not None:
|
|
450
|
+
return handler(expr)
|
|
451
|
+
|
|
452
|
+
# should we try dispatching some triops with roundingmode as binops?
|
|
263
453
|
|
|
264
454
|
if once(expr.op) and self.l is not None:
|
|
265
455
|
self.l.error("Unsupported Triop %s.", expr.op)
|
|
456
|
+
return self._top(pyvex.get_type_size(expr.result_type(self.tyenv)))
|
|
266
457
|
|
|
267
|
-
|
|
458
|
+
def _handle_expr_Qop(self, expr: pyvex.expr.Qop) -> DataType_co:
|
|
459
|
+
assert expr.op.startswith("Iop_")
|
|
460
|
+
handler = longest_prefix_lookup(expr.op[4:], self._qop_handlers)
|
|
461
|
+
if handler is not None:
|
|
462
|
+
return handler(expr)
|
|
268
463
|
|
|
269
|
-
|
|
270
|
-
|
|
464
|
+
if once(expr.op) and self.l is not None:
|
|
465
|
+
self.l.error("Unsupported Qop %s.", expr.op)
|
|
466
|
+
return self._top(pyvex.get_type_size(expr.result_type(self.tyenv)))
|
|
271
467
|
|
|
272
|
-
def
|
|
273
|
-
|
|
468
|
+
def _handle_expr_CCall(self, expr: pyvex.expr.CCall) -> DataType_co: # pylint:disable=useless-return
|
|
469
|
+
handler = longest_prefix_lookup(expr.cee.name, self._ccall_handlers)
|
|
470
|
+
if handler is not None:
|
|
471
|
+
return handler(expr)
|
|
274
472
|
|
|
275
|
-
|
|
276
|
-
|
|
473
|
+
if once(expr.cee.name) and self.l is not None:
|
|
474
|
+
self.l.error("Unsupported CCall %s.", expr.cee.name)
|
|
475
|
+
return self._top(pyvex.get_type_size(expr.result_type(self.tyenv)))
|
|
277
476
|
|
|
278
|
-
|
|
279
|
-
|
|
477
|
+
@abstractmethod
|
|
478
|
+
def _handle_expr_Const(self, expr: pyvex.expr.Const) -> DataType_co: ...
|
|
280
479
|
|
|
281
|
-
def _handle_NegF(self, expr):
|
|
282
|
-
return self._top(expr.result_size(self.tyenv))
|
|
283
480
|
|
|
284
|
-
|
|
285
|
-
|
|
481
|
+
class SimEngineNostmtVEX(
|
|
482
|
+
Generic[StateType, DataType_co, ResultType], SimEngineLightVEX[StateType, DataType_co, ResultType, None]
|
|
483
|
+
):
|
|
484
|
+
"""
|
|
485
|
+
A base class of SimEngineLightVEX that has default handlers for statements if they just need to return None, so you
|
|
486
|
+
don't have to implement every single statement handler as ``return None``.
|
|
487
|
+
"""
|
|
286
488
|
|
|
287
|
-
def
|
|
288
|
-
|
|
489
|
+
def _handle_stmt_WrTmp(self, stmt):
|
|
490
|
+
pass
|
|
289
491
|
|
|
290
|
-
def
|
|
291
|
-
|
|
492
|
+
def _handle_stmt_Put(self, stmt):
|
|
493
|
+
pass
|
|
292
494
|
|
|
293
|
-
def
|
|
294
|
-
|
|
495
|
+
def _handle_stmt_PutI(self, stmt):
|
|
496
|
+
pass
|
|
295
497
|
|
|
296
|
-
def
|
|
297
|
-
|
|
498
|
+
def _handle_stmt_Store(self, stmt):
|
|
499
|
+
pass
|
|
298
500
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return None
|
|
501
|
+
def _handle_stmt_StoreG(self, stmt):
|
|
502
|
+
pass
|
|
302
503
|
|
|
303
|
-
def
|
|
304
|
-
|
|
504
|
+
def _handle_stmt_LoadG(self, stmt):
|
|
505
|
+
pass
|
|
305
506
|
|
|
306
|
-
def
|
|
307
|
-
|
|
507
|
+
def _handle_stmt_CAS(self, stmt):
|
|
508
|
+
pass
|
|
308
509
|
|
|
309
|
-
def
|
|
310
|
-
|
|
510
|
+
def _handle_stmt_LLSC(self, stmt):
|
|
511
|
+
pass
|
|
311
512
|
|
|
312
|
-
def
|
|
313
|
-
|
|
314
|
-
self._expr(stmt.dst)
|
|
513
|
+
def _handle_stmt_MBE(self, stmt):
|
|
514
|
+
pass
|
|
315
515
|
|
|
316
|
-
def
|
|
317
|
-
|
|
318
|
-
cond = self._expr(expr.cond)
|
|
319
|
-
if cond is True:
|
|
320
|
-
return self._expr(expr.iftrue)
|
|
321
|
-
if cond is False:
|
|
322
|
-
return self._expr(expr.iffalse)
|
|
323
|
-
return None
|
|
516
|
+
def _handle_stmt_Exit(self, stmt):
|
|
517
|
+
pass
|
|
324
518
|
|
|
325
|
-
def
|
|
326
|
-
|
|
519
|
+
def _handle_stmt_NoOp(self, stmt):
|
|
520
|
+
pass
|
|
327
521
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
with contextlib.suppress(UnsupportedIROpError, SimOperationError):
|
|
331
|
-
simop = vexop_to_simop(expr.op)
|
|
522
|
+
def _handle_stmt_IMark(self, stmt):
|
|
523
|
+
pass
|
|
332
524
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
# Notice order of "Not" comparisons
|
|
336
|
-
elif expr.op == "Iop_Not1":
|
|
337
|
-
handler = "_handle_Not1"
|
|
338
|
-
elif expr.op.startswith("Iop_Not"):
|
|
339
|
-
handler = "_handle_Not"
|
|
340
|
-
elif expr.op.startswith("Iop_Clz"):
|
|
341
|
-
handler = "_handle_Clz"
|
|
342
|
-
elif expr.op.startswith("Iop_Ctz"):
|
|
343
|
-
handler = "_handle_Ctz"
|
|
344
|
-
elif expr.op.startswith("Iop_NegF"):
|
|
345
|
-
handler = "_handle_NegF"
|
|
346
|
-
elif expr.op.startswith("Iop_AbsF"):
|
|
347
|
-
handler = "_handle_AbsF"
|
|
348
|
-
|
|
349
|
-
if handler is not None and hasattr(self, handler):
|
|
350
|
-
return getattr(self, handler)(expr)
|
|
351
|
-
if self.l is not None:
|
|
352
|
-
self.l.error("Unsupported Unop %s.", expr.op)
|
|
353
|
-
return None
|
|
525
|
+
def _handle_stmt_AbiHint(self, stmt):
|
|
526
|
+
pass
|
|
354
527
|
|
|
355
|
-
def _handle_Binop(self, expr: pyvex.IRExpr.Binop):
|
|
356
|
-
handler = None
|
|
357
|
-
if expr.op.startswith("Iop_And"):
|
|
358
|
-
handler = "_handle_And"
|
|
359
|
-
elif expr.op.startswith("Iop_Mod"):
|
|
360
|
-
handler = "_handle_Mod"
|
|
361
|
-
elif expr.op.startswith("Iop_Or"):
|
|
362
|
-
handler = "_handle_Or"
|
|
363
|
-
elif expr.op.startswith("Iop_Add"):
|
|
364
|
-
handler = "_handle_Add"
|
|
365
|
-
elif expr.op.startswith("Iop_HAdd"):
|
|
366
|
-
handler = "_handle_HAdd"
|
|
367
|
-
elif expr.op.startswith("Iop_Sub"):
|
|
368
|
-
handler = "_handle_Sub"
|
|
369
|
-
elif expr.op.startswith("Iop_QSub"):
|
|
370
|
-
handler = "_handle_QSub"
|
|
371
|
-
elif expr.op.startswith("Iop_Mull"):
|
|
372
|
-
handler = "_handle_Mull"
|
|
373
|
-
elif expr.op.startswith("Iop_Mul"):
|
|
374
|
-
handler = "_handle_Mul"
|
|
375
|
-
elif expr.op.startswith("Iop_DivMod"):
|
|
376
|
-
handler = "_handle_DivMod"
|
|
377
|
-
elif expr.op.startswith("Iop_Div"):
|
|
378
|
-
handler = "_handle_Div"
|
|
379
|
-
elif expr.op.startswith("Iop_Xor"):
|
|
380
|
-
handler = "_handle_Xor"
|
|
381
|
-
elif expr.op.startswith("Iop_Shl"):
|
|
382
|
-
handler = "_handle_Shl"
|
|
383
|
-
elif expr.op.startswith("Iop_Shr"):
|
|
384
|
-
handler = "_handle_Shr"
|
|
385
|
-
elif expr.op.startswith("Iop_Sal"):
|
|
386
|
-
# intended use of SHL
|
|
387
|
-
handler = "_handle_Shl"
|
|
388
|
-
elif expr.op.startswith("Iop_Sar"):
|
|
389
|
-
handler = "_handle_Sar"
|
|
390
|
-
elif expr.op.startswith("Iop_CmpEQ"):
|
|
391
|
-
handler = "_handle_CmpEQ"
|
|
392
|
-
elif expr.op.startswith("Iop_CmpNE"):
|
|
393
|
-
handler = "_handle_CmpNE"
|
|
394
|
-
elif expr.op.startswith("Iop_CmpLT"):
|
|
395
|
-
handler = "_handle_CmpLT"
|
|
396
|
-
elif expr.op.startswith("Iop_CmpLE"):
|
|
397
|
-
handler = "_handle_CmpLE"
|
|
398
|
-
elif expr.op.startswith("Iop_CmpGE"):
|
|
399
|
-
handler = "_handle_CmpGE"
|
|
400
|
-
elif expr.op.startswith("Iop_CmpGT"):
|
|
401
|
-
handler = "_handle_CmpGT"
|
|
402
|
-
elif expr.op.startswith("Iop_CmpORD"):
|
|
403
|
-
handler = "_handle_CmpORD"
|
|
404
|
-
elif expr.op.startswith("Iop_CmpF"):
|
|
405
|
-
handler = "_handle_CmpF"
|
|
406
|
-
elif expr.op == "Iop_32HLto64":
|
|
407
|
-
handler = "_handle_32HLto64"
|
|
408
|
-
elif expr.op.startswith("Const"):
|
|
409
|
-
handler = "_handle_Const"
|
|
410
|
-
elif expr.op.startswith("Iop_16HLto32"):
|
|
411
|
-
handler = "_handle_16HLto32"
|
|
412
|
-
elif expr.op.startswith("Iop_ExpCmpNE64"):
|
|
413
|
-
handler = "_handle_ExpCmpNE64"
|
|
414
|
-
elif expr.op.startswith("Iop_SinF"):
|
|
415
|
-
handler = "_handle_SinF"
|
|
416
|
-
elif expr.op.startswith("Iop_CosF"):
|
|
417
|
-
handler = "_handle_CosF"
|
|
418
|
-
|
|
419
|
-
vector_size, vector_count = None, None
|
|
420
|
-
if handler is not None:
|
|
421
|
-
# vector information
|
|
422
|
-
m = re.match(r"Iop_[^\d]+(\d+)[SU]{0,1}x(\d+)", expr.op)
|
|
423
|
-
if m is not None:
|
|
424
|
-
vector_size = int(m.group(1))
|
|
425
|
-
vector_count = int(m.group(2))
|
|
426
|
-
handler += "_v"
|
|
427
|
-
|
|
428
|
-
if handler is not None and hasattr(self, handler):
|
|
429
|
-
if vector_size is not None and vector_count is not None:
|
|
430
|
-
return getattr(self, handler)(expr, vector_size, vector_count)
|
|
431
|
-
return getattr(self, handler)(expr)
|
|
432
|
-
if once(expr.op) and self.l is not None:
|
|
433
|
-
self.l.warning("Unsupported Binop %s.", expr.op)
|
|
434
528
|
|
|
435
|
-
|
|
529
|
+
# noinspection PyPep8Naming
|
|
530
|
+
class SimEngineLightAIL(
|
|
531
|
+
Generic[StateType, DataType_co, StmtDataType, ResultType],
|
|
532
|
+
SimEngineLight[StateType, DataType_co, ailment.Block, ResultType],
|
|
533
|
+
):
|
|
534
|
+
"""
|
|
535
|
+
A mixin for doing static analysis on AIL
|
|
536
|
+
"""
|
|
537
|
+
|
|
538
|
+
def __init__(self, *args, **kwargs):
|
|
539
|
+
self._stmt_handlers: dict[str, Callable[[Any], StmtDataType]] = {
|
|
540
|
+
"Assignment": self._handle_stmt_Assignment,
|
|
541
|
+
"Store": self._handle_stmt_Store,
|
|
542
|
+
"Jump": self._handle_stmt_Jump,
|
|
543
|
+
"ConditionalJump": self._handle_stmt_ConditionalJump,
|
|
544
|
+
"Call": self._handle_stmt_Call,
|
|
545
|
+
"Return": self._handle_stmt_Return,
|
|
546
|
+
"DirtyStatement": self._handle_stmt_DirtyStatement,
|
|
547
|
+
"Label": self._handle_stmt_Label,
|
|
548
|
+
}
|
|
549
|
+
self._expr_handlers: dict[str, Callable[[Any], DataType_co]] = {
|
|
550
|
+
"Atom": self._handle_expr_Atom,
|
|
551
|
+
"Const": self._handle_expr_Const,
|
|
552
|
+
"Tmp": self._handle_expr_Tmp,
|
|
553
|
+
"VirtualVariable": self._handle_expr_VirtualVariable,
|
|
554
|
+
"Phi": self._handle_expr_Phi,
|
|
555
|
+
"Op": self._handle_expr_Op,
|
|
556
|
+
"UnaryOp": self._handle_expr_UnaryOp,
|
|
557
|
+
"BinaryOp": self._handle_expr_BinaryOp,
|
|
558
|
+
"Convert": self._handle_expr_Convert,
|
|
559
|
+
"Reinterpret": self._handle_expr_Reinterpret,
|
|
560
|
+
"Load": self._handle_expr_Load,
|
|
561
|
+
"Register": self._handle_expr_Register,
|
|
562
|
+
"ITE": self._handle_expr_ITE,
|
|
563
|
+
"Call": self._handle_expr_Call,
|
|
564
|
+
"DirtyExpression": self._handle_expr_DirtyExpression,
|
|
565
|
+
"VEXCCallExpression": self._handle_expr_VEXCCallExpression,
|
|
566
|
+
"MultiStatementExpression": self._handle_expr_MultiStatementExpression,
|
|
567
|
+
"BasePointerOffset": self._handle_expr_BasePointerOffset,
|
|
568
|
+
"StackBaseOffset": self._handle_expr_StackBaseOffset,
|
|
569
|
+
}
|
|
570
|
+
self._unop_handlers: dict[str, Callable[[ailment.UnaryOp], DataType_co]] = {
|
|
571
|
+
"Not": self._handle_unop_Not,
|
|
572
|
+
"Neg": self._handle_unop_Neg,
|
|
573
|
+
"BitwiseNeg": self._handle_unop_BitwiseNeg,
|
|
574
|
+
"Reference": self._handle_unop_Reference,
|
|
575
|
+
"Dereference": self._handle_unop_Dereference,
|
|
576
|
+
"Clz": self._handle_unop_Clz,
|
|
577
|
+
"Ctz": self._handle_unop_Ctz,
|
|
578
|
+
"GetMSBs": self._handle_unop_GetMSBs,
|
|
579
|
+
"unpack": self._handle_unop_unpack,
|
|
580
|
+
"Sqrt": self._handle_unop_Sqrt,
|
|
581
|
+
"RSqrtEst": self._handle_unop_RSqrtEst,
|
|
582
|
+
}
|
|
583
|
+
self._binop_handlers: dict[str, Callable[[ailment.BinaryOp], DataType_co]] = {
|
|
584
|
+
"Add": self._handle_binop_Add,
|
|
585
|
+
"AddF": self._handle_binop_AddF,
|
|
586
|
+
"AddV": self._handle_binop_AddV,
|
|
587
|
+
"Sub": self._handle_binop_Sub,
|
|
588
|
+
"SubF": self._handle_binop_SubF,
|
|
589
|
+
"SubV": self._handle_binop_SubV,
|
|
590
|
+
"Mul": self._handle_binop_Mul,
|
|
591
|
+
"Mull": self._handle_binop_Mull,
|
|
592
|
+
"MulF": self._handle_binop_MulF,
|
|
593
|
+
"MulV": self._handle_binop_MulV,
|
|
594
|
+
"MulHiV": self._handle_binop_MulHiV,
|
|
595
|
+
"Div": self._handle_binop_Div,
|
|
596
|
+
"DivF": self._handle_binop_DivF,
|
|
597
|
+
"DivV": self._handle_binop_DivV,
|
|
598
|
+
"Mod": self._handle_binop_Mod,
|
|
599
|
+
"Xor": self._handle_binop_Xor,
|
|
600
|
+
"And": self._handle_binop_And,
|
|
601
|
+
"LogicalAnd": self._handle_binop_LogicalAnd,
|
|
602
|
+
"Or": self._handle_binop_Or,
|
|
603
|
+
"LogicalOr": self._handle_binop_LogicalOr,
|
|
604
|
+
"Shl": self._handle_binop_Shl,
|
|
605
|
+
"Shr": self._handle_binop_Shr,
|
|
606
|
+
"Sar": self._handle_binop_Sar,
|
|
607
|
+
"CmpF": self._handle_binop_CmpF,
|
|
608
|
+
"CmpEQ": self._handle_binop_CmpEQ,
|
|
609
|
+
"CmpNE": self._handle_binop_CmpNE,
|
|
610
|
+
"CmpLT": self._handle_binop_CmpLT,
|
|
611
|
+
"CmpLE": self._handle_binop_CmpLE,
|
|
612
|
+
"CmpGT": self._handle_binop_CmpGT,
|
|
613
|
+
"CmpGE": self._handle_binop_CmpGE,
|
|
614
|
+
"Concat": self._handle_binop_Concat,
|
|
615
|
+
"Ror": self._handle_binop_Ror,
|
|
616
|
+
"Rol": self._handle_binop_Rol,
|
|
617
|
+
"Carry": self._handle_binop_Carry,
|
|
618
|
+
"SCarry": self._handle_binop_SCarry,
|
|
619
|
+
"SBorrow": self._handle_binop_SBorrow,
|
|
620
|
+
"InterleaveLOV": self._handle_binop_InterleaveLOV,
|
|
621
|
+
"InterleaveHIV": self._handle_binop_InterleaveHIV,
|
|
622
|
+
"CasCmpEQ": self._handle_binop_CasCmpEQ,
|
|
623
|
+
"CasCmpNE": self._handle_binop_CasCmpNE,
|
|
624
|
+
"ExpCmpNE": self._handle_binop_ExpCmpNE,
|
|
625
|
+
"SarNV": self._handle_binop_SarNV,
|
|
626
|
+
"ShrNV": self._handle_binop_ShrNV,
|
|
627
|
+
"ShlNV": self._handle_binop_ShlNV,
|
|
628
|
+
"CmpEQV": self._handle_binop_CmpEQV,
|
|
629
|
+
"CmpNEV": self._handle_binop_CmpNEV,
|
|
630
|
+
"CmpGEV": self._handle_binop_CmpGEV,
|
|
631
|
+
"CmpGTV": self._handle_binop_CmpGTV,
|
|
632
|
+
"CmpLEV": self._handle_binop_CmpLTV,
|
|
633
|
+
"CmpLTV": self._handle_binop_CmpLEV,
|
|
634
|
+
"MinV": self._handle_binop_MinV,
|
|
635
|
+
"MaxV": self._handle_binop_MaxV,
|
|
636
|
+
"QAddV": self._handle_binop_QAddV,
|
|
637
|
+
"QNarrowBinV": self._handle_binop_QNarrowBinV,
|
|
638
|
+
"PermV": self._handle_binop_PermV,
|
|
639
|
+
"Set": self._handle_binop_Set,
|
|
640
|
+
}
|
|
641
|
+
super().__init__(*args, **kwargs)
|
|
436
642
|
|
|
437
|
-
def
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
643
|
+
def _process(
|
|
644
|
+
self, state: StateType, *, block: ailment.Block | None = None, whitelist: set[int] | None = None, **kwargs
|
|
645
|
+
) -> ResultType:
|
|
646
|
+
self.tmps = {}
|
|
647
|
+
if block is None:
|
|
648
|
+
block = self.lift(state)
|
|
649
|
+
self.block = block
|
|
650
|
+
self.state = state
|
|
651
|
+
self.stmt_idx = 0
|
|
652
|
+
self.ins_addr = 0
|
|
653
|
+
|
|
654
|
+
stmt_data = self._process_stmts(whitelist=whitelist)
|
|
655
|
+
result = self._process_block_end(block, stmt_data, whitelist)
|
|
656
|
+
del self.tmps
|
|
657
|
+
del self.block
|
|
658
|
+
del self.state
|
|
659
|
+
del self.stmt_idx
|
|
660
|
+
del self.ins_addr
|
|
661
|
+
return result
|
|
662
|
+
|
|
663
|
+
@abstractmethod
|
|
664
|
+
def _process_block_end(
|
|
665
|
+
self, block: ailment.Block, stmt_data: list[StmtDataType], whitelist: set[int] | None
|
|
666
|
+
) -> ResultType: ...
|
|
441
667
|
|
|
442
668
|
#
|
|
443
|
-
#
|
|
669
|
+
# Helper methods
|
|
444
670
|
#
|
|
445
671
|
|
|
446
|
-
def
|
|
447
|
-
return
|
|
672
|
+
def _codeloc(self, block_only=False, context=None):
|
|
673
|
+
return CodeLocation(
|
|
674
|
+
self.block.addr,
|
|
675
|
+
None if block_only else self.stmt_idx,
|
|
676
|
+
ins_addr=None if block_only else self.ins_addr,
|
|
677
|
+
context=context,
|
|
678
|
+
block_idx=self.block.idx,
|
|
679
|
+
)
|
|
448
680
|
|
|
449
|
-
|
|
450
|
-
|
|
681
|
+
#
|
|
682
|
+
# Statements
|
|
683
|
+
#
|
|
451
684
|
|
|
452
|
-
def
|
|
453
|
-
|
|
685
|
+
def _process_stmts(self, whitelist: set[int] | None) -> list[StmtDataType]:
|
|
686
|
+
result = []
|
|
454
687
|
|
|
455
|
-
|
|
456
|
-
|
|
688
|
+
for stmt_idx, stmt in enumerate(self.block.statements):
|
|
689
|
+
if whitelist is not None and stmt_idx not in whitelist:
|
|
690
|
+
continue
|
|
691
|
+
|
|
692
|
+
self.stmt_idx = stmt_idx
|
|
693
|
+
self.ins_addr = stmt.ins_addr
|
|
694
|
+
result.append(self._stmt(stmt))
|
|
695
|
+
|
|
696
|
+
return result
|
|
697
|
+
|
|
698
|
+
def _stmt(self, stmt: ailment.statement.Statement) -> StmtDataType:
|
|
699
|
+
stmt_type_name = type(stmt).__name__
|
|
700
|
+
return self._stmt_handlers[stmt_type_name](stmt)
|
|
457
701
|
|
|
458
|
-
|
|
459
|
-
|
|
702
|
+
@abstractmethod
|
|
703
|
+
def _handle_stmt_Assignment(self, stmt: ailment.statement.Assignment) -> StmtDataType: ...
|
|
460
704
|
|
|
461
|
-
|
|
462
|
-
|
|
705
|
+
@abstractmethod
|
|
706
|
+
def _handle_stmt_Store(self, stmt: ailment.statement.Store) -> StmtDataType: ...
|
|
463
707
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
if expr_ is None:
|
|
467
|
-
return None
|
|
468
|
-
to_size = expr.result_size(self.tyenv)
|
|
469
|
-
if self._is_top(expr_):
|
|
470
|
-
return self._top(to_size)
|
|
708
|
+
@abstractmethod
|
|
709
|
+
def _handle_stmt_Jump(self, stmt: ailment.statement.Jump) -> StmtDataType: ...
|
|
471
710
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
# truncation
|
|
475
|
-
return expr_[to_size - 1 : 0]
|
|
476
|
-
if expr_.size() < to_size:
|
|
477
|
-
# extension
|
|
478
|
-
return claripy.ZeroExt(to_size - expr_.size(), expr_)
|
|
479
|
-
return expr_
|
|
711
|
+
@abstractmethod
|
|
712
|
+
def _handle_stmt_ConditionalJump(self, stmt: ailment.statement.ConditionalJump) -> StmtDataType: ...
|
|
480
713
|
|
|
481
|
-
|
|
714
|
+
@abstractmethod
|
|
715
|
+
def _handle_stmt_Call(self, stmt: ailment.statement.Call) -> StmtDataType: ...
|
|
716
|
+
|
|
717
|
+
@abstractmethod
|
|
718
|
+
def _handle_stmt_Return(self, stmt: ailment.statement.Return) -> StmtDataType: ...
|
|
719
|
+
|
|
720
|
+
@abstractmethod
|
|
721
|
+
def _handle_stmt_DirtyStatement(self, stmt: ailment.statement.DirtyStatement) -> StmtDataType: ...
|
|
722
|
+
|
|
723
|
+
@abstractmethod
|
|
724
|
+
def _handle_stmt_Label(self, stmt: ailment.statement.Label) -> StmtDataType: ...
|
|
482
725
|
|
|
483
726
|
#
|
|
484
|
-
#
|
|
727
|
+
# Expressions
|
|
485
728
|
#
|
|
486
729
|
|
|
487
|
-
def
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if expr_0 is None:
|
|
491
|
-
return None, None
|
|
492
|
-
if self._is_top(expr_0):
|
|
493
|
-
return None, self._top(expr_0.size())
|
|
730
|
+
def _expr(self, expr: ailment.Expression) -> DataType_co:
|
|
731
|
+
expr_type_name = type(expr).__name__
|
|
732
|
+
return self._expr_handlers[expr_type_name](expr)
|
|
494
733
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
return None, None
|
|
498
|
-
if self._is_top(expr_1):
|
|
499
|
-
return None, self._top(expr_0.size()) # always use the size of expr_0
|
|
734
|
+
def _handle_expr_Atom(self, expr: ailment.expression.Atom) -> DataType_co:
|
|
735
|
+
raise TypeError("We should never see raw Atoms")
|
|
500
736
|
|
|
501
|
-
|
|
737
|
+
@abstractmethod
|
|
738
|
+
def _handle_expr_Const(self, expr: ailment.expression.Const) -> DataType_co: ...
|
|
502
739
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
if args is None:
|
|
506
|
-
return r
|
|
507
|
-
expr_0, expr_1 = args
|
|
740
|
+
@abstractmethod
|
|
741
|
+
def _handle_expr_Tmp(self, expr: ailment.expression.Tmp) -> DataType_co: ...
|
|
508
742
|
|
|
509
|
-
|
|
510
|
-
|
|
743
|
+
@abstractmethod
|
|
744
|
+
def _handle_expr_VirtualVariable(self, expr: ailment.expression.VirtualVariable) -> DataType_co: ...
|
|
511
745
|
|
|
512
|
-
|
|
746
|
+
@abstractmethod
|
|
747
|
+
def _handle_expr_Phi(self, expr: ailment.expression.Phi) -> DataType_co: ...
|
|
513
748
|
|
|
514
|
-
def
|
|
515
|
-
|
|
516
|
-
if args is None:
|
|
517
|
-
return r
|
|
518
|
-
expr_0, expr_1 = args
|
|
749
|
+
def _handle_expr_Op(self, expr: ailment.expression.Op) -> DataType_co:
|
|
750
|
+
raise TypeError("We should never see raw Ops")
|
|
519
751
|
|
|
520
|
-
|
|
521
|
-
|
|
752
|
+
def _handle_expr_UnaryOp(self, expr: ailment.expression.UnaryOp) -> DataType_co:
|
|
753
|
+
return self._unop_handlers[expr.op](expr)
|
|
522
754
|
|
|
523
|
-
|
|
755
|
+
def _handle_expr_BinaryOp(self, expr: ailment.expression.BinaryOp) -> DataType_co:
|
|
756
|
+
return self._binop_handlers[expr.op](expr)
|
|
524
757
|
|
|
525
|
-
|
|
526
|
-
|
|
758
|
+
@abstractmethod
|
|
759
|
+
def _handle_expr_Convert(self, expr: ailment.expression.Convert) -> DataType_co: ...
|
|
527
760
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
expr_0 = self._expr(arg0)
|
|
531
|
-
if expr_0 is None:
|
|
532
|
-
return None
|
|
533
|
-
if self._is_top(expr_0):
|
|
534
|
-
return self._top(expr_0.size())
|
|
761
|
+
@abstractmethod
|
|
762
|
+
def _handle_expr_Reinterpret(self, expr: ailment.expression.Reinterpret) -> DataType_co: ...
|
|
535
763
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
except TypeError as e:
|
|
539
|
-
if self.l is not None:
|
|
540
|
-
self.l.exception(e)
|
|
541
|
-
return None
|
|
542
|
-
|
|
543
|
-
def _handle_Clz(self, expr):
|
|
544
|
-
arg0 = expr.args[0]
|
|
545
|
-
expr_0 = self._expr(arg0)
|
|
546
|
-
if expr_0 is None:
|
|
547
|
-
return None
|
|
548
|
-
if self._is_top(expr_0):
|
|
549
|
-
return self._top(expr_0.size())
|
|
550
|
-
return self._top(expr_0.size())
|
|
551
|
-
|
|
552
|
-
def _handle_Ctz(self, expr):
|
|
553
|
-
arg0 = expr.args[0]
|
|
554
|
-
expr_0 = self._expr(arg0)
|
|
555
|
-
if expr_0 is None:
|
|
556
|
-
return None
|
|
557
|
-
if self._is_top(expr_0):
|
|
558
|
-
return self._top(expr_0.size())
|
|
559
|
-
return self._top(expr_0.size())
|
|
560
|
-
|
|
561
|
-
def _handle_Add(self, expr):
|
|
562
|
-
args, r = self._binop_get_args(expr)
|
|
563
|
-
if args is None:
|
|
564
|
-
return r
|
|
565
|
-
expr_0, expr_1 = args
|
|
566
|
-
|
|
567
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
568
|
-
return self._top(expr_0.size())
|
|
569
|
-
|
|
570
|
-
return expr_0 + expr_1
|
|
571
|
-
|
|
572
|
-
def _handle_Sub(self, expr):
|
|
573
|
-
args, r = self._binop_get_args(expr)
|
|
574
|
-
if args is None:
|
|
575
|
-
return r
|
|
576
|
-
expr_0, expr_1 = args
|
|
577
|
-
|
|
578
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
579
|
-
return self._top(expr_0.size())
|
|
580
|
-
|
|
581
|
-
return expr_0 - expr_1
|
|
582
|
-
|
|
583
|
-
def _handle_Mul(self, expr):
|
|
584
|
-
args, r = self._binop_get_args(expr)
|
|
585
|
-
if args is None:
|
|
586
|
-
return r
|
|
587
|
-
expr_0, expr_1 = args
|
|
588
|
-
|
|
589
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
590
|
-
return self._top(expr_0.size())
|
|
591
|
-
|
|
592
|
-
return expr_0 * expr_1
|
|
593
|
-
|
|
594
|
-
def _handle_Mull(self, expr):
|
|
595
|
-
self._binop_get_args(expr)
|
|
596
|
-
return self._top(expr.result_size(self.tyenv))
|
|
597
|
-
|
|
598
|
-
def _handle_DivMod(self, expr):
|
|
599
|
-
args, r = self._binop_get_args(expr)
|
|
600
|
-
if args is None:
|
|
601
|
-
return r
|
|
602
|
-
expr_0, expr_1 = args
|
|
603
|
-
|
|
604
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
605
|
-
return self._top(expr.result_size(self.tyenv))
|
|
606
|
-
|
|
607
|
-
if expr_1.concrete and expr_1.concrete_value == 0:
|
|
608
|
-
return self._top(expr.result_size(self.tyenv))
|
|
609
|
-
|
|
610
|
-
signed = "U" in expr.op # Iop_DivModU64to32 vs Iop_DivMod
|
|
611
|
-
from_size = expr_0.size()
|
|
612
|
-
to_size = expr_1.size()
|
|
613
|
-
if signed:
|
|
614
|
-
quotient = expr_0.SDiv(claripy.SignExt(from_size - to_size, expr_1))
|
|
615
|
-
remainder = expr_0.SMod(claripy.SignExt(from_size - to_size, expr_1))
|
|
616
|
-
quotient_size = to_size
|
|
617
|
-
remainder_size = to_size
|
|
618
|
-
return claripy.Concat(
|
|
619
|
-
claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient)
|
|
620
|
-
)
|
|
621
|
-
quotient = expr_0 // claripy.ZeroExt(from_size - to_size, expr_1)
|
|
622
|
-
remainder = expr_0 % claripy.ZeroExt(from_size - to_size, expr_1)
|
|
623
|
-
quotient_size = to_size
|
|
624
|
-
remainder_size = to_size
|
|
625
|
-
return claripy.Concat(
|
|
626
|
-
claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient)
|
|
627
|
-
)
|
|
764
|
+
@abstractmethod
|
|
765
|
+
def _handle_expr_Load(self, expr: ailment.expression.Load) -> DataType_co: ...
|
|
628
766
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
if args is None:
|
|
632
|
-
return r
|
|
633
|
-
expr_0, expr_1 = args
|
|
767
|
+
@abstractmethod
|
|
768
|
+
def _handle_expr_Register(self, expr: ailment.expression.Register) -> DataType_co: ...
|
|
634
769
|
|
|
635
|
-
|
|
636
|
-
|
|
770
|
+
@abstractmethod
|
|
771
|
+
def _handle_expr_ITE(self, expr: ailment.expression.ITE) -> DataType_co: ...
|
|
637
772
|
|
|
638
|
-
|
|
639
|
-
|
|
773
|
+
@abstractmethod
|
|
774
|
+
def _handle_expr_Call(self, expr: ailment.statement.Call) -> DataType_co: ...
|
|
640
775
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
except ZeroDivisionError:
|
|
644
|
-
return self._top(expr.result_size(self.tyenv))
|
|
776
|
+
@abstractmethod
|
|
777
|
+
def _handle_expr_DirtyExpression(self, expr: ailment.expression.DirtyExpression) -> DataType_co: ...
|
|
645
778
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
if args is None:
|
|
649
|
-
return r
|
|
650
|
-
expr_0, expr_1 = args
|
|
779
|
+
@abstractmethod
|
|
780
|
+
def _handle_expr_VEXCCallExpression(self, expr: ailment.expression.VEXCCallExpression) -> DataType_co: ...
|
|
651
781
|
|
|
652
|
-
|
|
653
|
-
|
|
782
|
+
@abstractmethod
|
|
783
|
+
def _handle_expr_MultiStatementExpression(
|
|
784
|
+
self, expr: ailment.expression.MultiStatementExpression
|
|
785
|
+
) -> DataType_co: ...
|
|
654
786
|
|
|
655
|
-
|
|
656
|
-
|
|
787
|
+
@abstractmethod
|
|
788
|
+
def _handle_expr_BasePointerOffset(self, expr: ailment.expression.BasePointerOffset) -> DataType_co: ...
|
|
657
789
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
except ZeroDivisionError:
|
|
661
|
-
return self._top(expr_0.size())
|
|
790
|
+
@abstractmethod
|
|
791
|
+
def _handle_expr_StackBaseOffset(self, expr: ailment.expression.StackBaseOffset) -> DataType_co: ...
|
|
662
792
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
return r
|
|
667
|
-
expr_0, expr_1 = args
|
|
793
|
+
#
|
|
794
|
+
# UnOps
|
|
795
|
+
#
|
|
668
796
|
|
|
669
|
-
|
|
670
|
-
|
|
797
|
+
@abstractmethod
|
|
798
|
+
def _handle_unop_Not(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
671
799
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
except TypeError as e:
|
|
675
|
-
if self.l is not None:
|
|
676
|
-
self.l.warning(e)
|
|
677
|
-
return None
|
|
678
|
-
|
|
679
|
-
def _handle_Shl(self, expr):
|
|
680
|
-
args, r = self._binop_get_args(expr)
|
|
681
|
-
if args is None:
|
|
682
|
-
return r
|
|
683
|
-
expr_0, expr_1 = args
|
|
684
|
-
|
|
685
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
686
|
-
return self._top(expr_0.size())
|
|
687
|
-
|
|
688
|
-
if isinstance(expr_1, claripy.ast.Base) and expr_1.op == "BVV":
|
|
689
|
-
# convert it to an int when possible
|
|
690
|
-
expr_1 = expr_1.args[0]
|
|
691
|
-
else:
|
|
692
|
-
# make sure the sizes are the same - VEX does not care about it
|
|
693
|
-
if expr_1.size() < expr_0.size():
|
|
694
|
-
expr_1 = claripy.ZeroExt(expr_0.size() - expr_1.size(), expr_1)
|
|
695
|
-
elif expr_1.size() > expr_0.size():
|
|
696
|
-
expr_1 = claripy.Extract(expr_0.size() - 1, 0, expr_1)
|
|
697
|
-
|
|
698
|
-
return expr_0 << expr_1
|
|
699
|
-
|
|
700
|
-
def _handle_Shr(self, expr):
|
|
701
|
-
args, r = self._binop_get_args(expr)
|
|
702
|
-
if args is None:
|
|
703
|
-
return r
|
|
704
|
-
expr_0, expr_1 = args
|
|
705
|
-
|
|
706
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
707
|
-
return self._top(expr_0.size())
|
|
708
|
-
|
|
709
|
-
if isinstance(expr_1, claripy.ast.Base) and expr_1.op == "BVV":
|
|
710
|
-
# convert it to an int when possible
|
|
711
|
-
expr_1 = expr_1.args[0]
|
|
712
|
-
else:
|
|
713
|
-
# make sure the sizes are the same - VEX does not care about it
|
|
714
|
-
if expr_1.size() < expr_0.size():
|
|
715
|
-
expr_1 = claripy.ZeroExt(expr_0.size() - expr_1.size(), expr_1)
|
|
716
|
-
elif expr_1.size() > expr_0.size():
|
|
717
|
-
expr_1 = claripy.Extract(expr_0.size() - 1, 0, expr_1)
|
|
718
|
-
|
|
719
|
-
return claripy.LShR(expr_0, expr_1)
|
|
720
|
-
|
|
721
|
-
def _handle_Sar(self, expr):
|
|
722
|
-
# EDG asks: is this right?
|
|
723
|
-
args, r = self._binop_get_args(expr)
|
|
724
|
-
if args is None:
|
|
725
|
-
return r
|
|
726
|
-
expr_0, expr_1 = args
|
|
727
|
-
|
|
728
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
729
|
-
return self._top(expr_0.size())
|
|
730
|
-
|
|
731
|
-
if isinstance(expr_1, claripy.ast.Base) and expr_1.op == "BVV":
|
|
732
|
-
# convert it to an int when possible
|
|
733
|
-
expr_1 = expr_1.args[0]
|
|
734
|
-
else:
|
|
735
|
-
# make sure the sizes are the same - VEX does not care about it
|
|
736
|
-
if expr_1.size() < expr_0.size():
|
|
737
|
-
expr_1 = claripy.ZeroExt(expr_0.size() - expr_1.size(), expr_1)
|
|
738
|
-
elif expr_1.size() > expr_0.size():
|
|
739
|
-
expr_1 = claripy.Extract(expr_0.size() - 1, 0, expr_1)
|
|
740
|
-
|
|
741
|
-
return expr_0 >> expr_1
|
|
742
|
-
|
|
743
|
-
def _handle_CmpEQ(self, expr):
|
|
744
|
-
args, r = self._binop_get_args(expr)
|
|
745
|
-
if args is None:
|
|
746
|
-
return r
|
|
747
|
-
expr_0, expr_1 = args
|
|
748
|
-
|
|
749
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
750
|
-
return self._top(1)
|
|
751
|
-
|
|
752
|
-
return expr_0 == expr_1
|
|
753
|
-
|
|
754
|
-
def _handle_CmpNE(self, expr):
|
|
755
|
-
args, r = self._binop_get_args(expr)
|
|
756
|
-
if args is None:
|
|
757
|
-
return r
|
|
758
|
-
expr_0, expr_1 = args
|
|
759
|
-
|
|
760
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
761
|
-
return self._top(1)
|
|
762
|
-
|
|
763
|
-
return expr_0 != expr_1
|
|
764
|
-
|
|
765
|
-
def _handle_CmpLE(self, expr):
|
|
766
|
-
args, r = self._binop_get_args(expr)
|
|
767
|
-
if args is None:
|
|
768
|
-
return r
|
|
769
|
-
expr_0, expr_1 = args
|
|
770
|
-
|
|
771
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
772
|
-
return self._top(1)
|
|
773
|
-
|
|
774
|
-
return expr_0 <= expr_1
|
|
775
|
-
|
|
776
|
-
def _handle_CmpGE(self, expr):
|
|
777
|
-
args, r = self._binop_get_args(expr)
|
|
778
|
-
if args is None:
|
|
779
|
-
return r
|
|
780
|
-
expr_0, expr_1 = args
|
|
781
|
-
|
|
782
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
783
|
-
return self._top(1)
|
|
784
|
-
|
|
785
|
-
return expr_0 >= expr_1
|
|
786
|
-
|
|
787
|
-
def _handle_CmpLT(self, expr):
|
|
788
|
-
args, r = self._binop_get_args(expr)
|
|
789
|
-
if args is None:
|
|
790
|
-
return r
|
|
791
|
-
expr_0, expr_1 = args
|
|
792
|
-
|
|
793
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
794
|
-
return self._top(1)
|
|
795
|
-
|
|
796
|
-
return expr_0 < expr_1
|
|
800
|
+
@abstractmethod
|
|
801
|
+
def _handle_unop_Neg(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
797
802
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
if args is None:
|
|
801
|
-
return r
|
|
802
|
-
expr_0, expr_1 = args
|
|
803
|
-
|
|
804
|
-
if self._is_top(expr_0) or self._is_top(expr_1):
|
|
805
|
-
return self._top(1)
|
|
806
|
-
|
|
807
|
-
return expr_0 > expr_1
|
|
803
|
+
@abstractmethod
|
|
804
|
+
def _handle_unop_BitwiseNeg(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
808
805
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
return self._top(expr.result_size(self.tyenv))
|
|
806
|
+
@abstractmethod
|
|
807
|
+
def _handle_unop_Reference(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
812
808
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
return self._top(expr.result_size(self.tyenv))
|
|
809
|
+
@abstractmethod
|
|
810
|
+
def _handle_unop_Dereference(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
816
811
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
return self._top(expr.result_size(self.tyenv))
|
|
812
|
+
@abstractmethod
|
|
813
|
+
def _handle_unop_Clz(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
820
814
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
return self._top(expr.result_size(self.tyenv))
|
|
815
|
+
@abstractmethod
|
|
816
|
+
def _handle_unop_Ctz(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
824
817
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
return self._top(expr.result_size(self.tyenv))
|
|
818
|
+
@abstractmethod
|
|
819
|
+
def _handle_unop_GetMSBs(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
828
820
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
return self._top(expr.result_size(self.tyenv))
|
|
821
|
+
@abstractmethod
|
|
822
|
+
def _handle_unop_unpack(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
832
823
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
return None
|
|
824
|
+
@abstractmethod
|
|
825
|
+
def _handle_unop_Sqrt(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
836
826
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
if args is None:
|
|
840
|
-
if r is not None:
|
|
841
|
-
# the size of r should be 32 but we need to return a 64-bit expression
|
|
842
|
-
assert r.size() == 32
|
|
843
|
-
r = claripy.ZeroExt(32, r)
|
|
844
|
-
return r
|
|
827
|
+
@abstractmethod
|
|
828
|
+
def _handle_unop_RSqrtEst(self, expr: ailment.expression.UnaryOp) -> DataType_co: ...
|
|
845
829
|
|
|
846
|
-
|
|
830
|
+
#
|
|
831
|
+
# BinOps
|
|
832
|
+
#
|
|
833
|
+
@abstractmethod
|
|
834
|
+
def _handle_binop_Add(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
847
835
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return self._top(expr.result_size(self.tyenv))
|
|
836
|
+
@abstractmethod
|
|
837
|
+
def _handle_binop_AddF(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
851
838
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
return self._top(expr.result_size(self.tyenv))
|
|
839
|
+
@abstractmethod
|
|
840
|
+
def _handle_binop_AddV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
855
841
|
|
|
842
|
+
@abstractmethod
|
|
843
|
+
def _handle_binop_Sub(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
856
844
|
|
|
857
|
-
|
|
858
|
-
|
|
845
|
+
@abstractmethod
|
|
846
|
+
def _handle_binop_SubF(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
847
|
+
|
|
848
|
+
@abstractmethod
|
|
849
|
+
def _handle_binop_SubV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
850
|
+
|
|
851
|
+
@abstractmethod
|
|
852
|
+
def _handle_binop_Mul(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
853
|
+
|
|
854
|
+
@abstractmethod
|
|
855
|
+
def _handle_binop_Mull(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
856
|
+
|
|
857
|
+
@abstractmethod
|
|
858
|
+
def _handle_binop_MulF(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
859
|
+
|
|
860
|
+
@abstractmethod
|
|
861
|
+
def _handle_binop_MulV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
862
|
+
|
|
863
|
+
@abstractmethod
|
|
864
|
+
def _handle_binop_MulHiV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
865
|
+
|
|
866
|
+
@abstractmethod
|
|
867
|
+
def _handle_binop_Div(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
868
|
+
|
|
869
|
+
@abstractmethod
|
|
870
|
+
def _handle_binop_DivF(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
871
|
+
|
|
872
|
+
@abstractmethod
|
|
873
|
+
def _handle_binop_DivV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
874
|
+
|
|
875
|
+
@abstractmethod
|
|
876
|
+
def _handle_binop_Mod(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
877
|
+
|
|
878
|
+
@abstractmethod
|
|
879
|
+
def _handle_binop_Xor(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
880
|
+
|
|
881
|
+
@abstractmethod
|
|
882
|
+
def _handle_binop_And(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
883
|
+
|
|
884
|
+
@abstractmethod
|
|
885
|
+
def _handle_binop_LogicalAnd(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
886
|
+
|
|
887
|
+
@abstractmethod
|
|
888
|
+
def _handle_binop_Or(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
889
|
+
|
|
890
|
+
@abstractmethod
|
|
891
|
+
def _handle_binop_LogicalOr(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
892
|
+
|
|
893
|
+
@abstractmethod
|
|
894
|
+
def _handle_binop_Shl(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
895
|
+
|
|
896
|
+
@abstractmethod
|
|
897
|
+
def _handle_binop_Shr(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
898
|
+
|
|
899
|
+
@abstractmethod
|
|
900
|
+
def _handle_binop_Sar(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
901
|
+
|
|
902
|
+
@abstractmethod
|
|
903
|
+
def _handle_binop_CmpF(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
904
|
+
|
|
905
|
+
@abstractmethod
|
|
906
|
+
def _handle_binop_CmpEQ(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
907
|
+
|
|
908
|
+
@abstractmethod
|
|
909
|
+
def _handle_binop_CmpNE(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
910
|
+
|
|
911
|
+
@abstractmethod
|
|
912
|
+
def _handle_binop_CmpLT(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
913
|
+
|
|
914
|
+
@abstractmethod
|
|
915
|
+
def _handle_binop_CmpLE(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
916
|
+
|
|
917
|
+
@abstractmethod
|
|
918
|
+
def _handle_binop_CmpGT(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
919
|
+
|
|
920
|
+
@abstractmethod
|
|
921
|
+
def _handle_binop_CmpGE(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
922
|
+
|
|
923
|
+
@abstractmethod
|
|
924
|
+
def _handle_binop_Concat(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
925
|
+
|
|
926
|
+
@abstractmethod
|
|
927
|
+
def _handle_binop_Ror(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
928
|
+
|
|
929
|
+
@abstractmethod
|
|
930
|
+
def _handle_binop_Rol(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
931
|
+
|
|
932
|
+
@abstractmethod
|
|
933
|
+
def _handle_binop_Carry(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
934
|
+
|
|
935
|
+
@abstractmethod
|
|
936
|
+
def _handle_binop_SCarry(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
937
|
+
|
|
938
|
+
@abstractmethod
|
|
939
|
+
def _handle_binop_SBorrow(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
940
|
+
|
|
941
|
+
@abstractmethod
|
|
942
|
+
def _handle_binop_InterleaveLOV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
943
|
+
|
|
944
|
+
@abstractmethod
|
|
945
|
+
def _handle_binop_InterleaveHIV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
946
|
+
|
|
947
|
+
@abstractmethod
|
|
948
|
+
def _handle_binop_CasCmpEQ(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
949
|
+
|
|
950
|
+
@abstractmethod
|
|
951
|
+
def _handle_binop_CasCmpNE(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
952
|
+
|
|
953
|
+
@abstractmethod
|
|
954
|
+
def _handle_binop_ExpCmpNE(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
955
|
+
|
|
956
|
+
@abstractmethod
|
|
957
|
+
def _handle_binop_SarNV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
958
|
+
|
|
959
|
+
@abstractmethod
|
|
960
|
+
def _handle_binop_ShrNV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
961
|
+
|
|
962
|
+
@abstractmethod
|
|
963
|
+
def _handle_binop_ShlNV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
964
|
+
|
|
965
|
+
@abstractmethod
|
|
966
|
+
def _handle_binop_CmpEQV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
967
|
+
|
|
968
|
+
@abstractmethod
|
|
969
|
+
def _handle_binop_CmpNEV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
970
|
+
|
|
971
|
+
@abstractmethod
|
|
972
|
+
def _handle_binop_CmpGEV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
973
|
+
|
|
974
|
+
@abstractmethod
|
|
975
|
+
def _handle_binop_CmpGTV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
976
|
+
|
|
977
|
+
@abstractmethod
|
|
978
|
+
def _handle_binop_CmpLEV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
979
|
+
|
|
980
|
+
@abstractmethod
|
|
981
|
+
def _handle_binop_CmpLTV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
982
|
+
|
|
983
|
+
@abstractmethod
|
|
984
|
+
def _handle_binop_MinV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
985
|
+
|
|
986
|
+
@abstractmethod
|
|
987
|
+
def _handle_binop_MaxV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
988
|
+
|
|
989
|
+
@abstractmethod
|
|
990
|
+
def _handle_binop_QAddV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
991
|
+
|
|
992
|
+
@abstractmethod
|
|
993
|
+
def _handle_binop_QNarrowBinV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
994
|
+
|
|
995
|
+
@abstractmethod
|
|
996
|
+
def _handle_binop_PermV(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
997
|
+
|
|
998
|
+
@abstractmethod
|
|
999
|
+
def _handle_binop_Set(self, expr: ailment.expression.BinaryOp) -> DataType_co: ...
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
class SimEngineNostmtAIL(
|
|
1003
|
+
Generic[StateType, DataType_co, StmtDataType, ResultType],
|
|
1004
|
+
SimEngineLightAIL[StateType, DataType_co, StmtDataType | None, ResultType],
|
|
1005
|
+
):
|
|
859
1006
|
"""
|
|
860
|
-
A
|
|
1007
|
+
A base class of SimEngineLightAIL that has default handlers for statements if they just need to return None, so you
|
|
1008
|
+
don't have to implement every single statement handler as ``return None``.
|
|
861
1009
|
"""
|
|
862
1010
|
|
|
863
|
-
def
|
|
864
|
-
|
|
865
|
-
): # pylint:disable=arguments-differ
|
|
866
|
-
self.tmps = {}
|
|
867
|
-
self.block: ailment.Block = block
|
|
868
|
-
self.state = state
|
|
869
|
-
if self.arch is None:
|
|
870
|
-
# we only access state.arch if the arch of this engine itself is not previously configured
|
|
871
|
-
self.arch = state.arch
|
|
1011
|
+
def _handle_stmt_Assignment(self, stmt) -> StmtDataType | None:
|
|
1012
|
+
pass
|
|
872
1013
|
|
|
873
|
-
|
|
1014
|
+
def _handle_stmt_Store(self, stmt) -> StmtDataType | None:
|
|
1015
|
+
pass
|
|
874
1016
|
|
|
875
|
-
|
|
876
|
-
|
|
1017
|
+
def _handle_stmt_Jump(self, stmt) -> StmtDataType | None:
|
|
1018
|
+
pass
|
|
877
1019
|
|
|
878
|
-
def
|
|
879
|
-
|
|
880
|
-
whitelist = set(whitelist)
|
|
1020
|
+
def _handle_stmt_ConditionalJump(self, stmt) -> StmtDataType | None:
|
|
1021
|
+
pass
|
|
881
1022
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
continue
|
|
1023
|
+
def _handle_stmt_Call(self, stmt) -> StmtDataType | None:
|
|
1024
|
+
pass
|
|
885
1025
|
|
|
886
|
-
|
|
887
|
-
|
|
1026
|
+
def _handle_stmt_Return(self, stmt) -> StmtDataType | None:
|
|
1027
|
+
pass
|
|
888
1028
|
|
|
889
|
-
|
|
1029
|
+
def _handle_stmt_DirtyStatement(self, stmt) -> StmtDataType | None:
|
|
1030
|
+
pass
|
|
890
1031
|
|
|
891
|
-
def
|
|
892
|
-
|
|
893
|
-
if isinstance(expr, ailment.Stmt.Call):
|
|
894
|
-
# Call can be both an expression and a statement. Add a suffix to make sure we are working on the expression
|
|
895
|
-
# variant.
|
|
896
|
-
expr_type_name += "Expr"
|
|
897
|
-
|
|
898
|
-
h = None
|
|
899
|
-
handler = f"_handle_{expr_type_name}"
|
|
900
|
-
if hasattr(self, handler):
|
|
901
|
-
h = getattr(self, handler)
|
|
902
|
-
|
|
903
|
-
if h is None:
|
|
904
|
-
handler = f"_ail_handle_{expr_type_name}"
|
|
905
|
-
if hasattr(self, handler):
|
|
906
|
-
h = getattr(self, handler)
|
|
907
|
-
|
|
908
|
-
if h is not None:
|
|
909
|
-
return h(expr)
|
|
910
|
-
if self.l is not None:
|
|
911
|
-
self.l.warning("Unsupported expression type %s.", type(expr).__name__)
|
|
912
|
-
return None
|
|
1032
|
+
def _handle_stmt_Label(self, stmt) -> StmtDataType | None:
|
|
1033
|
+
pass
|
|
913
1034
|
|
|
914
|
-
#
|
|
915
|
-
# Helper methods
|
|
916
|
-
#
|
|
917
1035
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
1036
|
+
class SimEngineNoexprAIL(
|
|
1037
|
+
Generic[StateType, DataType_co, StmtDataType, ResultType],
|
|
1038
|
+
SimEngineLightAIL[StateType, DataType_co | None, StmtDataType, ResultType],
|
|
1039
|
+
):
|
|
1040
|
+
"""
|
|
1041
|
+
A base class of SimEngineLightAIL that has default handlers for expressions if they just need to return None, so you
|
|
1042
|
+
don't have to implement every single expression handler as ``return None``.
|
|
1043
|
+
"""
|
|
926
1044
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
#
|
|
1045
|
+
def _handle_expr_Atom(self, expr: ailment.expression.Atom) -> DataType_co | None:
|
|
1046
|
+
pass
|
|
930
1047
|
|
|
931
|
-
def
|
|
932
|
-
|
|
933
|
-
if hasattr(self, handler):
|
|
934
|
-
return getattr(self, handler)(stmt)
|
|
1048
|
+
def _handle_expr_Const(self, expr: ailment.expression.Const) -> DataType_co | None:
|
|
1049
|
+
pass
|
|
935
1050
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
if hasattr(self, old_handler):
|
|
939
|
-
return getattr(self, old_handler)(stmt)
|
|
1051
|
+
def _handle_expr_Tmp(self, expr: ailment.expression.Tmp) -> DataType_co | None:
|
|
1052
|
+
pass
|
|
940
1053
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1054
|
+
def _handle_expr_VirtualVariable(self, expr: ailment.expression.VirtualVariable) -> DataType_co | None:
|
|
1055
|
+
pass
|
|
1056
|
+
|
|
1057
|
+
def _handle_expr_Phi(self, expr: ailment.expression.Phi) -> DataType_co | None:
|
|
1058
|
+
pass
|
|
944
1059
|
|
|
945
|
-
def
|
|
1060
|
+
def _handle_expr_Convert(self, expr: ailment.expression.Convert) -> DataType_co | None:
|
|
946
1061
|
pass
|
|
947
1062
|
|
|
948
|
-
def
|
|
1063
|
+
def _handle_expr_Reinterpret(self, expr: ailment.expression.Reinterpret) -> DataType_co | None:
|
|
949
1064
|
pass
|
|
950
1065
|
|
|
951
|
-
def
|
|
1066
|
+
def _handle_expr_Load(self, expr: ailment.expression.Load) -> DataType_co | None:
|
|
952
1067
|
pass
|
|
953
1068
|
|
|
954
|
-
def
|
|
1069
|
+
def _handle_expr_Register(self, expr: ailment.expression.Register) -> DataType_co | None:
|
|
955
1070
|
pass
|
|
956
1071
|
|
|
957
|
-
def
|
|
1072
|
+
def _handle_expr_ITE(self, expr: ailment.expression.ITE) -> DataType_co | None:
|
|
958
1073
|
pass
|
|
959
1074
|
|
|
960
|
-
def
|
|
961
|
-
|
|
1075
|
+
def _handle_expr_Call(self, expr: ailment.statement.Call) -> DataType_co | None:
|
|
1076
|
+
pass
|
|
962
1077
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
#
|
|
1078
|
+
def _handle_expr_DirtyExpression(self, expr: ailment.expression.DirtyExpression) -> DataType_co | None:
|
|
1079
|
+
pass
|
|
966
1080
|
|
|
967
|
-
def
|
|
968
|
-
|
|
1081
|
+
def _handle_expr_VEXCCallExpression(self, expr: ailment.expression.VEXCCallExpression) -> DataType_co | None:
|
|
1082
|
+
pass
|
|
969
1083
|
|
|
970
|
-
def
|
|
971
|
-
|
|
1084
|
+
def _handle_expr_MultiStatementExpression(
|
|
1085
|
+
self, expr: ailment.expression.MultiStatementExpression
|
|
1086
|
+
) -> DataType_co | None:
|
|
1087
|
+
pass
|
|
972
1088
|
|
|
973
|
-
def
|
|
974
|
-
|
|
1089
|
+
def _handle_expr_BasePointerOffset(self, expr: ailment.expression.BasePointerOffset) -> DataType_co | None:
|
|
1090
|
+
pass
|
|
975
1091
|
|
|
976
|
-
def
|
|
977
|
-
|
|
1092
|
+
def _handle_expr_StackBaseOffset(self, expr: ailment.expression.StackBaseOffset) -> DataType_co | None:
|
|
1093
|
+
pass
|
|
978
1094
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
except KeyError:
|
|
982
|
-
return None
|
|
983
|
-
|
|
984
|
-
def _ail_handle_Load(self, expr: ailment.Expr.Load):
|
|
985
|
-
self._expr(expr.addr)
|
|
986
|
-
return expr
|
|
987
|
-
|
|
988
|
-
def _ail_handle_CallExpr(self, expr: ailment.Stmt.Call):
|
|
989
|
-
if not isinstance(expr.target, str):
|
|
990
|
-
self._expr(expr.target)
|
|
991
|
-
return expr
|
|
992
|
-
|
|
993
|
-
def _ail_handle_Reinterpret(self, expr: ailment.Expr.Reinterpret):
|
|
994
|
-
arg = self._expr(expr.operand)
|
|
995
|
-
|
|
996
|
-
if isinstance(arg, int) and (
|
|
997
|
-
expr.from_bits == 32 and expr.from_type == "I" and expr.to_bits == 32 and expr.to_type == "F"
|
|
998
|
-
):
|
|
999
|
-
# int -> float
|
|
1000
|
-
b = struct.pack("<I", arg)
|
|
1001
|
-
return struct.unpack("<f", b)[0]
|
|
1002
|
-
if (
|
|
1003
|
-
isinstance(arg, float)
|
|
1004
|
-
and expr.from_bits == 32
|
|
1005
|
-
and expr.from_type == "F"
|
|
1006
|
-
and expr.to_bits == 32
|
|
1007
|
-
and expr.to_type == "I"
|
|
1008
|
-
):
|
|
1009
|
-
# float -> int
|
|
1010
|
-
b = struct.pack("<f", arg)
|
|
1011
|
-
return struct.unpack("<I", b)[0]
|
|
1012
|
-
|
|
1013
|
-
return expr
|
|
1014
|
-
|
|
1015
|
-
def _ail_handle_DirtyExpression(self, expr: ailment.Expr.DirtyExpression):
|
|
1016
|
-
for operand in expr.operands:
|
|
1017
|
-
self._expr(operand)
|
|
1018
|
-
if expr.guard is not None:
|
|
1019
|
-
self._expr(expr.guard)
|
|
1020
|
-
if expr.maddr is not None:
|
|
1021
|
-
self._expr(expr.maddr)
|
|
1022
|
-
return expr
|
|
1023
|
-
|
|
1024
|
-
def _ail_handle_UnaryOp(self, expr):
|
|
1025
|
-
handler_name = f"_handle_{expr.op}"
|
|
1026
|
-
try:
|
|
1027
|
-
handler = getattr(self, handler_name)
|
|
1028
|
-
except AttributeError:
|
|
1029
|
-
handler_name = f"_ail_handle_{expr.op}"
|
|
1030
|
-
try:
|
|
1031
|
-
handler = getattr(self, handler_name)
|
|
1032
|
-
except AttributeError:
|
|
1033
|
-
if self.l is not None:
|
|
1034
|
-
self.l.warning("Unsupported UnaryOp %s.", expr.op)
|
|
1035
|
-
return None
|
|
1036
|
-
|
|
1037
|
-
return handler(expr)
|
|
1038
|
-
|
|
1039
|
-
def _ail_handle_BinaryOp(self, expr):
|
|
1040
|
-
handler_name = f"_handle_{expr.op}"
|
|
1041
|
-
try:
|
|
1042
|
-
handler = getattr(self, handler_name)
|
|
1043
|
-
except AttributeError:
|
|
1044
|
-
handler_name = f"_ail_handle_{expr.op}"
|
|
1045
|
-
try:
|
|
1046
|
-
handler = getattr(self, handler_name)
|
|
1047
|
-
except AttributeError:
|
|
1048
|
-
if self.l is not None:
|
|
1049
|
-
self.l.warning("Unsupported BinaryOp %s.", expr.op)
|
|
1050
|
-
return None
|
|
1051
|
-
|
|
1052
|
-
return handler(expr)
|
|
1053
|
-
|
|
1054
|
-
def _ail_handle_TernaryOp(self, expr):
|
|
1055
|
-
handler_name = f"_handle_{expr.op}"
|
|
1056
|
-
try:
|
|
1057
|
-
handler = getattr(self, handler_name)
|
|
1058
|
-
except AttributeError:
|
|
1059
|
-
handler_name = f"_ail_handle_{expr.op}"
|
|
1060
|
-
try:
|
|
1061
|
-
handler = getattr(self, handler_name)
|
|
1062
|
-
except AttributeError:
|
|
1063
|
-
if self.l is not None:
|
|
1064
|
-
self.l.warning("Unsupported Ternary %s.", expr.op)
|
|
1065
|
-
return None
|
|
1066
|
-
|
|
1067
|
-
return handler(expr)
|
|
1095
|
+
def _handle_unop_Not(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1096
|
+
pass
|
|
1068
1097
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
#
|
|
1098
|
+
def _handle_unop_Neg(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1099
|
+
pass
|
|
1072
1100
|
|
|
1073
|
-
def
|
|
1074
|
-
|
|
1101
|
+
def _handle_unop_BitwiseNeg(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1102
|
+
pass
|
|
1075
1103
|
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
if expr_0 is None:
|
|
1079
|
-
expr_0 = arg0
|
|
1080
|
-
if expr_1 is None:
|
|
1081
|
-
expr_1 = arg1
|
|
1104
|
+
def _handle_unop_Reference(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1105
|
+
pass
|
|
1082
1106
|
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
if expr_0.value == expr_1.value:
|
|
1086
|
-
return ailment.Expr.Const(None, None, 1, 1)
|
|
1087
|
-
return ailment.Expr.Const(None, None, 0, 1)
|
|
1088
|
-
except TypeError:
|
|
1089
|
-
pass
|
|
1090
|
-
return ailment.Expr.BinaryOp(expr.idx, "CmpEQ", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1091
|
-
|
|
1092
|
-
def _ail_handle_CmpNE(self, expr):
|
|
1093
|
-
arg0, arg1 = expr.operands
|
|
1094
|
-
|
|
1095
|
-
expr_0 = self._expr(arg0)
|
|
1096
|
-
expr_1 = self._expr(arg1)
|
|
1097
|
-
if expr_0 is None:
|
|
1098
|
-
expr_0 = arg0
|
|
1099
|
-
if expr_1 is None:
|
|
1100
|
-
expr_1 = arg1
|
|
1107
|
+
def _handle_unop_Dereference(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1108
|
+
pass
|
|
1101
1109
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if expr_0.value != expr_1.value:
|
|
1105
|
-
return ailment.Expr.Const(None, None, 1, 1)
|
|
1106
|
-
return ailment.Expr.Const(None, None, 0, 1)
|
|
1107
|
-
except TypeError:
|
|
1108
|
-
pass
|
|
1109
|
-
return ailment.Expr.BinaryOp(expr.idx, "CmpNE", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1110
|
-
|
|
1111
|
-
def _ail_handle_CmpLT(self, expr):
|
|
1112
|
-
arg0, arg1 = expr.operands
|
|
1113
|
-
|
|
1114
|
-
expr_0 = self._expr(arg0)
|
|
1115
|
-
expr_1 = self._expr(arg1)
|
|
1116
|
-
if expr_0 is None:
|
|
1117
|
-
expr_0 = arg0
|
|
1118
|
-
if expr_1 is None:
|
|
1119
|
-
expr_1 = arg1
|
|
1110
|
+
def _handle_unop_GetMSBs(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1111
|
+
pass
|
|
1120
1112
|
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
if expr_0.value < expr_1.value:
|
|
1124
|
-
return ailment.Expr.Const(None, None, 1, 1)
|
|
1125
|
-
return ailment.Expr.Const(None, None, 0, 1)
|
|
1126
|
-
except TypeError:
|
|
1127
|
-
pass
|
|
1128
|
-
return ailment.Expr.BinaryOp(expr.idx, "CmpLT", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1129
|
-
|
|
1130
|
-
def _ail_handle_Add(self, expr):
|
|
1131
|
-
arg0, arg1 = expr.operands
|
|
1132
|
-
|
|
1133
|
-
expr_0 = self._expr(arg0)
|
|
1134
|
-
expr_1 = self._expr(arg1)
|
|
1135
|
-
if expr_0 is None:
|
|
1136
|
-
expr_0 = arg0
|
|
1137
|
-
if expr_1 is None:
|
|
1138
|
-
expr_1 = arg1
|
|
1113
|
+
def _handle_unop_unpack(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1114
|
+
pass
|
|
1139
1115
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
except TypeError:
|
|
1143
|
-
return ailment.Expr.BinaryOp(
|
|
1144
|
-
expr.idx,
|
|
1145
|
-
"Add",
|
|
1146
|
-
[expr_0, expr_1],
|
|
1147
|
-
expr.signed,
|
|
1148
|
-
floating_point=expr.floating_point,
|
|
1149
|
-
rounding_mode=expr.rounding_mode,
|
|
1150
|
-
**expr.tags,
|
|
1151
|
-
)
|
|
1152
|
-
|
|
1153
|
-
def _ail_handle_Sub(self, expr):
|
|
1154
|
-
arg0, arg1 = expr.operands
|
|
1155
|
-
|
|
1156
|
-
expr_0 = self._expr(arg0) if not isinstance(arg0, claripy.ast.Base) else arg0
|
|
1157
|
-
expr_1 = self._expr(arg1) if not isinstance(arg1, claripy.ast.Base) else self._expr(arg1)
|
|
1158
|
-
|
|
1159
|
-
if expr_0 is None:
|
|
1160
|
-
expr_0 = arg0
|
|
1161
|
-
if expr_1 is None:
|
|
1162
|
-
expr_1 = arg1
|
|
1116
|
+
def _handle_unop_RSqrtEst(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1117
|
+
pass
|
|
1163
1118
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
except TypeError:
|
|
1167
|
-
return ailment.Expr.BinaryOp(
|
|
1168
|
-
expr.idx,
|
|
1169
|
-
"Sub",
|
|
1170
|
-
[expr_0, expr_1],
|
|
1171
|
-
expr.signed,
|
|
1172
|
-
floating_point=expr.floating_point,
|
|
1173
|
-
rounding_mode=expr.rounding_mode,
|
|
1174
|
-
**expr.tags,
|
|
1175
|
-
)
|
|
1176
|
-
|
|
1177
|
-
def _ail_handle_Div(self, expr):
|
|
1178
|
-
arg0, arg1 = expr.operands
|
|
1179
|
-
|
|
1180
|
-
expr_0 = self._expr(arg0)
|
|
1181
|
-
expr_1 = self._expr(arg1)
|
|
1182
|
-
|
|
1183
|
-
if expr_0 is None:
|
|
1184
|
-
expr_0 = arg0
|
|
1185
|
-
if expr_1 is None:
|
|
1186
|
-
expr_1 = arg1
|
|
1119
|
+
def _handle_binop_Add(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1120
|
+
pass
|
|
1187
1121
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
except TypeError:
|
|
1191
|
-
return ailment.Expr.BinaryOp(
|
|
1192
|
-
expr.idx,
|
|
1193
|
-
"Div",
|
|
1194
|
-
[expr_0, expr_1],
|
|
1195
|
-
expr.signed,
|
|
1196
|
-
floating_point=expr.floating_point,
|
|
1197
|
-
rounding_mode=expr.rounding_mode,
|
|
1198
|
-
**expr.tags,
|
|
1199
|
-
)
|
|
1200
|
-
|
|
1201
|
-
def _ail_handle_DivMod(self, expr):
|
|
1202
|
-
arg0, arg1 = expr.operands
|
|
1203
|
-
|
|
1204
|
-
expr_0 = self._expr(arg0)
|
|
1205
|
-
expr_1 = self._expr(arg1)
|
|
1206
|
-
|
|
1207
|
-
if expr_0 is None:
|
|
1208
|
-
expr_0 = arg0
|
|
1209
|
-
if expr_1 is None:
|
|
1210
|
-
expr_1 = arg1
|
|
1211
|
-
|
|
1212
|
-
return ailment.Expr.BinaryOp(
|
|
1213
|
-
expr.idx,
|
|
1214
|
-
"DivMod",
|
|
1215
|
-
[expr_0, expr_1],
|
|
1216
|
-
expr.signed,
|
|
1217
|
-
bits=expr.bits,
|
|
1218
|
-
from_bits=expr.from_bits,
|
|
1219
|
-
to_bits=expr.to_bits,
|
|
1220
|
-
**expr.tags,
|
|
1221
|
-
)
|
|
1122
|
+
def _handle_binop_AddF(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1123
|
+
pass
|
|
1222
1124
|
|
|
1223
|
-
def
|
|
1224
|
-
|
|
1125
|
+
def _handle_binop_AddV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1126
|
+
pass
|
|
1225
1127
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1128
|
+
def _handle_binop_Sub(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1129
|
+
pass
|
|
1228
1130
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
if expr_1 is None:
|
|
1232
|
-
expr_1 = arg1
|
|
1131
|
+
def _handle_binop_SubF(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1132
|
+
pass
|
|
1233
1133
|
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
except TypeError:
|
|
1237
|
-
return ailment.Expr.BinaryOp(expr.idx, "Mod", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1134
|
+
def _handle_binop_SubV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1135
|
+
pass
|
|
1238
1136
|
|
|
1239
|
-
def
|
|
1240
|
-
|
|
1137
|
+
def _handle_binop_Mul(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1138
|
+
pass
|
|
1241
1139
|
|
|
1242
|
-
|
|
1243
|
-
|
|
1140
|
+
def _handle_binop_Mull(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1141
|
+
pass
|
|
1244
1142
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
if expr_1 is None:
|
|
1248
|
-
expr_1 = arg1
|
|
1143
|
+
def _handle_binop_MulF(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1144
|
+
pass
|
|
1249
1145
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
except TypeError:
|
|
1253
|
-
return ailment.Expr.BinaryOp(
|
|
1254
|
-
expr.idx,
|
|
1255
|
-
"Mul",
|
|
1256
|
-
[expr_0, expr_1],
|
|
1257
|
-
expr.signed,
|
|
1258
|
-
bits=expr.bits,
|
|
1259
|
-
floating_point=expr.floating_point,
|
|
1260
|
-
rounding_mode=expr.rounding_mode,
|
|
1261
|
-
**expr.tags,
|
|
1262
|
-
)
|
|
1263
|
-
|
|
1264
|
-
def _ail_handle_Mull(self, expr):
|
|
1265
|
-
arg0, arg1 = expr.operands
|
|
1266
|
-
|
|
1267
|
-
expr_0 = self._expr(arg0)
|
|
1268
|
-
expr_1 = self._expr(arg1)
|
|
1269
|
-
|
|
1270
|
-
if expr_0 is None:
|
|
1271
|
-
expr_0 = arg0
|
|
1272
|
-
if expr_1 is None:
|
|
1273
|
-
expr_1 = arg1
|
|
1274
|
-
|
|
1275
|
-
if isinstance(expr_0, claripy.ast.Bits) and isinstance(expr_1, claripy.ast.Bits):
|
|
1276
|
-
expr0_ext = claripy.ZeroExt(expr.bits - expr_0.size(), expr_0) if expr.bits > expr_0.size() else expr_0
|
|
1277
|
-
expr1_ext = claripy.ZeroExt(expr.bits - expr_1.size(), expr_1) if expr.bits > expr_1.size() else expr_1
|
|
1278
|
-
return expr0_ext * expr1_ext
|
|
1279
|
-
|
|
1280
|
-
return ailment.Expr.BinaryOp(
|
|
1281
|
-
expr.idx,
|
|
1282
|
-
"Mull",
|
|
1283
|
-
[expr_0, expr_1],
|
|
1284
|
-
expr.signed,
|
|
1285
|
-
bits=expr.bits,
|
|
1286
|
-
floating_point=expr.floating_point,
|
|
1287
|
-
rounding_mode=expr.rounding_mode,
|
|
1288
|
-
**expr.tags,
|
|
1289
|
-
)
|
|
1146
|
+
def _handle_binop_MulV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1147
|
+
pass
|
|
1290
1148
|
|
|
1291
|
-
def
|
|
1292
|
-
|
|
1149
|
+
def _handle_binop_MulHiV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1150
|
+
pass
|
|
1293
1151
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1152
|
+
def _handle_binop_Div(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1153
|
+
pass
|
|
1296
1154
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
if expr_1 is None:
|
|
1300
|
-
expr_1 = arg1
|
|
1155
|
+
def _handle_binop_DivF(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1156
|
+
pass
|
|
1301
1157
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
except TypeError:
|
|
1305
|
-
return ailment.Expr.BinaryOp(expr.idx, "And", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1158
|
+
def _handle_binop_DivV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1159
|
+
pass
|
|
1306
1160
|
|
|
1307
|
-
def
|
|
1308
|
-
|
|
1161
|
+
def _handle_binop_Mod(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1162
|
+
pass
|
|
1309
1163
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1164
|
+
def _handle_binop_Xor(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1165
|
+
pass
|
|
1312
1166
|
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
if expr_1 is None:
|
|
1316
|
-
expr_1 = arg1
|
|
1167
|
+
def _handle_binop_And(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1168
|
+
pass
|
|
1317
1169
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
except TypeError:
|
|
1321
|
-
return ailment.Expr.BinaryOp(expr.idx, "Or", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1170
|
+
def _handle_binop_LogicalAnd(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1171
|
+
pass
|
|
1322
1172
|
|
|
1323
|
-
def
|
|
1324
|
-
|
|
1173
|
+
def _handle_binop_Or(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1174
|
+
pass
|
|
1325
1175
|
|
|
1326
|
-
|
|
1327
|
-
|
|
1176
|
+
def _handle_binop_LogicalOr(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1177
|
+
pass
|
|
1328
1178
|
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
if expr_1 is None:
|
|
1332
|
-
expr_1 = arg1
|
|
1179
|
+
def _handle_binop_Shl(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1180
|
+
pass
|
|
1333
1181
|
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
except TypeError:
|
|
1337
|
-
return ailment.Expr.BinaryOp(expr.idx, "Xor", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1182
|
+
def _handle_binop_Shr(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1183
|
+
pass
|
|
1338
1184
|
|
|
1339
|
-
def
|
|
1340
|
-
|
|
1341
|
-
expr_0 = self._expr(arg0)
|
|
1342
|
-
expr_1 = self._expr(arg1)
|
|
1185
|
+
def _handle_binop_Sar(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1186
|
+
pass
|
|
1343
1187
|
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
if expr_1 is None:
|
|
1347
|
-
expr_1 = arg1
|
|
1188
|
+
def _handle_binop_CmpF(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1189
|
+
pass
|
|
1348
1190
|
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
return expr_0 >> expr_1.concrete_value
|
|
1352
|
-
except TypeError:
|
|
1353
|
-
pass
|
|
1191
|
+
def _handle_binop_CmpEQ(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1192
|
+
pass
|
|
1354
1193
|
|
|
1355
|
-
|
|
1194
|
+
def _handle_binop_CmpNE(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1195
|
+
pass
|
|
1356
1196
|
|
|
1357
|
-
def
|
|
1358
|
-
|
|
1359
|
-
expr_0 = self._expr(arg0)
|
|
1360
|
-
expr_1 = self._expr(arg1)
|
|
1197
|
+
def _handle_binop_CmpLT(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1198
|
+
pass
|
|
1361
1199
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
if expr_1 is None:
|
|
1365
|
-
expr_1 = arg1
|
|
1200
|
+
def _handle_binop_CmpLE(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1201
|
+
pass
|
|
1366
1202
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
return ailment.Expr.BinaryOp(expr.idx, "Shl", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1203
|
+
def _handle_binop_CmpGT(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1204
|
+
pass
|
|
1370
1205
|
|
|
1371
|
-
def
|
|
1372
|
-
|
|
1206
|
+
def _handle_binop_CmpGE(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1207
|
+
pass
|
|
1373
1208
|
|
|
1374
|
-
def
|
|
1375
|
-
|
|
1376
|
-
expr_0 = self._expr(arg0)
|
|
1377
|
-
expr_1 = self._expr(arg1)
|
|
1209
|
+
def _handle_binop_Concat(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1210
|
+
pass
|
|
1378
1211
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
if expr_1 is None:
|
|
1382
|
-
expr_1 = arg1
|
|
1212
|
+
def _handle_binop_Ror(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1213
|
+
pass
|
|
1383
1214
|
|
|
1384
|
-
|
|
1215
|
+
def _handle_binop_Rol(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1216
|
+
pass
|
|
1385
1217
|
|
|
1386
|
-
def
|
|
1387
|
-
|
|
1388
|
-
expr_0 = self._expr(arg0)
|
|
1389
|
-
expr_1 = self._expr(arg1)
|
|
1218
|
+
def _handle_binop_Carry(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1219
|
+
pass
|
|
1390
1220
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
if expr_1 is None:
|
|
1394
|
-
expr_1 = arg1
|
|
1221
|
+
def _handle_binop_SCarry(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1222
|
+
pass
|
|
1395
1223
|
|
|
1396
|
-
|
|
1224
|
+
def _handle_binop_SBorrow(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1225
|
+
pass
|
|
1397
1226
|
|
|
1398
|
-
def
|
|
1399
|
-
|
|
1400
|
-
expr_0 = self._expr(arg0)
|
|
1401
|
-
expr_1 = self._expr(arg1)
|
|
1227
|
+
def _handle_binop_InterleaveLOV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1228
|
+
pass
|
|
1402
1229
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
if expr_1 is None:
|
|
1406
|
-
expr_1 = arg1
|
|
1230
|
+
def _handle_binop_InterleaveHIV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1231
|
+
pass
|
|
1407
1232
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
return ailment.Expr.BinaryOp(expr.idx, "Sar", [expr_0, expr_1], expr.signed, **expr.tags)
|
|
1233
|
+
def _handle_binop_CasCmpNE(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1234
|
+
pass
|
|
1411
1235
|
|
|
1412
|
-
def
|
|
1413
|
-
|
|
1414
|
-
expr_0 = self._expr(arg0)
|
|
1415
|
-
expr_1 = self._expr(arg1)
|
|
1236
|
+
def _handle_binop_ExpCmpNE(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1237
|
+
pass
|
|
1416
1238
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
if expr_1 is None:
|
|
1420
|
-
expr_1 = arg1
|
|
1239
|
+
def _handle_binop_SarNV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1240
|
+
pass
|
|
1421
1241
|
|
|
1422
|
-
|
|
1242
|
+
def _handle_binop_ShrNV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1243
|
+
pass
|
|
1423
1244
|
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
#
|
|
1245
|
+
def _handle_binop_ShlNV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1246
|
+
pass
|
|
1427
1247
|
|
|
1428
|
-
def
|
|
1429
|
-
|
|
1430
|
-
if data is not None and type(data) is int:
|
|
1431
|
-
return data
|
|
1432
|
-
return None
|
|
1248
|
+
def _handle_binop_CmpEQV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1249
|
+
pass
|
|
1433
1250
|
|
|
1434
|
-
def
|
|
1435
|
-
|
|
1436
|
-
if data is None:
|
|
1437
|
-
return None
|
|
1251
|
+
def _handle_binop_CmpNEV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1252
|
+
pass
|
|
1438
1253
|
|
|
1439
|
-
|
|
1254
|
+
def _handle_binop_CmpGEV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1255
|
+
pass
|
|
1440
1256
|
|
|
1441
|
-
def
|
|
1442
|
-
|
|
1443
|
-
if data is None:
|
|
1444
|
-
return None
|
|
1257
|
+
def _handle_binop_CmpGTV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1258
|
+
pass
|
|
1445
1259
|
|
|
1446
|
-
|
|
1260
|
+
def _handle_binop_CmpLEV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1261
|
+
pass
|
|
1447
1262
|
|
|
1448
|
-
def
|
|
1449
|
-
|
|
1450
|
-
if data is None:
|
|
1451
|
-
return None
|
|
1263
|
+
def _handle_binop_CmpLTV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1264
|
+
pass
|
|
1452
1265
|
|
|
1453
|
-
|
|
1266
|
+
def _handle_binop_PermV(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1267
|
+
pass
|
|
1454
1268
|
|
|
1269
|
+
def _handle_binop_Set(self, expr: ailment.expression.BinaryOp) -> DataType_co | None:
|
|
1270
|
+
pass
|
|
1455
1271
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1272
|
+
def _handle_unop_Clz(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1273
|
+
pass
|
|
1274
|
+
|
|
1275
|
+
def _handle_unop_Ctz(self, expr: ailment.expression.UnaryOp) -> DataType_co | None:
|
|
1276
|
+
pass
|