angr 9.2.166__cp310-abi3-manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of angr might be problematic. Click here for more details.

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