angr 9.2.156__cp310-cp310-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.

Files changed (1393) hide show
  1. angr/__init__.py +363 -0
  2. angr/__main__.py +152 -0
  3. angr/analyses/__init__.py +113 -0
  4. angr/analyses/analysis.py +407 -0
  5. angr/analyses/backward_slice.py +686 -0
  6. angr/analyses/binary_optimizer.py +670 -0
  7. angr/analyses/bindiff.py +1512 -0
  8. angr/analyses/boyscout.py +76 -0
  9. angr/analyses/callee_cleanup_finder.py +74 -0
  10. angr/analyses/calling_convention/__init__.py +6 -0
  11. angr/analyses/calling_convention/calling_convention.py +1092 -0
  12. angr/analyses/calling_convention/fact_collector.py +636 -0
  13. angr/analyses/calling_convention/utils.py +60 -0
  14. angr/analyses/cdg.py +189 -0
  15. angr/analyses/cfg/__init__.py +23 -0
  16. angr/analyses/cfg/cfb.py +428 -0
  17. angr/analyses/cfg/cfg.py +74 -0
  18. angr/analyses/cfg/cfg_arch_options.py +95 -0
  19. angr/analyses/cfg/cfg_base.py +2886 -0
  20. angr/analyses/cfg/cfg_emulated.py +3447 -0
  21. angr/analyses/cfg/cfg_fast.py +5273 -0
  22. angr/analyses/cfg/cfg_fast_soot.py +662 -0
  23. angr/analyses/cfg/cfg_job_base.py +203 -0
  24. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +28 -0
  25. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
  26. angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
  27. angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +149 -0
  28. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +186 -0
  29. angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
  30. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +76 -0
  31. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2367 -0
  32. angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
  33. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
  34. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
  35. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
  36. angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
  37. angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
  38. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
  39. angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
  40. angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
  41. angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
  42. angr/analyses/cfg_slice_to_sink/graph.py +87 -0
  43. angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
  44. angr/analyses/class_identifier.py +63 -0
  45. angr/analyses/code_tagging.py +123 -0
  46. angr/analyses/codecave.py +77 -0
  47. angr/analyses/complete_calling_conventions.py +461 -0
  48. angr/analyses/congruency_check.py +377 -0
  49. angr/analyses/data_dep/__init__.py +16 -0
  50. angr/analyses/data_dep/data_dependency_analysis.py +595 -0
  51. angr/analyses/data_dep/dep_nodes.py +171 -0
  52. angr/analyses/data_dep/sim_act_location.py +49 -0
  53. angr/analyses/datagraph_meta.py +105 -0
  54. angr/analyses/ddg.py +1670 -0
  55. angr/analyses/decompiler/__init__.py +41 -0
  56. angr/analyses/decompiler/ail_simplifier.py +1872 -0
  57. angr/analyses/decompiler/ailgraph_walker.py +49 -0
  58. angr/analyses/decompiler/block_io_finder.py +302 -0
  59. angr/analyses/decompiler/block_similarity.py +196 -0
  60. angr/analyses/decompiler/block_simplifier.py +371 -0
  61. angr/analyses/decompiler/callsite_maker.py +555 -0
  62. angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
  63. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +580 -0
  64. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +20 -0
  65. angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +313 -0
  66. angr/analyses/decompiler/clinic.py +3222 -0
  67. angr/analyses/decompiler/condition_processor.py +1245 -0
  68. angr/analyses/decompiler/counters/__init__.py +16 -0
  69. angr/analyses/decompiler/counters/boolean_counter.py +27 -0
  70. angr/analyses/decompiler/counters/call_counter.py +47 -0
  71. angr/analyses/decompiler/counters/expression_counters.py +77 -0
  72. angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
  73. angr/analyses/decompiler/decompilation_cache.py +46 -0
  74. angr/analyses/decompiler/decompilation_options.py +275 -0
  75. angr/analyses/decompiler/decompiler.py +692 -0
  76. angr/analyses/decompiler/dephication/__init__.py +6 -0
  77. angr/analyses/decompiler/dephication/dephication_base.py +89 -0
  78. angr/analyses/decompiler/dephication/graph_dephication.py +63 -0
  79. angr/analyses/decompiler/dephication/graph_rewriting.py +116 -0
  80. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +326 -0
  81. angr/analyses/decompiler/dephication/rewriting_engine.py +504 -0
  82. angr/analyses/decompiler/dephication/seqnode_dephication.py +134 -0
  83. angr/analyses/decompiler/empty_node_remover.py +212 -0
  84. angr/analyses/decompiler/expression_narrower.py +287 -0
  85. angr/analyses/decompiler/goto_manager.py +112 -0
  86. angr/analyses/decompiler/graph_region.py +398 -0
  87. angr/analyses/decompiler/jump_target_collector.py +37 -0
  88. angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
  89. angr/analyses/decompiler/label_collector.py +32 -0
  90. angr/analyses/decompiler/optimization_passes/__init__.py +151 -0
  91. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
  92. angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
  93. angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
  94. angr/analyses/decompiler/optimization_passes/condition_constprop.py +219 -0
  95. angr/analyses/decompiler/optimization_passes/const_derefs.py +266 -0
  96. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
  97. angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
  98. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
  99. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
  100. angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
  101. angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
  102. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
  103. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1218 -0
  104. angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
  105. angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
  106. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
  107. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +165 -0
  108. angr/analyses/decompiler/optimization_passes/engine_base.py +500 -0
  109. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +135 -0
  110. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
  111. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +615 -0
  112. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
  113. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +335 -0
  114. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +922 -0
  115. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
  116. angr/analyses/decompiler/optimization_passes/optimization_pass.py +659 -0
  117. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +221 -0
  118. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
  119. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
  120. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +640 -0
  121. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
  122. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +235 -0
  123. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
  124. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +149 -0
  125. angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
  126. angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
  127. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +421 -0
  128. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
  129. angr/analyses/decompiler/peephole_optimizations/__init__.py +127 -0
  130. angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
  131. angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
  132. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
  133. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
  134. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
  135. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py +57 -0
  136. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
  137. angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
  138. angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
  139. angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
  140. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
  141. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
  142. angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
  143. angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
  144. angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
  145. angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +115 -0
  146. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
  147. angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
  148. angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
  149. angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +189 -0
  150. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
  151. angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
  152. angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
  153. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +372 -0
  154. angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
  155. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +160 -0
  156. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +109 -0
  157. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +170 -0
  158. angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
  159. angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
  160. angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
  161. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
  162. angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
  163. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
  164. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +116 -0
  165. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +247 -0
  166. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
  167. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
  168. angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
  169. angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
  170. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
  171. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +44 -0
  172. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
  173. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
  174. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
  175. angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
  176. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
  177. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +112 -0
  178. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
  179. angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
  180. angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +53 -0
  181. angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
  182. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
  183. angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
  184. angr/analyses/decompiler/presets/__init__.py +20 -0
  185. angr/analyses/decompiler/presets/basic.py +32 -0
  186. angr/analyses/decompiler/presets/fast.py +58 -0
  187. angr/analyses/decompiler/presets/full.py +68 -0
  188. angr/analyses/decompiler/presets/preset.py +37 -0
  189. angr/analyses/decompiler/redundant_label_remover.py +134 -0
  190. angr/analyses/decompiler/region_identifier.py +1218 -0
  191. angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
  192. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
  193. angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
  194. angr/analyses/decompiler/region_simplifiers/expr_folding.py +789 -0
  195. angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
  196. angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
  197. angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
  198. angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
  199. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
  200. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +234 -0
  201. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
  202. angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
  203. angr/analyses/decompiler/region_walker.py +24 -0
  204. angr/analyses/decompiler/return_maker.py +72 -0
  205. angr/analyses/decompiler/seq_to_blocks.py +20 -0
  206. angr/analyses/decompiler/sequence_walker.py +257 -0
  207. angr/analyses/decompiler/ssailification/__init__.py +4 -0
  208. angr/analyses/decompiler/ssailification/rewriting.py +379 -0
  209. angr/analyses/decompiler/ssailification/rewriting_engine.py +1053 -0
  210. angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
  211. angr/analyses/decompiler/ssailification/ssailification.py +276 -0
  212. angr/analyses/decompiler/ssailification/traversal.py +124 -0
  213. angr/analyses/decompiler/ssailification/traversal_engine.py +297 -0
  214. angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
  215. angr/analyses/decompiler/stack_item.py +36 -0
  216. angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
  217. angr/analyses/decompiler/structured_codegen/base.py +132 -0
  218. angr/analyses/decompiler/structured_codegen/c.py +4069 -0
  219. angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
  220. angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
  221. angr/analyses/decompiler/structuring/__init__.py +30 -0
  222. angr/analyses/decompiler/structuring/dream.py +1217 -0
  223. angr/analyses/decompiler/structuring/phoenix.py +2999 -0
  224. angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
  225. angr/analyses/decompiler/structuring/sailr.py +112 -0
  226. angr/analyses/decompiler/structuring/structurer_base.py +1067 -0
  227. angr/analyses/decompiler/structuring/structurer_nodes.py +438 -0
  228. angr/analyses/decompiler/utils.py +1106 -0
  229. angr/analyses/deobfuscator/__init__.py +18 -0
  230. angr/analyses/deobfuscator/api_obf_finder.py +325 -0
  231. angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +51 -0
  232. angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
  233. angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
  234. angr/analyses/deobfuscator/string_obf_finder.py +861 -0
  235. angr/analyses/deobfuscator/string_obf_opt_passes.py +133 -0
  236. angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
  237. angr/analyses/disassembly.py +1301 -0
  238. angr/analyses/disassembly_utils.py +101 -0
  239. angr/analyses/dominance_frontier.py +57 -0
  240. angr/analyses/fcp/__init__.py +4 -0
  241. angr/analyses/fcp/fcp.py +426 -0
  242. angr/analyses/find_objects_static.py +205 -0
  243. angr/analyses/flirt/__init__.py +47 -0
  244. angr/analyses/flirt/consts.py +160 -0
  245. angr/analyses/flirt/flirt.py +244 -0
  246. angr/analyses/flirt/flirt_function.py +20 -0
  247. angr/analyses/flirt/flirt_matcher.py +351 -0
  248. angr/analyses/flirt/flirt_module.py +32 -0
  249. angr/analyses/flirt/flirt_node.py +23 -0
  250. angr/analyses/flirt/flirt_sig.py +356 -0
  251. angr/analyses/flirt/flirt_utils.py +31 -0
  252. angr/analyses/forward_analysis/__init__.py +12 -0
  253. angr/analyses/forward_analysis/forward_analysis.py +530 -0
  254. angr/analyses/forward_analysis/job_info.py +64 -0
  255. angr/analyses/forward_analysis/visitors/__init__.py +14 -0
  256. angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
  257. angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
  258. angr/analyses/forward_analysis/visitors/graph.py +242 -0
  259. angr/analyses/forward_analysis/visitors/loop.py +29 -0
  260. angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
  261. angr/analyses/identifier/__init__.py +5 -0
  262. angr/analyses/identifier/custom_callable.py +137 -0
  263. angr/analyses/identifier/errors.py +10 -0
  264. angr/analyses/identifier/func.py +60 -0
  265. angr/analyses/identifier/functions/__init__.py +37 -0
  266. angr/analyses/identifier/functions/atoi.py +73 -0
  267. angr/analyses/identifier/functions/based_atoi.py +125 -0
  268. angr/analyses/identifier/functions/fdprintf.py +123 -0
  269. angr/analyses/identifier/functions/free.py +64 -0
  270. angr/analyses/identifier/functions/int2str.py +287 -0
  271. angr/analyses/identifier/functions/malloc.py +111 -0
  272. angr/analyses/identifier/functions/memcmp.py +67 -0
  273. angr/analyses/identifier/functions/memcpy.py +89 -0
  274. angr/analyses/identifier/functions/memset.py +43 -0
  275. angr/analyses/identifier/functions/printf.py +123 -0
  276. angr/analyses/identifier/functions/recv_until.py +312 -0
  277. angr/analyses/identifier/functions/skip_calloc.py +73 -0
  278. angr/analyses/identifier/functions/skip_realloc.py +97 -0
  279. angr/analyses/identifier/functions/skip_recv_n.py +105 -0
  280. angr/analyses/identifier/functions/snprintf.py +112 -0
  281. angr/analyses/identifier/functions/sprintf.py +116 -0
  282. angr/analyses/identifier/functions/strcasecmp.py +33 -0
  283. angr/analyses/identifier/functions/strcmp.py +113 -0
  284. angr/analyses/identifier/functions/strcpy.py +43 -0
  285. angr/analyses/identifier/functions/strlen.py +27 -0
  286. angr/analyses/identifier/functions/strncmp.py +104 -0
  287. angr/analyses/identifier/functions/strncpy.py +65 -0
  288. angr/analyses/identifier/functions/strtol.py +89 -0
  289. angr/analyses/identifier/identify.py +825 -0
  290. angr/analyses/identifier/runner.py +360 -0
  291. angr/analyses/init_finder.py +289 -0
  292. angr/analyses/loop_analysis.py +349 -0
  293. angr/analyses/loopfinder.py +171 -0
  294. angr/analyses/patchfinder.py +137 -0
  295. angr/analyses/pathfinder.py +282 -0
  296. angr/analyses/propagator/__init__.py +5 -0
  297. angr/analyses/propagator/engine_base.py +62 -0
  298. angr/analyses/propagator/engine_vex.py +297 -0
  299. angr/analyses/propagator/propagator.py +361 -0
  300. angr/analyses/propagator/top_checker_mixin.py +218 -0
  301. angr/analyses/propagator/values.py +117 -0
  302. angr/analyses/propagator/vex_vars.py +68 -0
  303. angr/analyses/proximity_graph.py +444 -0
  304. angr/analyses/reaching_definitions/__init__.py +67 -0
  305. angr/analyses/reaching_definitions/call_trace.py +73 -0
  306. angr/analyses/reaching_definitions/dep_graph.py +433 -0
  307. angr/analyses/reaching_definitions/engine_ail.py +1130 -0
  308. angr/analyses/reaching_definitions/engine_vex.py +1127 -0
  309. angr/analyses/reaching_definitions/external_codeloc.py +0 -0
  310. angr/analyses/reaching_definitions/function_handler.py +637 -0
  311. angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
  312. angr/analyses/reaching_definitions/function_handler_library/stdio.py +268 -0
  313. angr/analyses/reaching_definitions/function_handler_library/stdlib.py +189 -0
  314. angr/analyses/reaching_definitions/function_handler_library/string.py +147 -0
  315. angr/analyses/reaching_definitions/function_handler_library/unistd.py +44 -0
  316. angr/analyses/reaching_definitions/heap_allocator.py +70 -0
  317. angr/analyses/reaching_definitions/rd_initializer.py +237 -0
  318. angr/analyses/reaching_definitions/rd_state.py +579 -0
  319. angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
  320. angr/analyses/reaching_definitions/subject.py +65 -0
  321. angr/analyses/reassembler.py +2900 -0
  322. angr/analyses/s_liveness.py +203 -0
  323. angr/analyses/s_propagator.py +544 -0
  324. angr/analyses/s_reaching_definitions/__init__.py +12 -0
  325. angr/analyses/s_reaching_definitions/s_rda_model.py +135 -0
  326. angr/analyses/s_reaching_definitions/s_rda_view.py +315 -0
  327. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +174 -0
  328. angr/analyses/smc.py +161 -0
  329. angr/analyses/soot_class_hierarchy.py +273 -0
  330. angr/analyses/stack_pointer_tracker.py +957 -0
  331. angr/analyses/static_hooker.py +53 -0
  332. angr/analyses/typehoon/__init__.py +5 -0
  333. angr/analyses/typehoon/dfa.py +118 -0
  334. angr/analyses/typehoon/lifter.py +122 -0
  335. angr/analyses/typehoon/simple_solver.py +1450 -0
  336. angr/analyses/typehoon/translator.py +279 -0
  337. angr/analyses/typehoon/typeconsts.py +336 -0
  338. angr/analyses/typehoon/typehoon.py +305 -0
  339. angr/analyses/typehoon/typevars.py +578 -0
  340. angr/analyses/typehoon/variance.py +11 -0
  341. angr/analyses/unpacker/__init__.py +6 -0
  342. angr/analyses/unpacker/obfuscation_detector.py +103 -0
  343. angr/analyses/unpacker/packing_detector.py +138 -0
  344. angr/analyses/variable_recovery/__init__.py +9 -0
  345. angr/analyses/variable_recovery/annotations.py +58 -0
  346. angr/analyses/variable_recovery/engine_ail.py +891 -0
  347. angr/analyses/variable_recovery/engine_base.py +1185 -0
  348. angr/analyses/variable_recovery/engine_vex.py +593 -0
  349. angr/analyses/variable_recovery/irsb_scanner.py +143 -0
  350. angr/analyses/variable_recovery/variable_recovery.py +573 -0
  351. angr/analyses/variable_recovery/variable_recovery_base.py +461 -0
  352. angr/analyses/variable_recovery/variable_recovery_fast.py +652 -0
  353. angr/analyses/veritesting.py +626 -0
  354. angr/analyses/vfg.py +1898 -0
  355. angr/analyses/vsa_ddg.py +420 -0
  356. angr/analyses/vtable.py +92 -0
  357. angr/analyses/xrefs.py +286 -0
  358. angr/angrdb/__init__.py +14 -0
  359. angr/angrdb/db.py +206 -0
  360. angr/angrdb/models.py +184 -0
  361. angr/angrdb/serializers/__init__.py +10 -0
  362. angr/angrdb/serializers/cfg_model.py +41 -0
  363. angr/angrdb/serializers/comments.py +60 -0
  364. angr/angrdb/serializers/funcs.py +61 -0
  365. angr/angrdb/serializers/kb.py +111 -0
  366. angr/angrdb/serializers/labels.py +59 -0
  367. angr/angrdb/serializers/loader.py +165 -0
  368. angr/angrdb/serializers/structured_code.py +125 -0
  369. angr/angrdb/serializers/variables.py +58 -0
  370. angr/angrdb/serializers/xrefs.py +48 -0
  371. angr/annocfg.py +317 -0
  372. angr/blade.py +426 -0
  373. angr/block.py +509 -0
  374. angr/callable.py +168 -0
  375. angr/calling_conventions.py +2580 -0
  376. angr/code_location.py +163 -0
  377. angr/codenode.py +145 -0
  378. angr/concretization_strategies/__init__.py +32 -0
  379. angr/concretization_strategies/any.py +17 -0
  380. angr/concretization_strategies/any_named.py +35 -0
  381. angr/concretization_strategies/base.py +81 -0
  382. angr/concretization_strategies/controlled_data.py +58 -0
  383. angr/concretization_strategies/eval.py +19 -0
  384. angr/concretization_strategies/logging.py +35 -0
  385. angr/concretization_strategies/max.py +25 -0
  386. angr/concretization_strategies/nonzero.py +16 -0
  387. angr/concretization_strategies/nonzero_range.py +22 -0
  388. angr/concretization_strategies/norepeats.py +37 -0
  389. angr/concretization_strategies/norepeats_range.py +37 -0
  390. angr/concretization_strategies/range.py +19 -0
  391. angr/concretization_strategies/signed_add.py +31 -0
  392. angr/concretization_strategies/single.py +15 -0
  393. angr/concretization_strategies/solutions.py +20 -0
  394. angr/concretization_strategies/unlimited_range.py +17 -0
  395. angr/distributed/__init__.py +9 -0
  396. angr/distributed/server.py +197 -0
  397. angr/distributed/worker.py +185 -0
  398. angr/engines/__init__.py +67 -0
  399. angr/engines/engine.py +29 -0
  400. angr/engines/failure.py +27 -0
  401. angr/engines/hook.py +68 -0
  402. angr/engines/light/__init__.py +23 -0
  403. angr/engines/light/data.py +681 -0
  404. angr/engines/light/engine.py +1285 -0
  405. angr/engines/pcode/__init__.py +9 -0
  406. angr/engines/pcode/behavior.py +997 -0
  407. angr/engines/pcode/cc.py +128 -0
  408. angr/engines/pcode/emulate.py +443 -0
  409. angr/engines/pcode/engine.py +242 -0
  410. angr/engines/pcode/lifter.py +1428 -0
  411. angr/engines/procedure.py +70 -0
  412. angr/engines/soot/__init__.py +5 -0
  413. angr/engines/soot/engine.py +410 -0
  414. angr/engines/soot/exceptions.py +17 -0
  415. angr/engines/soot/expressions/__init__.py +87 -0
  416. angr/engines/soot/expressions/arrayref.py +22 -0
  417. angr/engines/soot/expressions/base.py +21 -0
  418. angr/engines/soot/expressions/binop.py +28 -0
  419. angr/engines/soot/expressions/cast.py +22 -0
  420. angr/engines/soot/expressions/condition.py +35 -0
  421. angr/engines/soot/expressions/constants.py +47 -0
  422. angr/engines/soot/expressions/instanceOf.py +15 -0
  423. angr/engines/soot/expressions/instancefieldref.py +8 -0
  424. angr/engines/soot/expressions/invoke.py +114 -0
  425. angr/engines/soot/expressions/length.py +8 -0
  426. angr/engines/soot/expressions/local.py +8 -0
  427. angr/engines/soot/expressions/new.py +16 -0
  428. angr/engines/soot/expressions/newArray.py +54 -0
  429. angr/engines/soot/expressions/newMultiArray.py +86 -0
  430. angr/engines/soot/expressions/paramref.py +8 -0
  431. angr/engines/soot/expressions/phi.py +30 -0
  432. angr/engines/soot/expressions/staticfieldref.py +8 -0
  433. angr/engines/soot/expressions/thisref.py +7 -0
  434. angr/engines/soot/expressions/unsupported.py +7 -0
  435. angr/engines/soot/field_dispatcher.py +46 -0
  436. angr/engines/soot/method_dispatcher.py +46 -0
  437. angr/engines/soot/statements/__init__.py +44 -0
  438. angr/engines/soot/statements/assign.py +30 -0
  439. angr/engines/soot/statements/base.py +79 -0
  440. angr/engines/soot/statements/goto.py +14 -0
  441. angr/engines/soot/statements/identity.py +15 -0
  442. angr/engines/soot/statements/if_.py +19 -0
  443. angr/engines/soot/statements/invoke.py +12 -0
  444. angr/engines/soot/statements/return_.py +20 -0
  445. angr/engines/soot/statements/switch.py +41 -0
  446. angr/engines/soot/statements/throw.py +15 -0
  447. angr/engines/soot/values/__init__.py +38 -0
  448. angr/engines/soot/values/arrayref.py +122 -0
  449. angr/engines/soot/values/base.py +7 -0
  450. angr/engines/soot/values/constants.py +18 -0
  451. angr/engines/soot/values/instancefieldref.py +44 -0
  452. angr/engines/soot/values/local.py +18 -0
  453. angr/engines/soot/values/paramref.py +18 -0
  454. angr/engines/soot/values/staticfieldref.py +38 -0
  455. angr/engines/soot/values/strref.py +38 -0
  456. angr/engines/soot/values/thisref.py +149 -0
  457. angr/engines/successors.py +654 -0
  458. angr/engines/syscall.py +51 -0
  459. angr/engines/unicorn.py +490 -0
  460. angr/engines/vex/__init__.py +20 -0
  461. angr/engines/vex/claripy/__init__.py +5 -0
  462. angr/engines/vex/claripy/ccall.py +2097 -0
  463. angr/engines/vex/claripy/datalayer.py +141 -0
  464. angr/engines/vex/claripy/irop.py +1276 -0
  465. angr/engines/vex/heavy/__init__.py +16 -0
  466. angr/engines/vex/heavy/actions.py +231 -0
  467. angr/engines/vex/heavy/concretizers.py +403 -0
  468. angr/engines/vex/heavy/dirty.py +466 -0
  469. angr/engines/vex/heavy/heavy.py +370 -0
  470. angr/engines/vex/heavy/inspect.py +52 -0
  471. angr/engines/vex/heavy/resilience.py +85 -0
  472. angr/engines/vex/heavy/super_fastpath.py +34 -0
  473. angr/engines/vex/lifter.py +420 -0
  474. angr/engines/vex/light/__init__.py +11 -0
  475. angr/engines/vex/light/light.py +551 -0
  476. angr/engines/vex/light/resilience.py +74 -0
  477. angr/engines/vex/light/slicing.py +52 -0
  478. angr/errors.py +609 -0
  479. angr/exploration_techniques/__init__.py +53 -0
  480. angr/exploration_techniques/base.py +126 -0
  481. angr/exploration_techniques/bucketizer.py +94 -0
  482. angr/exploration_techniques/common.py +56 -0
  483. angr/exploration_techniques/dfs.py +37 -0
  484. angr/exploration_techniques/director.py +520 -0
  485. angr/exploration_techniques/driller_core.py +100 -0
  486. angr/exploration_techniques/explorer.py +152 -0
  487. angr/exploration_techniques/lengthlimiter.py +22 -0
  488. angr/exploration_techniques/local_loop_seer.py +65 -0
  489. angr/exploration_techniques/loop_seer.py +236 -0
  490. angr/exploration_techniques/manual_mergepoint.py +82 -0
  491. angr/exploration_techniques/memory_watcher.py +43 -0
  492. angr/exploration_techniques/oppologist.py +92 -0
  493. angr/exploration_techniques/slicecutor.py +118 -0
  494. angr/exploration_techniques/spiller.py +280 -0
  495. angr/exploration_techniques/spiller_db.py +27 -0
  496. angr/exploration_techniques/stochastic.py +56 -0
  497. angr/exploration_techniques/stub_stasher.py +19 -0
  498. angr/exploration_techniques/suggestions.py +159 -0
  499. angr/exploration_techniques/tech_builder.py +49 -0
  500. angr/exploration_techniques/threading.py +69 -0
  501. angr/exploration_techniques/timeout.py +34 -0
  502. angr/exploration_techniques/tracer.py +1098 -0
  503. angr/exploration_techniques/unique.py +106 -0
  504. angr/exploration_techniques/veritesting.py +37 -0
  505. angr/factory.py +404 -0
  506. angr/flirt/__init__.py +97 -0
  507. angr/flirt/build_sig.py +305 -0
  508. angr/graph_utils.py +0 -0
  509. angr/keyed_region.py +525 -0
  510. angr/knowledge_base.py +143 -0
  511. angr/knowledge_plugins/__init__.py +43 -0
  512. angr/knowledge_plugins/callsite_prototypes.py +53 -0
  513. angr/knowledge_plugins/cfg/__init__.py +18 -0
  514. angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
  515. angr/knowledge_plugins/cfg/cfg_model.py +1045 -0
  516. angr/knowledge_plugins/cfg/cfg_node.py +536 -0
  517. angr/knowledge_plugins/cfg/indirect_jump.py +65 -0
  518. angr/knowledge_plugins/cfg/memory_data.py +156 -0
  519. angr/knowledge_plugins/comments.py +16 -0
  520. angr/knowledge_plugins/custom_strings.py +38 -0
  521. angr/knowledge_plugins/data.py +22 -0
  522. angr/knowledge_plugins/debug_variables.py +216 -0
  523. angr/knowledge_plugins/functions/__init__.py +9 -0
  524. angr/knowledge_plugins/functions/function.py +1772 -0
  525. angr/knowledge_plugins/functions/function_manager.py +526 -0
  526. angr/knowledge_plugins/functions/function_parser.py +299 -0
  527. angr/knowledge_plugins/functions/soot_function.py +128 -0
  528. angr/knowledge_plugins/indirect_jumps.py +35 -0
  529. angr/knowledge_plugins/key_definitions/__init__.py +17 -0
  530. angr/knowledge_plugins/key_definitions/atoms.py +374 -0
  531. angr/knowledge_plugins/key_definitions/constants.py +29 -0
  532. angr/knowledge_plugins/key_definitions/definition.py +214 -0
  533. angr/knowledge_plugins/key_definitions/environment.py +96 -0
  534. angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
  535. angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
  536. angr/knowledge_plugins/key_definitions/live_definitions.py +1010 -0
  537. angr/knowledge_plugins/key_definitions/liveness.py +165 -0
  538. angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
  539. angr/knowledge_plugins/key_definitions/tag.py +78 -0
  540. angr/knowledge_plugins/key_definitions/undefined.py +70 -0
  541. angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
  542. angr/knowledge_plugins/key_definitions/uses.py +178 -0
  543. angr/knowledge_plugins/labels.py +110 -0
  544. angr/knowledge_plugins/obfuscations.py +37 -0
  545. angr/knowledge_plugins/patches.py +126 -0
  546. angr/knowledge_plugins/plugin.py +24 -0
  547. angr/knowledge_plugins/propagations/__init__.py +10 -0
  548. angr/knowledge_plugins/propagations/prop_value.py +191 -0
  549. angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
  550. angr/knowledge_plugins/propagations/propagation_model.py +73 -0
  551. angr/knowledge_plugins/propagations/states.py +552 -0
  552. angr/knowledge_plugins/structured_code.py +63 -0
  553. angr/knowledge_plugins/types.py +88 -0
  554. angr/knowledge_plugins/variables/__init__.py +8 -0
  555. angr/knowledge_plugins/variables/variable_access.py +113 -0
  556. angr/knowledge_plugins/variables/variable_manager.py +1368 -0
  557. angr/knowledge_plugins/xrefs/__init__.py +12 -0
  558. angr/knowledge_plugins/xrefs/xref.py +150 -0
  559. angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
  560. angr/knowledge_plugins/xrefs/xref_types.py +16 -0
  561. angr/lib/angr_native.so +0 -0
  562. angr/misc/__init__.py +19 -0
  563. angr/misc/ansi.py +47 -0
  564. angr/misc/autoimport.py +90 -0
  565. angr/misc/bug_report.py +117 -0
  566. angr/misc/hookset.py +106 -0
  567. angr/misc/loggers.py +130 -0
  568. angr/misc/picklable_lock.py +46 -0
  569. angr/misc/plugins.py +289 -0
  570. angr/misc/telemetry.py +54 -0
  571. angr/misc/testing.py +24 -0
  572. angr/misc/ux.py +31 -0
  573. angr/procedures/__init__.py +12 -0
  574. angr/procedures/advapi32/__init__.py +0 -0
  575. angr/procedures/cgc/__init__.py +3 -0
  576. angr/procedures/cgc/_terminate.py +11 -0
  577. angr/procedures/cgc/allocate.py +75 -0
  578. angr/procedures/cgc/deallocate.py +67 -0
  579. angr/procedures/cgc/fdwait.py +65 -0
  580. angr/procedures/cgc/random.py +67 -0
  581. angr/procedures/cgc/receive.py +93 -0
  582. angr/procedures/cgc/transmit.py +65 -0
  583. angr/procedures/definitions/__init__.py +779 -0
  584. angr/procedures/definitions/cgc.py +20 -0
  585. angr/procedures/definitions/glibc.py +8372 -0
  586. angr/procedures/definitions/gnulib.py +32 -0
  587. angr/procedures/definitions/libstdcpp.py +21 -0
  588. angr/procedures/definitions/linux_kernel.py +6171 -0
  589. angr/procedures/definitions/linux_loader.py +7 -0
  590. angr/procedures/definitions/msvcr.py +16 -0
  591. angr/procedures/definitions/parse_syscalls_from_local_system.py +50 -0
  592. angr/procedures/definitions/parse_win32json.py +2553 -0
  593. angr/procedures/definitions/types_stl.py +22 -0
  594. angr/procedures/definitions/types_win32.py +34482 -0
  595. angr/procedures/definitions/wdk_api-ms-win-dx-d3dkmt-l1-1-4.py +30 -0
  596. angr/procedures/definitions/wdk_api-ms-win-dx-d3dkmt-l1-1-6.py +26 -0
  597. angr/procedures/definitions/wdk_clfs.py +140 -0
  598. angr/procedures/definitions/wdk_fltmgr.py +556 -0
  599. angr/procedures/definitions/wdk_fwpkclnt.py +30 -0
  600. angr/procedures/definitions/wdk_fwpuclnt.py +316 -0
  601. angr/procedures/definitions/wdk_gdi32.py +366 -0
  602. angr/procedures/definitions/wdk_hal.py +78 -0
  603. angr/procedures/definitions/wdk_ksecdd.py +62 -0
  604. angr/procedures/definitions/wdk_ndis.py +238 -0
  605. angr/procedures/definitions/wdk_ntoskrnl.py +3451 -0
  606. angr/procedures/definitions/wdk_offreg.py +72 -0
  607. angr/procedures/definitions/wdk_pshed.py +36 -0
  608. angr/procedures/definitions/wdk_secur32.py +40 -0
  609. angr/procedures/definitions/wdk_vhfum.py +34 -0
  610. angr/procedures/definitions/win32_aclui.py +30 -0
  611. angr/procedures/definitions/win32_activeds.py +68 -0
  612. angr/procedures/definitions/win32_advapi32.py +1684 -0
  613. angr/procedures/definitions/win32_advpack.py +124 -0
  614. angr/procedures/definitions/win32_amsi.py +38 -0
  615. angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-1.py +44 -0
  616. angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-3.py +34 -0
  617. angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-6.py +26 -0
  618. angr/procedures/definitions/win32_api-ms-win-core-apiquery-l2-1-0.py +26 -0
  619. angr/procedures/definitions/win32_api-ms-win-core-backgroundtask-l1-1-0.py +26 -0
  620. angr/procedures/definitions/win32_api-ms-win-core-comm-l1-1-1.py +26 -0
  621. angr/procedures/definitions/win32_api-ms-win-core-comm-l1-1-2.py +26 -0
  622. angr/procedures/definitions/win32_api-ms-win-core-enclave-l1-1-1.py +30 -0
  623. angr/procedures/definitions/win32_api-ms-win-core-errorhandling-l1-1-3.py +26 -0
  624. angr/procedures/definitions/win32_api-ms-win-core-featurestaging-l1-1-0.py +34 -0
  625. angr/procedures/definitions/win32_api-ms-win-core-featurestaging-l1-1-1.py +26 -0
  626. angr/procedures/definitions/win32_api-ms-win-core-file-fromapp-l1-1-0.py +46 -0
  627. angr/procedures/definitions/win32_api-ms-win-core-handle-l1-1-0.py +26 -0
  628. angr/procedures/definitions/win32_api-ms-win-core-ioring-l1-1-0.py +48 -0
  629. angr/procedures/definitions/win32_api-ms-win-core-marshal-l1-1-0.py +32 -0
  630. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-3.py +32 -0
  631. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-4.py +26 -0
  632. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-5.py +30 -0
  633. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-6.py +32 -0
  634. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-7.py +28 -0
  635. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-8.py +30 -0
  636. angr/procedures/definitions/win32_api-ms-win-core-path-l1-1-0.py +68 -0
  637. angr/procedures/definitions/win32_api-ms-win-core-psm-appnotify-l1-1-0.py +28 -0
  638. angr/procedures/definitions/win32_api-ms-win-core-psm-appnotify-l1-1-1.py +28 -0
  639. angr/procedures/definitions/win32_api-ms-win-core-realtime-l1-1-1.py +30 -0
  640. angr/procedures/definitions/win32_api-ms-win-core-realtime-l1-1-2.py +30 -0
  641. angr/procedures/definitions/win32_api-ms-win-core-slapi-l1-1-0.py +26 -0
  642. angr/procedures/definitions/win32_api-ms-win-core-state-helpers-l1-1-0.py +26 -0
  643. angr/procedures/definitions/win32_api-ms-win-core-synch-l1-2-0.py +30 -0
  644. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-0.py +26 -0
  645. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-3.py +28 -0
  646. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-4.py +28 -0
  647. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-6.py +26 -0
  648. angr/procedures/definitions/win32_api-ms-win-core-util-l1-1-1.py +28 -0
  649. angr/procedures/definitions/win32_api-ms-win-core-winrt-error-l1-1-0.py +44 -0
  650. angr/procedures/definitions/win32_api-ms-win-core-winrt-error-l1-1-1.py +38 -0
  651. angr/procedures/definitions/win32_api-ms-win-core-winrt-l1-1-0.py +40 -0
  652. angr/procedures/definitions/win32_api-ms-win-core-winrt-registration-l1-1-0.py +24 -0
  653. angr/procedures/definitions/win32_api-ms-win-core-winrt-robuffer-l1-1-0.py +24 -0
  654. angr/procedures/definitions/win32_api-ms-win-core-winrt-roparameterizediid-l1-1-0.py +28 -0
  655. angr/procedures/definitions/win32_api-ms-win-core-winrt-string-l1-1-0.py +76 -0
  656. angr/procedures/definitions/win32_api-ms-win-core-winrt-string-l1-1-1.py +24 -0
  657. angr/procedures/definitions/win32_api-ms-win-core-wow64-l1-1-1.py +30 -0
  658. angr/procedures/definitions/win32_api-ms-win-devices-query-l1-1-0.py +42 -0
  659. angr/procedures/definitions/win32_api-ms-win-devices-query-l1-1-1.py +34 -0
  660. angr/procedures/definitions/win32_api-ms-win-dx-d3dkmt-l1-1-0.py +26 -0
  661. angr/procedures/definitions/win32_api-ms-win-gaming-deviceinformation-l1-1-0.py +26 -0
  662. angr/procedures/definitions/win32_api-ms-win-gaming-expandedresources-l1-1-0.py +30 -0
  663. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-0.py +38 -0
  664. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-1.py +28 -0
  665. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-2.py +38 -0
  666. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-3.py +28 -0
  667. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-4.py +40 -0
  668. angr/procedures/definitions/win32_api-ms-win-mm-misc-l1-1-1.py +26 -0
  669. angr/procedures/definitions/win32_api-ms-win-net-isolation-l1-1-0.py +40 -0
  670. angr/procedures/definitions/win32_api-ms-win-security-base-l1-2-2.py +26 -0
  671. angr/procedures/definitions/win32_api-ms-win-security-isolatedcontainer-l1-1-0.py +26 -0
  672. angr/procedures/definitions/win32_api-ms-win-security-isolatedcontainer-l1-1-1.py +26 -0
  673. angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-3.py +26 -0
  674. angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-4.py +26 -0
  675. angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-5.py +28 -0
  676. angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-0.py +30 -0
  677. angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-1.py +36 -0
  678. angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-2.py +26 -0
  679. angr/procedures/definitions/win32_api-ms-win-shcore-stream-winrt-l1-1-0.py +28 -0
  680. angr/procedures/definitions/win32_api-ms-win-wsl-api-l1-1-0.py +38 -0
  681. angr/procedures/definitions/win32_apphelp.py +26 -0
  682. angr/procedures/definitions/win32_authz.py +90 -0
  683. angr/procedures/definitions/win32_avicap32.py +32 -0
  684. angr/procedures/definitions/win32_avifil32.py +144 -0
  685. angr/procedures/definitions/win32_avrt.py +52 -0
  686. angr/procedures/definitions/win32_bcp47mrm.py +28 -0
  687. angr/procedures/definitions/win32_bcrypt.py +130 -0
  688. angr/procedures/definitions/win32_bcryptprimitives.py +28 -0
  689. angr/procedures/definitions/win32_bluetoothapis.py +106 -0
  690. angr/procedures/definitions/win32_bthprops.py +34 -0
  691. angr/procedures/definitions/win32_bthprops_cpl.py +36 -0
  692. angr/procedures/definitions/win32_cabinet.py +68 -0
  693. angr/procedures/definitions/win32_certadm.py +60 -0
  694. angr/procedures/definitions/win32_certpoleng.py +40 -0
  695. angr/procedures/definitions/win32_cfgmgr32.py +502 -0
  696. angr/procedures/definitions/win32_chakra.py +198 -0
  697. angr/procedures/definitions/win32_cldapi.py +96 -0
  698. angr/procedures/definitions/win32_clfsw32.py +142 -0
  699. angr/procedures/definitions/win32_clusapi.py +584 -0
  700. angr/procedures/definitions/win32_comctl32.py +254 -0
  701. angr/procedures/definitions/win32_comdlg32.py +66 -0
  702. angr/procedures/definitions/win32_compstui.py +32 -0
  703. angr/procedures/definitions/win32_computecore.py +132 -0
  704. angr/procedures/definitions/win32_computenetwork.py +110 -0
  705. angr/procedures/definitions/win32_computestorage.py +48 -0
  706. angr/procedures/definitions/win32_comsvcs.py +38 -0
  707. angr/procedures/definitions/win32_coremessaging.py +24 -0
  708. angr/procedures/definitions/win32_credui.py +62 -0
  709. angr/procedures/definitions/win32_crypt32.py +482 -0
  710. angr/procedures/definitions/win32_cryptnet.py +34 -0
  711. angr/procedures/definitions/win32_cryptui.py +44 -0
  712. angr/procedures/definitions/win32_cryptxml.py +62 -0
  713. angr/procedures/definitions/win32_cscapi.py +32 -0
  714. angr/procedures/definitions/win32_d2d1.py +50 -0
  715. angr/procedures/definitions/win32_d3d10.py +78 -0
  716. angr/procedures/definitions/win32_d3d10_1.py +28 -0
  717. angr/procedures/definitions/win32_d3d11.py +30 -0
  718. angr/procedures/definitions/win32_d3d12.py +40 -0
  719. angr/procedures/definitions/win32_d3d9.py +46 -0
  720. angr/procedures/definitions/win32_d3dcompiler_47.py +76 -0
  721. angr/procedures/definitions/win32_d3dcsx.py +42 -0
  722. angr/procedures/definitions/win32_davclnt.py +60 -0
  723. angr/procedures/definitions/win32_dbgeng.py +32 -0
  724. angr/procedures/definitions/win32_dbghelp.py +462 -0
  725. angr/procedures/definitions/win32_dbgmodel.py +26 -0
  726. angr/procedures/definitions/win32_dciman32.py +64 -0
  727. angr/procedures/definitions/win32_dcomp.py +48 -0
  728. angr/procedures/definitions/win32_ddraw.py +38 -0
  729. angr/procedures/definitions/win32_deviceaccess.py +26 -0
  730. angr/procedures/definitions/win32_dflayout.py +26 -0
  731. angr/procedures/definitions/win32_dhcpcsvc.py +54 -0
  732. angr/procedures/definitions/win32_dhcpcsvc6.py +36 -0
  733. angr/procedures/definitions/win32_dhcpsapi.py +416 -0
  734. angr/procedures/definitions/win32_diagnosticdataquery.py +94 -0
  735. angr/procedures/definitions/win32_dinput8.py +26 -0
  736. angr/procedures/definitions/win32_directml.py +28 -0
  737. angr/procedures/definitions/win32_dmprocessxmlfiltered.py +26 -0
  738. angr/procedures/definitions/win32_dnsapi.py +152 -0
  739. angr/procedures/definitions/win32_drt.py +56 -0
  740. angr/procedures/definitions/win32_drtprov.py +42 -0
  741. angr/procedures/definitions/win32_drttransport.py +28 -0
  742. angr/procedures/definitions/win32_dsound.py +44 -0
  743. angr/procedures/definitions/win32_dsparse.py +62 -0
  744. angr/procedures/definitions/win32_dsprop.py +38 -0
  745. angr/procedures/definitions/win32_dssec.py +32 -0
  746. angr/procedures/definitions/win32_dsuiext.py +32 -0
  747. angr/procedures/definitions/win32_dwmapi.py +86 -0
  748. angr/procedures/definitions/win32_dwrite.py +26 -0
  749. angr/procedures/definitions/win32_dxcompiler.py +28 -0
  750. angr/procedures/definitions/win32_dxcore.py +26 -0
  751. angr/procedures/definitions/win32_dxgi.py +36 -0
  752. angr/procedures/definitions/win32_dxva2.py +100 -0
  753. angr/procedures/definitions/win32_eappcfg.py +52 -0
  754. angr/procedures/definitions/win32_eappprxy.py +60 -0
  755. angr/procedures/definitions/win32_efswrt.py +28 -0
  756. angr/procedures/definitions/win32_elscore.py +34 -0
  757. angr/procedures/definitions/win32_esent.py +482 -0
  758. angr/procedures/definitions/win32_evr.py +38 -0
  759. angr/procedures/definitions/win32_faultrep.py +32 -0
  760. angr/procedures/definitions/win32_fhsvcctl.py +38 -0
  761. angr/procedures/definitions/win32_firewallapi.py +30 -0
  762. angr/procedures/definitions/win32_fltlib.py +80 -0
  763. angr/procedures/definitions/win32_fontsub.py +28 -0
  764. angr/procedures/definitions/win32_forceinline.py +30 -0
  765. angr/procedures/definitions/win32_fwpuclnt.py +408 -0
  766. angr/procedures/definitions/win32_fxsutility.py +28 -0
  767. angr/procedures/definitions/win32_gdi32.py +886 -0
  768. angr/procedures/definitions/win32_gdiplus.py +1282 -0
  769. angr/procedures/definitions/win32_glu32.py +128 -0
  770. angr/procedures/definitions/win32_gpedit.py +36 -0
  771. angr/procedures/definitions/win32_hhctrl_ocx.py +28 -0
  772. angr/procedures/definitions/win32_hid.py +114 -0
  773. angr/procedures/definitions/win32_hlink.py +80 -0
  774. angr/procedures/definitions/win32_hrtfapo.py +26 -0
  775. angr/procedures/definitions/win32_httpapi.py +110 -0
  776. angr/procedures/definitions/win32_icm32.py +66 -0
  777. angr/procedures/definitions/win32_icmui.py +28 -0
  778. angr/procedures/definitions/win32_icu.py +2074 -0
  779. angr/procedures/definitions/win32_ieframe.py +82 -0
  780. angr/procedures/definitions/win32_imagehlp.py +76 -0
  781. angr/procedures/definitions/win32_imgutil.py +42 -0
  782. angr/procedures/definitions/win32_imm32.py +188 -0
  783. angr/procedures/definitions/win32_infocardapi.py +58 -0
  784. angr/procedures/definitions/win32_inkobjcore.py +78 -0
  785. angr/procedures/definitions/win32_iphlpapi.py +426 -0
  786. angr/procedures/definitions/win32_iscsidsc.py +182 -0
  787. angr/procedures/definitions/win32_isolatedwindowsenvironmentutils.py +28 -0
  788. angr/procedures/definitions/win32_kernel32.py +3185 -0
  789. angr/procedures/definitions/win32_kernelbase.py +36 -0
  790. angr/procedures/definitions/win32_keycredmgr.py +32 -0
  791. angr/procedures/definitions/win32_ksproxy_ax.py +36 -0
  792. angr/procedures/definitions/win32_ksuser.py +40 -0
  793. angr/procedures/definitions/win32_ktmw32.py +102 -0
  794. angr/procedures/definitions/win32_licenseprotection.py +28 -0
  795. angr/procedures/definitions/win32_loadperf.py +48 -0
  796. angr/procedures/definitions/win32_magnification.py +62 -0
  797. angr/procedures/definitions/win32_mapi32.py +156 -0
  798. angr/procedures/definitions/win32_mdmlocalmanagement.py +30 -0
  799. angr/procedures/definitions/win32_mdmregistration.py +54 -0
  800. angr/procedures/definitions/win32_mf.py +148 -0
  801. angr/procedures/definitions/win32_mfcore.py +28 -0
  802. angr/procedures/definitions/win32_mfplat.py +314 -0
  803. angr/procedures/definitions/win32_mfplay.py +26 -0
  804. angr/procedures/definitions/win32_mfreadwrite.py +34 -0
  805. angr/procedures/definitions/win32_mfsensorgroup.py +44 -0
  806. angr/procedures/definitions/win32_mfsrcsnk.py +28 -0
  807. angr/procedures/definitions/win32_mgmtapi.py +42 -0
  808. angr/procedures/definitions/win32_mi.py +26 -0
  809. angr/procedures/definitions/win32_mmdevapi.py +26 -0
  810. angr/procedures/definitions/win32_mpr.py +118 -0
  811. angr/procedures/definitions/win32_mprapi.py +248 -0
  812. angr/procedures/definitions/win32_mqrt.py +92 -0
  813. angr/procedures/definitions/win32_mrmsupport.py +78 -0
  814. angr/procedures/definitions/win32_msacm32.py +108 -0
  815. angr/procedures/definitions/win32_msajapi.py +1118 -0
  816. angr/procedures/definitions/win32_mscms.py +182 -0
  817. angr/procedures/definitions/win32_mscoree.py +78 -0
  818. angr/procedures/definitions/win32_msctfmonitor.py +30 -0
  819. angr/procedures/definitions/win32_msdelta.py +56 -0
  820. angr/procedures/definitions/win32_msdmo.py +46 -0
  821. angr/procedures/definitions/win32_msdrm.py +192 -0
  822. angr/procedures/definitions/win32_msi.py +552 -0
  823. angr/procedures/definitions/win32_msimg32.py +30 -0
  824. angr/procedures/definitions/win32_mspatcha.py +56 -0
  825. angr/procedures/definitions/win32_mspatchc.py +42 -0
  826. angr/procedures/definitions/win32_msports.py +38 -0
  827. angr/procedures/definitions/win32_msrating.py +62 -0
  828. angr/procedures/definitions/win32_mssign32.py +44 -0
  829. angr/procedures/definitions/win32_mstask.py +28 -0
  830. angr/procedures/definitions/win32_msvfw32.py +110 -0
  831. angr/procedures/definitions/win32_mswsock.py +56 -0
  832. angr/procedures/definitions/win32_mtxdm.py +26 -0
  833. angr/procedures/definitions/win32_ncrypt.py +102 -0
  834. angr/procedures/definitions/win32_ndfapi.py +56 -0
  835. angr/procedures/definitions/win32_netapi32.py +436 -0
  836. angr/procedures/definitions/win32_netsh.py +40 -0
  837. angr/procedures/definitions/win32_netshell.py +28 -0
  838. angr/procedures/definitions/win32_newdev.py +46 -0
  839. angr/procedures/definitions/win32_ninput.py +84 -0
  840. angr/procedures/definitions/win32_normaliz.py +28 -0
  841. angr/procedures/definitions/win32_ntdll.py +171 -0
  842. angr/procedures/definitions/win32_ntdllk.py +26 -0
  843. angr/procedures/definitions/win32_ntdsapi.py +186 -0
  844. angr/procedures/definitions/win32_ntlanman.py +44 -0
  845. angr/procedures/definitions/win32_odbc32.py +392 -0
  846. angr/procedures/definitions/win32_odbcbcp.py +78 -0
  847. angr/procedures/definitions/win32_ole32.py +658 -0
  848. angr/procedures/definitions/win32_oleacc.py +58 -0
  849. angr/procedures/definitions/win32_oleaut32.py +834 -0
  850. angr/procedures/definitions/win32_oledlg.py +70 -0
  851. angr/procedures/definitions/win32_ondemandconnroutehelper.py +34 -0
  852. angr/procedures/definitions/win32_opengl32.py +734 -0
  853. angr/procedures/definitions/win32_opmxbox.py +30 -0
  854. angr/procedures/definitions/win32_p2p.py +240 -0
  855. angr/procedures/definitions/win32_p2pgraph.py +98 -0
  856. angr/procedures/definitions/win32_pdh.py +220 -0
  857. angr/procedures/definitions/win32_peerdist.py +80 -0
  858. angr/procedures/definitions/win32_powrprof.py +192 -0
  859. angr/procedures/definitions/win32_prntvpt.py +46 -0
  860. angr/procedures/definitions/win32_projectedfslib.py +62 -0
  861. angr/procedures/definitions/win32_propsys.py +460 -0
  862. angr/procedures/definitions/win32_psapi.py +78 -0
  863. angr/procedures/definitions/win32_quartz.py +28 -0
  864. angr/procedures/definitions/win32_query.py +32 -0
  865. angr/procedures/definitions/win32_qwave.py +46 -0
  866. angr/procedures/definitions/win32_rasapi32.py +192 -0
  867. angr/procedures/definitions/win32_rasdlg.py +36 -0
  868. angr/procedures/definitions/win32_resutils.py +264 -0
  869. angr/procedures/definitions/win32_rometadata.py +24 -0
  870. angr/procedures/definitions/win32_rpcns4.py +146 -0
  871. angr/procedures/definitions/win32_rpcproxy.py +32 -0
  872. angr/procedures/definitions/win32_rpcrt4.py +918 -0
  873. angr/procedures/definitions/win32_rstrtmgr.py +46 -0
  874. angr/procedures/definitions/win32_rtm.py +176 -0
  875. angr/procedures/definitions/win32_rtutils.py +106 -0
  876. angr/procedures/definitions/win32_rtworkq.py +90 -0
  877. angr/procedures/definitions/win32_sas.py +26 -0
  878. angr/procedures/definitions/win32_scarddlg.py +34 -0
  879. angr/procedures/definitions/win32_schannel.py +42 -0
  880. angr/procedures/definitions/win32_sechost.py +28 -0
  881. angr/procedures/definitions/win32_secur32.py +202 -0
  882. angr/procedures/definitions/win32_sensapi.py +30 -0
  883. angr/procedures/definitions/win32_sensorsutilsv2.py +104 -0
  884. angr/procedures/definitions/win32_setupapi.py +692 -0
  885. angr/procedures/definitions/win32_sfc.py +36 -0
  886. angr/procedures/definitions/win32_shdocvw.py +30 -0
  887. angr/procedures/definitions/win32_shell32.py +512 -0
  888. angr/procedures/definitions/win32_shlwapi.py +744 -0
  889. angr/procedures/definitions/win32_slc.py +88 -0
  890. angr/procedures/definitions/win32_slcext.py +32 -0
  891. angr/procedures/definitions/win32_slwga.py +26 -0
  892. angr/procedures/definitions/win32_snmpapi.py +76 -0
  893. angr/procedures/definitions/win32_spoolss.py +76 -0
  894. angr/procedures/definitions/win32_srclient.py +26 -0
  895. angr/procedures/definitions/win32_srpapi.py +46 -0
  896. angr/procedures/definitions/win32_sspicli.py +38 -0
  897. angr/procedures/definitions/win32_sti.py +26 -0
  898. angr/procedures/definitions/win32_t2embed.py +52 -0
  899. angr/procedures/definitions/win32_tapi32.py +522 -0
  900. angr/procedures/definitions/win32_tbs.py +52 -0
  901. angr/procedures/definitions/win32_tdh.py +78 -0
  902. angr/procedures/definitions/win32_tokenbinding.py +44 -0
  903. angr/procedures/definitions/win32_traffic.py +64 -0
  904. angr/procedures/definitions/win32_txfw32.py +42 -0
  905. angr/procedures/definitions/win32_ualapi.py +32 -0
  906. angr/procedures/definitions/win32_uiautomationcore.py +220 -0
  907. angr/procedures/definitions/win32_urlmon.py +178 -0
  908. angr/procedures/definitions/win32_user32.py +1551 -0
  909. angr/procedures/definitions/win32_userenv.py +112 -0
  910. angr/procedures/definitions/win32_usp10.py +104 -0
  911. angr/procedures/definitions/win32_uxtheme.py +178 -0
  912. angr/procedures/definitions/win32_verifier.py +26 -0
  913. angr/procedures/definitions/win32_version.py +52 -0
  914. angr/procedures/definitions/win32_vertdll.py +38 -0
  915. angr/procedures/definitions/win32_virtdisk.py +82 -0
  916. angr/procedures/definitions/win32_vmdevicehost.py +50 -0
  917. angr/procedures/definitions/win32_vmsavedstatedumpprovider.py +110 -0
  918. angr/procedures/definitions/win32_vssapi.py +26 -0
  919. angr/procedures/definitions/win32_wcmapi.py +34 -0
  920. angr/procedures/definitions/win32_wdsbp.py +38 -0
  921. angr/procedures/definitions/win32_wdsclientapi.py +98 -0
  922. angr/procedures/definitions/win32_wdsmc.py +36 -0
  923. angr/procedures/definitions/win32_wdspxe.py +86 -0
  924. angr/procedures/definitions/win32_wdstptc.py +50 -0
  925. angr/procedures/definitions/win32_webauthn.py +50 -0
  926. angr/procedures/definitions/win32_webservices.py +410 -0
  927. angr/procedures/definitions/win32_websocket.py +50 -0
  928. angr/procedures/definitions/win32_wecapi.py +54 -0
  929. angr/procedures/definitions/win32_wer.py +66 -0
  930. angr/procedures/definitions/win32_wevtapi.py +94 -0
  931. angr/procedures/definitions/win32_winbio.py +132 -0
  932. angr/procedures/definitions/win32_windows_ai_machinelearning.py +26 -0
  933. angr/procedures/definitions/win32_windows_data_pdf.py +24 -0
  934. angr/procedures/definitions/win32_windows_media_mediacontrol.py +40 -0
  935. angr/procedures/definitions/win32_windows_networking.py +26 -0
  936. angr/procedures/definitions/win32_windows_ui_xaml.py +28 -0
  937. angr/procedures/definitions/win32_windowscodecs.py +42 -0
  938. angr/procedures/definitions/win32_winfax.py +136 -0
  939. angr/procedures/definitions/win32_winhttp.py +136 -0
  940. angr/procedures/definitions/win32_winhvemulation.py +32 -0
  941. angr/procedures/definitions/win32_winhvplatform.py +156 -0
  942. angr/procedures/definitions/win32_wininet.py +616 -0
  943. angr/procedures/definitions/win32_winml.py +26 -0
  944. angr/procedures/definitions/win32_winmm.py +376 -0
  945. angr/procedures/definitions/win32_winscard.py +164 -0
  946. angr/procedures/definitions/win32_winspool.py +364 -0
  947. angr/procedures/definitions/win32_winspool_drv.py +368 -0
  948. angr/procedures/definitions/win32_wintrust.py +144 -0
  949. angr/procedures/definitions/win32_winusb.py +92 -0
  950. angr/procedures/definitions/win32_wlanapi.py +144 -0
  951. angr/procedures/definitions/win32_wlanui.py +26 -0
  952. angr/procedures/definitions/win32_wldap32.py +510 -0
  953. angr/procedures/definitions/win32_wldp.py +42 -0
  954. angr/procedures/definitions/win32_wmvcore.py +46 -0
  955. angr/procedures/definitions/win32_wnvapi.py +28 -0
  956. angr/procedures/definitions/win32_wofutil.py +46 -0
  957. angr/procedures/definitions/win32_ws2_32.py +344 -0
  958. angr/procedures/definitions/win32_wscapi.py +36 -0
  959. angr/procedures/definitions/win32_wsclient.py +30 -0
  960. angr/procedures/definitions/win32_wsdapi.py +88 -0
  961. angr/procedures/definitions/win32_wsmsvc.py +90 -0
  962. angr/procedures/definitions/win32_wsnmp32.py +122 -0
  963. angr/procedures/definitions/win32_wtsapi32.py +150 -0
  964. angr/procedures/definitions/win32_xaudio2_8.py +32 -0
  965. angr/procedures/definitions/win32_xinput1_4.py +38 -0
  966. angr/procedures/definitions/win32_xinputuap.py +36 -0
  967. angr/procedures/definitions/win32_xmllite.py +36 -0
  968. angr/procedures/definitions/win32_xolehlp.py +32 -0
  969. angr/procedures/definitions/win32_xpsprint.py +28 -0
  970. angr/procedures/glibc/__ctype_b_loc.py +21 -0
  971. angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
  972. angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
  973. angr/procedures/glibc/__errno_location.py +7 -0
  974. angr/procedures/glibc/__init__.py +3 -0
  975. angr/procedures/glibc/__libc_init.py +37 -0
  976. angr/procedures/glibc/__libc_start_main.py +301 -0
  977. angr/procedures/glibc/dynamic_loading.py +20 -0
  978. angr/procedures/glibc/scanf.py +11 -0
  979. angr/procedures/glibc/sscanf.py +6 -0
  980. angr/procedures/gnulib/__init__.py +3 -0
  981. angr/procedures/gnulib/xalloc_die.py +14 -0
  982. angr/procedures/gnulib/xstrtol_fatal.py +14 -0
  983. angr/procedures/java/__init__.py +42 -0
  984. angr/procedures/java/unconstrained.py +65 -0
  985. angr/procedures/java_io/__init__.py +0 -0
  986. angr/procedures/java_io/read.py +12 -0
  987. angr/procedures/java_io/write.py +17 -0
  988. angr/procedures/java_jni/__init__.py +482 -0
  989. angr/procedures/java_jni/array_operations.py +312 -0
  990. angr/procedures/java_jni/class_and_interface_operations.py +31 -0
  991. angr/procedures/java_jni/field_access.py +173 -0
  992. angr/procedures/java_jni/global_and_local_refs.py +57 -0
  993. angr/procedures/java_jni/method_calls.py +365 -0
  994. angr/procedures/java_jni/not_implemented.py +26 -0
  995. angr/procedures/java_jni/object_operations.py +94 -0
  996. angr/procedures/java_jni/string_operations.py +87 -0
  997. angr/procedures/java_jni/version_information.py +12 -0
  998. angr/procedures/java_lang/__init__.py +0 -0
  999. angr/procedures/java_lang/character.py +30 -0
  1000. angr/procedures/java_lang/double.py +24 -0
  1001. angr/procedures/java_lang/exit.py +13 -0
  1002. angr/procedures/java_lang/getsimplename.py +18 -0
  1003. angr/procedures/java_lang/integer.py +43 -0
  1004. angr/procedures/java_lang/load_library.py +9 -0
  1005. angr/procedures/java_lang/math.py +15 -0
  1006. angr/procedures/java_lang/string.py +78 -0
  1007. angr/procedures/java_lang/stringbuilder.py +44 -0
  1008. angr/procedures/java_lang/system.py +18 -0
  1009. angr/procedures/java_util/__init__.py +0 -0
  1010. angr/procedures/java_util/collection.py +35 -0
  1011. angr/procedures/java_util/iterator.py +46 -0
  1012. angr/procedures/java_util/list.py +99 -0
  1013. angr/procedures/java_util/map.py +131 -0
  1014. angr/procedures/java_util/random.py +14 -0
  1015. angr/procedures/java_util/scanner_nextline.py +23 -0
  1016. angr/procedures/libc/__init__.py +3 -0
  1017. angr/procedures/libc/abort.py +9 -0
  1018. angr/procedures/libc/access.py +13 -0
  1019. angr/procedures/libc/atoi.py +14 -0
  1020. angr/procedures/libc/atol.py +13 -0
  1021. angr/procedures/libc/calloc.py +8 -0
  1022. angr/procedures/libc/closelog.py +10 -0
  1023. angr/procedures/libc/err.py +14 -0
  1024. angr/procedures/libc/error.py +54 -0
  1025. angr/procedures/libc/exit.py +11 -0
  1026. angr/procedures/libc/fclose.py +19 -0
  1027. angr/procedures/libc/feof.py +21 -0
  1028. angr/procedures/libc/fflush.py +16 -0
  1029. angr/procedures/libc/fgetc.py +27 -0
  1030. angr/procedures/libc/fgets.py +68 -0
  1031. angr/procedures/libc/fopen.py +63 -0
  1032. angr/procedures/libc/fprintf.py +25 -0
  1033. angr/procedures/libc/fputc.py +23 -0
  1034. angr/procedures/libc/fputs.py +24 -0
  1035. angr/procedures/libc/fread.py +24 -0
  1036. angr/procedures/libc/free.py +9 -0
  1037. angr/procedures/libc/fscanf.py +20 -0
  1038. angr/procedures/libc/fseek.py +34 -0
  1039. angr/procedures/libc/ftell.py +22 -0
  1040. angr/procedures/libc/fwrite.py +19 -0
  1041. angr/procedures/libc/getchar.py +13 -0
  1042. angr/procedures/libc/getdelim.py +99 -0
  1043. angr/procedures/libc/getegid.py +8 -0
  1044. angr/procedures/libc/geteuid.py +8 -0
  1045. angr/procedures/libc/getgid.py +8 -0
  1046. angr/procedures/libc/gets.py +68 -0
  1047. angr/procedures/libc/getuid.py +8 -0
  1048. angr/procedures/libc/malloc.py +12 -0
  1049. angr/procedures/libc/memcmp.py +69 -0
  1050. angr/procedures/libc/memcpy.py +38 -0
  1051. angr/procedures/libc/memset.py +72 -0
  1052. angr/procedures/libc/openlog.py +10 -0
  1053. angr/procedures/libc/perror.py +13 -0
  1054. angr/procedures/libc/printf.py +34 -0
  1055. angr/procedures/libc/putchar.py +13 -0
  1056. angr/procedures/libc/puts.py +19 -0
  1057. angr/procedures/libc/rand.py +8 -0
  1058. angr/procedures/libc/realloc.py +8 -0
  1059. angr/procedures/libc/rewind.py +12 -0
  1060. angr/procedures/libc/scanf.py +20 -0
  1061. angr/procedures/libc/setbuf.py +9 -0
  1062. angr/procedures/libc/setvbuf.py +7 -0
  1063. angr/procedures/libc/snprintf.py +36 -0
  1064. angr/procedures/libc/sprintf.py +25 -0
  1065. angr/procedures/libc/srand.py +7 -0
  1066. angr/procedures/libc/sscanf.py +13 -0
  1067. angr/procedures/libc/stpcpy.py +18 -0
  1068. angr/procedures/libc/strcat.py +14 -0
  1069. angr/procedures/libc/strchr.py +48 -0
  1070. angr/procedures/libc/strcmp.py +31 -0
  1071. angr/procedures/libc/strcpy.py +13 -0
  1072. angr/procedures/libc/strlen.py +114 -0
  1073. angr/procedures/libc/strncat.py +19 -0
  1074. angr/procedures/libc/strncmp.py +183 -0
  1075. angr/procedures/libc/strncpy.py +22 -0
  1076. angr/procedures/libc/strnlen.py +13 -0
  1077. angr/procedures/libc/strstr.py +101 -0
  1078. angr/procedures/libc/strtol.py +261 -0
  1079. angr/procedures/libc/strtoul.py +9 -0
  1080. angr/procedures/libc/system.py +13 -0
  1081. angr/procedures/libc/time.py +9 -0
  1082. angr/procedures/libc/tmpnam.py +20 -0
  1083. angr/procedures/libc/tolower.py +10 -0
  1084. angr/procedures/libc/toupper.py +10 -0
  1085. angr/procedures/libc/ungetc.py +20 -0
  1086. angr/procedures/libc/vsnprintf.py +17 -0
  1087. angr/procedures/libc/wchar.py +16 -0
  1088. angr/procedures/libstdcpp/__init__.py +0 -0
  1089. angr/procedures/libstdcpp/_unwind_resume.py +11 -0
  1090. angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
  1091. angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
  1092. angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
  1093. angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
  1094. angr/procedures/libstdcpp/std__terminate.py +13 -0
  1095. angr/procedures/linux_kernel/__init__.py +3 -0
  1096. angr/procedures/linux_kernel/access.py +18 -0
  1097. angr/procedures/linux_kernel/arch_prctl.py +34 -0
  1098. angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
  1099. angr/procedures/linux_kernel/brk.py +18 -0
  1100. angr/procedures/linux_kernel/cwd.py +28 -0
  1101. angr/procedures/linux_kernel/fstat.py +138 -0
  1102. angr/procedures/linux_kernel/fstat64.py +170 -0
  1103. angr/procedures/linux_kernel/futex.py +17 -0
  1104. angr/procedures/linux_kernel/getegid.py +17 -0
  1105. angr/procedures/linux_kernel/geteuid.py +17 -0
  1106. angr/procedures/linux_kernel/getgid.py +17 -0
  1107. angr/procedures/linux_kernel/getpid.py +14 -0
  1108. angr/procedures/linux_kernel/getrlimit.py +24 -0
  1109. angr/procedures/linux_kernel/gettid.py +9 -0
  1110. angr/procedures/linux_kernel/getuid.py +17 -0
  1111. angr/procedures/linux_kernel/iovec.py +47 -0
  1112. angr/procedures/linux_kernel/lseek.py +42 -0
  1113. angr/procedures/linux_kernel/mmap.py +16 -0
  1114. angr/procedures/linux_kernel/mprotect.py +42 -0
  1115. angr/procedures/linux_kernel/munmap.py +8 -0
  1116. angr/procedures/linux_kernel/openat.py +26 -0
  1117. angr/procedures/linux_kernel/set_tid_address.py +8 -0
  1118. angr/procedures/linux_kernel/sigaction.py +19 -0
  1119. angr/procedures/linux_kernel/sigprocmask.py +23 -0
  1120. angr/procedures/linux_kernel/stat.py +23 -0
  1121. angr/procedures/linux_kernel/sysinfo.py +59 -0
  1122. angr/procedures/linux_kernel/tgkill.py +10 -0
  1123. angr/procedures/linux_kernel/time.py +34 -0
  1124. angr/procedures/linux_kernel/uid.py +30 -0
  1125. angr/procedures/linux_kernel/uname.py +29 -0
  1126. angr/procedures/linux_kernel/unlink.py +22 -0
  1127. angr/procedures/linux_kernel/vsyscall.py +16 -0
  1128. angr/procedures/linux_loader/__init__.py +3 -0
  1129. angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
  1130. angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
  1131. angr/procedures/linux_loader/sim_loader.py +54 -0
  1132. angr/procedures/linux_loader/tls.py +40 -0
  1133. angr/procedures/msvcr/__getmainargs.py +16 -0
  1134. angr/procedures/msvcr/__init__.py +4 -0
  1135. angr/procedures/msvcr/_initterm.py +38 -0
  1136. angr/procedures/msvcr/fmode.py +31 -0
  1137. angr/procedures/ntdll/__init__.py +0 -0
  1138. angr/procedures/ntdll/exceptions.py +60 -0
  1139. angr/procedures/posix/__init__.py +3 -0
  1140. angr/procedures/posix/accept.py +29 -0
  1141. angr/procedures/posix/bind.py +13 -0
  1142. angr/procedures/posix/bzero.py +9 -0
  1143. angr/procedures/posix/chroot.py +27 -0
  1144. angr/procedures/posix/close.py +9 -0
  1145. angr/procedures/posix/closedir.py +7 -0
  1146. angr/procedures/posix/dup.py +56 -0
  1147. angr/procedures/posix/fcntl.py +10 -0
  1148. angr/procedures/posix/fdopen.py +76 -0
  1149. angr/procedures/posix/fileno.py +18 -0
  1150. angr/procedures/posix/fork.py +13 -0
  1151. angr/procedures/posix/getenv.py +35 -0
  1152. angr/procedures/posix/gethostbyname.py +43 -0
  1153. angr/procedures/posix/getpass.py +19 -0
  1154. angr/procedures/posix/getsockopt.py +11 -0
  1155. angr/procedures/posix/htonl.py +11 -0
  1156. angr/procedures/posix/htons.py +11 -0
  1157. angr/procedures/posix/inet_ntoa.py +59 -0
  1158. angr/procedures/posix/listen.py +13 -0
  1159. angr/procedures/posix/mmap.py +144 -0
  1160. angr/procedures/posix/open.py +18 -0
  1161. angr/procedures/posix/opendir.py +10 -0
  1162. angr/procedures/posix/poll.py +55 -0
  1163. angr/procedures/posix/pread64.py +46 -0
  1164. angr/procedures/posix/pthread.py +87 -0
  1165. angr/procedures/posix/pwrite64.py +46 -0
  1166. angr/procedures/posix/read.py +13 -0
  1167. angr/procedures/posix/readdir.py +62 -0
  1168. angr/procedures/posix/recv.py +13 -0
  1169. angr/procedures/posix/recvfrom.py +13 -0
  1170. angr/procedures/posix/select.py +48 -0
  1171. angr/procedures/posix/send.py +23 -0
  1172. angr/procedures/posix/setsockopt.py +9 -0
  1173. angr/procedures/posix/sigaction.py +23 -0
  1174. angr/procedures/posix/sim_time.py +48 -0
  1175. angr/procedures/posix/sleep.py +8 -0
  1176. angr/procedures/posix/socket.py +18 -0
  1177. angr/procedures/posix/strcasecmp.py +26 -0
  1178. angr/procedures/posix/strdup.py +18 -0
  1179. angr/procedures/posix/strtok_r.py +64 -0
  1180. angr/procedures/posix/syslog.py +15 -0
  1181. angr/procedures/posix/tz.py +9 -0
  1182. angr/procedures/posix/unlink.py +11 -0
  1183. angr/procedures/posix/usleep.py +8 -0
  1184. angr/procedures/posix/write.py +13 -0
  1185. angr/procedures/procedure_dict.py +50 -0
  1186. angr/procedures/stubs/CallReturn.py +13 -0
  1187. angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
  1188. angr/procedures/stubs/Nop.py +7 -0
  1189. angr/procedures/stubs/PathTerminator.py +9 -0
  1190. angr/procedures/stubs/Redirect.py +18 -0
  1191. angr/procedures/stubs/ReturnChar.py +11 -0
  1192. angr/procedures/stubs/ReturnUnconstrained.py +24 -0
  1193. angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
  1194. angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
  1195. angr/procedures/stubs/UserHook.py +18 -0
  1196. angr/procedures/stubs/__init__.py +3 -0
  1197. angr/procedures/stubs/b64_decode.py +15 -0
  1198. angr/procedures/stubs/caller.py +14 -0
  1199. angr/procedures/stubs/crazy_scanf.py +20 -0
  1200. angr/procedures/stubs/format_parser.py +669 -0
  1201. angr/procedures/stubs/syscall_stub.py +24 -0
  1202. angr/procedures/testing/__init__.py +3 -0
  1203. angr/procedures/testing/manyargs.py +9 -0
  1204. angr/procedures/testing/retreg.py +8 -0
  1205. angr/procedures/tracer/__init__.py +4 -0
  1206. angr/procedures/tracer/random.py +9 -0
  1207. angr/procedures/tracer/receive.py +23 -0
  1208. angr/procedures/tracer/transmit.py +26 -0
  1209. angr/procedures/uclibc/__init__.py +3 -0
  1210. angr/procedures/uclibc/__uClibc_main.py +10 -0
  1211. angr/procedures/win32/EncodePointer.py +7 -0
  1212. angr/procedures/win32/ExitProcess.py +9 -0
  1213. angr/procedures/win32/GetCommandLine.py +12 -0
  1214. angr/procedures/win32/GetCurrentProcessId.py +7 -0
  1215. angr/procedures/win32/GetCurrentThreadId.py +7 -0
  1216. angr/procedures/win32/GetLastInputInfo.py +40 -0
  1217. angr/procedures/win32/GetModuleHandle.py +29 -0
  1218. angr/procedures/win32/GetProcessAffinityMask.py +37 -0
  1219. angr/procedures/win32/InterlockedExchange.py +15 -0
  1220. angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
  1221. angr/procedures/win32/VirtualAlloc.py +114 -0
  1222. angr/procedures/win32/VirtualProtect.py +60 -0
  1223. angr/procedures/win32/__init__.py +3 -0
  1224. angr/procedures/win32/critical_section.py +12 -0
  1225. angr/procedures/win32/dynamic_loading.py +104 -0
  1226. angr/procedures/win32/file_handles.py +47 -0
  1227. angr/procedures/win32/gethostbyname.py +12 -0
  1228. angr/procedures/win32/heap.py +45 -0
  1229. angr/procedures/win32/is_bad_ptr.py +26 -0
  1230. angr/procedures/win32/local_storage.py +88 -0
  1231. angr/procedures/win32/mutex.py +11 -0
  1232. angr/procedures/win32/sim_time.py +135 -0
  1233. angr/procedures/win32/system_paths.py +35 -0
  1234. angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
  1235. angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
  1236. angr/procedures/win32_kernel/__fastfail.py +15 -0
  1237. angr/procedures/win32_kernel/__init__.py +3 -0
  1238. angr/procedures/win_user32/__init__.py +0 -0
  1239. angr/procedures/win_user32/chars.py +15 -0
  1240. angr/procedures/win_user32/keyboard.py +14 -0
  1241. angr/procedures/win_user32/messagebox.py +49 -0
  1242. angr/project.py +837 -0
  1243. angr/protos/__init__.py +19 -0
  1244. angr/protos/cfg_pb2.py +31 -0
  1245. angr/protos/function_pb2.py +27 -0
  1246. angr/protos/primitives_pb2.py +52 -0
  1247. angr/protos/variables_pb2.py +44 -0
  1248. angr/protos/xrefs_pb2.py +25 -0
  1249. angr/py.typed +1 -0
  1250. angr/rustylib.cpython-310-aarch64-linux-gnu.so +0 -0
  1251. angr/rustylib.pyi +165 -0
  1252. angr/serializable.py +66 -0
  1253. angr/sim_manager.py +971 -0
  1254. angr/sim_options.py +438 -0
  1255. angr/sim_procedure.py +606 -0
  1256. angr/sim_state.py +901 -0
  1257. angr/sim_state_options.py +403 -0
  1258. angr/sim_type.py +3679 -0
  1259. angr/sim_variable.py +434 -0
  1260. angr/simos/__init__.py +47 -0
  1261. angr/simos/cgc.py +153 -0
  1262. angr/simos/javavm.py +458 -0
  1263. angr/simos/linux.py +509 -0
  1264. angr/simos/simos.py +444 -0
  1265. angr/simos/snimmuc_nxp.py +149 -0
  1266. angr/simos/userland.py +163 -0
  1267. angr/simos/windows.py +601 -0
  1268. angr/simos/xbox.py +32 -0
  1269. angr/slicer.py +352 -0
  1270. angr/state_hierarchy.py +262 -0
  1271. angr/state_plugins/__init__.py +84 -0
  1272. angr/state_plugins/callstack.py +398 -0
  1273. angr/state_plugins/cgc.py +155 -0
  1274. angr/state_plugins/debug_variables.py +192 -0
  1275. angr/state_plugins/filesystem.py +463 -0
  1276. angr/state_plugins/gdb.py +148 -0
  1277. angr/state_plugins/globals.py +65 -0
  1278. angr/state_plugins/heap/__init__.py +15 -0
  1279. angr/state_plugins/heap/heap_base.py +128 -0
  1280. angr/state_plugins/heap/heap_brk.py +136 -0
  1281. angr/state_plugins/heap/heap_freelist.py +213 -0
  1282. angr/state_plugins/heap/heap_libc.py +46 -0
  1283. angr/state_plugins/heap/heap_ptmalloc.py +620 -0
  1284. angr/state_plugins/heap/utils.py +22 -0
  1285. angr/state_plugins/history.py +548 -0
  1286. angr/state_plugins/inspect.py +375 -0
  1287. angr/state_plugins/javavm_classloader.py +134 -0
  1288. angr/state_plugins/jni_references.py +95 -0
  1289. angr/state_plugins/libc.py +1263 -0
  1290. angr/state_plugins/light_registers.py +168 -0
  1291. angr/state_plugins/log.py +84 -0
  1292. angr/state_plugins/loop_data.py +92 -0
  1293. angr/state_plugins/plugin.py +170 -0
  1294. angr/state_plugins/posix.py +703 -0
  1295. angr/state_plugins/preconstrainer.py +196 -0
  1296. angr/state_plugins/scratch.py +173 -0
  1297. angr/state_plugins/sim_action.py +326 -0
  1298. angr/state_plugins/sim_action_object.py +271 -0
  1299. angr/state_plugins/sim_event.py +59 -0
  1300. angr/state_plugins/solver.py +1127 -0
  1301. angr/state_plugins/symbolizer.py +291 -0
  1302. angr/state_plugins/trace_additions.py +738 -0
  1303. angr/state_plugins/uc_manager.py +94 -0
  1304. angr/state_plugins/unicorn_engine.py +1886 -0
  1305. angr/state_plugins/view.py +340 -0
  1306. angr/storage/__init__.py +15 -0
  1307. angr/storage/file.py +1210 -0
  1308. angr/storage/memory_mixins/__init__.py +317 -0
  1309. angr/storage/memory_mixins/actions_mixin.py +72 -0
  1310. angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
  1311. angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
  1312. angr/storage/memory_mixins/clouseau_mixin.py +137 -0
  1313. angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
  1314. angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
  1315. angr/storage/memory_mixins/default_filler_mixin.py +144 -0
  1316. angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
  1317. angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
  1318. angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
  1319. angr/storage/memory_mixins/keyvalue_memory_mixin.py +42 -0
  1320. angr/storage/memory_mixins/label_merger_mixin.py +31 -0
  1321. angr/storage/memory_mixins/memory_mixin.py +174 -0
  1322. angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
  1323. angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
  1324. angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
  1325. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
  1326. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
  1327. angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
  1328. angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
  1329. angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
  1330. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
  1331. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
  1332. angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
  1333. angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
  1334. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
  1335. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
  1336. angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
  1337. angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
  1338. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +503 -0
  1339. angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
  1340. angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
  1341. angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
  1342. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
  1343. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
  1344. angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
  1345. angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
  1346. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
  1347. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
  1348. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +441 -0
  1349. angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
  1350. angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
  1351. angr/storage/memory_mixins/simplification_mixin.py +15 -0
  1352. angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
  1353. angr/storage/memory_mixins/slotted_memory.py +140 -0
  1354. angr/storage/memory_mixins/smart_find_mixin.py +161 -0
  1355. angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
  1356. angr/storage/memory_mixins/top_merger_mixin.py +25 -0
  1357. angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
  1358. angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
  1359. angr/storage/memory_object.py +195 -0
  1360. angr/tablespecs.py +91 -0
  1361. angr/utils/__init__.py +46 -0
  1362. angr/utils/ail.py +70 -0
  1363. angr/utils/algo.py +34 -0
  1364. angr/utils/bits.py +46 -0
  1365. angr/utils/constants.py +9 -0
  1366. angr/utils/cowdict.py +63 -0
  1367. angr/utils/cpp.py +17 -0
  1368. angr/utils/doms.py +149 -0
  1369. angr/utils/dynamic_dictlist.py +89 -0
  1370. angr/utils/endness.py +18 -0
  1371. angr/utils/enums_conv.py +97 -0
  1372. angr/utils/env.py +12 -0
  1373. angr/utils/formatting.py +128 -0
  1374. angr/utils/funcid.py +159 -0
  1375. angr/utils/graph.py +898 -0
  1376. angr/utils/lazy_import.py +13 -0
  1377. angr/utils/library.py +211 -0
  1378. angr/utils/loader.py +55 -0
  1379. angr/utils/mp.py +66 -0
  1380. angr/utils/orderedset.py +74 -0
  1381. angr/utils/ssa/__init__.py +395 -0
  1382. angr/utils/ssa/tmp_uses_collector.py +23 -0
  1383. angr/utils/ssa/vvar_uses_collector.py +37 -0
  1384. angr/utils/tagged_interval_map.py +112 -0
  1385. angr/utils/timing.py +74 -0
  1386. angr/utils/types.py +151 -0
  1387. angr/vaults.py +367 -0
  1388. angr-9.2.156.dist-info/METADATA +112 -0
  1389. angr-9.2.156.dist-info/RECORD +1393 -0
  1390. angr-9.2.156.dist-info/WHEEL +5 -0
  1391. angr-9.2.156.dist-info/entry_points.txt +2 -0
  1392. angr-9.2.156.dist-info/licenses/LICENSE +27 -0
  1393. angr-9.2.156.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3222 @@
