angr 9.2.101__py3-none-manylinux2014_x86_64.whl → 9.2.103__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/analysis.py +7 -6
- angr/analyses/calling_convention.py +33 -35
- angr/analyses/cdg.py +2 -4
- angr/analyses/cfg/cfb.py +4 -3
- angr/analyses/cfg/cfg_base.py +14 -14
- angr/analyses/cfg/cfg_emulated.py +3 -4
- angr/analyses/cfg/cfg_fast.py +46 -46
- angr/analyses/cfg/cfg_fast_soot.py +1 -2
- angr/analyses/cfg/cfg_job_base.py +2 -2
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +14 -13
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +5 -5
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +3 -3
- angr/analyses/complete_calling_conventions.py +13 -12
- angr/analyses/data_dep/data_dependency_analysis.py +24 -24
- angr/analyses/data_dep/dep_nodes.py +3 -3
- angr/analyses/ddg.py +1 -2
- angr/analyses/decompiler/ail_simplifier.py +35 -34
- angr/analyses/decompiler/block_io_finder.py +20 -20
- angr/analyses/decompiler/block_similarity.py +4 -6
- angr/analyses/decompiler/block_simplifier.py +17 -16
- angr/analyses/decompiler/callsite_maker.py +25 -10
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -3
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +2 -4
- angr/analyses/decompiler/clinic.py +250 -45
- angr/analyses/decompiler/condition_processor.py +15 -8
- angr/analyses/decompiler/decompilation_cache.py +7 -7
- angr/analyses/decompiler/decompilation_options.py +4 -4
- angr/analyses/decompiler/decompiler.py +19 -15
- angr/analyses/decompiler/expression_counters.py +10 -9
- angr/analyses/decompiler/goto_manager.py +2 -4
- angr/analyses/decompiler/graph_region.py +9 -9
- angr/analyses/decompiler/jump_target_collector.py +1 -2
- angr/analyses/decompiler/optimization_passes/__init__.py +4 -3
- angr/analyses/decompiler/optimization_passes/code_motion.py +5 -6
- angr/analyses/decompiler/optimization_passes/const_derefs.py +4 -4
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +73 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +25 -3
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +6 -5
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +3 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +2 -2
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +17 -17
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +12 -13
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +25 -21
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +3 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +1 -2
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +7 -7
- angr/analyses/decompiler/optimization_passes/spilled_register_finder.py +18 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +2 -3
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -2
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/__init__.py +4 -3
- angr/analyses/decompiler/peephole_optimizations/base.py +13 -15
- angr/analyses/decompiler/peephole_optimizations/bswap.py +1 -3
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +72 -0
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +5 -10
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +3 -4
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +2 -3
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +4 -4
- angr/analyses/decompiler/redundant_label_remover.py +4 -5
- angr/analyses/decompiler/region_identifier.py +4 -5
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -2
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +19 -20
- angr/analyses/decompiler/region_simplifiers/goto.py +2 -3
- angr/analyses/decompiler/region_simplifiers/loop.py +1 -2
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -2
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +1 -3
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +19 -19
- angr/analyses/decompiler/return_maker.py +1 -2
- angr/analyses/decompiler/structured_codegen/base.py +5 -6
- angr/analyses/decompiler/structured_codegen/c.py +39 -38
- angr/analyses/decompiler/structuring/__init__.py +1 -1
- angr/analyses/decompiler/structuring/dream.py +17 -16
- angr/analyses/decompiler/structuring/phoenix.py +45 -46
- angr/analyses/decompiler/structuring/recursive_structurer.py +4 -4
- angr/analyses/decompiler/structuring/structurer_base.py +16 -15
- angr/analyses/decompiler/structuring/structurer_nodes.py +10 -9
- angr/analyses/decompiler/utils.py +17 -16
- angr/analyses/disassembly.py +7 -6
- angr/analyses/flirt.py +9 -9
- angr/analyses/forward_analysis/forward_analysis.py +15 -14
- angr/analyses/forward_analysis/visitors/function_graph.py +1 -2
- angr/analyses/forward_analysis/visitors/graph.py +16 -15
- angr/analyses/propagator/engine_ail.py +30 -26
- angr/analyses/propagator/outdated_definition_walker.py +8 -7
- angr/analyses/propagator/propagator.py +11 -13
- angr/analyses/proximity_graph.py +21 -21
- angr/analyses/reaching_definitions/__init__.py +3 -3
- angr/analyses/reaching_definitions/call_trace.py +3 -6
- angr/analyses/reaching_definitions/dep_graph.py +41 -48
- angr/analyses/reaching_definitions/engine_ail.py +11 -5
- angr/analyses/reaching_definitions/engine_vex.py +9 -8
- angr/analyses/reaching_definitions/function_handler.py +51 -34
- angr/analyses/reaching_definitions/heap_allocator.py +3 -4
- angr/analyses/reaching_definitions/rd_initializer.py +8 -8
- angr/analyses/reaching_definitions/rd_state.py +57 -58
- angr/analyses/reaching_definitions/reaching_definitions.py +18 -17
- angr/analyses/reaching_definitions/subject.py +2 -3
- angr/analyses/stack_pointer_tracker.py +15 -6
- angr/analyses/typehoon/dfa.py +4 -4
- angr/analyses/typehoon/simple_solver.py +48 -52
- angr/analyses/typehoon/translator.py +3 -6
- angr/analyses/typehoon/typeconsts.py +13 -14
- angr/analyses/typehoon/typehoon.py +9 -9
- angr/analyses/typehoon/typevars.py +18 -17
- angr/analyses/variable_recovery/engine_ail.py +5 -5
- angr/analyses/variable_recovery/engine_base.py +25 -21
- angr/analyses/variable_recovery/irsb_scanner.py +8 -9
- angr/analyses/variable_recovery/variable_recovery.py +1 -2
- angr/analyses/variable_recovery/variable_recovery_base.py +14 -13
- angr/analyses/variable_recovery/variable_recovery_fast.py +8 -8
- angr/analyses/veritesting.py +1 -2
- angr/analyses/vfg.py +57 -56
- angr/analyses/xrefs.py +1 -2
- angr/angrdb/db.py +7 -7
- angr/angrdb/serializers/kb.py +16 -13
- angr/angrdb/serializers/loader.py +1 -2
- angr/angrdb/serializers/structured_code.py +2 -2
- angr/annocfg.py +1 -2
- angr/block.py +16 -6
- angr/calling_conventions.py +27 -27
- angr/code_location.py +8 -8
- angr/codenode.py +1 -2
- angr/concretization_strategies/max.py +1 -3
- angr/distributed/server.py +1 -3
- angr/distributed/worker.py +1 -2
- angr/engines/engine.py +2 -3
- angr/engines/light/engine.py +4 -4
- angr/engines/pcode/behavior.py +20 -2
- angr/engines/pcode/emulate.py +1 -1
- angr/engines/pcode/engine.py +7 -7
- angr/engines/pcode/lifter.py +78 -77
- angr/engines/vex/claripy/ccall.py +1 -2
- angr/engines/vex/claripy/datalayer.py +1 -2
- angr/engines/vex/light/light.py +1 -2
- angr/exploration_techniques/tracer.py +4 -4
- angr/factory.py +12 -15
- angr/flirt/__init__.py +8 -8
- angr/flirt/build_sig.py +2 -3
- angr/keyed_region.py +2 -2
- angr/knowledge_base/knowledge_base.py +3 -3
- angr/knowledge_plugins/callsite_prototypes.py +4 -6
- angr/knowledge_plugins/cfg/cfg_manager.py +19 -6
- angr/knowledge_plugins/cfg/cfg_model.py +26 -27
- angr/knowledge_plugins/cfg/cfg_node.py +2 -2
- angr/knowledge_plugins/cfg/indirect_jump.py +6 -8
- angr/knowledge_plugins/cfg/memory_data.py +8 -9
- angr/knowledge_plugins/custom_strings.py +1 -3
- angr/knowledge_plugins/debug_variables.py +2 -2
- angr/knowledge_plugins/functions/function.py +21 -22
- angr/knowledge_plugins/functions/function_manager.py +5 -5
- angr/knowledge_plugins/indirect_jumps.py +1 -3
- angr/knowledge_plugins/key_definitions/atoms.py +7 -7
- angr/knowledge_plugins/key_definitions/definition.py +14 -14
- angr/knowledge_plugins/key_definitions/environment.py +5 -7
- angr/knowledge_plugins/key_definitions/heap_address.py +1 -3
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +3 -2
- angr/knowledge_plugins/key_definitions/live_definitions.py +60 -59
- angr/knowledge_plugins/key_definitions/liveness.py +16 -16
- angr/knowledge_plugins/key_definitions/rd_model.py +15 -15
- angr/knowledge_plugins/key_definitions/uses.py +11 -11
- angr/knowledge_plugins/patches.py +4 -8
- angr/knowledge_plugins/propagations/prop_value.py +10 -9
- angr/knowledge_plugins/propagations/propagation_manager.py +3 -5
- angr/knowledge_plugins/propagations/propagation_model.py +9 -9
- angr/knowledge_plugins/propagations/states.py +52 -22
- angr/knowledge_plugins/structured_code/manager.py +2 -2
- angr/knowledge_plugins/sync/sync_controller.py +3 -3
- angr/knowledge_plugins/variables/variable_access.py +4 -4
- angr/knowledge_plugins/variables/variable_manager.py +56 -39
- angr/knowledge_plugins/xrefs/xref.py +9 -11
- angr/knowledge_plugins/xrefs/xref_manager.py +3 -4
- angr/misc/ansi.py +1 -2
- angr/misc/autoimport.py +3 -3
- angr/misc/plugins.py +9 -9
- angr/procedures/definitions/__init__.py +16 -16
- angr/procedures/definitions/linux_kernel.py +1 -1
- angr/procedures/definitions/parse_win32json.py +1 -1
- angr/procedures/java_jni/__init__.py +1 -1
- angr/procedures/java_jni/array_operations.py +1 -2
- angr/procedures/java_jni/method_calls.py +1 -2
- angr/procedures/posix/inet_ntoa.py +1 -2
- angr/procedures/stubs/format_parser.py +3 -3
- angr/project.py +13 -11
- angr/sim_manager.py +12 -12
- angr/sim_procedure.py +7 -3
- angr/sim_state.py +2 -2
- angr/sim_type.py +60 -45
- angr/sim_variable.py +5 -5
- angr/simos/simos.py +1 -2
- angr/simos/userland.py +1 -2
- angr/state_plugins/callstack.py +3 -2
- angr/state_plugins/history.py +1 -2
- angr/state_plugins/solver.py +34 -34
- angr/storage/memory_mixins/__init__.py +4 -3
- angr/storage/memory_mixins/actions_mixin.py +1 -3
- angr/storage/memory_mixins/address_concretization_mixin.py +1 -3
- angr/storage/memory_mixins/convenient_mappings_mixin.py +3 -4
- angr/storage/memory_mixins/default_filler_mixin.py +1 -1
- angr/storage/memory_mixins/label_merger_mixin.py +2 -2
- angr/storage/memory_mixins/multi_value_merger_mixin.py +4 -3
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +9 -8
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +12 -11
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +8 -8
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +2 -3
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +10 -11
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +11 -10
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +18 -17
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +12 -11
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +3 -3
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +3 -2
- angr/storage/memory_mixins/regioned_memory/region_data.py +1 -2
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +2 -2
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +3 -3
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +18 -21
- angr/storage/memory_mixins/size_resolution_mixin.py +1 -2
- angr/storage/memory_mixins/symbolic_merger_mixin.py +3 -2
- angr/storage/memory_mixins/top_merger_mixin.py +3 -2
- angr/storage/memory_object.py +2 -4
- angr/utils/algo.py +3 -2
- angr/utils/dynamic_dictlist.py +5 -5
- angr/utils/formatting.py +4 -4
- angr/utils/funcid.py +1 -2
- angr/utils/graph.py +5 -6
- angr/utils/library.py +5 -5
- angr/utils/mp.py +5 -4
- angr/utils/segment_list.py +3 -4
- angr/utils/typing.py +3 -2
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/RECORD +239 -236
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
import math
|
|
5
5
|
import re
|
|
6
6
|
import string
|
|
7
|
-
from typing import DefaultDict
|
|
7
|
+
from typing import DefaultDict
|
|
8
8
|
from collections import defaultdict, OrderedDict
|
|
9
9
|
from enum import Enum, unique
|
|
10
10
|
|
|
@@ -153,7 +153,7 @@ class PendingJobs:
|
|
|
153
153
|
|
|
154
154
|
__nonzero__ = __bool__
|
|
155
155
|
|
|
156
|
-
def _pop_job(self, func_addr:
|
|
156
|
+
def _pop_job(self, func_addr: int | None):
|
|
157
157
|
jobs = self._jobs[func_addr]
|
|
158
158
|
j = jobs.pop(-1)
|
|
159
159
|
if not jobs:
|
|
@@ -457,16 +457,16 @@ class CFGJob:
|
|
|
457
457
|
addr: int,
|
|
458
458
|
func_addr: int,
|
|
459
459
|
jumpkind: str,
|
|
460
|
-
ret_target:
|
|
461
|
-
last_addr:
|
|
462
|
-
src_node:
|
|
463
|
-
src_ins_addr:
|
|
464
|
-
src_stmt_idx:
|
|
460
|
+
ret_target: int | None = None,
|
|
461
|
+
last_addr: int | None = None,
|
|
462
|
+
src_node: CFGNode | None = None,
|
|
463
|
+
src_ins_addr: int | None = None,
|
|
464
|
+
src_stmt_idx: int | None = None,
|
|
465
465
|
returning_source=None,
|
|
466
466
|
syscall: bool = False,
|
|
467
|
-
func_edges:
|
|
467
|
+
func_edges: list | None = None,
|
|
468
468
|
job_type: CFGJobType = CFGJobType.NORMAL,
|
|
469
|
-
gp:
|
|
469
|
+
gp: int | None = None,
|
|
470
470
|
):
|
|
471
471
|
self.addr = addr
|
|
472
472
|
self.func_addr = func_addr
|
|
@@ -615,8 +615,8 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
615
615
|
nodecode_window_size=512,
|
|
616
616
|
nodecode_threshold=0.3,
|
|
617
617
|
nodecode_step=16483,
|
|
618
|
-
indirect_calls_always_return:
|
|
619
|
-
jumptable_resolver_resolves_calls:
|
|
618
|
+
indirect_calls_always_return: bool | None = None,
|
|
619
|
+
jumptable_resolver_resolves_calls: bool | None = None,
|
|
620
620
|
start=None, # deprecated
|
|
621
621
|
end=None, # deprecated
|
|
622
622
|
collect_data_references=None, # deprecated
|
|
@@ -808,7 +808,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
808
808
|
self._known_thunks = {}
|
|
809
809
|
|
|
810
810
|
self._initial_state = None
|
|
811
|
-
self._next_addr:
|
|
811
|
+
self._next_addr: int | None = None
|
|
812
812
|
|
|
813
813
|
# Create the segment list
|
|
814
814
|
self._seg_list = SegmentList()
|
|
@@ -828,10 +828,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
828
828
|
self._traced_addresses = None
|
|
829
829
|
self._function_returns = None
|
|
830
830
|
self._function_exits = None
|
|
831
|
-
self._gp_value:
|
|
832
|
-
self._ro_region_cdata_cache:
|
|
831
|
+
self._gp_value: int | None = None
|
|
832
|
+
self._ro_region_cdata_cache: list | None = None
|
|
833
833
|
self._job_ctr = 0
|
|
834
|
-
self._decoding_assumptions:
|
|
834
|
+
self._decoding_assumptions: dict[int, DecodingAssumption] = {}
|
|
835
835
|
self._decoding_assumption_relations = None
|
|
836
836
|
|
|
837
837
|
# A mapping between address and the actual data in memory
|
|
@@ -1174,7 +1174,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1174
1174
|
|
|
1175
1175
|
return nodecode_bytes / total_bytes
|
|
1176
1176
|
|
|
1177
|
-
def _next_code_addr_smart(self) ->
|
|
1177
|
+
def _next_code_addr_smart(self) -> int | None:
|
|
1178
1178
|
# in the smart scanning mode, if there are more than N consecutive no-decode cases, we skip an entire window of
|
|
1179
1179
|
# bytes.
|
|
1180
1180
|
nodecode_bytes_ratio = (
|
|
@@ -1215,7 +1215,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1215
1215
|
|
|
1216
1216
|
# Initialize variables used during analysis
|
|
1217
1217
|
self._pending_jobs: PendingJobs = PendingJobs(self.functions, self._deregister_analysis_job)
|
|
1218
|
-
self._traced_addresses:
|
|
1218
|
+
self._traced_addresses: set[int] = {a for a, n in self._nodes_by_addr.items() if n}
|
|
1219
1219
|
self._function_returns = defaultdict(set)
|
|
1220
1220
|
|
|
1221
1221
|
# Populate known objects in segment tracker
|
|
@@ -1230,7 +1230,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1230
1230
|
# should record all exits from a single function, and then add
|
|
1231
1231
|
# necessary calling edges in our call map during the post-processing
|
|
1232
1232
|
# phase.
|
|
1233
|
-
self._function_exits: DefaultDict[int,
|
|
1233
|
+
self._function_exits: DefaultDict[int, set[int]] = defaultdict(set)
|
|
1234
1234
|
|
|
1235
1235
|
# Create an initial state. Store it to self so we can use it globally.
|
|
1236
1236
|
self._initial_state = self.project.factory.blank_state(
|
|
@@ -1245,7 +1245,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1245
1245
|
if self._use_exceptions:
|
|
1246
1246
|
self._preprocess_exception_handlings()
|
|
1247
1247
|
|
|
1248
|
-
starting_points:
|
|
1248
|
+
starting_points: set[int] = set()
|
|
1249
1249
|
|
|
1250
1250
|
if self._use_symbols:
|
|
1251
1251
|
starting_points |= self._function_addresses_from_symbols
|
|
@@ -1257,7 +1257,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1257
1257
|
starting_points |= set(self._extra_function_starts)
|
|
1258
1258
|
|
|
1259
1259
|
# Sort it
|
|
1260
|
-
sorted_starting_points:
|
|
1260
|
+
sorted_starting_points: list[int] = sorted(list(starting_points), reverse=False)
|
|
1261
1261
|
|
|
1262
1262
|
if self._start_at_entry and self.project.entry is not None and self._inside_regions(self.project.entry):
|
|
1263
1263
|
if self.project.entry not in starting_points:
|
|
@@ -1281,7 +1281,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1281
1281
|
self._remaining_function_prologue_addrs = sorted(self._func_addrs_from_prologues())
|
|
1282
1282
|
|
|
1283
1283
|
# assumption management
|
|
1284
|
-
self._decoding_assumptions:
|
|
1284
|
+
self._decoding_assumptions: dict[int, DecodingAssumption] = {}
|
|
1285
1285
|
self._decoding_assumption_relations = networkx.DiGraph()
|
|
1286
1286
|
|
|
1287
1287
|
# register read-only regions to PyVEX
|
|
@@ -1329,7 +1329,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1329
1329
|
def _intra_analysis(self):
|
|
1330
1330
|
pass
|
|
1331
1331
|
|
|
1332
|
-
def _get_successors(self, job: CFGJob) ->
|
|
1332
|
+
def _get_successors(self, job: CFGJob) -> list[CFGJob]: # type: ignore[override] # pylint:disable=arguments-differ
|
|
1333
1333
|
# current_function_addr = job.func_addr
|
|
1334
1334
|
# addr = job.addr
|
|
1335
1335
|
|
|
@@ -1412,7 +1412,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1412
1412
|
func = self.kb.functions.get_by_addr(func_addr)
|
|
1413
1413
|
if func.is_plt or func.is_simprocedure or func.is_syscall:
|
|
1414
1414
|
return
|
|
1415
|
-
if not (
|
|
1415
|
+
if not (9 <= len(func.block_addrs_set) < 12):
|
|
1416
1416
|
return
|
|
1417
1417
|
|
|
1418
1418
|
from angr.analyses.decompiler.clinic import ClinicMode # pylint:disable=wrong-import-position
|
|
@@ -1759,7 +1759,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1759
1759
|
UPDATE_RATIO = 0.5
|
|
1760
1760
|
|
|
1761
1761
|
all_memory_data = sorted(list(self.model.memory_data.items()), key=lambda x: x[0]) # sorted by addr
|
|
1762
|
-
to_update:
|
|
1762
|
+
to_update: dict[int, bytes] = {}
|
|
1763
1763
|
total_string_refs: int = 0
|
|
1764
1764
|
for i, (addr, md) in enumerate(all_memory_data):
|
|
1765
1765
|
if not md.sort == MemoryDataSort.String:
|
|
@@ -1862,7 +1862,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1862
1862
|
|
|
1863
1863
|
# Basic block scanning
|
|
1864
1864
|
|
|
1865
|
-
def _scan_block(self, cfg_job: CFGJob) ->
|
|
1865
|
+
def _scan_block(self, cfg_job: CFGJob) -> list[CFGJob]:
|
|
1866
1866
|
"""
|
|
1867
1867
|
Scan a basic block starting at a specific address
|
|
1868
1868
|
|
|
@@ -1889,7 +1889,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1889
1889
|
|
|
1890
1890
|
return entries
|
|
1891
1891
|
|
|
1892
|
-
def _scan_procedure(self, cfg_job, current_func_addr) ->
|
|
1892
|
+
def _scan_procedure(self, cfg_job, current_func_addr) -> list[CFGJob]:
|
|
1893
1893
|
"""
|
|
1894
1894
|
Checks the hooking procedure for this address searching for new static
|
|
1895
1895
|
exit points to add to successors (generating entries for them)
|
|
@@ -1945,7 +1945,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1945
1945
|
# Mark the address as traced
|
|
1946
1946
|
self._traced_addresses.add(addr)
|
|
1947
1947
|
|
|
1948
|
-
entries:
|
|
1948
|
+
entries: list[CFGJob] = []
|
|
1949
1949
|
|
|
1950
1950
|
if (
|
|
1951
1951
|
cfg_job.src_node is not None
|
|
@@ -2020,7 +2020,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2020
2020
|
|
|
2021
2021
|
return entries
|
|
2022
2022
|
|
|
2023
|
-
def _scan_irsb(self, cfg_job, current_func_addr) ->
|
|
2023
|
+
def _scan_irsb(self, cfg_job, current_func_addr) -> list[CFGJob]:
|
|
2024
2024
|
"""
|
|
2025
2025
|
Generate a list of successors (generating them each as entries) to IRSB.
|
|
2026
2026
|
Updates previous CFG nodes with edges.
|
|
@@ -2161,7 +2161,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2161
2161
|
|
|
2162
2162
|
def _create_jobs(
|
|
2163
2163
|
self, target, jumpkind, current_function_addr, irsb, addr, cfg_node, ins_addr, stmt_idx
|
|
2164
|
-
) ->
|
|
2164
|
+
) -> list[CFGJob]:
|
|
2165
2165
|
"""
|
|
2166
2166
|
Given a node and details of a successor, makes a list of CFGJobs
|
|
2167
2167
|
and if it is a call or exit marks it appropriately so in the CFG
|
|
@@ -2176,7 +2176,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2176
2176
|
:param int stmt_idx: ID of the source statement.
|
|
2177
2177
|
:return: a list of CFGJobs
|
|
2178
2178
|
"""
|
|
2179
|
-
target_addr:
|
|
2179
|
+
target_addr: int | None
|
|
2180
2180
|
if type(target) is pyvex.IRExpr.Const: # pylint: disable=unidiomatic-typecheck
|
|
2181
2181
|
target_addr = target.con.value
|
|
2182
2182
|
elif type(target) in (
|
|
@@ -2201,7 +2201,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2201
2201
|
else:
|
|
2202
2202
|
raise AngrCFGError("This shouldn't be possible")
|
|
2203
2203
|
|
|
2204
|
-
jobs:
|
|
2204
|
+
jobs: list[CFGJob] = []
|
|
2205
2205
|
is_syscall = jumpkind.startswith("Ijk_Sys")
|
|
2206
2206
|
|
|
2207
2207
|
# Special handling:
|
|
@@ -2410,10 +2410,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2410
2410
|
stmt_idx: int,
|
|
2411
2411
|
ins_addr: int,
|
|
2412
2412
|
current_function_addr: int,
|
|
2413
|
-
target_addr:
|
|
2413
|
+
target_addr: int | None,
|
|
2414
2414
|
jumpkind: str,
|
|
2415
2415
|
is_syscall: bool = False,
|
|
2416
|
-
) ->
|
|
2416
|
+
) -> list[CFGJob]:
|
|
2417
2417
|
"""
|
|
2418
2418
|
Generate a CFGJob for target address, also adding to _pending_entries
|
|
2419
2419
|
if returning to succeeding position (if irsb arg is populated)
|
|
@@ -2430,7 +2430,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2430
2430
|
:return: A list of CFGJobs
|
|
2431
2431
|
"""
|
|
2432
2432
|
|
|
2433
|
-
jobs:
|
|
2433
|
+
jobs: list[CFGJob] = []
|
|
2434
2434
|
|
|
2435
2435
|
if is_syscall:
|
|
2436
2436
|
# Fix the target_addr for syscalls
|
|
@@ -2531,7 +2531,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2531
2531
|
if callee_might_return:
|
|
2532
2532
|
func_edges = []
|
|
2533
2533
|
if return_site is not None:
|
|
2534
|
-
call_returning:
|
|
2534
|
+
call_returning: bool | None
|
|
2535
2535
|
if callee_function is not None:
|
|
2536
2536
|
call_returning = self._is_call_returning(cfg_node, callee_function.addr)
|
|
2537
2537
|
else:
|
|
@@ -2899,8 +2899,8 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2899
2899
|
stmt_idx: int,
|
|
2900
2900
|
insn_addr: int,
|
|
2901
2901
|
data_addr: int,
|
|
2902
|
-
data_size:
|
|
2903
|
-
data_type:
|
|
2902
|
+
data_size: int | None = None,
|
|
2903
|
+
data_type: MemoryDataSort | None = None,
|
|
2904
2904
|
) -> None:
|
|
2905
2905
|
"""
|
|
2906
2906
|
Checks addresses are in the correct segments and creates or updates
|
|
@@ -2995,7 +2995,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2995
2995
|
|
|
2996
2996
|
return False
|
|
2997
2997
|
|
|
2998
|
-
def _indirect_jump_resolved(self, jump: IndirectJump, jump_addr, resolved_by, targets:
|
|
2998
|
+
def _indirect_jump_resolved(self, jump: IndirectJump, jump_addr, resolved_by, targets: list[int]):
|
|
2999
2999
|
"""
|
|
3000
3000
|
Called when an indirect jump is successfully resolved.
|
|
3001
3001
|
|
|
@@ -3546,7 +3546,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
3546
3546
|
|
|
3547
3547
|
del self._function_returns[nonreturning_function.addr]
|
|
3548
3548
|
|
|
3549
|
-
def _pop_pending_job(self, returning=True) ->
|
|
3549
|
+
def _pop_pending_job(self, returning=True) -> CFGJob | None:
|
|
3550
3550
|
while self._pending_jobs:
|
|
3551
3551
|
job = self._pending_jobs.pop_job(returning=returning)
|
|
3552
3552
|
if job is not None and job.job_type == CFGJobType.DATAREF_HINTS and self._seg_list.is_occupied(job.addr):
|
|
@@ -3563,7 +3563,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
3563
3563
|
#
|
|
3564
3564
|
|
|
3565
3565
|
def _graph_add_edge(
|
|
3566
|
-
self, cfg_node: CFGNode, src_node:
|
|
3566
|
+
self, cfg_node: CFGNode, src_node: CFGNode | None, src_jumpkind: str, src_ins_addr: int, src_stmt_idx: int
|
|
3567
3567
|
):
|
|
3568
3568
|
"""
|
|
3569
3569
|
Add edge between nodes, or add node if entry point
|
|
@@ -4061,7 +4061,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4061
4061
|
# Initial registers
|
|
4062
4062
|
#
|
|
4063
4063
|
|
|
4064
|
-
def _get_initial_registers(self, addr, cfg_job, current_function_addr) ->
|
|
4064
|
+
def _get_initial_registers(self, addr, cfg_job, current_function_addr) -> list[tuple[int, int, int]] | None:
|
|
4065
4065
|
initial_regs = None
|
|
4066
4066
|
if self.project.arch.name in {"MIPS64", "MIPS32"}:
|
|
4067
4067
|
initial_regs = [
|
|
@@ -4533,7 +4533,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4533
4533
|
return None, None, None, None
|
|
4534
4534
|
|
|
4535
4535
|
def _process_block_arch_specific(
|
|
4536
|
-
self, addr: int, cfg_node: CFGNode, irsb: pyvex.IRSB, func_addr: int, caller_gp:
|
|
4536
|
+
self, addr: int, cfg_node: CFGNode, irsb: pyvex.IRSB, func_addr: int, caller_gp: int | None = None
|
|
4537
4537
|
) -> None: # pylint: disable=unused-argument
|
|
4538
4538
|
"""
|
|
4539
4539
|
According to arch types ['ARMEL', 'ARMHF', 'MIPS32', 'X86'] does different
|
|
@@ -4704,7 +4704,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4704
4704
|
func = self.kb.functions.get_by_addr(func_addr)
|
|
4705
4705
|
func.info["bp_as_gpr"] = rbp_as_gpr
|
|
4706
4706
|
|
|
4707
|
-
def _extract_node_cluster_by_dependency(self, addr, include_successors=False) ->
|
|
4707
|
+
def _extract_node_cluster_by_dependency(self, addr, include_successors=False) -> set[int]:
|
|
4708
4708
|
to_remove = {addr}
|
|
4709
4709
|
queue = [addr]
|
|
4710
4710
|
while queue:
|
|
@@ -4840,7 +4840,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4840
4840
|
# the ARM node and the THUMB node no longer exist.
|
|
4841
4841
|
self._traced_addresses.discard(assumption.addr)
|
|
4842
4842
|
|
|
4843
|
-
def _mips_determine_function_gp(self, addr: int, irsb: pyvex.IRSB, func_addr: int) ->
|
|
4843
|
+
def _mips_determine_function_gp(self, addr: int, irsb: pyvex.IRSB, func_addr: int) -> int | None:
|
|
4844
4844
|
# check if gp is being written to
|
|
4845
4845
|
last_gp_setting_insn_id = None
|
|
4846
4846
|
insn_ctr = 0
|
|
@@ -4900,7 +4900,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4900
4900
|
|
|
4901
4901
|
return result
|
|
4902
4902
|
|
|
4903
|
-
def _x86_gcc_pie_find_pc_register_adjustment(self, addr: int, reg_offset: int) ->
|
|
4903
|
+
def _x86_gcc_pie_find_pc_register_adjustment(self, addr: int, reg_offset: int) -> int | None:
|
|
4904
4904
|
"""
|
|
4905
4905
|
Match against a single instruction that adds or subtracts a constant from a specified register.
|
|
4906
4906
|
|
|
@@ -4958,7 +4958,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4958
4958
|
return stmt2.data.args[1].con.value
|
|
4959
4959
|
return None
|
|
4960
4960
|
|
|
4961
|
-
def _is_call_returning(self, callsite_cfgnode: CFGNode, callee_func_addr: int) ->
|
|
4961
|
+
def _is_call_returning(self, callsite_cfgnode: CFGNode, callee_func_addr: int) -> bool | None:
|
|
4962
4962
|
"""
|
|
4963
4963
|
Determine if a function call is returning or not, with a special care for DYNAMIC_RET functions.
|
|
4964
4964
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
|
-
from typing import List
|
|
5
4
|
|
|
6
5
|
from sortedcontainers import SortedDict
|
|
7
6
|
from copy import copy
|
|
@@ -380,7 +379,7 @@ class CFGFastSoot(CFGFast):
|
|
|
380
379
|
|
|
381
380
|
return stmts_count
|
|
382
381
|
|
|
383
|
-
def _scan_block(self, cfg_job) ->
|
|
382
|
+
def _scan_block(self, cfg_job) -> list[CFGJob]:
|
|
384
383
|
"""
|
|
385
384
|
Scan a basic block starting at a specific address
|
|
386
385
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from archinfo.arch_soot import SootAddressDescriptor
|
|
5
5
|
|
|
@@ -131,7 +131,7 @@ class CFGJobBase:
|
|
|
131
131
|
src_block_id=None,
|
|
132
132
|
src_exit_stmt_idx=None,
|
|
133
133
|
src_ins_addr=None,
|
|
134
|
-
jumpkind:
|
|
134
|
+
jumpkind: str | None = None,
|
|
135
135
|
call_stack=None,
|
|
136
136
|
is_narrowing=False,
|
|
137
137
|
skip=False,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint:disable=wrong-import-position,wrong-import-order
|
|
2
2
|
import enum
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
from collections.abc import Sequence
|
|
4
5
|
import logging
|
|
5
6
|
import functools
|
|
6
7
|
from collections import defaultdict, OrderedDict
|
|
@@ -75,7 +76,7 @@ class AddressTransformation:
|
|
|
75
76
|
Describe and record an address transformation operation.
|
|
76
77
|
"""
|
|
77
78
|
|
|
78
|
-
def __init__(self, op: AddressTransformationTypes, operands:
|
|
79
|
+
def __init__(self, op: AddressTransformationTypes, operands: list, first_load: bool = False):
|
|
79
80
|
self.op = op
|
|
80
81
|
self.operands = operands
|
|
81
82
|
self.first_load = first_load
|
|
@@ -295,7 +296,7 @@ class JumpTableProcessor(
|
|
|
295
296
|
not be able to recover all jump targets later in block 0x4051b0.
|
|
296
297
|
"""
|
|
297
298
|
|
|
298
|
-
def __init__(self, project, indirect_jump_node_pred_addrs:
|
|
299
|
+
def __init__(self, project, indirect_jump_node_pred_addrs: set[int], bp_sp_diff=0x100):
|
|
299
300
|
super().__init__()
|
|
300
301
|
self.project = project
|
|
301
302
|
self._bp_sp_diff = bp_sp_diff # bp - sp
|
|
@@ -303,7 +304,7 @@ class JumpTableProcessor(
|
|
|
303
304
|
self._indirect_jump_node_pred_addrs = indirect_jump_node_pred_addrs
|
|
304
305
|
|
|
305
306
|
self._SPOFFSET_BASE = claripy.BVS("SpOffset", self.project.arch.bits, explicit_name=True)
|
|
306
|
-
self._REGOFFSET_BASE:
|
|
307
|
+
self._REGOFFSET_BASE: dict[int, claripy.ast.BV] = {}
|
|
307
308
|
|
|
308
309
|
def _top(self, size: int):
|
|
309
310
|
return None
|
|
@@ -320,7 +321,7 @@ class JumpTableProcessor(
|
|
|
320
321
|
return v
|
|
321
322
|
|
|
322
323
|
@staticmethod
|
|
323
|
-
def _extract_spoffset_from_expr(expr: claripy.ast.Base) ->
|
|
324
|
+
def _extract_spoffset_from_expr(expr: claripy.ast.Base) -> SpOffset | None:
|
|
324
325
|
if expr.op == "BVS":
|
|
325
326
|
for anno in expr.annotations:
|
|
326
327
|
if isinstance(anno, RegOffsetAnnotation):
|
|
@@ -351,7 +352,7 @@ class JumpTableProcessor(
|
|
|
351
352
|
return v
|
|
352
353
|
|
|
353
354
|
@staticmethod
|
|
354
|
-
def _extract_regoffset_from_expr(expr: claripy.ast.Base) ->
|
|
355
|
+
def _extract_regoffset_from_expr(expr: claripy.ast.Base) -> RegisterOffset | None:
|
|
355
356
|
if expr.op == "BVS":
|
|
356
357
|
for anno in expr.annotations:
|
|
357
358
|
if isinstance(anno, RegOffsetAnnotation):
|
|
@@ -902,10 +903,10 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
902
903
|
addr: int,
|
|
903
904
|
func: "Function",
|
|
904
905
|
b: Blade,
|
|
905
|
-
cv_manager:
|
|
906
|
+
cv_manager: ConstantValueManager | None,
|
|
906
907
|
potential_call_table: bool = False,
|
|
907
908
|
func_graph_complete: bool = True,
|
|
908
|
-
) ->
|
|
909
|
+
) -> tuple[bool, Sequence[int] | None]:
|
|
909
910
|
"""
|
|
910
911
|
Internal method for resolving jump tables.
|
|
911
912
|
|
|
@@ -1173,7 +1174,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1173
1174
|
# initialization
|
|
1174
1175
|
load_stmt_loc, load_stmt, load_size = None, None, None
|
|
1175
1176
|
stmts_to_remove = [stmt_loc]
|
|
1176
|
-
stmts_adding_base_addr:
|
|
1177
|
+
stmts_adding_base_addr: list[JumpTargetBaseAddr] = []
|
|
1177
1178
|
# All temporary variables that hold indirect addresses loaded out of the memory
|
|
1178
1179
|
# Obviously, load_stmt.tmp must be here
|
|
1179
1180
|
# if there are additional data transferring statements between the Load statement and the base-address-adding
|
|
@@ -1189,7 +1190,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1189
1190
|
# all_addr_holders will be {(0x4c64c4, 11): (AddressTransferringTypes.SignedExtension, 32, 64,),
|
|
1190
1191
|
# (0x4c64c4, 12); (AddressTransferringTypes.Assignment,),
|
|
1191
1192
|
# }
|
|
1192
|
-
transformations:
|
|
1193
|
+
transformations: dict[tuple[int, int], AddressTransformation] = OrderedDict()
|
|
1193
1194
|
|
|
1194
1195
|
initial_block_addr = stmt_loc[0]
|
|
1195
1196
|
all_load_stmts = sorted(self._all_qualified_load_stmts_in_slice(b, stmt_loc[0]))
|
|
@@ -1480,7 +1481,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1480
1481
|
|
|
1481
1482
|
return load_stmt_loc, load_stmt, load_size, stmts_to_remove, stmts_adding_base_addr, transformations
|
|
1482
1483
|
|
|
1483
|
-
def _find_load_pc_ite_statement(self, b: Blade, stmt_loc:
|
|
1484
|
+
def _find_load_pc_ite_statement(self, b: Blade, stmt_loc: tuple[int, int]):
|
|
1484
1485
|
"""
|
|
1485
1486
|
Find the location of the final ITE statement that loads indirect jump targets into a tmp.
|
|
1486
1487
|
|
|
@@ -1658,7 +1659,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1658
1659
|
load_stmt,
|
|
1659
1660
|
load_size,
|
|
1660
1661
|
stmts_adding_base_addr,
|
|
1661
|
-
transformations:
|
|
1662
|
+
transformations: dict[tuple[int, int], AddressTransformation],
|
|
1662
1663
|
potential_call_table: bool = False,
|
|
1663
1664
|
):
|
|
1664
1665
|
"""
|
|
@@ -2302,7 +2303,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2302
2303
|
or self.project.loader.find_section_containing(addr) is not None
|
|
2303
2304
|
)
|
|
2304
2305
|
|
|
2305
|
-
def _all_qualified_load_stmts_in_slice(self, b: Blade, addr: int) ->
|
|
2306
|
+
def _all_qualified_load_stmts_in_slice(self, b: Blade, addr: int) -> list[int]:
|
|
2306
2307
|
"""
|
|
2307
2308
|
Recognize all qualified load statements in a slice. A qualified load statements refers to those that are
|
|
2308
2309
|
loading jump targets (or jump offsets) from a jump table, or loading jump table offsets from a jump-table
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# pylint:disable=too-many-boolean-expressions,global-statement
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
import pyvex
|
|
@@ -203,7 +203,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
203
203
|
l.info("Indirect jump at %#x cannot be resolved by %s.", addr, repr(self))
|
|
204
204
|
return False, []
|
|
205
205
|
|
|
206
|
-
def _try_handle_simple_case_0(self, gp: int, blade: Blade) ->
|
|
206
|
+
def _try_handle_simple_case_0(self, gp: int, blade: Blade) -> int | None:
|
|
207
207
|
# we only attempt to support the following case:
|
|
208
208
|
# + A | t37 = GET:I32(gp)
|
|
209
209
|
# + B | t36 = Add32(t37,0xffff8624)
|
|
@@ -307,7 +307,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
307
307
|
except KeyError:
|
|
308
308
|
return None
|
|
309
309
|
|
|
310
|
-
def _try_handle_simple_case_1(self, gp: int, blade: Blade) ->
|
|
310
|
+
def _try_handle_simple_case_1(self, gp: int, blade: Blade) -> int | None:
|
|
311
311
|
# we only attempt to support the following case:
|
|
312
312
|
# + A | t22 = GET:I32(gp)
|
|
313
313
|
# + B | t21 = Add32(t22,0xffff8020)
|
|
@@ -456,7 +456,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
456
456
|
return None
|
|
457
457
|
|
|
458
458
|
@staticmethod
|
|
459
|
-
def _previous_node(blade: Blade, curr_node:
|
|
459
|
+
def _previous_node(blade: Blade, curr_node: tuple[int, int]) -> tuple[int, int] | None:
|
|
460
460
|
if blade.slice.in_degree(curr_node) != 1:
|
|
461
461
|
return None
|
|
462
462
|
nn = next(iter(blade.slice.predecessors(curr_node)))
|
|
@@ -493,7 +493,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
493
493
|
@staticmethod
|
|
494
494
|
def _is_gp_used_on_slice(project, b: Blade) -> bool:
|
|
495
495
|
gp_offset = project.arch.registers["gp"][0]
|
|
496
|
-
blocks_on_slice:
|
|
496
|
+
blocks_on_slice: dict[int, "Block"] = {}
|
|
497
497
|
for block_addr, block_stmt_idx in b.slice.nodes():
|
|
498
498
|
if block_addr not in blocks_on_slice:
|
|
499
499
|
blocks_on_slice[block_addr] = project.factory.block(block_addr, cross_insn_opt=False)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any
|
|
2
2
|
from functools import reduce
|
|
3
3
|
|
|
4
4
|
from .transitions import merge_transitions
|
|
@@ -56,7 +56,7 @@ class CFGSliceToSink:
|
|
|
56
56
|
return set(reduce(lambda acc, destinations: acc + destinations, self._transitions.values(), []))
|
|
57
57
|
|
|
58
58
|
@property
|
|
59
|
-
def nodes(self) ->
|
|
59
|
+
def nodes(self) -> list[int]:
|
|
60
60
|
"""
|
|
61
61
|
:return: The complete list of addresses present in the slice.
|
|
62
62
|
"""
|
|
@@ -91,7 +91,7 @@ class CFGSliceToSink:
|
|
|
91
91
|
"""
|
|
92
92
|
return not bool(self._transitions)
|
|
93
93
|
|
|
94
|
-
def path_between(self, source: int, destination: int, visited:
|
|
94
|
+
def path_between(self, source: int, destination: int, visited: set[Any] | None = None) -> bool:
|
|
95
95
|
"""
|
|
96
96
|
Check the existence of a path in the slice between two given node adresses.
|
|
97
97
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# pylint:disable=import-outside-toplevel
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional, TYPE_CHECKING
|
|
3
|
+
from collections.abc import Callable, Iterable
|
|
3
4
|
import queue
|
|
4
5
|
import threading
|
|
5
6
|
import time
|
|
@@ -40,17 +41,17 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
40
41
|
recover_variables=False,
|
|
41
42
|
low_priority=False,
|
|
42
43
|
force=False,
|
|
43
|
-
cfg:
|
|
44
|
+
cfg: CFGModel | None = None,
|
|
44
45
|
analyze_callsites: bool = False,
|
|
45
46
|
skip_signature_matched_functions: bool = False,
|
|
46
|
-
max_function_blocks:
|
|
47
|
-
max_function_size:
|
|
47
|
+
max_function_blocks: int | None = None,
|
|
48
|
+
max_function_size: int | None = None,
|
|
48
49
|
workers: int = 0,
|
|
49
|
-
cc_callback:
|
|
50
|
-
prioritize_func_addrs:
|
|
50
|
+
cc_callback: Callable | None = None,
|
|
51
|
+
prioritize_func_addrs: Iterable[int] | None = None,
|
|
51
52
|
skip_other_funcs: bool = False,
|
|
52
53
|
auto_start: bool = True,
|
|
53
|
-
func_graphs:
|
|
54
|
+
func_graphs: dict[int, "networkx.DiGraph"] | None = None,
|
|
54
55
|
):
|
|
55
56
|
"""
|
|
56
57
|
|
|
@@ -84,7 +85,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
84
85
|
self._auto_start = auto_start
|
|
85
86
|
self._total_funcs = None
|
|
86
87
|
self._func_graphs = {} if not func_graphs else func_graphs
|
|
87
|
-
self.prototype_libnames:
|
|
88
|
+
self.prototype_libnames: set[str] = set()
|
|
88
89
|
|
|
89
90
|
self._func_addrs = [] # a list that holds addresses of all functions to be analyzed
|
|
90
91
|
self._results = []
|
|
@@ -160,7 +161,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
160
161
|
self._prioritize_func_addrs = None # no longer useful
|
|
161
162
|
|
|
162
163
|
def _set_function_prototype(
|
|
163
|
-
self, func: "Function", prototype: Optional["SimTypeFunction"], prototype_libname:
|
|
164
|
+
self, func: "Function", prototype: Optional["SimTypeFunction"], prototype_libname: str | None
|
|
164
165
|
) -> None:
|
|
165
166
|
if func.prototype is None or func.is_prototype_guessed or self._force:
|
|
166
167
|
func.is_prototype_guessed = True
|
|
@@ -294,7 +295,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
294
295
|
continue
|
|
295
296
|
|
|
296
297
|
if callee_info is not None:
|
|
297
|
-
callee_info:
|
|
298
|
+
callee_info: dict[int, tuple[Optional["SimCC"], Optional["SimTypeFunction"], str | None]]
|
|
298
299
|
for callee, (callee_cc, callee_proto, callee_proto_libname) in callee_info.items():
|
|
299
300
|
callee_func = self.kb.functions.get_by_addr(callee)
|
|
300
301
|
callee_func.calling_convention = callee_cc
|
|
@@ -315,7 +316,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
315
316
|
|
|
316
317
|
def _analyze_core(
|
|
317
318
|
self, func_addr: int
|
|
318
|
-
) ->
|
|
319
|
+
) -> tuple[Optional["SimCC"], Optional["SimTypeFunction"], Optional["str"], Optional["VariableManagerInternal"]]:
|
|
319
320
|
func = self.kb.functions.get_by_addr(func_addr)
|
|
320
321
|
if func.ran_cca:
|
|
321
322
|
return (
|
|
@@ -384,7 +385,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
384
385
|
|
|
385
386
|
def _get_callees_cc_prototypes(
|
|
386
387
|
self, caller_func_addr: int
|
|
387
|
-
) ->
|
|
388
|
+
) -> dict[int, tuple[Optional["SimCC"], Optional["SimTypeFunction"], str | None]]:
|
|
388
389
|
d = {}
|
|
389
390
|
for callee in self.kb.functions.callgraph.successors(caller_func_addr):
|
|
390
391
|
if callee != caller_func_addr and callee not in d:
|