1
+ # pylint:disable=too-many-boolean-expressions
2
+ from __future__ import annotations
3
+ from typing import Any, NamedTuple, TYPE_CHECKING
4
+ import copy
5
+ import logging
6
+ import enum
7
+ from collections import defaultdict, namedtuple
8
+ from collections.abc import Iterable
9
+ from dataclasses import dataclass
10
+
11
+ import networkx
12
+ import capstone
13
+
14
+ import ailment
15
+
16
+ from angr.errors import AngrDecompilationError
17
+ from angr.knowledge_base import KnowledgeBase
18
+ from angr.knowledge_plugins.functions import Function
19
+ from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort
20
+ from angr.knowledge_plugins.key_definitions import atoms
21
+ from angr.codenode import BlockNode
22
+ from angr.utils import timethis
23
+ from angr.utils.graph import GraphUtils
24
+ from angr.utils.types import dereference_simtype_by_lib
25
+ from angr.calling_conventions import SimRegArg, SimStackArg, SimFunctionArgument
26
+ from angr.sim_type import (
27
+ SimTypeChar,
28
+ SimTypeInt,
29
+ SimTypeLongLong,
30
+ SimTypeShort,
31
+ SimTypeFunction,
32
+ SimTypeBottom,
33
+ SimTypeFloat,
34
+ SimTypePointer,
35
+ )
36
+ from angr.analyses.stack_pointer_tracker import Register, OffsetVal
37
+ from angr.sim_variable import SimVariable, SimStackVariable, SimRegisterVariable, SimMemoryVariable
38
+ from angr.procedures.stubs.UnresolvableCallTarget import UnresolvableCallTarget
39
+ from angr.procedures.stubs.UnresolvableJumpTarget import UnresolvableJumpTarget
40
+ from angr.analyses import Analysis, register_analysis
41
+ from angr.analyses.cfg.cfg_base import CFGBase
42
+ from angr.analyses.reaching_definitions import ReachingDefinitionsAnalysis
43
+ from .ssailification.ssailification import Ssailification
44
+ from .stack_item import StackItem, StackItemType
45
+ from .return_maker import ReturnMaker
46
+ from .ailgraph_walker import AILGraphWalker, RemoveNodeNotice
47
+ from .optimization_passes import (
48
+ OptimizationPassStage,
49
+ RegisterSaveAreaSimplifier,
50
+ StackCanarySimplifier,
51
+ TagSlicer,
52
+ DUPLICATING_OPTS,
53
+ CONDENSING_OPTS,
54
+ )
55
+
56
+ if TYPE_CHECKING:
57
+ from angr.knowledge_plugins.cfg import CFGModel
58
+ from .decompilation_cache import DecompilationCache
59
+ from .peephole_optimizations import PeepholeOptimizationStmtBase, PeepholeOptimizationExprBase
60
+
61
+ l = logging.getLogger(name=__name__)
62
+
63
+
64
+ BlockCache = namedtuple("BlockCache", ("rd", "prop"))
65
+
66
+
67
+ class ClinicMode(enum.Enum):
68
+ """
69
+ Analysis mode for Clinic.
70
+ """
71
+
72
+ DECOMPILE = 1
73
+ COLLECT_DATA_REFS = 2
74
+
75
+
76
+ @dataclass
77
+ class DataRefDesc:
78
+ """
79
+ The fields of this class is compatible with items inside IRSB.data_refs.
80
+ """
81
+
82
+ data_addr: int
83
+ data_size: int
84
+ block_addr: int
85
+ stmt_idx: int
86
+ ins_addr: int
87
+ data_type_str: str
88
+
89
+
90
+ class Clinic(Analysis):
91
+ """
92
+ A Clinic deals with AILments.
93
+ """
94
+
95
+ _ail_manager: ailment.Manager
96
+
97
+ def __init__(
98
+ self,
99
+ func,
100
+ remove_dead_memdefs=False,
101
+ exception_edges=False,
102
+ sp_tracker_track_memory=True,
103
+ fold_callexprs_into_conditions=False,
104
+ insert_labels=True,
105
+ optimization_passes=None,
106
+ cfg=None,
107
+ peephole_optimizations: None | (
108
+ Iterable[type[PeepholeOptimizationStmtBase] | type[PeepholeOptimizationExprBase]]
109
+ ) = None, # pylint:disable=line-too-long
110
+ must_struct: set[str] | None = None,
111
+ variable_kb=None,
112
+ reset_variable_names=False,
113
+ rewrite_ites_to_diamonds=True,
114
+ cache: DecompilationCache | None = None,
115
+ mode: ClinicMode = ClinicMode.DECOMPILE,
116
+ sp_shift: int = 0,
117
+ inline_functions: set[Function] | None = None,
118
+ inlined_counts: dict[int, int] | None = None,
119
+ inlining_parents: set[int] | None = None,
120
+ vvar_id_start: int = 0,
121
+ optimization_scratch: dict[str, Any] | None = None,
122
+ desired_variables: set[str] | None = None,
123
+ force_loop_single_exit: bool = True,
124
+ complete_successors: bool = False,
125
+ max_type_constraints: int = 4000,
126
+ ):
127
+ if not func.normalized and mode == ClinicMode.DECOMPILE:
128
+ raise ValueError("Decompilation must work on normalized function graphs.")
129
+
130
+ self.function = func
131
+
132
+ self.graph = None
133
+ self.cc_graph: networkx.DiGraph | None = None
134
+ self.unoptimized_graph: networkx.DiGraph | None = None
135
+ self.arg_list = None
136
+ self.arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]] | None = None
137
+ self.variable_kb = variable_kb
138
+ self.externs: set[SimMemoryVariable] = set()
139
+ self.data_refs: dict[int, list[DataRefDesc]] = {} # data address to data reference description
140
+ self.optimization_scratch = optimization_scratch if optimization_scratch is not None else {}
141
+
142
+ self._func_graph: networkx.DiGraph | None = None
143
+ self._blocks_by_addr_and_size = {}
144
+ self.entry_node_addr: tuple[int, int | None] = self.function.addr, None
145
+
146
+ self._fold_callexprs_into_conditions = fold_callexprs_into_conditions
147
+ self._insert_labels = insert_labels
148
+ self._remove_dead_memdefs = remove_dead_memdefs
149
+ self._exception_edges = exception_edges
150
+ self._sp_tracker_track_memory = sp_tracker_track_memory
151
+ self._cfg: CFGModel | None = cfg
152
+ self.peephole_optimizations = peephole_optimizations
153
+ self._must_struct = must_struct
154
+ self._reset_variable_names = reset_variable_names
155
+ self._rewrite_ites_to_diamonds = rewrite_ites_to_diamonds
156
+ self.reaching_definitions: ReachingDefinitionsAnalysis | None = None
157
+ self._cache = cache
158
+ self._mode = mode
159
+ self._max_type_constraints = max_type_constraints
160
+ self.vvar_id_start = vvar_id_start
161
+ self.vvar_to_vvar: dict[int, int] | None = None
162
+ # during SSA conversion, we create secondary stack variables because they overlap and are larger than the
163
+ # actual stack variables. these secondary stack variables can be safely eliminated if not used by anything.
164
+ self.secondary_stackvars: set[int] = set()
165
+
166
+ # inlining help
167
+ self._sp_shift = sp_shift
168
+ self._max_stack_depth = 0
169
+ self._inline_functions = inline_functions if inline_functions else set()
170
+ self._inlined_counts = {} if inlined_counts is None else inlined_counts
171
+ self._inlining_parents = inlining_parents or ()
172
+ self._desired_variables = desired_variables
173
+ self._force_loop_single_exit = force_loop_single_exit
174
+ self._complete_successors = complete_successors
175
+
176
+ self._register_save_areas_removed: bool = False
177
+ self.edges_to_remove: list[tuple[tuple[int, int | None], tuple[int, int | None]]] = []
178
+ self.copied_var_ids: set[int] = set()
179
+
180
+ self._new_block_addrs = set()
181
+
182
+ # sanity checks
183
+ if not self.kb.functions:
184
+ l.warning("No function is available in kb.functions. It will lead to a suboptimal conversion result.")
185
+
186
+ if optimization_passes is not None:
187
+ self._optimization_passes = optimization_passes
188
+ else:
189
+ self._optimization_passes = []
190
+
191
+ self.stack_items: dict[int, StackItem] = {}
192
+ if self.project.arch.call_pushes_ret:
193
+ self.stack_items[0] = StackItem(0, self.project.arch.bytes, "ret_addr", StackItemType.RET_ADDR)
194
+
195
+ if self._mode == ClinicMode.DECOMPILE:
196
+ self._analyze_for_decompiling()
197
+ elif self._mode == ClinicMode.COLLECT_DATA_REFS:
198
+ self._analyze_for_data_refs()
199
+ else:
200
+ raise TypeError(f"Unsupported analysis mode {self._mode}")
201
+
202
+ #
203
+ # Public methods
204
+ #
205
+
206
+ def block(self, addr, size):
207
+ """
208
+ Get the converted block at the given specific address with the given size.
209
+
210
+ :param int addr:
211
+ :param int size:
212
+ :return:
213
+ """
214
+
215
+ try:
216
+ return self._blocks_by_addr_and_size[(addr, size)] if self._blocks_by_addr_and_size is not None else None
217
+ except KeyError:
218
+ return None
219
+
220
+ def dbg_repr(self):
221
+ """
222
+
223
+ :return:
224
+ """
225
+ assert self.graph is not None
226
+
227
+ s = ""
228
+
229
+ for block in sorted(self.graph.nodes(), key=lambda x: x.addr):
230
+ s += str(block) + "\n\n"
231
+
232
+ return s
233
+
234
+ #
235
+ # Private methods
236
+ #
237
+
238
+ def _analyze_for_decompiling(self):
239
+ if not (ail_graph := self._decompilation_graph_recovery()):
240
+ return
241
+ ail_graph = self._decompilation_fixups(ail_graph)
242
+
243
+ if self._inline_functions:
244
+ self._max_stack_depth += self.calculate_stack_depth()
245
+ ail_graph = self._inline_child_functions(ail_graph)
246
+
247
+ ail_graph = self._decompilation_simplifications(ail_graph)
248
+
249
+ if self._desired_variables:
250
+ ail_graph = self._slice_variables(ail_graph)
251
+ self.graph = ail_graph
252
+
253
+ def _decompilation_graph_recovery(self):
254
+ is_pcode_arch = ":" in self.project.arch.name
255
+
256
+ # Set up the function graph according to configurations
257
+ self._update_progress(0.0, text="Setting up function graph")
258
+ self._set_function_graph()
259
+
260
+ # Remove alignment blocks
261
+ self._update_progress(5.0, text="Removing alignment blocks")
262
+ self._remove_alignment_blocks()
263
+
264
+ # if the graph is empty, don't continue
265
+ if not self._func_graph:
266
+ return None
267
+
268
+ # Make sure calling conventions of all functions that the current function calls have been recovered
269
+ if not is_pcode_arch:
270
+ self._update_progress(10.0, text="Recovering calling conventions")
271
+ self._recover_calling_conventions()
272
+
273
+ # initialize the AIL conversion manager
274
+ self._ail_manager = ailment.Manager(arch=self.project.arch)
275
+
276
+ # Convert VEX blocks to AIL blocks and then simplify them
277
+
278
+ self._update_progress(20.0, text="Converting VEX to AIL")
279
+ self._convert_all()
280
+
281
+ return self._make_ailgraph()
282
+
283
+ def _decompilation_fixups(self, ail_graph):
284
+ is_pcode_arch = ":" in self.project.arch.name
285
+
286
+ self._remove_redundant_jump_blocks(ail_graph)
287
+ # _fix_abnormal_switch_case_heads may re-lift from VEX blocks, so it should be placed as high up as possible
288
+ self._fix_abnormal_switch_case_heads(ail_graph)
289
+ if self._rewrite_ites_to_diamonds:
290
+ self._rewrite_ite_expressions(ail_graph)
291
+ self._remove_redundant_jump_blocks(ail_graph)
292
+ if self._insert_labels:
293
+ self._insert_block_labels(ail_graph)
294
+
295
+ # Run simplification passes
296
+ self._update_progress(22.0, text="Optimizing fresh ailment graph")
297
+ ail_graph = self._run_simplification_passes(ail_graph, OptimizationPassStage.AFTER_AIL_GRAPH_CREATION)
298
+
299
+ # Fix "fake" indirect jumps and calls
300
+ self._update_progress(25.0, text="Analyzing simple indirect jumps")
301
+ ail_graph = self._replace_single_target_indirect_transitions(ail_graph)
302
+
303
+ # Fix tail calls
304
+ self._update_progress(28.0, text="Analyzing tail calls")
305
+ ail_graph = self._replace_tail_jumps_with_calls(ail_graph)
306
+
307
+ if is_pcode_arch:
308
+ self._update_progress(29.0, text="Recovering calling conventions (AIL mode)")
309
+ self._recover_calling_conventions(func_graph=ail_graph)
310
+
311
+ return self._apply_callsite_prototype_and_calling_convention(ail_graph)
312
+
313
+ def _slice_variables(self, ail_graph):
314
+ assert self.variable_kb is not None and self._desired_variables is not None
315
+
316
+ nodes_index = {(n.addr, n.idx): n for n in ail_graph.nodes()}
317
+
318
+ vfm = self.variable_kb.variables.function_managers[self.function.addr]
319
+ for v_name in self._desired_variables:
320
+ v = next(iter(vv for vv in vfm._unified_variables if vv.name == v_name))
321
+ for va in vfm.get_variable_accesses(v):
322
+ nodes_index[(va.location.block_addr, va.location.block_idx)].statements[va.location.stmt_idx].tags[
323
+ "keep_in_slice"
324
+ ] = True
325
+
326
+ a = TagSlicer(
327
+ self.function,
328
+ graph=ail_graph,
329
+ variable_kb=self.variable_kb,
330
+ )
331
+ if a.out_graph:
332
+ # use the new graph
333
+ ail_graph = a.out_graph
334
+ return ail_graph
335
+
336
+ def _inline_child_functions(self, ail_graph):
337
+ for blk in ail_graph.nodes():
338
+ for idx, stmt in enumerate(blk.statements):
339
+ if isinstance(stmt, ailment.Stmt.Call) and isinstance(stmt.target, ailment.Expr.Const):
340
+ callee = self.function._function_manager.function(stmt.target.value)
341
+ if (
342
+ callee.addr == self.function.addr
343
+ or callee.addr in self._inlining_parents
344
+ or callee not in self._inline_functions
345
+ or callee.is_plt
346
+ or callee.is_simprocedure
347
+ ):
348
+ continue
349
+
350
+ ail_graph = self._inline_call(ail_graph, blk, idx, callee)
351
+ return ail_graph
352
+
353
+ def _inline_call(self, ail_graph, caller_block, call_idx, callee):
354
+ callee_clinic = self.project.analyses.Clinic(
355
+ callee,
356
+ mode=ClinicMode.DECOMPILE,
357
+ inline_functions=self._inline_functions,
358
+ inlining_parents=(*self._inlining_parents, self.function.addr),
359
+ inlined_counts=self._inlined_counts,
360
+ optimization_passes=[StackCanarySimplifier],
361
+ sp_shift=self._max_stack_depth,
362
+ vvar_id_start=self.vvar_id_start,
363
+ fail_fast=self._fail_fast, # type: ignore
364
+ )
365
+ self.vvar_id_start = callee_clinic.vvar_id_start + 1
366
+ self._max_stack_depth = callee_clinic._max_stack_depth
367
+ callee_graph = callee_clinic.copy_graph()
368
+
369
+ # uniquely mark all the blocks in case of duplicates (e.g., foo(); foo();)
370
+ self._inlined_counts.setdefault(callee.addr, 0)
371
+ for blk in callee_graph.nodes():
372
+ blk.idx = self._inlined_counts[callee.addr]
373
+ self._inlined_counts[callee.addr] += 1
374
+
375
+ # figure out where the callee should start at and return to
376
+ callee_start = next(n for n in callee_graph if n.addr == callee.addr)
377
+ caller_successors = list(ail_graph.out_edges(caller_block, data=True))
378
+ assert len(caller_successors) == 1
379
+ caller_successor = caller_successors[0][1]
380
+ ail_graph.remove_edge(caller_block, caller_successor)
381
+
382
+ # update all callee return nodes with caller successor
383
+ ail_graph = networkx.union(ail_graph, callee_graph)
384
+ for blk in callee_graph.nodes():
385
+ for idx, stmt in enumerate(list(blk.statements)):
386
+ if isinstance(stmt, ailment.Stmt.Return):
387
+ # replace the return statement with an assignment to the return register
388
+ blk.statements.pop(idx)
389
+
390
+ if stmt.ret_exprs and self.project.arch.ret_offset is not None:
391
+ assign_to_retreg = ailment.Stmt.Assignment(
392
+ self._ail_manager.next_atom(),
393
+ ailment.Expr.Register(
394
+ self._ail_manager.next_atom(),
395
+ None,
396
+ self.project.arch.ret_offset,
397
+ self.project.arch.bits,
398
+ ),
399
+ stmt.ret_exprs[0],
400
+ **stmt.tags,
401
+ )
402
+ blk.statements.insert(idx, assign_to_retreg)
403
+ idx += 1
404
+ ail_graph.add_edge(blk, caller_successor)
405
+ break
406
+
407
+ # update the call edge
408
+ caller_block.statements[call_idx] = ailment.Stmt.Jump(
409
+ None,
410
+ ailment.Expr.Const(None, None, callee.addr, self.project.arch.bits),
411
+ callee_start.idx,
412
+ **caller_block.statements[call_idx].tags,
413
+ )
414
+ if (
415
+ isinstance(caller_block.statements[call_idx - 2], ailment.Stmt.Store)
416
+ and caller_block.statements[call_idx - 2].data.value == caller_successor.addr
417
+ ):
418
+ # don't push the return address
419
+ caller_block.statements.pop(call_idx - 5) # t6 = rsp<8>
420
+ caller_block.statements.pop(call_idx - 5) # t5 = (t6 - 0x8<64>)
421
+ caller_block.statements.pop(call_idx - 5) # rsp<8> = t5
422
+ caller_block.statements.pop(
423
+ call_idx - 5
424
+ ) # STORE(addr=t5, data=0x40121b<64>, size=8, endness=Iend_LE, guard=None)
425
+ caller_block.statements.pop(call_idx - 5) # t7 = (t5 - 0x80<64>) <- wtf is this??
426
+ elif (
427
+ isinstance(caller_block.statements[call_idx - 1], ailment.Stmt.Store)
428
+ and caller_block.statements[call_idx - 1].addr.base == "stack_base"
429
+ and caller_block.statements[call_idx - 1].data.value == caller_successor.addr
430
+ ):
431
+ caller_block.statements.pop(call_idx - 1) # s_10 =L 0x401225<64><8>
432
+
433
+ # update caller_block to setup parameters
434
+ if callee_clinic.arg_vvars:
435
+ for arg_idx in sorted(callee_clinic.arg_vvars.keys()):
436
+ param_vvar, reg_arg = callee_clinic.arg_vvars[arg_idx]
437
+ if isinstance(reg_arg, SimRegisterVariable):
438
+ reg_offset = reg_arg.reg
439
+ stmt = ailment.Stmt.Assignment(
440
+ self._ail_manager.next_atom(),
441
+ param_vvar,
442
+ ailment.Expr.Register(self._ail_manager.next_atom(), None, reg_offset, reg_arg.bits),
443
+ ins_addr=caller_block.addr + caller_block.original_size,
444
+ )
445
+ caller_block.statements.append(stmt)
446
+ else:
447
+ raise NotImplementedError("Unsupported parameter type")
448
+
449
+ ail_graph.add_edge(caller_block, callee_start)
450
+
451
+ return ail_graph
452
+
453
+ def calculate_stack_depth(self):
454
+ # we need to reserve space for our own stack
455
+ spt = self._track_stack_pointers()
456
+ stack_offsets = spt.offsets_for(self.project.arch.sp_offset)
457
+ if max(stack_offsets) > 2 ** (self.project.arch.bits - 1):
458
+ # why is this unsigned...
459
+ depth = min(s for s in stack_offsets if s > 2 ** (self.project.arch.bits - 1)) - 2**self.project.arch.bits
460
+ else:
461
+ depth = min(stack_offsets)
462
+
463
+ if spt.inconsistent_for(self.project.arch.sp_offset):
464
+ l.warning("Inconsistency found during stack pointer tracking. Stack depth may be incorrect.")
465
+ depth -= 0x1000
466
+
467
+ return depth
468
+
469
+ def _decompilation_simplifications(self, ail_graph):
470
+ # Make returns
471
+ self._update_progress(30.0, text="Making return sites")
472
+ if self.function.prototype is None or not isinstance(self.function.prototype.returnty, SimTypeBottom):
473
+ ail_graph = self._make_returns(ail_graph)
474
+
475
+ ail_graph = self._run_simplification_passes(
476
+ ail_graph, stage=OptimizationPassStage.BEFORE_SSA_LEVEL0_TRANSFORMATION
477
+ )
478
+
479
+ # Make function arguments
480
+ self._update_progress(33.0, text="Making argument list")
481
+ arg_list = self._make_argument_list()
482
+ arg_vvars = self._create_function_argument_vvars(arg_list)
483
+ func_args = {arg_vvar for arg_vvar, _ in arg_vvars.values()}
484
+
485
+ # duplicate orphaned conditional jump blocks
486
+ ail_graph = self._duplicate_orphaned_cond_jumps(ail_graph)
487
+ # rewrite jmp_rax function calls
488
+ ail_graph = self._rewrite_jump_rax_calls(ail_graph)
489
+
490
+ # Transform the graph into partial SSA form
491
+ self._update_progress(35.0, text="Transforming to partial-SSA form")
492
+ ail_graph = self._transform_to_ssa_level0(ail_graph, func_args)
493
+
494
+ # full-function constant-only propagation
495
+ self._update_progress(36.0, text="Constant propagation")
496
+ self._simplify_function(
497
+ ail_graph,
498
+ remove_dead_memdefs=False,
499
+ unify_variables=False,
500
+ narrow_expressions=False,
501
+ only_consts=True,
502
+ fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
503
+ max_iterations=1,
504
+ )
505
+
506
+ # cached block-level reaching definition analysis results and propagator results
507
+ block_simplification_cache: dict[ailment.Block, NamedTuple] | None = {}
508
+
509
+ # Track stack pointers
510
+ self._update_progress(37.0, text="Tracking stack pointers")
511
+ spt = self._track_stack_pointers()
512
+
513
+ preserve_vvar_ids: set[int] = set()
514
+ type_hints: list[tuple[atoms.VirtualVariable | atoms.MemoryLocation, str]] = []
515
+
516
+ # Simplify blocks
517
+ # we never remove dead memory definitions before making callsites. otherwise stack arguments may go missing
518
+ # before they are recognized as stack arguments.
519
+ self._update_progress(38.0, text="Simplifying blocks 1")
520
+ ail_graph = self._simplify_blocks(
521
+ ail_graph,
522
+ stack_pointer_tracker=spt,
523
+ cache=block_simplification_cache,
524
+ preserve_vvar_ids=preserve_vvar_ids,
525
+ type_hints=type_hints,
526
+ )
527
+ self._rewrite_alloca(ail_graph)
528
+
529
+ # Run simplification passes
530
+ self._update_progress(40.0, text="Running simplifications 1")
531
+ ail_graph = self._run_simplification_passes(
532
+ ail_graph,
533
+ stack_pointer_tracker=spt,
534
+ stack_items=self.stack_items,
535
+ stage=OptimizationPassStage.AFTER_SINGLE_BLOCK_SIMPLIFICATION,
536
+ )
537
+
538
+ # Simplify the entire function for the first time
539
+ self._update_progress(45.0, text="Simplifying function 1")
540
+ self._simplify_function(
541
+ ail_graph,
542
+ remove_dead_memdefs=False,
543
+ unify_variables=False,
544
+ narrow_expressions=True,
545
+ fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
546
+ arg_vvars=arg_vvars,
547
+ )
548
+
549
+ # Run simplification passes again. there might be more chances for peephole optimizations after function-level
550
+ # simplification
551
+ self._update_progress(48.0, text="Simplifying blocks 2")
552
+ ail_graph = self._simplify_blocks(
553
+ ail_graph,
554
+ stack_pointer_tracker=spt,
555
+ cache=block_simplification_cache,
556
+ preserve_vvar_ids=preserve_vvar_ids,
557
+ type_hints=type_hints,
558
+ )
559
+
560
+ # Run simplification passes
561
+ self._update_progress(49.0, text="Running simplifications 2")
562
+ ail_graph = self._run_simplification_passes(
563
+ ail_graph, stage=OptimizationPassStage.BEFORE_SSA_LEVEL1_TRANSFORMATION
564
+ )
565
+
566
+ # rewrite (qualified) stack variables into SSA form
567
+ ail_graph = self._transform_to_ssa_level1(ail_graph, func_args)
568
+
569
+ # clear _blocks_by_addr_and_size so no one can use it again
570
+ # TODO: Totally remove this dict
571
+ self._blocks_by_addr_and_size = None
572
+
573
+ # Rust-specific; only call this on Rust binaries when we can identify language and compiler
574
+ ail_graph = self._rewrite_rust_probestack_call(ail_graph)
575
+ # Windows-specific
576
+ ail_graph = self._rewrite_windows_chkstk_call(ail_graph)
577
+
578
+ # Make call-sites
579
+ self._update_progress(50.0, text="Making callsites")
580
+ _, stackarg_offsets, removed_vvar_ids = self._make_callsites(
581
+ ail_graph, func_args, stack_pointer_tracker=spt, preserve_vvar_ids=preserve_vvar_ids
582
+ )
583
+
584
+ # Run simplification passes
585
+ self._update_progress(53.0, text="Running simplifications 2")
586
+ ail_graph = self._run_simplification_passes(ail_graph, stage=OptimizationPassStage.AFTER_MAKING_CALLSITES)
587
+
588
+ # Simplify the entire function for the second time
589
+ self._update_progress(55.0, text="Simplifying function 2")
590
+ self._simplify_function(
591
+ ail_graph,
592
+ remove_dead_memdefs=self._remove_dead_memdefs,
593
+ stack_arg_offsets=stackarg_offsets,
594
+ unify_variables=True,
595
+ narrow_expressions=True,
596
+ fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
597
+ removed_vvar_ids=removed_vvar_ids,
598
+ arg_vvars=arg_vvars,
599
+ preserve_vvar_ids=preserve_vvar_ids,
600
+ )
601
+
602
+ # After global optimization, there might be more chances for peephole optimizations.
603
+ # Simplify blocks for the second time
604
+ self._update_progress(60.0, text="Simplifying blocks 3")
605
+ ail_graph = self._simplify_blocks(
606
+ ail_graph,
607
+ stack_pointer_tracker=spt,
608
+ cache=block_simplification_cache,
609
+ preserve_vvar_ids=preserve_vvar_ids,
610
+ type_hints=type_hints,
611
+ )
612
+
613
+ # Run simplification passes
614
+ self._update_progress(65.0, text="Running simplifications 3")
615
+ ail_graph = self._run_simplification_passes(
616
+ ail_graph, stack_items=self.stack_items, stage=OptimizationPassStage.AFTER_GLOBAL_SIMPLIFICATION
617
+ )
618
+
619
+ # Simplify the entire function for the third time
620
+ self._update_progress(70.0, text="Simplifying function 3")
621
+ self._simplify_function(
622
+ ail_graph,
623
+ remove_dead_memdefs=self._remove_dead_memdefs,
624
+ stack_arg_offsets=stackarg_offsets,
625
+ unify_variables=True,
626
+ narrow_expressions=True,
627
+ fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
628
+ arg_vvars=arg_vvars,
629
+ preserve_vvar_ids=preserve_vvar_ids,
630
+ )
631
+
632
+ self._update_progress(75.0, text="Simplifying blocks 4")
633
+ ail_graph = self._simplify_blocks(
634
+ ail_graph,
635
+ stack_pointer_tracker=spt,
636
+ cache=block_simplification_cache,
637
+ preserve_vvar_ids=preserve_vvar_ids,
638
+ type_hints=type_hints,
639
+ )
640
+
641
+ # Simplify the entire function for the fourth time
642
+ self._update_progress(78.0, text="Simplifying function 4")
643
+ self._simplify_function(
644
+ ail_graph,
645
+ remove_dead_memdefs=self._remove_dead_memdefs,
646
+ stack_arg_offsets=stackarg_offsets,
647
+ unify_variables=True,
648
+ narrow_expressions=True,
649
+ fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
650
+ arg_vvars=arg_vvars,
651
+ preserve_vvar_ids=preserve_vvar_ids,
652
+ )
653
+
654
+ self._update_progress(79.0, text="Running simplifications 4")
655
+ ail_graph = self._run_simplification_passes(
656
+ ail_graph, stack_items=self.stack_items, stage=OptimizationPassStage.BEFORE_VARIABLE_RECOVERY
657
+ )
658
+
659
+ # update arg_list
660
+ arg_list = []
661
+ for idx in sorted(arg_vvars):
662
+ arg_list.append(arg_vvars[idx][1])
663
+
664
+ # Get virtual variable mapping that can de-phi the SSA representation
665
+ vvar2vvar, copied_vvar_ids = self._collect_dephi_vvar_mapping_and_rewrite_blocks(ail_graph, arg_vvars)
666
+
667
+ # Recover variables on AIL blocks
668
+ self._update_progress(80.0, text="Recovering variables")
669
+ variable_kb = self._recover_and_link_variables(ail_graph, arg_list, arg_vvars, vvar2vvar, type_hints)
670
+
671
+ # Run simplification passes
672
+ self._update_progress(85.0, text="Running simplifications 4")
673
+ ail_graph = self._run_simplification_passes(
674
+ ail_graph,
675
+ stage=OptimizationPassStage.AFTER_VARIABLE_RECOVERY,
676
+ avoid_vvar_ids=copied_vvar_ids,
677
+ )
678
+
679
+ # Make function prototype
680
+ self._update_progress(90.0, text="Making function prototype")
681
+ self._make_function_prototype(arg_list, variable_kb)
682
+
683
+ # remove empty nodes from the graph
684
+ ail_graph = self.remove_empty_nodes(ail_graph)
685
+ # note that there are still edges to remove before we can structure this graph!
686
+
687
+ self.arg_list = arg_list
688
+ self.arg_vvars = arg_vvars
689
+ self.variable_kb = variable_kb
690
+ self.cc_graph = self.copy_graph(ail_graph)
691
+ self.externs = self._collect_externs(ail_graph, variable_kb)
692
+ self.vvar_to_vvar = vvar2vvar
693
+ self.copied_var_ids = copied_vvar_ids
694
+ return ail_graph
695
+
696
+ def _analyze_for_data_refs(self):
697
+ # Set up the function graph according to configurations
698
+ self._update_progress(0.0, text="Setting up function graph")
699
+ self._set_function_graph()
700
+
701
+ # Remove alignment blocks
702
+ self._update_progress(5.0, text="Removing alignment blocks")
703
+ self._remove_alignment_blocks()
704
+
705
+ # if the graph is empty, don't continue
706
+ if not self._func_graph:
707
+ return
708
+
709
+ # initialize the AIL conversion manager
710
+ self._ail_manager = ailment.Manager(arch=self.project.arch)
711
+
712
+ # Track stack pointers
713
+ self._update_progress(15.0, text="Tracking stack pointers")
714
+ spt = self._track_stack_pointers()
715
+
716
+ # Convert VEX blocks to AIL blocks and then simplify them
717
+
718
+ self._update_progress(20.0, text="Converting VEX to AIL")
719
+ self._convert_all()
720
+
721
+ # there must be at least one Load or one Store
722
+ assert self._blocks_by_addr_and_size is not None
723
+ found_load_or_store = False
724
+ for ail_block in self._blocks_by_addr_and_size.values():
725
+ for stmt in ail_block.statements:
726
+ if isinstance(stmt, ailment.Stmt.Store):
727
+ found_load_or_store = True
728
+ break
729
+ if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.Load):
730
+ found_load_or_store = True
731
+ break
732
+ if not found_load_or_store:
733
+ self.data_refs = {}
734
+ return
735
+
736
+ ail_graph = self._make_ailgraph()
737
+ self._remove_redundant_jump_blocks(ail_graph)
738
+
739
+ # full-function constant-only propagation
740
+ self._update_progress(33.0, text="Constant propagation")
741
+ self._simplify_function(
742
+ ail_graph,
743
+ remove_dead_memdefs=False,
744
+ unify_variables=False,
745
+ narrow_expressions=False,
746
+ only_consts=True,
747
+ fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
748
+ max_iterations=1,
749
+ )
750
+
751
+ # cached block-level reaching definition analysis results and propagator results
752
+ block_simplification_cache: dict[ailment.Block, NamedTuple] | None = {}
753
+
754
+ # Simplify blocks
755
+ # we never remove dead memory definitions before making callsites. otherwise stack arguments may go missing
756
+ # before they are recognized as stack arguments.
757
+ self._update_progress(35.0, text="Simplifying blocks 1")
758
+ ail_graph = self._simplify_blocks(ail_graph, stack_pointer_tracker=spt, cache=block_simplification_cache)
759
+
760
+ # Simplify the entire function for the first time
761
+ self._update_progress(45.0, text="Simplifying function 1")
762
+ self._simplify_function(
763
+ ail_graph,
764
+ remove_dead_memdefs=False,
765
+ unify_variables=False,
766
+ narrow_expressions=False,
767
+ fold_callexprs_into_conditions=False,
768
+ rewrite_ccalls=False,
769
+ max_iterations=1,
770
+ )
771
+
772
+ # clear _blocks_by_addr_and_size so no one can use it again
773
+ # TODO: Totally remove this dict
774
+ self._blocks_by_addr_and_size = None
775
+
776
+ self.graph = ail_graph
777
+ self.arg_list = None
778
+ self.variable_kb = None
779
+ self.cc_graph = None
780
+ self.externs = set()
781
+ self.data_refs: dict[int, list[DataRefDesc]] = self._collect_data_refs(ail_graph)
782
+
783
+ @staticmethod
784
+ def _copy_graph(graph: networkx.DiGraph) -> networkx.DiGraph:
785
+ """
786
+ Copy AIL Graph.
787
+
788
+ :return: A copy of the AIl graph.
789
+ """
790
+ graph_copy = networkx.DiGraph()
791
+ block_mapping = {}
792
+ # copy all blocks
793
+ for block in graph.nodes():
794
+ new_block = copy.copy(block)
795
+ new_stmts = copy.copy(block.statements)
796
+ new_block.statements = new_stmts
797
+ block_mapping[block] = new_block
798
+ graph_copy.add_node(new_block)
799
+
800
+ # copy all edges
801
+ for src, dst, data in graph.edges(data=True):
802
+ new_src = block_mapping[src]
803
+ new_dst = block_mapping[dst]
804
+ graph_copy.add_edge(new_src, new_dst, **data)
805
+ return graph_copy
806
+
807
+ def copy_graph(self, graph=None) -> networkx.DiGraph:
808
+ return self._copy_graph(graph or self.graph) # type:ignore
809
+
810
+ @timethis
811
+ def _set_function_graph(self):
812
+ self._func_graph = self.function.graph_ex(exception_edges=self._exception_edges)
813
+
814
+ @timethis
815
+ def _remove_alignment_blocks(self):
816
+ """
817
+ Alignment blocks are basic blocks that only consist of nops. They should not be included in the graph.
818
+ """
819
+ assert self._func_graph is not None
820
+ for node in list(self._func_graph.nodes()):
821
+ if self._func_graph.in_degree(node) == 0 and CFGBase._is_noop_block(
822
+ self.project.arch, self.project.factory.block(node.addr, node.size)
823
+ ):
824
+ if (node.addr, None) == self.entry_node_addr:
825
+ # this is the entry node. after removing this node, the new entry node will be its successor
826
+ if self._func_graph.out_degree[node] == 1:
827
+ succ = next(iter(self._func_graph.successors(node)))
828
+ self.entry_node_addr = succ.addr, None
829
+ else:
830
+ # we just don't remove this node...
831
+ continue
832
+ self._func_graph.remove_node(node)
833
+
834
+ @timethis
835
+ def _recover_calling_conventions(self, func_graph=None) -> None:
836
+ """
837
+ Examine the calling convention and function prototype for each function called. For functions with missing
838
+ calling conventions or function prototypes, analyze each *call site* and recover the calling convention and
839
+ function prototype of the callee function.
840
+
841
+ :return: None
842
+ """
843
+
844
+ attempted_funcs: set[int] = set()
845
+
846
+ for node in self.function.transition_graph:
847
+ if (
848
+ isinstance(node, BlockNode)
849
+ and node.addr != self.function.addr
850
+ and self.kb.functions.contains_addr(node.addr)
851
+ ):
852
+ # tail jumps
853
+ target_func = self.kb.functions.get_by_addr(node.addr)
854
+ elif isinstance(node, Function):
855
+ target_func = node
856
+ else:
857
+ # TODO: Enable call-site analysis for indirect calls
858
+ continue
859
+
860
+ if target_func.addr in attempted_funcs:
861
+ continue
862
+ attempted_funcs.add(target_func.addr)
863
+
864
+ # case 0: the calling convention and prototype are available
865
+ if target_func.calling_convention is not None and target_func.prototype is not None:
866
+ continue
867
+
868
+ call_sites = []
869
+ for pred, _, data in self.function.transition_graph.in_edges(node, data=True):
870
+ if data.get("type", None) != "return":
871
+ call_sites.append(pred)
872
+ # case 1: calling conventions and prototypes are available at every single call site
873
+ if call_sites and all(self.kb.callsite_prototypes.has_prototype(callsite.addr) for callsite in call_sites):
874
+ continue
875
+
876
+ # case 2: the callee is a SimProcedure
877
+ if target_func.is_simprocedure:
878
+ cc = self.project.analyses.CallingConvention(target_func, fail_fast=self._fail_fast) # type: ignore
879
+ if cc.cc is not None and cc.prototype is not None:
880
+ target_func.calling_convention = cc.cc
881
+ target_func.prototype = cc.prototype
882
+ target_func.prototype_libname = cc.prototype_libname
883
+ continue
884
+
885
+ # case 3: the callee is a PLT function
886
+ if target_func.is_plt:
887
+ cc = self.project.analyses.CallingConvention(target_func, fail_fast=self._fail_fast) # type: ignore
888
+ if cc.cc is not None and cc.prototype is not None:
889
+ target_func.calling_convention = cc.cc
890
+ target_func.prototype = cc.prototype
891
+ target_func.prototype_libname = cc.prototype_libname
892
+ continue
893
+
894
+ # case 4: fall back to call site analysis
895
+ for callsite in call_sites:
896
+ if self.kb.callsite_prototypes.has_prototype(callsite.addr):
897
+ continue
898
+
899
+ # parse the call instruction address from the edge
900
+ callsite_ins_addr = None
901
+ edge_data = [
902
+ data
903
+ for src, dst, data in self.function.transition_graph.in_edges(node, data=True)
904
+ if src is callsite
905
+ ]
906
+ if len(edge_data) == 1:
907
+ callsite_ins_addr = edge_data[0].get("ins_addr", None)
908
+ if callsite_ins_addr is None:
909
+ # parse the block...
910
+ callsite_block = self.project.factory.block(callsite.addr, size=callsite.size)
911
+ if self.project.arch.branch_delay_slot:
912
+ if callsite_block.instructions < 2:
913
+ continue
914
+ callsite_ins_addr = callsite_block.instruction_addrs[-2]
915
+ else:
916
+ if callsite_block.instructions == 0:
917
+ continue
918
+ callsite_ins_addr = callsite_block.instruction_addrs[-1]
919
+
920
+ cc = self.project.analyses.CallingConvention(
921
+ None,
922
+ analyze_callsites=True,
923
+ caller_func_addr=self.function.addr,
924
+ callsite_block_addr=callsite.addr,
925
+ callsite_insn_addr=callsite_ins_addr,
926
+ func_graph=func_graph,
927
+ fail_fast=self._fail_fast, # type:ignore
928
+ )
929
+
930
+ if cc.cc is not None and cc.prototype is not None:
931
+ self.kb.callsite_prototypes.set_prototype(callsite.addr, cc.cc, cc.prototype, manual=False)
932
+ if func_graph is not None and cc.prototype.returnty is not None:
933
+ # patch the AIL call statement if we can find one
934
+ callsite_ail_block: ailment.Block | None = next(
935
+ iter(bb for bb in func_graph if bb.addr == callsite.addr), None
936
+ )
937
+ if callsite_ail_block is not None and callsite_ail_block.statements:
938
+ last_stmt = callsite_ail_block.statements[-1]
939
+ if (
940
+ isinstance(last_stmt, ailment.Stmt.Call)
941
+ and last_stmt.ret_expr is None
942
+ and isinstance(cc.cc.RETURN_VAL, SimRegArg)
943
+ ):
944
+ reg_offset, reg_size = self.project.arch.registers[cc.cc.RETURN_VAL.reg_name]
945
+ last_stmt.ret_expr = ailment.Expr.Register(
946
+ None,
947
+ None,
948
+ reg_offset,
949
+ reg_size * 8,
950
+ ins_addr=callsite_ins_addr,
951
+ reg_name=cc.cc.RETURN_VAL.reg_name,
952
+ )
953
+ last_stmt.bits = reg_size * 8
954
+
955
+ # finally, recover the calling convention of the current function
956
+ if self.function.prototype is None or self.function.calling_convention is None:
957
+ self.project.analyses.CompleteCallingConventions(
958
+ fail_fast=self._fail_fast, # type: ignore
959
+ recover_variables=True,
960
+ prioritize_func_addrs=[self.function.addr],
961
+ skip_other_funcs=True,
962
+ skip_signature_matched_functions=False,
963
+ func_graphs={self.function.addr: func_graph} if func_graph is not None else None,
964
+ )
965
+
966
+ @timethis
967
+ def _track_stack_pointers(self):
968
+ """
969
+ For each instruction, track its stack pointer offset and stack base pointer offset.
970
+
971
+ :return: None
972
+ """
973
+
974
+ regs = {self.project.arch.sp_offset}
975
+ initial_reg_values = {
976
+ self.project.arch.sp_offset: OffsetVal(
977
+ Register(self.project.arch.sp_offset, self.project.arch.bits), self._sp_shift
978
+ )
979
+ }
980
+ if hasattr(self.project.arch, "bp_offset") and self.project.arch.bp_offset is not None:
981
+ regs.add(self.project.arch.bp_offset)
982
+ initial_reg_values[self.project.arch.bp_offset] = OffsetVal(
983
+ Register(self.project.arch.bp_offset, self.project.arch.bits), self._sp_shift
984
+ )
985
+
986
+ regs |= self._find_regs_compared_against_sp(self._func_graph)
987
+
988
+ spt = self.project.analyses.StackPointerTracker(
989
+ self.function,
990
+ regs,
991
+ fail_fast=self._fail_fast,
992
+ track_memory=self._sp_tracker_track_memory,
993
+ cross_insn_opt=False,
994
+ initial_reg_values=initial_reg_values,
995
+ )
996
+
997
+ if spt.inconsistent_for(self.project.arch.sp_offset):
998
+ l.warning("Inconsistency found during stack pointer tracking. Decompilation results might be incorrect.")
999
+ return spt
1000
+
1001
+ @timethis
1002
+ def _convert_all(self):
1003
+ """
1004
+ Convert all VEX blocks in the function graph to AIL blocks, and fill self._blocks.
1005
+
1006
+ :return: None
1007
+ """
1008
+ assert self._func_graph is not None
1009
+ assert self._blocks_by_addr_and_size is not None
1010
+
1011
+ for block_node in self._func_graph.nodes():
1012
+ ail_block = self._convert(block_node)
1013
+
1014
+ if type(ail_block) is ailment.Block:
1015
+ # remove constant pc assignments
1016
+ ail_block.statements = [
1017
+ stmt
1018
+ for stmt in ail_block.statements
1019
+ if not (
1020
+ isinstance(stmt, ailment.Stmt.Assignment)
1021
+ and isinstance(stmt.dst, ailment.Expr.Register)
1022
+ and stmt.dst.reg_offset == self.project.arch.ip_offset
1023
+ and isinstance(stmt.src, ailment.Expr.Const)
1024
+ )
1025
+ ]
1026
+
1027
+ self._blocks_by_addr_and_size[(block_node.addr, block_node.size)] = ail_block
1028
+
1029
+ def _convert(self, block_node):
1030
+ """
1031
+ Convert a BlockNode to an AIL block.
1032
+
1033
+ :param block_node: A BlockNode instance.
1034
+ :return: A converted AIL block.
1035
+ :rtype: ailment.Block
1036
+ """
1037
+
1038
+ if type(block_node) is not BlockNode:
1039
+ return block_node
1040
+
1041
+ if block_node.size == 0:
1042
+ return ailment.Block(block_node.addr, 0, statements=[])
1043
+
1044
+ block = self.project.factory.block(block_node.addr, block_node.size, cross_insn_opt=False)
1045
+ converted = self._convert_vex(block)
1046
+
1047
+ # architecture-specific setup
1048
+ if block.addr == self.function.addr and self.project.arch.name in {"X86", "AMD64"}:
1049
+ # setup dflag; this is a hack for most sane ABIs. we may move this logic elsewhere if there are adversarial
1050
+ # binaries that mess with dflags and pass them across functions
1051
+ dflag_offset, dflag_size = self.project.arch.registers["d"]
1052
+ dflag = ailment.Expr.Register(
1053
+ self._ail_manager.next_atom(),
1054
+ None,
1055
+ dflag_offset,
1056
+ dflag_size * self.project.arch.byte_width,
1057
+ ins_addr=block.addr,
1058
+ )
1059
+ forward = ailment.Expr.Const(
1060
+ self._ail_manager.next_atom(), None, 1, dflag_size * self.project.arch.byte_width, ins_addr=block.addr
1061
+ )
1062
+ dflag_assignment = ailment.Stmt.Assignment(
1063
+ self._ail_manager.next_atom(), dflag, forward, ins_addr=block.addr
1064
+ )
1065
+ converted.statements.insert(0, dflag_assignment)
1066
+
1067
+ return converted
1068
+
1069
+ def _convert_vex(self, block):
1070
+ if block.vex.jumpkind not in {"Ijk_Call", "Ijk_Boring", "Ijk_Ret"} and not block.vex.jumpkind.startswith(
1071
+ "Ijk_Sys"
1072
+ ):
1073
+ # we don't support lifting this block. use a dummy block instead
1074
+ dirty_expr = ailment.Expr.DirtyExpression(
1075
+ self._ail_manager.next_atom,
1076
+ f"Unsupported jumpkind {block.vex.jumpkind} at address {block.addr}",
1077
+ [],
1078
+ bits=0,
1079
+ )
1080
+ statements = [
1081
+ ailment.Stmt.DirtyStatement(
1082
+ self._ail_manager.next_atom(),
1083
+ dirty_expr,
1084
+ ins_addr=block.addr,
1085
+ )
1086
+ ]
1087
+ return ailment.Block(block.addr, block.size, statements=statements)
1088
+
1089
+ return ailment.IRSBConverter.convert(block.vex, self._ail_manager)
1090
+
1091
+ @timethis
1092
+ def _replace_single_target_indirect_transitions(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
1093
+ """
1094
+ Remove single-target indirect jumps and calls and replace them with direct jumps or calls.
1095
+ """
1096
+ if self._cfg is None:
1097
+ return ail_graph
1098
+
1099
+ for block in ail_graph.nodes():
1100
+ if not block.statements:
1101
+ continue
1102
+ last_stmt = block.statements[-1]
1103
+ if isinstance(last_stmt, ailment.Stmt.Call) and not isinstance(last_stmt.target, ailment.Expr.Const):
1104
+ # indirect call
1105
+ # consult CFG to see if this is a call with a single successor
1106
+ node = self._cfg.get_any_node(block.addr)
1107
+ if node is None:
1108
+ continue
1109
+ successors = [
1110
+ node
1111
+ for node, jk in self._cfg.get_successors_and_jumpkinds(node)
1112
+ if jk == "Ijk_Call" or jk.startswith("Ijk_Sys")
1113
+ ]
1114
+ if len(successors) == 1:
1115
+ succ_addr = successors[0].addr
1116
+ if not self.project.is_hooked(succ_addr) or not isinstance(
1117
+ self.project.hooked_by(successors[0].addr), UnresolvableCallTarget
1118
+ ):
1119
+ # found a single successor - replace the last statement
1120
+ assert isinstance(last_stmt.target, ailment.Expr.Expression) # not a string
1121
+ new_last_stmt = last_stmt.copy()
1122
+ assert isinstance(successors[0].addr, int)
1123
+ new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
1124
+ block.statements[-1] = new_last_stmt
1125
+
1126
+ elif isinstance(last_stmt, ailment.Stmt.Jump) and not isinstance(last_stmt.target, ailment.Expr.Const):
1127
+ # indirect jump
1128
+ # consult CFG to see if there is a jump with a single successor
1129
+ node = self._cfg.get_any_node(block.addr)
1130
+ if node is None:
1131
+ continue
1132
+ successors = self._cfg.get_successors(node, excluding_fakeret=True, jumpkind="Ijk_Boring")
1133
+ if len(successors) == 1 and not isinstance(
1134
+ self.project.hooked_by(successors[0].addr), UnresolvableJumpTarget
1135
+ ):
1136
+ # found a single successor - replace the last statement
1137
+ new_last_stmt = last_stmt.copy()
1138
+ new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
1139
+ block.statements[-1] = new_last_stmt
1140
+
1141
+ return ail_graph
1142
+
1143
+ @timethis
1144
+ def _replace_tail_jumps_with_calls(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
1145
+ """
1146
+ Replace tail jumps them with a return statement and a call expression.
1147
+ """
1148
+ for block in list(ail_graph.nodes()):
1149
+ out_degree = ail_graph.out_degree[block]
1150
+
1151
+ if out_degree != 0:
1152
+ continue
1153
+
1154
+ last_stmt = block.statements[-1]
1155
+ if isinstance(last_stmt, ailment.Stmt.Jump):
1156
+ # jumping to somewhere outside the current function
1157
+ # rewrite it as a call *if and only if* the target is identified as a function
1158
+ target = last_stmt.target
1159
+ if isinstance(target, ailment.Const):
1160
+ target_addr = target.value
1161
+ if self.kb.functions.contains_addr(target_addr):
1162
+ # replace the statement
1163
+ target_func = self.kb.functions.get_by_addr(target_addr)
1164
+ if target_func.returning and self.project.arch.ret_offset is not None:
1165
+ ret_reg_offset = self.project.arch.ret_offset
1166
+ ret_expr = ailment.Expr.Register(
1167
+ None,
1168
+ None,
1169
+ ret_reg_offset,
1170
+ self.project.arch.bits,
1171
+ reg_name=self.project.arch.translate_register_name(
1172
+ ret_reg_offset, size=self.project.arch.bits
1173
+ ),
1174
+ **target.tags,
1175
+ )
1176
+ call_stmt = ailment.Stmt.Call(
1177
+ None,
1178
+ target,
1179
+ calling_convention=None, # target_func.calling_convention,
1180
+ prototype=None, # target_func.prototype,
1181
+ ret_expr=ret_expr,
1182
+ **last_stmt.tags,
1183
+ )
1184
+ block.statements[-1] = call_stmt
1185
+
1186
+ ret_stmt = ailment.Stmt.Return(None, [], **last_stmt.tags)
1187
+ ret_block = ailment.Block(self.new_block_addr(), 1, statements=[ret_stmt])
1188
+ ail_graph.add_edge(block, ret_block, type="fake_return")
1189
+ else:
1190
+ stmt = ailment.Stmt.Call(None, target, **last_stmt.tags)
1191
+ block.statements[-1] = stmt
1192
+
1193
+ return ail_graph
1194
+
1195
+ def _apply_callsite_prototype_and_calling_convention(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
1196
+ for block in ail_graph.nodes():
1197
+ if not block.statements:
1198
+ continue
1199
+
1200
+ last_stmt = block.statements[-1]
1201
+ if not isinstance(last_stmt, ailment.Stmt.Call):
1202
+ continue
1203
+
1204
+ cc = last_stmt.calling_convention
1205
+ prototype = last_stmt.prototype
1206
+ if cc and prototype:
1207
+ continue
1208
+
1209
+ # manually-specified call-site prototype
1210
+ has_callsite_prototype = self.kb.callsite_prototypes.has_prototype(block.addr)
1211
+ if has_callsite_prototype:
1212
+ manually_specified = self.kb.callsite_prototypes.get_prototype_type(block.addr)
1213
+ if manually_specified:
1214
+ cc = self.kb.callsite_prototypes.get_cc(block.addr)
1215
+ prototype = self.kb.callsite_prototypes.get_prototype(block.addr)
1216
+
1217
+ # function-specific prototype
1218
+ func = None
1219
+ if cc is None or prototype is None:
1220
+ target = None
1221
+ if isinstance(last_stmt.target, ailment.Expr.Const):
1222
+ target = last_stmt.target.value
1223
+
1224
+ if target is not None and target in self.kb.functions:
1225
+ # function-specific logic when the calling target is known
1226
+ func = self.kb.functions[target]
1227
+ if func.prototype is None:
1228
+ func.find_declaration()
1229
+ cc = func.calling_convention
1230
+ prototype = func.prototype
1231
+
1232
+ # automatically recovered call-site prototype
1233
+ if (cc is None or prototype is None) and has_callsite_prototype:
1234
+ cc = self.kb.callsite_prototypes.get_cc(block.addr)
1235
+ prototype = self.kb.callsite_prototypes.get_prototype(block.addr)
1236
+
1237
+ # ensure the prototype has been resolved
1238
+ if prototype is not None and func is not None:
1239
+ # make sure the function prototype is resolved.
1240
+ # TODO: Cache resolved function prototypes globally
1241
+ prototype_libname = func.prototype_libname
1242
+ if prototype_libname is not None:
1243
+ prototype = dereference_simtype_by_lib(prototype, prototype_libname)
1244
+
1245
+ if cc is None:
1246
+ l.warning("Call site %#x (callee %s) has an unknown calling convention.", block.addr, repr(func))
1247
+
1248
+ new_last_stmt = last_stmt.copy()
1249
+ new_last_stmt.calling_convention = cc
1250
+ new_last_stmt.prototype = prototype
1251
+ block.statements[-1] = new_last_stmt
1252
+
1253
+ return ail_graph
1254
+
1255
+ @timethis
1256
+ def _make_ailgraph(self) -> networkx.DiGraph:
1257
+ return self._function_graph_to_ail_graph(self._func_graph)
1258
+
1259
+ @timethis
1260
+ def _simplify_blocks(
1261
+ self,
1262
+ ail_graph: networkx.DiGraph,
1263
+ stack_pointer_tracker=None,
1264
+ cache: dict[ailment.Block, NamedTuple] | None = None,
1265
+ preserve_vvar_ids: set[int] | None = None,
1266
+ type_hints: list[tuple[atoms.VirtualVariable | atoms.MemoryLocation, str]] | None = None,
1267
+ ):
1268
+ """
1269
+ Simplify all blocks in self._blocks.
1270
+
1271
+ :param ail_graph: The AIL function graph.
1272
+ :param stack_pointer_tracker: The RegisterDeltaTracker analysis instance.
1273
+ :param cache: A block-level cache that stores reaching definition analysis results and
1274
+ propagation results.
1275
+ :return: None
1276
+ """
1277
+
1278
+ blocks_by_addr_and_idx: dict[tuple[int, int | None], ailment.Block] = {}
1279
+
1280
+ for ail_block in ail_graph.nodes():
1281
+ simplified = self._simplify_block(
1282
+ ail_block,
1283
+ stack_pointer_tracker=stack_pointer_tracker,
1284
+ cache=cache,
1285
+ preserve_vvar_ids=preserve_vvar_ids,
1286
+ type_hints=type_hints,
1287
+ )
1288
+ key = ail_block.addr, ail_block.idx
1289
+ blocks_by_addr_and_idx[key] = simplified
1290
+
1291
+ # update blocks_map to allow node_addr to node lookup
1292
+ def _replace_node_handler(node):
1293
+ key = node.addr, node.idx
1294
+ if key in blocks_by_addr_and_idx:
1295
+ return blocks_by_addr_and_idx[key]
1296
+ return None
1297
+
1298
+ AILGraphWalker(ail_graph, _replace_node_handler, replace_nodes=True).walk()
1299
+
1300
+ return ail_graph
1301
+
1302
+ def _simplify_block(
1303
+ self,
1304
+ ail_block,
1305
+ stack_pointer_tracker=None,
1306
+ cache=None,
1307
+ preserve_vvar_ids: set[int] | None = None,
1308
+ type_hints: list[tuple[atoms.VirtualVariable | atoms.MemoryLocation, str]] | None = None,
1309
+ ):
1310
+ """
1311
+ Simplify a single AIL block.
1312
+
1313
+ :param ailment.Block ail_block: The AIL block to simplify.
1314
+ :param stack_pointer_tracker: The RegisterDeltaTracker analysis instance.
1315
+ :return: A simplified AIL block.
1316
+ """
1317
+
1318
+ cached_rd, cached_prop = None, None
1319
+ cache_item = None
1320
+ cache_key = ail_block.addr, ail_block.idx
1321
+ if cache:
1322
+ cache_item = cache.get(cache_key, None)
1323
+ if cache_item:
1324
+ # cache hit
1325
+ cached_rd = cache_item.rd
1326
+ cached_prop = cache_item.prop
1327
+
1328
+ simp = self.project.analyses.AILBlockSimplifier(
1329
+ ail_block,
1330
+ self.function.addr,
1331
+ fail_fast=self._fail_fast,
1332
+ stack_pointer_tracker=stack_pointer_tracker,
1333
+ peephole_optimizations=self.peephole_optimizations,
1334
+ cached_reaching_definitions=cached_rd,
1335
+ cached_propagator=cached_prop,
1336
+ preserve_vvar_ids=preserve_vvar_ids,
1337
+ type_hints=type_hints,
1338
+ )
1339
+ # update the cache
1340
+ if cache is not None:
1341
+ if cache_item:
1342
+ del cache[cache_key]
1343
+ cache[cache_key] = BlockCache(simp._reaching_definitions, simp._propagator)
1344
+ return simp.result_block
1345
+
1346
+ @timethis
1347
+ def _simplify_function(
1348
+ self,
1349
+ ail_graph,
1350
+ remove_dead_memdefs=False,
1351
+ stack_arg_offsets=None,
1352
+ unify_variables=False,
1353
+ max_iterations: int = 8,
1354
+ narrow_expressions=False,
1355
+ only_consts=False,
1356
+ fold_callexprs_into_conditions=False,
1357
+ rewrite_ccalls=True,
1358
+ removed_vvar_ids: set[int] | None = None,
1359
+ arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]] | None = None,
1360
+ preserve_vvar_ids: set[int] | None = None,
1361
+ ) -> None:
1362
+ """
1363
+ Simplify the entire function until it reaches a fixed point.
1364
+ """
1365
+
1366
+ for idx in range(max_iterations):
1367
+ simplified = self._simplify_function_once(
1368
+ ail_graph,
1369
+ remove_dead_memdefs=remove_dead_memdefs,
1370
+ unify_variables=unify_variables,
1371
+ stack_arg_offsets=stack_arg_offsets,
1372
+ # only narrow once
1373
+ narrow_expressions=narrow_expressions and idx == 0,
1374
+ only_consts=only_consts,
1375
+ fold_callexprs_into_conditions=fold_callexprs_into_conditions,
1376
+ rewrite_ccalls=rewrite_ccalls,
1377
+ removed_vvar_ids=removed_vvar_ids,
1378
+ arg_vvars=arg_vvars,
1379
+ preserve_vvar_ids=preserve_vvar_ids,
1380
+ )
1381
+ if not simplified:
1382
+ break
1383
+
1384
+ @timethis
1385
+ def _simplify_function_once(
1386
+ self,
1387
+ ail_graph,
1388
+ remove_dead_memdefs=False,
1389
+ stack_arg_offsets=None,
1390
+ unify_variables=False,
1391
+ narrow_expressions=False,
1392
+ only_consts=False,
1393
+ fold_callexprs_into_conditions=False,
1394
+ rewrite_ccalls=True,
1395
+ removed_vvar_ids: set[int] | None = None,
1396
+ arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]] | None = None,
1397
+ preserve_vvar_ids: set[int] | None = None,
1398
+ ):
1399
+ """
1400
+ Simplify the entire function once.
1401
+
1402
+ :return: None
1403
+ """
1404
+
1405
+ simp = self.project.analyses.AILSimplifier(
1406
+ self.function,
1407
+ fail_fast=self._fail_fast,
1408
+ func_graph=ail_graph,
1409
+ remove_dead_memdefs=remove_dead_memdefs,
1410
+ unify_variables=unify_variables,
1411
+ stack_arg_offsets=stack_arg_offsets,
1412
+ ail_manager=self._ail_manager,
1413
+ gp=self.function.info.get("gp", None) if self.project.arch.name in {"MIPS32", "MIPS64"} else None,
1414
+ narrow_expressions=narrow_expressions,
1415
+ only_consts=only_consts,
1416
+ fold_callexprs_into_conditions=fold_callexprs_into_conditions,
1417
+ use_callee_saved_regs_at_return=not self._register_save_areas_removed,
1418
+ rewrite_ccalls=rewrite_ccalls,
1419
+ removed_vvar_ids=removed_vvar_ids,
1420
+ arg_vvars=arg_vvars,
1421
+ secondary_stackvars=self.secondary_stackvars,
1422
+ avoid_vvar_ids=preserve_vvar_ids,
1423
+ )
1424
+ # cache the simplifier's RDA analysis
1425
+ self.reaching_definitions = simp._reaching_definitions
1426
+
1427
+ # the function graph has been updated at this point
1428
+ return simp.simplified
1429
+
1430
+ @timethis
1431
+ def _run_simplification_passes(
1432
+ self,
1433
+ ail_graph,
1434
+ stage: OptimizationPassStage = OptimizationPassStage.AFTER_GLOBAL_SIMPLIFICATION,
1435
+ variable_kb=None,
1436
+ stack_items: dict[int, StackItem] | None = None,
1437
+ stack_pointer_tracker=None,
1438
+ **kwargs,
1439
+ ):
1440
+ addr_and_idx_to_blocks: dict[tuple[int, int | None], ailment.Block] = {}
1441
+ addr_to_blocks: dict[int, set[ailment.Block]] = defaultdict(set)
1442
+
1443
+ # update blocks_map to allow node_addr to node lookup
1444
+ def _updatedict_handler(node):
1445
+ addr_and_idx_to_blocks[(node.addr, node.idx)] = node
1446
+ addr_to_blocks[node.addr].add(node)
1447
+
1448
+ AILGraphWalker(ail_graph, _updatedict_handler).walk()
1449
+
1450
+ # Run each pass
1451
+ for pass_ in self._optimization_passes:
1452
+ if stage != pass_.STAGE:
1453
+ continue
1454
+
1455
+ if pass_ in DUPLICATING_OPTS + CONDENSING_OPTS and self.unoptimized_graph is None:
1456
+ # we should save a copy at the first time any optimization that could alter the structure
1457
+ # of the graph is applied
1458
+ self.unoptimized_graph = self._copy_graph(ail_graph)
1459
+
1460
+ pass_ = timethis(pass_)
1461
+ a = pass_(
1462
+ self.function,
1463
+ blocks_by_addr=addr_to_blocks,
1464
+ blocks_by_addr_and_idx=addr_and_idx_to_blocks,
1465
+ graph=ail_graph,
1466
+ variable_kb=variable_kb,
1467
+ vvar_id_start=self.vvar_id_start,
1468
+ entry_node_addr=self.entry_node_addr,
1469
+ scratch=self.optimization_scratch,
1470
+ force_loop_single_exit=self._force_loop_single_exit,
1471
+ complete_successors=self._complete_successors,
1472
+ stack_pointer_tracker=stack_pointer_tracker,
1473
+ **kwargs,
1474
+ )
1475
+ if a.out_graph:
1476
+ # use the new graph
1477
+ ail_graph = a.out_graph
1478
+ if isinstance(a, RegisterSaveAreaSimplifier):
1479
+ # register save area has been removed - we should no longer use callee-saved registers in RDA
1480
+ self._register_save_areas_removed = True
1481
+ # clear the cached RDA result
1482
+ self.reaching_definitions = None
1483
+ self.vvar_id_start = a.vvar_id_start
1484
+ if stack_items is not None and a.stack_items:
1485
+ stack_items.update(a.stack_items)
1486
+
1487
+ return ail_graph
1488
+
1489
+ @timethis
1490
+ def _create_function_argument_vvars(self, arg_list) -> dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]]:
1491
+ arg_vvars = {}
1492
+ for arg in arg_list:
1493
+ if isinstance(arg, SimRegisterVariable):
1494
+ # get the full register if needed
1495
+ arg_vvar = ailment.Expr.VirtualVariable(
1496
+ self._ail_manager.next_atom(),
1497
+ self.vvar_id_start,
1498
+ arg.bits,
1499
+ ailment.Expr.VirtualVariableCategory.PARAMETER,
1500
+ oident=(ailment.Expr.VirtualVariableCategory.REGISTER, arg.reg),
1501
+ ins_addr=self.function.addr,
1502
+ vex_block_addr=self.function.addr,
1503
+ )
1504
+ self.vvar_id_start += 1
1505
+ arg_vvars[arg_vvar.varid] = arg_vvar, arg
1506
+ elif isinstance(arg, SimStackVariable):
1507
+ arg_vvar = ailment.Expr.VirtualVariable(
1508
+ self._ail_manager.next_atom(),
1509
+ self.vvar_id_start,
1510
+ arg.bits,
1511
+ ailment.Expr.VirtualVariableCategory.PARAMETER,
1512
+ oident=(ailment.Expr.VirtualVariableCategory.STACK, arg.offset),
1513
+ ins_addr=self.function.addr,
1514
+ vex_block_addr=self.function.addr,
1515
+ )
1516
+ self.vvar_id_start += 1
1517
+ arg_vvars[arg_vvar.varid] = arg_vvar, arg
1518
+
1519
+ return arg_vvars
1520
+
1521
+ @timethis
1522
+ def _transform_to_ssa_level0(
1523
+ self, ail_graph: networkx.DiGraph, func_args: set[ailment.Expr.VirtualVariable]
1524
+ ) -> networkx.DiGraph:
1525
+ ssailification = self.project.analyses[Ssailification].prep(fail_fast=self._fail_fast)(
1526
+ self.function,
1527
+ ail_graph,
1528
+ entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
1529
+ ail_manager=self._ail_manager,
1530
+ ssa_stackvars=False,
1531
+ func_args=func_args,
1532
+ vvar_id_start=self.vvar_id_start,
1533
+ )
1534
+ self.vvar_id_start = ssailification.max_vvar_id + 1
1535
+ assert ssailification.out_graph is not None
1536
+ return ssailification.out_graph
1537
+
1538
+ @timethis
1539
+ def _transform_to_ssa_level1(
1540
+ self, ail_graph: networkx.DiGraph, func_args: set[ailment.Expr.VirtualVariable]
1541
+ ) -> networkx.DiGraph:
1542
+ ssailification = self.project.analyses.Ssailification(
1543
+ self.function,
1544
+ ail_graph,
1545
+ fail_fast=self._fail_fast,
1546
+ entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
1547
+ ail_manager=self._ail_manager,
1548
+ ssa_tmps=True,
1549
+ ssa_stackvars=True,
1550
+ func_args=func_args,
1551
+ vvar_id_start=self.vvar_id_start,
1552
+ )
1553
+ self.vvar_id_start = ssailification.max_vvar_id + 1
1554
+ self.secondary_stackvars = ssailification.secondary_stackvars
1555
+ return ssailification.out_graph
1556
+
1557
+ @timethis
1558
+ def _collect_dephi_vvar_mapping_and_rewrite_blocks(
1559
+ self, ail_graph: networkx.DiGraph, arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]]
1560
+ ) -> tuple[dict[int, int], set[int]]:
1561
+ dephication = self.project.analyses.GraphDephicationVVarMapping(
1562
+ self.function,
1563
+ ail_graph,
1564
+ fail_fast=self._fail_fast,
1565
+ entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
1566
+ vvar_id_start=self.vvar_id_start,
1567
+ arg_vvars=[arg_vvar for arg_vvar, _ in arg_vvars.values()],
1568
+ )
1569
+ self.vvar_id_start = dephication.vvar_id_start + 1
1570
+ return dephication.vvar_to_vvar_mapping, dephication.copied_vvar_ids
1571
+
1572
+ @timethis
1573
+ def _make_argument_list(self) -> list[SimVariable]:
1574
+ if self.function.calling_convention is not None and self.function.prototype is not None:
1575
+ args: list[SimFunctionArgument] = self.function.calling_convention.arg_locs(self.function.prototype)
1576
+ arg_vars: list[SimVariable] = []
1577
+ if args:
1578
+ arg_names = self.function.prototype.arg_names or [f"a{i}" for i in range(len(args))]
1579
+ for idx, arg in enumerate(args):
1580
+ if isinstance(arg, SimRegArg):
1581
+ argvar = SimRegisterVariable(
1582
+ self.project.arch.registers[arg.reg_name][0],
1583
+ arg.size,
1584
+ ident=f"arg_{idx}",
1585
+ name=arg_names[idx],
1586
+ region=self.function.addr,
1587
+ )
1588
+ elif isinstance(arg, SimStackArg):
1589
+ argvar = SimStackVariable(
1590
+ arg.stack_offset,
1591
+ arg.size,
1592
+ base="bp",
1593
+ ident=f"arg_{idx}",
1594
+ name=arg_names[idx],
1595
+ region=self.function.addr,
1596
+ )
1597
+ else:
1598
+ argvar = SimVariable(
1599
+ ident=f"arg_{idx}",
1600
+ name=arg_names[idx],
1601
+ region=self.function.addr,
1602
+ size=arg.size,
1603
+ )
1604
+ arg_vars.append(argvar)
1605
+ return arg_vars
1606
+ return []
1607
+
1608
+ @timethis
1609
+ def _make_callsites(
1610
+ self,
1611
+ ail_graph,
1612
+ func_args: set[ailment.Expr.VirtualVariable],
1613
+ stack_pointer_tracker=None,
1614
+ preserve_vvar_ids: set[int] | None = None,
1615
+ ):
1616
+ """
1617
+ Simplify all function call statements.
1618
+ """
1619
+
1620
+ # Computing reaching definitions
1621
+ rd = self.project.analyses.SReachingDefinitions(
1622
+ subject=self.function,
1623
+ func_graph=ail_graph,
1624
+ func_args=func_args,
1625
+ fail_fast=self._fail_fast,
1626
+ # use_callee_saved_regs_at_return=not self._register_save_areas_removed, FIXME
1627
+ )
1628
+
1629
+ class TempClass: # pylint:disable=missing-class-docstring
1630
+ stack_arg_offsets = set()
1631
+ removed_vvar_ids = set()
1632
+
1633
+ def _handler(block):
1634
+ csm = self.project.analyses.AILCallSiteMaker(
1635
+ block,
1636
+ fail_fast=self._fail_fast,
1637
+ reaching_definitions=rd,
1638
+ stack_pointer_tracker=stack_pointer_tracker,
1639
+ ail_manager=self._ail_manager,
1640
+ )
1641
+ if csm.stack_arg_offsets is not None:
1642
+ TempClass.stack_arg_offsets |= csm.stack_arg_offsets
1643
+ if csm.removed_vvar_ids:
1644
+ TempClass.removed_vvar_ids |= csm.removed_vvar_ids
1645
+ if csm.result_block and csm.result_block != block:
1646
+ ail_block = csm.result_block
1647
+ simp = self.project.analyses.AILBlockSimplifier(
1648
+ ail_block,
1649
+ self.function.addr,
1650
+ fail_fast=self._fail_fast,
1651
+ stack_pointer_tracker=stack_pointer_tracker,
1652
+ peephole_optimizations=self.peephole_optimizations,
1653
+ preserve_vvar_ids=preserve_vvar_ids,
1654
+ )
1655
+ return simp.result_block
1656
+ return None
1657
+
1658
+ # rewriting call-sites at this point, pre-inlining, causes issues with incorrect call signatures
1659
+ if not self._inlining_parents:
1660
+ AILGraphWalker(ail_graph, _handler, replace_nodes=True).walk()
1661
+
1662
+ return ail_graph, TempClass.stack_arg_offsets, TempClass.removed_vvar_ids
1663
+
1664
+ @timethis
1665
+ def _make_returns(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
1666
+ """
1667
+ Work on each return statement and fill in its return expressions.
1668
+ """
1669
+ if self.function.calling_convention is None:
1670
+ # unknown calling convention. cannot do much about return expressions.
1671
+ return ail_graph
1672
+
1673
+ ReturnMaker(self._ail_manager, self.project.arch, self.function, ail_graph)
1674
+
1675
+ return ail_graph
1676
+
1677
+ @timethis
1678
+ def _make_function_prototype(self, arg_list: list[SimVariable], variable_kb):
1679
+ if self.function.prototype is not None:
1680
+ if not self.function.is_prototype_guessed:
1681
+ # do not overwrite an existing function prototype
1682
+ # if you want to re-generate the prototype, clear the existing one first
1683
+ return
1684
+ if isinstance(self.function.prototype.returnty, SimTypeFloat) or any(
1685
+ isinstance(arg, SimTypeFloat) for arg in self.function.prototype.args
1686
+ ):
1687
+ # Type inference does not yet support floating point variables, but calling convention analysis does
1688
+ # FIXME: remove this branch once type inference supports floating point variables
1689
+ return
1690
+
1691
+ variables = variable_kb.variables[self.function.addr]
1692
+ func_args = []
1693
+ for arg in arg_list:
1694
+ func_arg = None
1695
+ arg_ty = variables.get_variable_type(arg)
1696
+ if arg_ty is None:
1697
+ # determine type based on size
1698
+ if isinstance(arg, (SimRegisterVariable, SimStackVariable)):
1699
+ if arg.size == 1:
1700
+ func_arg = SimTypeChar()
1701
+ elif arg.size == 2:
1702
+ func_arg = SimTypeShort()
1703
+ elif arg.size == 4:
1704
+ func_arg = SimTypeInt()
1705
+ elif arg.size == 8:
1706
+ func_arg = SimTypeLongLong()
1707
+ else:
1708
+ l.warning("Unsupported argument size %d.", arg.size)
1709
+ else:
1710
+ func_arg = arg_ty
1711
+
1712
+ func_args.append(func_arg)
1713
+
1714
+ if self.function.prototype is not None and self.function.prototype.returnty is not None:
1715
+ returnty = self.function.prototype.returnty
1716
+ else:
1717
+ returnty = SimTypeInt()
1718
+
1719
+ self.function.prototype = SimTypeFunction(func_args, returnty).with_arch(self.project.arch)
1720
+ self.function.is_prototype_guessed = False
1721
+
1722
+ @timethis
1723
+ def _recover_and_link_variables(
1724
+ self,
1725
+ ail_graph,
1726
+ arg_list: list,
1727
+ arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]],
1728
+ vvar2vvar: dict[int, int],
1729
+ type_hints: list[tuple[atoms.VirtualVariable | atoms.MemoryLocation, str]],
1730
+ ):
1731
+ # variable recovery
1732
+ tmp_kb = KnowledgeBase(self.project) if self.variable_kb is None else self.variable_kb
1733
+ tmp_kb.functions = self.kb.functions
1734
+ vr = self.project.analyses.VariableRecoveryFast(
1735
+ self.function, # pylint:disable=unused-variable
1736
+ fail_fast=self._fail_fast, # type:ignore
1737
+ func_graph=ail_graph,
1738
+ kb=tmp_kb, # type:ignore
1739
+ track_sp=False,
1740
+ func_args=arg_list,
1741
+ unify_variables=False,
1742
+ func_arg_vvars=arg_vvars,
1743
+ vvar_to_vvar=vvar2vvar,
1744
+ type_hints=type_hints,
1745
+ )
1746
+ # get ground-truth types
1747
+ var_manager = tmp_kb.variables[self.function.addr]
1748
+ groundtruth = {}
1749
+ for variable in var_manager.variables_with_manual_types:
1750
+ vartype = var_manager.variable_to_types.get(variable, None)
1751
+ if vartype is not None:
1752
+ for tv in vr.var_to_typevars[variable]:
1753
+ groundtruth[tv] = vartype
1754
+ # get maximum sizes of each stack variable, regardless of its original type
1755
+ stackvar_max_sizes = var_manager.get_stackvar_max_sizes(self.stack_items)
1756
+ tv_max_sizes = {}
1757
+ for v, s in stackvar_max_sizes.items():
1758
+ assert isinstance(v, SimStackVariable)
1759
+ if v in vr.var_to_typevars:
1760
+ for tv in vr.var_to_typevars[v]:
1761
+ tv_max_sizes[tv] = s
1762
+ if v.offset in vr.stack_offset_typevars:
1763
+ tv = vr.stack_offset_typevars[v.offset]
1764
+ tv_max_sizes[tv] = s
1765
+ # clean up existing types for this function
1766
+ var_manager.remove_types()
1767
+ # TODO: Type inference for global variables
1768
+ # run type inference
1769
+ if self._must_struct:
1770
+ must_struct = set()
1771
+ for var, typevars in vr.var_to_typevars.items():
1772
+ if var.ident in self._must_struct:
1773
+ must_struct |= typevars
1774
+ else:
1775
+ must_struct = None
1776
+ total_type_constraints = sum(len(tc) for tc in vr.type_constraints.values()) if vr.type_constraints else 0
1777
+ if total_type_constraints > self._max_type_constraints:
1778
+ l.warning(
1779
+ "The number of type constraints (%d) is greater than the threshold (%d). Skipping type inference.",
1780
+ total_type_constraints,
1781
+ self._max_type_constraints,
1782
+ )
1783
+ else:
1784
+ try:
1785
+ tp = self.project.analyses.Typehoon(
1786
+ vr.type_constraints,
1787
+ vr.func_typevar,
1788
+ kb=tmp_kb,
1789
+ fail_fast=self._fail_fast,
1790
+ var_mapping=vr.var_to_typevars,
1791
+ stack_offset_tvs=vr.stack_offset_typevars,
1792
+ must_struct=must_struct,
1793
+ ground_truth=groundtruth,
1794
+ stackvar_max_sizes=tv_max_sizes,
1795
+ )
1796
+ # tp.pp_constraints()
1797
+ # tp.pp_solution()
1798
+ tp.update_variable_types(
1799
+ self.function.addr,
1800
+ {
1801
+ v: t
1802
+ for v, t in vr.var_to_typevars.items()
1803
+ if isinstance(v, (SimRegisterVariable, SimStackVariable))
1804
+ },
1805
+ vr.stack_offset_typevars,
1806
+ )
1807
+ tp.update_variable_types(
1808
+ "global",
1809
+ {
1810
+ v: t
1811
+ for v, t in vr.var_to_typevars.items()
1812
+ if isinstance(v, SimMemoryVariable) and not isinstance(v, SimStackVariable)
1813
+ },
1814
+ )
1815
+ except Exception: # pylint:disable=broad-except
1816
+ l.warning(
1817
+ "Typehoon analysis failed. Variables will not have types. Please report to GitHub.", exc_info=True
1818
+ )
1819
+
1820
+ # for any left-over variables, assign Bottom type (which will get "corrected" into a default type in
1821
+ # VariableManager)
1822
+ bottype = SimTypeBottom().with_arch(self.project.arch)
1823
+ for var in var_manager._variables:
1824
+ if var not in var_manager.variable_to_types:
1825
+ var_manager.set_variable_type(var, bottype)
1826
+
1827
+ # Unify SSA variables
1828
+ tmp_kb.variables.global_manager.assign_variable_names(labels=self.kb.labels, types={SimMemoryVariable})
1829
+ liveness = self.project.analyses.SLiveness(
1830
+ self.function,
1831
+ func_graph=ail_graph,
1832
+ entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
1833
+ arg_vvars=[vvar for vvar, _ in arg_vvars.values()],
1834
+ )
1835
+ var_manager.unify_variables(interference=liveness.interference_graph())
1836
+ var_manager.assign_unified_variable_names(
1837
+ labels=self.kb.labels,
1838
+ arg_names=self.function.prototype.arg_names if self.function.prototype else None,
1839
+ reset=self._reset_variable_names,
1840
+ func_blocks=list(ail_graph),
1841
+ )
1842
+
1843
+ # Link variables and struct member information to every statement and expression
1844
+ for block in ail_graph.nodes():
1845
+ self._link_variables_on_block(block, tmp_kb)
1846
+
1847
+ if self._cache is not None:
1848
+ self._cache.type_constraints = vr.type_constraints
1849
+ self._cache.func_typevar = vr.func_typevar
1850
+ self._cache.var_to_typevar = vr.var_to_typevars
1851
+
1852
+ return tmp_kb
1853
+
1854
+ def _link_variables_on_block(self, block, kb):
1855
+ """
1856
+ Link atoms (AIL expressions) in the given block to corresponding variables identified previously.
1857
+
1858
+ :param ailment.Block block: The AIL block to work on.
1859
+ :return: None
1860
+ """
1861
+
1862
+ variable_manager = kb.variables[self.function.addr]
1863
+ global_variables = kb.variables["global"]
1864
+
1865
+ for stmt_idx, stmt in enumerate(block.statements):
1866
+ stmt_type = type(stmt)
1867
+ if stmt_type is ailment.Stmt.Store:
1868
+ # find a memory variable
1869
+ mem_vars = variable_manager.find_variables_by_atom(block.addr, stmt_idx, stmt, block_idx=block.idx)
1870
+ if len(mem_vars) == 1:
1871
+ stmt.variable, stmt.offset = next(iter(mem_vars))
1872
+ else:
1873
+ # check if the dest address is a variable
1874
+ stmt: ailment.Stmt.Store
1875
+ # special handling for constant addresses
1876
+ if isinstance(stmt.addr, ailment.Expr.Const):
1877
+ # global variable?
1878
+ variables = global_variables.get_global_variables(stmt.addr.value)
1879
+ if variables:
1880
+ var = next(iter(variables))
1881
+ stmt.variable = var
1882
+ stmt.offset = 0
1883
+ else:
1884
+ self._link_variables_on_expr(
1885
+ variable_manager, global_variables, block, stmt_idx, stmt, stmt.addr
1886
+ )
1887
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.data)
1888
+
1889
+ # link struct member info
1890
+ if isinstance(stmt.variable, SimStackVariable):
1891
+ off = stmt.variable.offset
1892
+ if off in variable_manager.stack_offset_to_struct_member_info:
1893
+ stmt.tags["struct_member_info"] = variable_manager.stack_offset_to_struct_member_info[off]
1894
+
1895
+ elif stmt_type is ailment.Stmt.Assignment or stmt_type is ailment.Stmt.WeakAssignment:
1896
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.dst)
1897
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.src)
1898
+
1899
+ elif stmt_type is ailment.Stmt.CAS:
1900
+ for expr in [
1901
+ stmt.addr,
1902
+ stmt.data_lo,
1903
+ stmt.data_hi,
1904
+ stmt.expd_lo,
1905
+ stmt.expd_hi,
1906
+ stmt.old_lo,
1907
+ stmt.old_hi,
1908
+ ]:
1909
+ if expr is not None:
1910
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr)
1911
+
1912
+ elif stmt_type is ailment.Stmt.ConditionalJump:
1913
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.condition)
1914
+
1915
+ elif stmt_type is ailment.Stmt.Jump and not isinstance(stmt.target, ailment.Expr.Const):
1916
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.target)
1917
+
1918
+ elif stmt_type is ailment.Stmt.Call:
1919
+ self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, stmt, is_expr=False)
1920
+
1921
+ elif stmt_type is ailment.Stmt.Return:
1922
+ assert isinstance(stmt, ailment.Stmt.Return)
1923
+ self._link_variables_on_return(variable_manager, global_variables, block, stmt_idx, stmt)
1924
+
1925
+ def _link_variables_on_return(
1926
+ self, variable_manager, global_variables, block: ailment.Block, stmt_idx: int, stmt: ailment.Stmt.Return
1927
+ ):
1928
+ if stmt.ret_exprs:
1929
+ for ret_expr in stmt.ret_exprs:
1930
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, ret_expr)
1931
+
1932
+ def _link_variables_on_call(self, variable_manager, global_variables, block, stmt_idx, stmt, is_expr=False):
1933
+ if not isinstance(stmt.target, ailment.Expr.Const):
1934
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.target)
1935
+ if stmt.args:
1936
+ for arg in stmt.args:
1937
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, arg)
1938
+ if not is_expr and stmt.ret_expr:
1939
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.ret_expr)
1940
+
1941
+ def _link_variables_on_expr(self, variable_manager, global_variables, block, stmt_idx, stmt, expr):
1942
+ """
1943
+ Link atoms (AIL expressions) in the given expression to corresponding variables identified previously.
1944
+
1945
+ :param variable_manager: Variable manager of the function.
1946
+ :param ailment.Block block: AIL block.
1947
+ :param int stmt_idx: ID of the statement.
1948
+ :param stmt: The AIL statement that `expr` belongs to.
1949
+ :param expr: The AIl expression to work on.
1950
+ :return: None
1951
+ """
1952
+
1953
+ if type(expr) is ailment.Expr.Register:
1954
+ # find a register variable
1955
+ reg_vars = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
1956
+ final_reg_vars = set()
1957
+ if len(reg_vars) > 1:
1958
+ # take phi variables
1959
+ for reg_var in reg_vars:
1960
+ if variable_manager.is_phi_variable(reg_var[0]):
1961
+ final_reg_vars.add(reg_var)
1962
+ else:
1963
+ final_reg_vars = reg_vars
1964
+ if len(final_reg_vars) >= 1:
1965
+ reg_var, offset = next(iter(final_reg_vars))
1966
+ expr.variable = reg_var
1967
+ expr.variable_offset = offset
1968
+
1969
+ elif type(expr) is ailment.Expr.VirtualVariable:
1970
+ vars_ = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
1971
+ if len(vars_) >= 1:
1972
+ var, offset = next(iter(vars_))
1973
+ expr.variable = var
1974
+ expr.variable_offset = offset
1975
+
1976
+ if isinstance(expr, ailment.Expr.VirtualVariable) and expr.was_stack:
1977
+ off = expr.stack_offset
1978
+ if off in variable_manager.stack_offset_to_struct_member_info:
1979
+ expr.tags["struct_member_info"] = variable_manager.stack_offset_to_struct_member_info[off]
1980
+
1981
+ elif type(expr) is ailment.Expr.Load:
1982
+ variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
1983
+ if len(variables) == 0:
1984
+ # if it's a constant addr, maybe it's referencing an extern location
1985
+ base_addr, offset = self.parse_variable_addr(expr.addr)
1986
+ if offset is not None and isinstance(offset, ailment.Expr.Expression):
1987
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, offset)
1988
+ if base_addr is not None:
1989
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, base_addr)
1990
+
1991
+ # if we are accessing the variable directly (offset == 0), we link the variable onto this expression
1992
+ if (
1993
+ offset == 0 or (isinstance(offset, ailment.Expr.Const) and offset.value == 0)
1994
+ ) and "reference_variable" in base_addr.tags:
1995
+ expr.variable = base_addr.reference_variable
1996
+ expr.variable_offset = base_addr.reference_variable_offset
1997
+
1998
+ if base_addr is None and offset is None:
1999
+ # this is a local variable
2000
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.addr)
2001
+ if "reference_variable" in expr.addr.tags and expr.addr.reference_variable is not None:
2002
+ # copy over the variable to this expr since the variable on a constant is supposed to be a
2003
+ # reference variable.
2004
+ expr.variable = expr.addr.reference_variable
2005
+ expr.variable_offset = expr.addr.reference_variable_offset
2006
+ else:
2007
+ if len(variables) > 1:
2008
+ l.error(
2009
+ "More than one variable are available for atom %s. Consider fixing it using phi nodes.", expr
2010
+ )
2011
+ var, offset = next(iter(variables))
2012
+ expr.variable = var
2013
+ expr.variable_offset = offset
2014
+
2015
+ if isinstance(var, SimStackVariable):
2016
+ off = var.offset
2017
+ if off in variable_manager.stack_offset_to_struct_member_info:
2018
+ expr.tags["struct_member_info"] = variable_manager.stack_offset_to_struct_member_info[off]
2019
+
2020
+ elif type(expr) is ailment.Expr.BinaryOp:
2021
+ variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
2022
+ if len(variables) >= 1:
2023
+ var, offset = next(iter(variables))
2024
+ expr.variable = var
2025
+ expr.variable_offset = offset
2026
+ else:
2027
+ self._link_variables_on_expr(
2028
+ variable_manager, global_variables, block, stmt_idx, stmt, expr.operands[0]
2029
+ )
2030
+ self._link_variables_on_expr(
2031
+ variable_manager, global_variables, block, stmt_idx, stmt, expr.operands[1]
2032
+ )
2033
+
2034
+ elif type(expr) is ailment.Expr.UnaryOp:
2035
+ variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
2036
+ if len(variables) >= 1:
2037
+ var, offset = next(iter(variables))
2038
+ expr.variable = var
2039
+ expr.variable_offset = offset
2040
+ else:
2041
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.operand)
2042
+
2043
+ elif type(expr) in {ailment.Expr.Convert, ailment.Expr.Reinterpret}:
2044
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.operand)
2045
+
2046
+ elif type(expr) is ailment.Expr.ITE:
2047
+ variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
2048
+ if len(variables) >= 1:
2049
+ var, offset = next(iter(variables))
2050
+ expr.variable = var
2051
+ expr.variable_offset = offset
2052
+ else:
2053
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.cond)
2054
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.iftrue)
2055
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.iffalse)
2056
+
2057
+ elif isinstance(expr, ailment.Expr.BasePointerOffset):
2058
+ variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
2059
+ if len(variables) >= 1:
2060
+ var, offset = next(iter(variables))
2061
+ expr.variable = var
2062
+ expr.variable_offset = offset
2063
+
2064
+ elif isinstance(expr, ailment.Expr.Const) and expr.is_int:
2065
+ # custom string?
2066
+ if hasattr(expr, "custom_string") and expr.custom_string is True:
2067
+ s = self.kb.custom_strings[expr.value]
2068
+ expr.tags["reference_values"] = {
2069
+ SimTypePointer(SimTypeChar().with_arch(self.project.arch)).with_arch(self.project.arch): s.decode(
2070
+ "latin-1"
2071
+ ),
2072
+ }
2073
+ else:
2074
+ # global variable?
2075
+ global_vars = global_variables.get_global_variables(expr.value)
2076
+ # detect if there is a related symbol
2077
+ if not global_vars and self.project.loader.find_object_containing(expr.value):
2078
+ symbol = self.project.loader.find_symbol(expr.value)
2079
+ if symbol is not None:
2080
+ # Create a new global variable if there isn't one already
2081
+ global_vars = global_variables.get_global_variables(symbol.rebased_addr)
2082
+ if not global_vars:
2083
+ global_var = SimMemoryVariable(symbol.rebased_addr, symbol.size, name=symbol.name)
2084
+ global_variables.add_variable("global", global_var.addr, global_var)
2085
+ global_vars = {global_var}
2086
+ if global_vars:
2087
+ global_var = next(iter(global_vars))
2088
+ expr.tags["reference_variable"] = global_var
2089
+ expr.tags["reference_variable_offset"] = 0
2090
+
2091
+ elif isinstance(expr, ailment.Stmt.Call):
2092
+ self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, expr, is_expr=True)
2093
+
2094
+ elif isinstance(expr, ailment.Expr.VEXCCallExpression):
2095
+ for operand in expr.operands:
2096
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, operand)
2097
+
2098
+ elif isinstance(expr, ailment.Expr.DirtyExpression):
2099
+ for operand in expr.operands:
2100
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, operand)
2101
+ if expr.maddr:
2102
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.maddr)
2103
+ if expr.guard:
2104
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.guard)
2105
+
2106
+ elif isinstance(expr, ailment.Expr.Phi):
2107
+ for _, vvar in expr.src_and_vvars:
2108
+ if vvar is not None:
2109
+ self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, vvar)
2110
+
2111
+ def _function_graph_to_ail_graph(self, func_graph, blocks_by_addr_and_size=None):
2112
+ if blocks_by_addr_and_size is None:
2113
+ blocks_by_addr_and_size = self._blocks_by_addr_and_size
2114
+ assert blocks_by_addr_and_size is not None
2115
+
2116
+ graph = networkx.DiGraph()
2117
+
2118
+ entry_node = next(iter(node for node in func_graph if node.addr == self.entry_node_addr[0]), None)
2119
+ if entry_node is None:
2120
+ raise AngrDecompilationError(
2121
+ f"Entry node with address {self.entry_node_addr[0]:#x} not found in the function graph"
2122
+ )
2123
+
2124
+ # add the entry node into the graph
2125
+ ail_block = blocks_by_addr_and_size.get((entry_node.addr, entry_node.size))
2126
+ if ail_block is None:
2127
+ raise AngrDecompilationError(f"AIL block at address {entry_node.addr:#x} not found")
2128
+ graph.add_node(ail_block)
2129
+
2130
+ # get all descendants and only include them in the AIL graph.
2131
+ # this way all unreachable blocks will be excluded from the AIL graph.
2132
+ descendants = networkx.descendants(func_graph, entry_node) | {entry_node}
2133
+ for src_node, dst_node, data in networkx.subgraph_view(
2134
+ func_graph, filter_node=lambda n: n in descendants
2135
+ ).edges(data=True):
2136
+ src = blocks_by_addr_and_size.get((src_node.addr, src_node.size))
2137
+ dst = blocks_by_addr_and_size.get((dst_node.addr, dst_node.size))
2138
+
2139
+ if src is not None and dst is not None:
2140
+ graph.add_edge(src, dst, **data)
2141
+
2142
+ return graph
2143
+
2144
+ @staticmethod
2145
+ def _duplicate_orphaned_cond_jumps(ail_graph) -> networkx.DiGraph:
2146
+ """
2147
+ Find conditional jumps that are orphaned (e.g., being the only instruction of the block). If these blocks have
2148
+ multiple predecessors, duplicate them to all predecessors. This is a workaround for cases where these
2149
+ conditional jumps rely on comparisons in more than one predecessor and we cannot resolve ccalls into
2150
+ comparisons.
2151
+
2152
+ This pass runs before any SSA transformations.
2153
+
2154
+ # 140017162 jz short 1400171e1
2155
+ """
2156
+
2157
+ for block in list(ail_graph):
2158
+ if len(block.statements) > 1 and block.statements[0].ins_addr == block.statements[-1].ins_addr:
2159
+ preds = list(ail_graph.predecessors(block))
2160
+ if len(preds) > 1 and block not in preds:
2161
+ has_ccall = any(
2162
+ isinstance(stmt, ailment.Stmt.Assignment)
2163
+ and isinstance(stmt.src, ailment.Expr.VEXCCallExpression)
2164
+ for stmt in block.statements
2165
+ )
2166
+ if has_ccall:
2167
+ # duplicate this block to its predecessors!
2168
+ preds = sorted(preds, key=lambda x: x.addr)
2169
+ succs = sorted(ail_graph.successors(block), key=lambda x: x.addr)
2170
+ # FIXME: We should track block IDs globally and ensure block IDs do not collide
2171
+ block_idx_start = block.idx + 1 if block.idx is not None else 1
2172
+ for pred in preds[1:]:
2173
+ ail_graph.remove_edge(pred, block)
2174
+ new_block = block.copy()
2175
+ new_block.idx = block_idx_start
2176
+ block_idx_start += 1
2177
+ ail_graph.add_edge(pred, new_block)
2178
+ for succ in succs:
2179
+ ail_graph.add_edge(new_block, succ if succ is not block else new_block)
2180
+
2181
+ return ail_graph
2182
+
2183
+ def _rewrite_jump_rax_calls(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
2184
+ """
2185
+ Rewrite calls to special functions (e.g., guard_dispatch_icall_nop) into `call rax`.
2186
+ """
2187
+
2188
+ if self.project.arch.name != "AMD64":
2189
+ return ail_graph
2190
+ if self._cfg is None:
2191
+ return ail_graph
2192
+
2193
+ for block in ail_graph:
2194
+ if not block.statements:
2195
+ continue
2196
+ assert block.addr is not None
2197
+ last_stmt = block.statements[-1]
2198
+ if isinstance(last_stmt, ailment.Stmt.Call):
2199
+ # we can't examine the call target at this point because constant propagation hasn't run yet; we consult
2200
+ # the CFG instead
2201
+ callsite_node = self._cfg.get_any_node(block.addr, anyaddr=True)
2202
+ if callsite_node is None:
2203
+ break
2204
+ callees = self._cfg.get_successors(callsite_node, jumpkind="Ijk_Call")
2205
+ if len(callees) != 1:
2206
+ break
2207
+ callee = callees[0].addr
2208
+ if self.kb.functions.contains_addr(callee):
2209
+ callee_func = self.kb.functions.get_by_addr(callee)
2210
+ if callee_func.info.get("jmp_rax", False) is True:
2211
+ # rewrite this statement into Call(rax)
2212
+ call_stmt = last_stmt.copy()
2213
+ call_stmt.target = ailment.Expr.Register(
2214
+ self._ail_manager.next_atom(),
2215
+ None,
2216
+ self.project.arch.registers["rax"][0],
2217
+ 64,
2218
+ ins_addr=call_stmt.ins_addr,
2219
+ )
2220
+ block.statements[-1] = call_stmt
2221
+
2222
+ return ail_graph
2223
+
2224
+ def _rewrite_ite_expressions(self, ail_graph):
2225
+ cfg = self._cfg
2226
+ for block in list(ail_graph):
2227
+ if cfg is not None and block.addr in cfg.jump_tables:
2228
+ continue
2229
+
2230
+ ite_ins_addrs = []
2231
+ cas_ins_addrs = set()
2232
+ for stmt in block.statements:
2233
+ if isinstance(stmt, ailment.Stmt.CAS):
2234
+ # we do not rewrite ITE statements that are caused by CAS statements
2235
+ cas_ins_addrs.add(stmt.ins_addr)
2236
+ elif (
2237
+ isinstance(stmt, ailment.Stmt.Assignment)
2238
+ and isinstance(stmt.src, ailment.Expr.ITE)
2239
+ and stmt.ins_addr not in ite_ins_addrs
2240
+ and stmt.ins_addr not in cas_ins_addrs
2241
+ ):
2242
+ ite_ins_addrs.append(stmt.ins_addr)
2243
+
2244
+ if ite_ins_addrs:
2245
+ block_addr = block.addr
2246
+ for ite_ins_addr in ite_ins_addrs:
2247
+ block_addr = self._create_triangle_for_ite_expression(ail_graph, block_addr, ite_ins_addr)
2248
+ if block_addr is None or block_addr >= block.addr + block.original_size:
2249
+ break
2250
+
2251
+ def _create_triangle_for_ite_expression(self, ail_graph, block_addr: int, ite_ins_addr: int):
2252
+ ite_insn_only_block = self.project.factory.block(ite_ins_addr, num_inst=1)
2253
+ ite_insn_size = ite_insn_only_block.size
2254
+ assert ite_insn_size is not None
2255
+ if ite_insn_size <= 2: # we need an address for true_block and another address for false_block
2256
+ return None
2257
+ if ite_insn_only_block.vex.exit_statements:
2258
+ return None
2259
+
2260
+ # relift the head and the ITE instruction
2261
+ new_head = self.project.factory.block(
2262
+ block_addr, size=ite_ins_addr - block_addr + ite_insn_size, cross_insn_opt=False
2263
+ )
2264
+ new_head_ail = ailment.IRSBConverter.convert(new_head.vex, self._ail_manager)
2265
+ # remove all statements between the ITE expression and the very end of the block
2266
+ ite_expr_stmt_idx = None
2267
+ ite_expr_stmt = None
2268
+ for idx, stmt in enumerate(new_head_ail.statements):
2269
+ if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
2270
+ ite_expr_stmt_idx = idx
2271
+ ite_expr_stmt = stmt
2272
+ break
2273
+ if ite_expr_stmt_idx is None:
2274
+ return None
2275
+ assert ite_expr_stmt is not None
2276
+
2277
+ ite_expr: ailment.Expr.ITE = ite_expr_stmt.src # type: ignore
2278
+ new_head_ail.statements = new_head_ail.statements[:ite_expr_stmt_idx]
2279
+ # build the conditional jump
2280
+ true_block_addr = ite_ins_addr + 1
2281
+ false_block_addr = ite_ins_addr + 2
2282
+ cond_jump_stmt = ailment.Stmt.ConditionalJump(
2283
+ ite_expr_stmt.idx,
2284
+ ite_expr.cond,
2285
+ ailment.Expr.Const(None, None, true_block_addr, self.project.arch.bits, **ite_expr_stmt.tags),
2286
+ ailment.Expr.Const(None, None, false_block_addr, self.project.arch.bits, **ite_expr_stmt.tags),
2287
+ **ite_expr_stmt.tags,
2288
+ )
2289
+ new_head_ail.statements.append(cond_jump_stmt)
2290
+
2291
+ # build the true block
2292
+ true_block = self.project.factory.block(ite_ins_addr, num_inst=1)
2293
+ true_block_ail = ailment.IRSBConverter.convert(true_block.vex, self._ail_manager)
2294
+ true_block_ail.addr = true_block_addr
2295
+
2296
+ ite_expr_stmt_idx = None
2297
+ ite_expr_stmt = None
2298
+ for idx, stmt in enumerate(true_block_ail.statements):
2299
+ if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
2300
+ ite_expr_stmt_idx = idx
2301
+ ite_expr_stmt = stmt
2302
+ break
2303
+ if ite_expr_stmt_idx is None:
2304
+ return None
2305
+ assert ite_expr_stmt is not None
2306
+
2307
+ true_block_ail.statements[ite_expr_stmt_idx] = ailment.Stmt.Assignment(
2308
+ ite_expr_stmt.idx, ite_expr_stmt.dst, ite_expr_stmt.src.iftrue, **ite_expr_stmt.tags
2309
+ )
2310
+
2311
+ # build the false block
2312
+ false_block = self.project.factory.block(ite_ins_addr, num_inst=1)
2313
+ false_block_ail = ailment.IRSBConverter.convert(false_block.vex, self._ail_manager)
2314
+ false_block_ail.addr = false_block_addr
2315
+
2316
+ ite_expr_stmt_idx = None
2317
+ ite_expr_stmt = None
2318
+ for idx, stmt in enumerate(false_block_ail.statements):
2319
+ if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
2320
+ ite_expr_stmt_idx = idx
2321
+ ite_expr_stmt = stmt
2322
+ break
2323
+ if ite_expr_stmt_idx is None:
2324
+ return None
2325
+ assert ite_expr_stmt is not None
2326
+
2327
+ false_block_ail.statements[ite_expr_stmt_idx] = ailment.Stmt.Assignment(
2328
+ ite_expr_stmt.idx, ite_expr_stmt.dst, ite_expr_stmt.src.iffalse, **ite_expr_stmt.tags
2329
+ )
2330
+
2331
+ original_block = next(iter(b for b in ail_graph if b.addr == block_addr))
2332
+
2333
+ original_block_in_edges = list(ail_graph.in_edges(original_block, data=True))
2334
+ original_block_out_edges = list(ail_graph.out_edges(original_block, data=True))
2335
+
2336
+ # build the target block if the target block does not exist in the current function
2337
+ end_block_addr = ite_ins_addr + ite_insn_size
2338
+ if block_addr < end_block_addr < block_addr + original_block.original_size:
2339
+ end_block = self.project.factory.block(
2340
+ ite_ins_addr + ite_insn_size,
2341
+ size=block_addr + original_block.original_size - (ite_ins_addr + ite_insn_size),
2342
+ cross_insn_opt=False,
2343
+ )
2344
+ end_block_ail = ailment.IRSBConverter.convert(end_block.vex, self._ail_manager)
2345
+ else:
2346
+ try:
2347
+ end_block_ail = next(iter(b for b in ail_graph if b.addr == end_block_addr))
2348
+ except StopIteration:
2349
+ return None
2350
+
2351
+ # last check: if the first instruction of the end block has Sar, then we bail (due to the peephole optimization
2352
+ # SarToSignedDiv)
2353
+ for stmt in end_block_ail.statements:
2354
+ if stmt.ins_addr > end_block_ail.addr:
2355
+ break
2356
+ if (
2357
+ isinstance(stmt, ailment.Stmt.Assignment)
2358
+ and isinstance(stmt.src, ailment.Expr.BinaryOp)
2359
+ and stmt.src.op == "Sar"
2360
+ ):
2361
+ return None
2362
+
2363
+ # corner-case: the last statement of original_block might have been patched by _remove_redundant_jump_blocks.
2364
+ # we detect such case and fix it in new_head_ail
2365
+ self._remove_redundant_jump_blocks_repatch_relifted_block(original_block, end_block_ail)
2366
+
2367
+ ail_graph.remove_node(original_block)
2368
+
2369
+ if end_block_ail not in ail_graph:
2370
+ # newly created. add it and the necessary edges into the graph
2371
+ for _, dst, data in original_block_out_edges:
2372
+ if dst is original_block:
2373
+ ail_graph.add_edge(end_block_ail, new_head_ail, **data)
2374
+ else:
2375
+ ail_graph.add_edge(end_block_ail, dst, **data)
2376
+
2377
+ # in edges
2378
+ for src, _, data in original_block_in_edges:
2379
+ if src is original_block:
2380
+ # loop
2381
+ ail_graph.add_edge(end_block_ail, new_head_ail, **data)
2382
+ else:
2383
+ ail_graph.add_edge(src, new_head_ail, **data)
2384
+
2385
+ # triangle
2386
+ ail_graph.add_edge(new_head_ail, true_block_ail)
2387
+ ail_graph.add_edge(new_head_ail, false_block_ail)
2388
+ ail_graph.add_edge(true_block_ail, end_block_ail)
2389
+ ail_graph.add_edge(false_block_ail, end_block_ail)
2390
+
2391
+ return end_block_ail.addr
2392
+
2393
+ def _fix_abnormal_switch_case_heads(self, ail_graph: networkx.DiGraph) -> None:
2394
+ """
2395
+ Detect the existence of switch-case heads whose indirect jump node has more than one predecessor, and attempt
2396
+ to fix those cases by altering the graph.
2397
+ """
2398
+
2399
+ if self._cfg is None:
2400
+ return
2401
+
2402
+ if not self._cfg.jump_tables:
2403
+ return
2404
+
2405
+ node_dict: defaultdict[int, list[ailment.Block]] = defaultdict(list)
2406
+ for node in ail_graph:
2407
+ node_dict[node.addr].append(node)
2408
+
2409
+ candidates = []
2410
+ for block_addr in self._cfg.jump_tables:
2411
+ block_nodes = node_dict[block_addr]
2412
+ for block_node in block_nodes:
2413
+ if ail_graph.in_degree[block_node] > 1:
2414
+ # found it
2415
+ candidates.append(block_node)
2416
+
2417
+ if not candidates:
2418
+ return
2419
+
2420
+ sorted_nodes = GraphUtils.quasi_topological_sort_nodes(ail_graph)
2421
+ node_to_rank = {node: rank for rank, node in enumerate(sorted_nodes)}
2422
+ for candidate in candidates:
2423
+ # determine the "intended" switch-case head using topological order
2424
+ preds = list(ail_graph.predecessors(candidate))
2425
+ preds = sorted(preds, key=lambda n_: node_to_rank[n_])
2426
+ intended_head = preds[0]
2427
+ other_heads = preds[1:]
2428
+
2429
+ # now here is the tricky part. there are two cases:
2430
+ # Case 1: the intended head and the other heads share the same suffix (of instructions)
2431
+ # Example:
2432
+ # ; binary 736cb27201273f6c4f83da362c9595b50d12333362e02bc7a77dd327cc6b045a
2433
+ # 0041DA97 mov ecx, [esp+2Ch+var_18] ; this is the intended head
2434
+ # 0041DA9B mov ecx, [ecx]
2435
+ # 0041DA9D cmp ecx, 9
2436
+ # 0041DAA0 jbe loc_41D5A8
2437
+ #
2438
+ # 0041D599 mov ecx, [ecx] ; this is the other head
2439
+ # 0041D59B mov [esp+2Ch+var_10], eax
2440
+ # 0041D59F cmp ecx, 9
2441
+ # 0041D5A2 ja loc_41DAA6 ; fallthrough to 0x41d5a8
2442
+ # given the overlap of two instructions at the end of both blocks, we will alter the second block to remove
2443
+ # the overlapped instructions and add an unconditional jump so that it jumps to 0x41da9d.
2444
+ # this is the most common case created by jump threading optimization in compilers. it's easy to handle.
2445
+
2446
+ # Case 2 & 3: the intended head and the other heads do not share the same suffix of instructions. in this
2447
+ # case, we have two choices:
2448
+ # Case 2: The intended head has two successors, but at least one unintended head has only one successor.
2449
+ # we cannot reliably convert the blocks into a properly structured switch-case construct. we will
2450
+ # last instruction of all other heads to jump to the cmp instruction in the intended head, but do
2451
+ # not remove any other instructions in these other heads. this is unsound, but is the best we can
2452
+ # do in this case.
2453
+ # Case 3: The intended head has only one successor (which is the indirect jump node). during structuring,
2454
+ # we expect it will be structured as a no-default-node switch-case construct. in this case, we
2455
+ # can simply remove the edges from all other heads to the jump node and only leave the edge from
2456
+ # the intended head to the jump node. we will see goto statements in the output, but this will
2457
+ # lead to correct structuring result.
2458
+
2459
+ overlaps = [self._get_overlapping_suffix_instructions(intended_head, head) for head in other_heads]
2460
+ if overlaps and (overlap := min(overlaps)) > 0:
2461
+ # Case 1
2462
+ self._fix_abnormal_switch_case_heads_case1(ail_graph, candidate, intended_head, other_heads, overlap)
2463
+ elif ail_graph.out_degree[intended_head] == 2:
2464
+ # Case 2
2465
+ l.warning("Switch-case at %#x has multiple head nodes but cannot be fixed soundly.", candidate.addr)
2466
+ # find the comparison instruction in the intended head
2467
+ comparison_stmt = None
2468
+ if "cc_op" in self.project.arch.registers:
2469
+ comparison_stmt = next(
2470
+ iter(
2471
+ stmt
2472
+ for stmt in intended_head.statements
2473
+ if isinstance(stmt, ailment.Stmt.Assignment)
2474
+ and isinstance(stmt.dst, ailment.Expr.Register)
2475
+ and stmt.dst.reg_offset == self.project.arch.registers["cc_op"][0]
2476
+ ),
2477
+ None,
2478
+ )
2479
+ intended_head_block = self.project.factory.block(intended_head.addr, size=intended_head.original_size)
2480
+ if comparison_stmt is not None:
2481
+ cmp_rpos = len(intended_head_block.instruction_addrs) - intended_head_block.instruction_addrs.index(
2482
+ comparison_stmt.ins_addr
2483
+ )
2484
+ else:
2485
+ cmp_rpos = min(len(intended_head_block.instruction_addrs), 2)
2486
+ self._fix_abnormal_switch_case_heads_case2(
2487
+ ail_graph,
2488
+ candidate,
2489
+ intended_head,
2490
+ other_heads,
2491
+ intended_head_split_insns=cmp_rpos,
2492
+ other_head_split_insns=0,
2493
+ )
2494
+ else:
2495
+ # Case 3
2496
+ self._fix_abnormal_switch_case_heads_case3(
2497
+ candidate,
2498
+ other_heads,
2499
+ )
2500
+
2501
+ def _get_overlapping_suffix_instructions(self, ailblock_0: ailment.Block, ailblock_1: ailment.Block) -> int:
2502
+ # we first compare their ending conditional jumps
2503
+ if not self._get_overlapping_suffix_instructions_compare_conditional_jumps(ailblock_0, ailblock_1):
2504
+ return 0
2505
+
2506
+ # we re-lift the blocks and compare the instructions
2507
+ block_0 = self.project.factory.block(ailblock_0.addr, size=ailblock_0.original_size)
2508
+ block_1 = self.project.factory.block(ailblock_1.addr, size=ailblock_1.original_size)
2509
+
2510
+ i0 = len(block_0.capstone.insns) - 2
2511
+ i1 = len(block_1.capstone.insns) - 2
2512
+ overlap = 1
2513
+ while i0 >= 0 and i1 >= 0:
2514
+ same = self._get_overlapping_suffix_instructions_compare_instructions(
2515
+ block_0.capstone.insns[i0], block_1.capstone.insns[i1]
2516
+ )
2517
+ if not same:
2518
+ break
2519
+ overlap += 1
2520
+ i0 -= 1
2521
+ i1 -= 1
2522
+
2523
+ return overlap
2524
+
2525
+ @staticmethod
2526
+ def _get_overlapping_suffix_instructions_compare_instructions(insn_0, insn_1) -> bool:
2527
+ return insn_0.mnemonic == insn_1.mnemonic and insn_0.op_str == insn_1.op_str
2528
+
2529
+ @staticmethod
2530
+ def _get_overlapping_suffix_instructions_compare_conditional_jumps(
2531
+ ailblock_0: ailment.Block, ailblock_1: ailment.Block
2532
+ ) -> bool:
2533
+ # TODO: The logic here is naive and highly customized to the only example I can access. Expand this method
2534
+ # later to handle more cases if needed.
2535
+ if len(ailblock_0.statements) == 0 or len(ailblock_1.statements) == 0:
2536
+ return False
2537
+
2538
+ # 12 | 0x41d5a2 | t17 = (t4 <= 0x9<32>)
2539
+ # 13 | 0x41d5a2 | t16 = Conv(1->32, t17)
2540
+ # 14 | 0x41d5a2 | t14 = t16
2541
+ # 15 | 0x41d5a2 | t18 = Conv(32->1, t14)
2542
+ # 16 | 0x41d5a2 | t9 = t18
2543
+ # 17 | 0x41d5a2 | if (t9) { Goto 0x41d5a8<32> } else { Goto 0x41daa6<32> }
2544
+
2545
+ last_stmt_0 = ailblock_0.statements[-1]
2546
+ last_stmt_1 = ailblock_1.statements[-1]
2547
+ if not (isinstance(last_stmt_0, ailment.Stmt.ConditionalJump) and last_stmt_0.likes(last_stmt_1)):
2548
+ return False
2549
+
2550
+ last_cmp_stmt_0 = next(
2551
+ iter(
2552
+ stmt
2553
+ for stmt in reversed(ailblock_0.statements)
2554
+ if isinstance(stmt, ailment.Stmt.Assignment)
2555
+ and isinstance(stmt.src, ailment.Expr.BinaryOp)
2556
+ and stmt.src.op in ailment.Expr.BinaryOp.COMPARISON_NEGATION
2557
+ and stmt.ins_addr == last_stmt_0.ins_addr
2558
+ ),
2559
+ None,
2560
+ )
2561
+ last_cmp_stmt_1 = next(
2562
+ iter(
2563
+ stmt
2564
+ for stmt in reversed(ailblock_1.statements)
2565
+ if isinstance(stmt, ailment.Stmt.Assignment)
2566
+ and isinstance(stmt.src, ailment.Expr.BinaryOp)
2567
+ and stmt.src.op in ailment.Expr.BinaryOp.COMPARISON_NEGATION
2568
+ and stmt.ins_addr == last_stmt_1.ins_addr
2569
+ ),
2570
+ None,
2571
+ )
2572
+ return (
2573
+ last_cmp_stmt_0 is not None
2574
+ and last_cmp_stmt_1 is not None
2575
+ and last_cmp_stmt_0.src.op == last_cmp_stmt_1.src.op
2576
+ and last_cmp_stmt_0.src.operands[1].likes(last_cmp_stmt_1.src.operands[1])
2577
+ )
2578
+
2579
+ def _fix_abnormal_switch_case_heads_case1(
2580
+ self,
2581
+ ail_graph: networkx.DiGraph,
2582
+ indirect_jump_node: ailment.Block,
2583
+ intended_head: ailment.Block,
2584
+ other_heads: list[ailment.Block],
2585
+ overlap: int,
2586
+ ) -> None:
2587
+ self._fix_abnormal_switch_case_heads_case2(
2588
+ ail_graph,
2589
+ indirect_jump_node,
2590
+ intended_head,
2591
+ other_heads,
2592
+ intended_head_split_insns=overlap,
2593
+ other_head_split_insns=overlap,
2594
+ )
2595
+
2596
+ def _fix_abnormal_switch_case_heads_case2(
2597
+ self,
2598
+ ail_graph: networkx.DiGraph,
2599
+ indirect_jump_node: ailment.Block,
2600
+ intended_head: ailment.Block,
2601
+ other_heads: list[ailment.Block],
2602
+ intended_head_split_insns: int = 1,
2603
+ other_head_split_insns: int = 0,
2604
+ ) -> None:
2605
+
2606
+ # split the intended head into two
2607
+ intended_head_block = self.project.factory.block(intended_head.addr, size=intended_head.original_size)
2608
+ split_ins_addr = intended_head_block.instruction_addrs[-intended_head_split_insns]
2609
+ # note that the two blocks can be fully overlapping, so block_0 will be empty...
2610
+ intended_head_block_0 = (
2611
+ self.project.factory.block(intended_head.addr, size=split_ins_addr - intended_head.addr)
2612
+ if split_ins_addr != intended_head.addr
2613
+ else None
2614
+ )
2615
+ intended_head_block_1 = self.project.factory.block(
2616
+ split_ins_addr, size=intended_head.addr + intended_head.original_size - split_ins_addr
2617
+ )
2618
+ intended_head_0 = self._convert_vex(intended_head_block_0) if intended_head_block_0 is not None else None
2619
+ intended_head_1 = self._convert_vex(intended_head_block_1)
2620
+
2621
+ # corner-case: the last statement of intended_head might have been patched by _remove_redundant_jump_blocks. we
2622
+ # detect such case and fix it in intended_head_1
2623
+ self._remove_redundant_jump_blocks_repatch_relifted_block(intended_head, intended_head_1)
2624
+
2625
+ # adjust the graph accordingly
2626
+ preds = list(ail_graph.predecessors(intended_head))
2627
+ succs = list(ail_graph.successors(intended_head))
2628
+ ail_graph.remove_node(intended_head)
2629
+
2630
+ if intended_head_0 is None:
2631
+ # perfect overlap; the first block is empty
2632
+ for pred in preds:
2633
+ if pred is intended_head:
2634
+ ail_graph.add_edge(intended_head_1, intended_head_1)
2635
+ else:
2636
+ ail_graph.add_edge(pred, intended_head_1)
2637
+ for succ in succs:
2638
+ if succ is intended_head:
2639
+ ail_graph.add_edge(intended_head_1, intended_head_1)
2640
+ else:
2641
+ ail_graph.add_edge(intended_head_1, succ)
2642
+ else:
2643
+ ail_graph.add_edge(intended_head_0, intended_head_1)
2644
+ for pred in preds:
2645
+ if pred is intended_head:
2646
+ ail_graph.add_edge(intended_head_1, intended_head_0)
2647
+ else:
2648
+ ail_graph.add_edge(pred, intended_head_0)
2649
+ for succ in succs:
2650
+ if succ is intended_head:
2651
+ ail_graph.add_edge(intended_head_1, intended_head_0)
2652
+ else:
2653
+ ail_graph.add_edge(intended_head_1, succ)
2654
+
2655
+ # split other heads
2656
+ for o in other_heads:
2657
+ if other_head_split_insns > 0:
2658
+ o_block = self.project.factory.block(o.addr, size=o.original_size)
2659
+ o_split_addr = o_block.instruction_addrs[-other_head_split_insns]
2660
+ new_o_block = (
2661
+ self.project.factory.block(o.addr, size=o_split_addr - o.addr) if o_split_addr != o.addr else None
2662
+ )
2663
+ new_head = self._convert_vex(new_o_block) if new_o_block is not None else None
2664
+ else:
2665
+ new_head = o
2666
+
2667
+ if new_head is None:
2668
+ # the head is removed - let's replace it with a jump to the target
2669
+ jump_stmt = ailment.Stmt.Jump(
2670
+ None,
2671
+ ailment.Expr.Const(None, None, intended_head_1.addr, self.project.arch.bits),
2672
+ target_idx=intended_head_1.idx,
2673
+ ins_addr=o.addr,
2674
+ )
2675
+ new_head = ailment.Block(o.addr, 1, statements=[jump_stmt], idx=o.idx)
2676
+ else:
2677
+ if (
2678
+ new_head.statements
2679
+ and isinstance(new_head.statements[-1], ailment.Stmt.Jump)
2680
+ and isinstance(new_head.statements[-1].target, ailment.Expr.Const)
2681
+ ):
2682
+ # update the jump target
2683
+ new_head.statements[-1] = ailment.Stmt.Jump(
2684
+ new_head.statements[-1].idx,
2685
+ ailment.Expr.Const(None, None, intended_head_1.addr, self.project.arch.bits),
2686
+ target_idx=intended_head_1.idx,
2687
+ **new_head.statements[-1].tags,
2688
+ )
2689
+
2690
+ # adjust the graph accordingly
2691
+ preds = list(ail_graph.predecessors(o))
2692
+ succs = list(ail_graph.successors(o))
2693
+ ail_graph.remove_node(o)
2694
+ for pred in preds:
2695
+ if pred is o:
2696
+ ail_graph.add_edge(new_head, new_head)
2697
+ else:
2698
+ ail_graph.add_edge(pred, new_head)
2699
+ for succ in succs:
2700
+ if succ is o:
2701
+ ail_graph.add_edge(new_head, new_head)
2702
+ elif succ is indirect_jump_node:
2703
+ ail_graph.add_edge(new_head, intended_head_1)
2704
+ else:
2705
+ # it should be going to the default node. ignore it
2706
+ pass
2707
+
2708
+ def _fix_abnormal_switch_case_heads_case3(
2709
+ self, indirect_jump_node: ailment.Block, other_heads: list[ailment.Block]
2710
+ ) -> None:
2711
+ # remove all edges from other_heads to the indirect jump node
2712
+ for other_head in other_heads:
2713
+ # delay the edge removal so that we don't mess up the SSA analysis
2714
+ self.edges_to_remove.append(
2715
+ ((other_head.addr, other_head.idx), (indirect_jump_node.addr, indirect_jump_node.idx))
2716
+ )
2717
+
2718
+ @staticmethod
2719
+ def _remove_redundant_jump_blocks(ail_graph):
2720
+ def first_conditional_jump(block: ailment.Block) -> ailment.Stmt.ConditionalJump | None:
2721
+ for stmt in block.statements:
2722
+ if isinstance(stmt, ailment.Stmt.ConditionalJump):
2723
+ return stmt
2724
+ return None
2725
+
2726
+ def patch_conditional_jump_target(cond_jump_stmt: ailment.Stmt.ConditionalJump, old_addr: int, new_addr: int):
2727
+ if (
2728
+ isinstance(cond_jump_stmt.true_target, ailment.Expr.Const)
2729
+ and cond_jump_stmt.true_target.value == old_addr
2730
+ ):
2731
+ cond_jump_stmt.true_target.value = new_addr
2732
+ if (
2733
+ isinstance(cond_jump_stmt.false_target, ailment.Expr.Const)
2734
+ and cond_jump_stmt.false_target.value == old_addr
2735
+ ):
2736
+ cond_jump_stmt.false_target.value = new_addr
2737
+
2738
+ # note that blocks don't have labels inserted at this point
2739
+ for node in list(ail_graph.nodes):
2740
+ if (
2741
+ len(node.statements) == 1
2742
+ and isinstance(node.statements[0], ailment.Stmt.Jump)
2743
+ and isinstance(node.statements[0].target, ailment.Expr.Const)
2744
+ ):
2745
+ jump_target = node.statements[0].target.value
2746
+ succs = list(ail_graph.successors(node))
2747
+ if len(succs) == 1 and succs[0].addr == jump_target:
2748
+ preds = list(ail_graph.predecessors(node))
2749
+ if len(preds) == 1 and ail_graph.out_degree[preds[0]] == 2:
2750
+ # remove this node
2751
+ for pred in preds:
2752
+ if pred.statements:
2753
+ last_stmt = pred.statements[-1]
2754
+ if (
2755
+ isinstance(last_stmt, ailment.Stmt.Jump)
2756
+ and isinstance(last_stmt.target, ailment.Expr.Const)
2757
+ and last_stmt.target.value == node.addr
2758
+ ):
2759
+ last_stmt.target.value = succs[0].addr
2760
+ elif isinstance(last_stmt, ailment.Stmt.ConditionalJump):
2761
+ patch_conditional_jump_target(last_stmt, node.addr, succs[0].addr)
2762
+ # if both branches jump to the same location, we replace it with a jump
2763
+ if (
2764
+ isinstance(last_stmt.true_target, ailment.Expr.Const)
2765
+ and isinstance(last_stmt.false_target, ailment.Expr.Const)
2766
+ and last_stmt.true_target.value == last_stmt.false_target.value
2767
+ ):
2768
+ last_stmt = ailment.Stmt.Jump(
2769
+ last_stmt.idx,
2770
+ last_stmt.true_target,
2771
+ target_idx=last_stmt.true_target.idx,
2772
+ ins_addr=last_stmt.ins_addr,
2773
+ )
2774
+ pred.statements[-1] = last_stmt
2775
+ first_cond_jump = first_conditional_jump(pred)
2776
+ if first_cond_jump is not None and first_cond_jump is not last_stmt:
2777
+ patch_conditional_jump_target(first_cond_jump, node.addr, succs[0].addr)
2778
+ ail_graph.add_edge(pred, succs[0])
2779
+ ail_graph.remove_node(node)
2780
+
2781
+ @staticmethod
2782
+ def _remove_redundant_jump_blocks_repatch_relifted_block(
2783
+ patched_block: ailment.Block, new_block: ailment.Block
2784
+ ) -> None:
2785
+ """
2786
+ The last statement of patched_block might have been patched by _remove_redundant_jump_blocks. In this case, we
2787
+ fix the last instruction for new_block, which is a newly lifted (from VEX) block that ends at the same address
2788
+ as patched_block.
2789
+
2790
+ :param patched_block: Previously patched block.
2791
+ :param new_block: Newly lifted block.
2792
+ """
2793
+
2794
+ if (
2795
+ isinstance(patched_block.statements[-1], ailment.Stmt.Jump)
2796
+ and isinstance(patched_block.statements[-1].target, ailment.Expr.Const)
2797
+ and isinstance(new_block.statements[-1], ailment.Stmt.Jump)
2798
+ and isinstance(new_block.statements[-1].target, ailment.Expr.Const)
2799
+ and not patched_block.statements[-1].likes(new_block.statements[-1])
2800
+ ):
2801
+ new_block.statements[-1].target = patched_block.statements[-1].target
2802
+ if (
2803
+ isinstance(patched_block.statements[-1], ailment.Stmt.ConditionalJump)
2804
+ and isinstance(patched_block.statements[-1].true_target, ailment.Expr.Const)
2805
+ and isinstance(patched_block.statements[-1].false_target, ailment.Expr.Const)
2806
+ and isinstance(new_block.statements[-1], ailment.Stmt.ConditionalJump)
2807
+ and isinstance(new_block.statements[-1].true_target, ailment.Expr.Const)
2808
+ and isinstance(new_block.statements[-1].false_target, ailment.Expr.Const)
2809
+ and not patched_block.statements[-1].likes(new_block.statements[-1])
2810
+ ):
2811
+ new_block.statements[-1].true_target = patched_block.statements[-1].true_target
2812
+ new_block.statements[-1].false_target = patched_block.statements[-1].false_target
2813
+
2814
+ @staticmethod
2815
+ def _insert_block_labels(ail_graph):
2816
+ for node in ail_graph.nodes:
2817
+ node: ailment.Block
2818
+ lbl = ailment.Stmt.Label(None, f"LABEL_{node.addr:x}", node.addr, block_idx=node.idx)
2819
+ node.statements.insert(0, lbl)
2820
+
2821
+ @staticmethod
2822
+ def _collect_externs(ail_graph, variable_kb):
2823
+ global_vars = variable_kb.variables.global_manager.get_variables()
2824
+ walker = ailment.AILBlockWalker()
2825
+ variables = set()
2826
+
2827
+ def handle_expr(
2828
+ expr_idx: int,
2829
+ expr: ailment.expression.Expression,
2830
+ stmt_idx: int,
2831
+ stmt: ailment.statement.Statement | None,
2832
+ block: ailment.Block | None,
2833
+ ):
2834
+ if expr is None:
2835
+ return None
2836
+ for v in [
2837
+ getattr(expr, "variable", None),
2838
+ expr.tags.get("reference_variable", None) if hasattr(expr, "tags") else None,
2839
+ ]:
2840
+ if v and v in global_vars:
2841
+ variables.add(v)
2842
+ return ailment.AILBlockWalker._handle_expr(walker, expr_idx, expr, stmt_idx, stmt, block)
2843
+
2844
+ def handle_Store(stmt_idx: int, stmt: ailment.statement.Store, block: ailment.Block | None):
2845
+ if stmt.variable and stmt.variable in global_vars:
2846
+ variables.add(stmt.variable)
2847
+ return ailment.AILBlockWalker._handle_Store(walker, stmt_idx, stmt, block)
2848
+
2849
+ walker.stmt_handlers[ailment.statement.Store] = handle_Store
2850
+ walker._handle_expr = handle_expr
2851
+ AILGraphWalker(ail_graph, walker.walk).walk()
2852
+ return variables
2853
+
2854
+ @staticmethod
2855
+ def _collect_data_refs(ail_graph) -> dict[int, list[DataRefDesc]]:
2856
+ # pylint:disable=unused-argument
2857
+ walker = ailment.AILBlockWalker()
2858
+ data_refs: dict[int, list[DataRefDesc]] = defaultdict(list)
2859
+
2860
+ def handle_Const(
2861
+ expr_idx: int,
2862
+ expr: ailment.expression.Const,
2863
+ stmt_idx: int,
2864
+ stmt: ailment.statement.Statement,
2865
+ block: ailment.Block,
2866
+ ):
2867
+ if isinstance(expr.value, int) and hasattr(expr, "ins_addr"):
2868
+ data_refs[block.addr].append(
2869
+ DataRefDesc(expr.value, 1, block.addr, stmt_idx, expr.ins_addr, MemoryDataSort.Unknown)
2870
+ )
2871
+ if hasattr(expr, "deref_src_addr"):
2872
+ data_refs[block.addr].append(
2873
+ DataRefDesc(
2874
+ expr.deref_src_addr, expr.size, block.addr, stmt_idx, expr.ins_addr, MemoryDataSort.Unknown
2875
+ )
2876
+ )
2877
+
2878
+ def handle_Load(
2879
+ expr_idx: int,
2880
+ expr: ailment.expression.Load,
2881
+ stmt_idx: int,
2882
+ stmt: ailment.statement.Statement,
2883
+ block: ailment.Block,
2884
+ ):
2885
+ if isinstance(expr.addr, ailment.expression.Const):
2886
+ addr = expr.addr
2887
+ if isinstance(addr.value, int) and hasattr(addr, "ins_addr"):
2888
+ data_refs[block.addr].append(
2889
+ DataRefDesc(
2890
+ addr.value,
2891
+ expr.size,
2892
+ block.addr,
2893
+ stmt_idx,
2894
+ addr.ins_addr,
2895
+ MemoryDataSort.Integer if expr.size == 4 else MemoryDataSort.Unknown,
2896
+ )
2897
+ )
2898
+ if hasattr(addr, "deref_src_addr"):
2899
+ data_refs[block.addr].append(
2900
+ DataRefDesc(
2901
+ addr.deref_src_addr,
2902
+ expr.size,
2903
+ block.addr,
2904
+ stmt_idx,
2905
+ addr.ins_addr,
2906
+ MemoryDataSort.Integer if expr.size == 4 else MemoryDataSort.Unknown,
2907
+ )
2908
+ )
2909
+ return None
2910
+
2911
+ return ailment.AILBlockWalker._handle_Load(walker, expr_idx, expr, stmt_idx, stmt, block)
2912
+
2913
+ def handle_Store(stmt_idx: int, stmt: ailment.statement.Store, block: ailment.Block):
2914
+ if isinstance(stmt.addr, ailment.expression.Const):
2915
+ addr = stmt.addr
2916
+ if isinstance(addr.value, int) and hasattr(addr, "ins_addr"):
2917
+ data_refs[block.addr].append(
2918
+ DataRefDesc(
2919
+ addr.value,
2920
+ stmt.size,
2921
+ block.addr,
2922
+ stmt_idx,
2923
+ addr.ins_addr,
2924
+ MemoryDataSort.Integer if stmt.size == 4 else MemoryDataSort.Unknown,
2925
+ )
2926
+ )
2927
+ if hasattr(addr, "deref_src_addr"):
2928
+ data_refs[block.addr].append(
2929
+ DataRefDesc(
2930
+ addr.deref_src_addr,
2931
+ stmt.size,
2932
+ block.addr,
2933
+ stmt_idx,
2934
+ addr.ins_addr,
2935
+ MemoryDataSort.Integer if stmt.size == 4 else MemoryDataSort.Unknown,
2936
+ )
2937
+ )
2938
+ return None
2939
+
2940
+ return ailment.AILBlockWalker._handle_Store(walker, stmt_idx, stmt, block)
2941
+
2942
+ walker.stmt_handlers[ailment.statement.Store] = handle_Store
2943
+ walker.expr_handlers[ailment.expression.Load] = handle_Load
2944
+ walker.expr_handlers[ailment.expression.Const] = handle_Const
2945
+ AILGraphWalker(ail_graph, walker.walk).walk()
2946
+ return data_refs
2947
+
2948
+ def _next_atom(self) -> int:
2949
+ return self._ail_manager.next_atom()
2950
+
2951
+ def parse_variable_addr(self, addr: ailment.Expr.Expression) -> tuple[Any, Any]:
2952
+ if isinstance(addr, ailment.Expr.Const):
2953
+ return addr, 0
2954
+ if isinstance(addr, ailment.Expr.BinaryOp) and addr.op == "Add":
2955
+ op0, op1 = addr.operands
2956
+ if (
2957
+ isinstance(op0, ailment.Expr.Const)
2958
+ and self.project.loader.find_object_containing(op0.value) is not None
2959
+ ):
2960
+ return op0, op1
2961
+ if (
2962
+ isinstance(op1, ailment.Expr.Const)
2963
+ and self.project.loader.find_object_containing(op1.value) is not None
2964
+ ):
2965
+ return op1, op0
2966
+ return op0, op1 # best-effort guess
2967
+ return None, None
2968
+
2969
+ def new_block_addr(self) -> int:
2970
+ """
2971
+ Return a block address that does not conflict with any existing blocks.
2972
+
2973
+ :return: The block address.
2974
+ """
2975
+ if self._new_block_addrs:
2976
+ new_addr = max(self._new_block_addrs) + 1
2977
+ else:
2978
+ new_addr = max(self.function.block_addrs_set) + 2048
2979
+ self._new_block_addrs.add(new_addr)
2980
+ return new_addr
2981
+
2982
+ @staticmethod
2983
+ @timethis
2984
+ def remove_empty_nodes(graph: networkx.DiGraph) -> networkx.DiGraph:
2985
+ def handle_node(node: ailment.Block):
2986
+ if not node.statements:
2987
+ preds = [pred for pred in graph.predecessors(node) if pred is not node]
2988
+ succs = [succ for succ in graph.successors(node) if succ is not node]
2989
+ if len(preds) == 1 and len(succs) == 1:
2990
+ pred = preds[0]
2991
+ succ = succs[0]
2992
+ value_updated = False
2993
+ # update the last statement of pred
2994
+ if pred.statements and isinstance(pred.statements[-1], ailment.Stmt.ConditionalJump):
2995
+ last_stmt = pred.statements[-1]
2996
+ if (
2997
+ isinstance(last_stmt.true_target, ailment.Expr.Const)
2998
+ and last_stmt.true_target.value == node.addr
2999
+ ):
3000
+ last_stmt.true_target.value = succ.addr
3001
+ value_updated = True
3002
+ if (
3003
+ isinstance(last_stmt.false_target, ailment.Expr.Const)
3004
+ and last_stmt.false_target.value == node.addr
3005
+ ):
3006
+ last_stmt.false_target.value = succ.addr
3007
+ value_updated = True
3008
+
3009
+ if value_updated:
3010
+ graph.add_edge(pred, succ)
3011
+ raise RemoveNodeNotice
3012
+ elif len(preds) >= 1 and len(succs) == 1:
3013
+ succ = succs[0]
3014
+ branch_updates = 0
3015
+ for pred in preds:
3016
+ # test how many last statements of pred can potentially be updated
3017
+ if pred.statements and isinstance(pred.statements[-1], ailment.Stmt.ConditionalJump):
3018
+ last_stmt = pred.statements[-1]
3019
+ if (
3020
+ isinstance(last_stmt.true_target, ailment.Expr.Const)
3021
+ and last_stmt.true_target.value == node.addr
3022
+ ):
3023
+ branch_updates += 1
3024
+ if (
3025
+ isinstance(last_stmt.false_target, ailment.Expr.Const)
3026
+ and last_stmt.false_target.value == node.addr
3027
+ ):
3028
+ branch_updates += 1
3029
+
3030
+ if branch_updates == len(preds):
3031
+ # actually do the update
3032
+ for pred in preds:
3033
+ graph.add_edge(pred, succ)
3034
+ if pred.statements and isinstance(pred.statements[-1], ailment.Stmt.ConditionalJump):
3035
+ last_stmt = pred.statements[-1]
3036
+ if (
3037
+ isinstance(last_stmt.true_target, ailment.Expr.Const)
3038
+ and last_stmt.true_target.value == node.addr
3039
+ ):
3040
+ last_stmt.true_target.value = succ.addr
3041
+ if (
3042
+ isinstance(last_stmt.false_target, ailment.Expr.Const)
3043
+ and last_stmt.false_target.value == node.addr
3044
+ ):
3045
+ last_stmt.false_target.value = succ.addr
3046
+ raise RemoveNodeNotice
3047
+ elif not preds or not succs:
3048
+ raise RemoveNodeNotice
3049
+
3050
+ AILGraphWalker(graph, handle_node, replace_nodes=True).walk()
3051
+ return graph
3052
+
3053
+ def _find_regs_compared_against_sp(self, func_graph):
3054
+ # TODO: Implement this function for architectures beyond amd64
3055
+ extra_regs = set()
3056
+ if self.project.arch.name == "AMD64":
3057
+ for node in func_graph.nodes:
3058
+ block = self.project.factory.block(node.addr, size=node.size).capstone
3059
+ for insn in block.insns:
3060
+ if insn.mnemonic == "cmp":
3061
+ capstone_reg_offset = None
3062
+ if (
3063
+ insn.operands[0].type == capstone.x86.X86_OP_REG
3064
+ and insn.operands[0].reg == capstone.x86.X86_REG_RSP
3065
+ and insn.operands[1].type == capstone.x86.X86_OP_REG
3066
+ ):
3067
+ capstone_reg_offset = insn.operands[1].reg
3068
+ elif (
3069
+ insn.operands[1].type == capstone.x86.X86_OP_REG
3070
+ and insn.operands[1].reg == capstone.x86.X86_REG_RSP
3071
+ and insn.operands[0].type == capstone.x86.X86_OP_REG
3072
+ ):
3073
+ capstone_reg_offset = insn.operands[0].reg
3074
+
3075
+ if capstone_reg_offset is not None:
3076
+ reg_name = insn.reg_name(capstone_reg_offset)
3077
+ extra_regs.add(self.project.arch.registers[reg_name][0])
3078
+
3079
+ return extra_regs
3080
+
3081
+ def _rewrite_rust_probestack_call(self, ail_graph):
3082
+ for node in ail_graph:
3083
+ if not node.statements or ail_graph.out_degree[node] != 1:
3084
+ continue
3085
+ last_stmt = node.statements[-1]
3086
+ if isinstance(last_stmt, ailment.Stmt.Call) and isinstance(last_stmt.target, ailment.Expr.Const):
3087
+ func = (
3088
+ self.project.kb.functions.get_by_addr(last_stmt.target.value)
3089
+ if self.project.kb.functions.contains_addr(last_stmt.target.value)
3090
+ else None
3091
+ )
3092
+ if func is not None and func.info.get("is_rust_probestack", False) is True:
3093
+ # get rid of this call
3094
+ node.statements = node.statements[:-1]
3095
+ if self.project.arch.call_pushes_ret and node.statements:
3096
+ last_stmt = node.statements[-1]
3097
+ succ = next(iter(ail_graph.successors(node)))
3098
+ if (
3099
+ isinstance(last_stmt, ailment.Stmt.Store)
3100
+ and isinstance(last_stmt.addr, ailment.Expr.StackBaseOffset)
3101
+ and isinstance(last_stmt.addr.offset, int)
3102
+ and last_stmt.addr.offset < 0
3103
+ and isinstance(last_stmt.data, ailment.Expr.Const)
3104
+ and last_stmt.data.value == succ.addr
3105
+ ) or (
3106
+ isinstance(last_stmt, ailment.Stmt.Assignment)
3107
+ and last_stmt.dst.was_stack
3108
+ and last_stmt.dst.stack_offset < 0
3109
+ and isinstance(last_stmt.src, ailment.Expr.Const)
3110
+ and last_stmt.src.value == succ.addr
3111
+ ):
3112
+ # remove the statement that pushes the return address
3113
+ node.statements = node.statements[:-1]
3114
+ break
3115
+ return ail_graph
3116
+
3117
+ def _rewrite_windows_chkstk_call(self, ail_graph) -> networkx.DiGraph:
3118
+ if not (self.project.simos is not None and self.project.simos.name == "Win32"):
3119
+ return ail_graph
3120
+
3121
+ for node in ail_graph:
3122
+ if not node.statements or ail_graph.out_degree[node] != 1:
3123
+ continue
3124
+ last_stmt = node.statements[-1]
3125
+ if isinstance(last_stmt, ailment.Stmt.Call) and isinstance(last_stmt.target, ailment.Expr.Const):
3126
+ func = (
3127
+ self.project.kb.functions.get_by_addr(last_stmt.target.value)
3128
+ if self.project.kb.functions.contains_addr(last_stmt.target.value)
3129
+ else None
3130
+ )
3131
+ if func is not None and (func.name == "__chkstk" or func.info.get("is_alloca_probe", False) is True):
3132
+ # get rid of this call
3133
+ node.statements = node.statements[:-1]
3134
+ if self.project.arch.call_pushes_ret and node.statements:
3135
+ last_stmt = node.statements[-1]
3136
+ succ = next(iter(ail_graph.successors(node)))
3137
+ if (
3138
+ isinstance(last_stmt, ailment.Stmt.Store)
3139
+ and isinstance(last_stmt.addr, ailment.Expr.StackBaseOffset)
3140
+ and isinstance(last_stmt.addr.offset, int)
3141
+ and last_stmt.addr.offset < 0
3142
+ and isinstance(last_stmt.data, ailment.Expr.Const)
3143
+ and last_stmt.data.value == succ.addr
3144
+ ) or (
3145
+ isinstance(last_stmt, ailment.Stmt.Assignment)
3146
+ and last_stmt.dst.was_stack
3147
+ and last_stmt.dst.stack_offset < 0
3148
+ and isinstance(last_stmt.src, ailment.Expr.Const)
3149
+ and last_stmt.src.value == succ.addr
3150
+ ):
3151
+ # remove the statement that pushes the return address
3152
+ node.statements = node.statements[:-1]
3153
+ break
3154
+ return ail_graph
3155
+
3156
+ def _rewrite_alloca(self, ail_graph):
3157
+ # pylint:disable=too-many-boolean-expressions
3158
+ alloca_node = None
3159
+ sp_equal_to = None
3160
+
3161
+ for node in ail_graph:
3162
+ if ail_graph.in_degree[node] == 2 and ail_graph.out_degree[node] == 2:
3163
+ succs = ail_graph.successors(node)
3164
+ if node in succs and len(node.statements) >= 6:
3165
+ # self loop!
3166
+ stmt0 = node.statements[1] # skip the LABEL statement
3167
+ stmt1 = node.statements[2]
3168
+ last_stmt = node.statements[-1]
3169
+ if (
3170
+ (
3171
+ isinstance(stmt0, ailment.Stmt.Assignment)
3172
+ and isinstance(stmt0.dst, ailment.Expr.Register)
3173
+ and isinstance(stmt0.src, ailment.Expr.StackBaseOffset)
3174
+ and stmt0.src.offset == -0x1000
3175
+ )
3176
+ and (
3177
+ isinstance(stmt1, ailment.Stmt.Store)
3178
+ and isinstance(stmt1.addr, ailment.Expr.StackBaseOffset)
3179
+ and stmt1.addr.offset == -0x1000
3180
+ and isinstance(stmt1.data, ailment.Expr.Load)
3181
+ and isinstance(stmt1.data.addr, ailment.Expr.StackBaseOffset)
3182
+ and stmt1.data.addr.offset == -0x1000
3183
+ )
3184
+ and (
3185
+ isinstance(last_stmt, ailment.Stmt.ConditionalJump)
3186
+ and isinstance(last_stmt.condition, ailment.Expr.BinaryOp)
3187
+ and last_stmt.condition.op == "CmpEQ"
3188
+ and isinstance(last_stmt.condition.operands[0], ailment.Expr.StackBaseOffset)
3189
+ and last_stmt.condition.operands[0].offset == -0x1000
3190
+ and isinstance(last_stmt.condition.operands[1], ailment.Expr.Register)
3191
+ and isinstance(last_stmt.false_target, ailment.Expr.Const)
3192
+ and last_stmt.false_target.value == node.addr
3193
+ )
3194
+ ):
3195
+ # found it!
3196
+ alloca_node = node
3197
+ sp_equal_to = ailment.Expr.BinaryOp(
3198
+ None,
3199
+ "Sub",
3200
+ [
3201
+ ailment.Expr.Register(None, None, self.project.arch.sp_offset, self.project.arch.bits),
3202
+ last_stmt.condition.operands[1],
3203
+ ],
3204
+ False,
3205
+ )
3206
+ break
3207
+
3208
+ if alloca_node is not None and sp_equal_to is not None:
3209
+ stmt0 = alloca_node.statements[1]
3210
+ statements = [ailment.Stmt.Call(stmt0.idx, "alloca", args=[sp_equal_to], **stmt0.tags)]
3211
+ new_node = ailment.Block(alloca_node.addr, alloca_node.original_size, statements=statements)
3212
+ # replace the node
3213
+ preds = [pred for pred in ail_graph.predecessors(alloca_node) if pred is not alloca_node]
3214
+ succs = [succ for succ in ail_graph.successors(alloca_node) if succ is not alloca_node]
3215
+ ail_graph.remove_node(alloca_node)
3216
+ for pred in preds:
3217
+ ail_graph.add_edge(pred, new_node)
3218
+ for succ in succs:
3219
+ ail_graph.add_edge(new_node, succ)
3220
+
3221
+
3222
+ register_analysis(Clinic, "Clinic")