angr 9.2.192__cp311-cp311-macosx_10_12_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.
Files changed (1442) hide show
  1. angr/__init__.py +366 -0
  2. angr/__main__.py +182 -0
  3. angr/ail_callable.py +79 -0
  4. angr/ailment/__init__.py +83 -0
  5. angr/ailment/block.py +88 -0
  6. angr/ailment/block_walker.py +856 -0
  7. angr/ailment/constant.py +3 -0
  8. angr/ailment/converter_common.py +11 -0
  9. angr/ailment/converter_pcode.py +648 -0
  10. angr/ailment/converter_vex.py +829 -0
  11. angr/ailment/expression.py +1655 -0
  12. angr/ailment/manager.py +34 -0
  13. angr/ailment/statement.py +973 -0
  14. angr/ailment/tagged_object.py +58 -0
  15. angr/ailment/utils.py +114 -0
  16. angr/analyses/__init__.py +117 -0
  17. angr/analyses/analysis.py +429 -0
  18. angr/analyses/backward_slice.py +686 -0
  19. angr/analyses/binary_optimizer.py +670 -0
  20. angr/analyses/bindiff.py +1512 -0
  21. angr/analyses/boyscout.py +76 -0
  22. angr/analyses/callee_cleanup_finder.py +74 -0
  23. angr/analyses/calling_convention/__init__.py +6 -0
  24. angr/analyses/calling_convention/calling_convention.py +1113 -0
  25. angr/analyses/calling_convention/fact_collector.py +647 -0
  26. angr/analyses/calling_convention/utils.py +60 -0
  27. angr/analyses/cdg.py +189 -0
  28. angr/analyses/cfg/__init__.py +23 -0
  29. angr/analyses/cfg/cfb.py +451 -0
  30. angr/analyses/cfg/cfg.py +74 -0
  31. angr/analyses/cfg/cfg_arch_options.py +95 -0
  32. angr/analyses/cfg/cfg_base.py +2954 -0
  33. angr/analyses/cfg/cfg_emulated.py +3451 -0
  34. angr/analyses/cfg/cfg_fast.py +5431 -0
  35. angr/analyses/cfg/cfg_fast_soot.py +662 -0
  36. angr/analyses/cfg/cfg_job_base.py +203 -0
  37. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +30 -0
  38. angr/analyses/cfg/indirect_jump_resolvers/aarch64_macho_got.py +77 -0
  39. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
  40. angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
  41. angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +159 -0
  42. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +339 -0
  43. angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
  44. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +82 -0
  45. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2490 -0
  46. angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
  47. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
  48. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
  49. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
  50. angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
  51. angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
  52. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
  53. angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
  54. angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
  55. angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
  56. angr/analyses/cfg_slice_to_sink/graph.py +87 -0
  57. angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
  58. angr/analyses/class_identifier.py +63 -0
  59. angr/analyses/code_tagging.py +123 -0
  60. angr/analyses/codecave.py +77 -0
  61. angr/analyses/complete_calling_conventions.py +475 -0
  62. angr/analyses/congruency_check.py +377 -0
  63. angr/analyses/data_dep/__init__.py +16 -0
  64. angr/analyses/data_dep/data_dependency_analysis.py +595 -0
  65. angr/analyses/data_dep/dep_nodes.py +171 -0
  66. angr/analyses/data_dep/sim_act_location.py +49 -0
  67. angr/analyses/datagraph_meta.py +105 -0
  68. angr/analyses/ddg.py +1670 -0
  69. angr/analyses/decompiler/__init__.py +41 -0
  70. angr/analyses/decompiler/ail_simplifier.py +2246 -0
  71. angr/analyses/decompiler/ailgraph_walker.py +49 -0
  72. angr/analyses/decompiler/block_io_finder.py +302 -0
  73. angr/analyses/decompiler/block_similarity.py +199 -0
  74. angr/analyses/decompiler/block_simplifier.py +397 -0
  75. angr/analyses/decompiler/callsite_maker.py +579 -0
  76. angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
  77. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +618 -0
  78. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +24 -0
  79. angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +354 -0
  80. angr/analyses/decompiler/clinic.py +3662 -0
  81. angr/analyses/decompiler/condition_processor.py +1323 -0
  82. angr/analyses/decompiler/counters/__init__.py +16 -0
  83. angr/analyses/decompiler/counters/boolean_counter.py +27 -0
  84. angr/analyses/decompiler/counters/call_counter.py +77 -0
  85. angr/analyses/decompiler/counters/expression_counters.py +77 -0
  86. angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
  87. angr/analyses/decompiler/decompilation_cache.py +54 -0
  88. angr/analyses/decompiler/decompilation_options.py +317 -0
  89. angr/analyses/decompiler/decompiler.py +796 -0
  90. angr/analyses/decompiler/dephication/__init__.py +6 -0
  91. angr/analyses/decompiler/dephication/dephication_base.py +100 -0
  92. angr/analyses/decompiler/dephication/graph_dephication.py +70 -0
  93. angr/analyses/decompiler/dephication/graph_rewriting.py +112 -0
  94. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +357 -0
  95. angr/analyses/decompiler/dephication/rewriting_engine.py +528 -0
  96. angr/analyses/decompiler/dephication/seqnode_dephication.py +156 -0
  97. angr/analyses/decompiler/dirty_rewriters/__init__.py +7 -0
  98. angr/analyses/decompiler/dirty_rewriters/amd64_dirty.py +74 -0
  99. angr/analyses/decompiler/dirty_rewriters/rewriter_base.py +27 -0
  100. angr/analyses/decompiler/empty_node_remover.py +212 -0
  101. angr/analyses/decompiler/expression_narrower.py +290 -0
  102. angr/analyses/decompiler/goto_manager.py +112 -0
  103. angr/analyses/decompiler/graph_region.py +441 -0
  104. angr/analyses/decompiler/jump_target_collector.py +37 -0
  105. angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
  106. angr/analyses/decompiler/label_collector.py +32 -0
  107. angr/analyses/decompiler/node_replacer.py +42 -0
  108. angr/analyses/decompiler/notes/__init__.py +9 -0
  109. angr/analyses/decompiler/notes/decompilation_note.py +48 -0
  110. angr/analyses/decompiler/notes/deobfuscated_strings.py +56 -0
  111. angr/analyses/decompiler/optimization_passes/__init__.py +164 -0
  112. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
  113. angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
  114. angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
  115. angr/analyses/decompiler/optimization_passes/condition_constprop.py +211 -0
  116. angr/analyses/decompiler/optimization_passes/const_derefs.py +127 -0
  117. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
  118. angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
  119. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
  120. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
  121. angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
  122. angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
  123. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
  124. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1221 -0
  125. angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
  126. angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
  127. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
  128. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +236 -0
  129. angr/analyses/decompiler/optimization_passes/eager_std_string_eval.py +186 -0
  130. angr/analyses/decompiler/optimization_passes/engine_base.py +502 -0
  131. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +138 -0
  132. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
  133. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +618 -0
  134. angr/analyses/decompiler/optimization_passes/inlined_strlen_simplifier.py +274 -0
  135. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
  136. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +337 -0
  137. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +939 -0
  138. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
  139. angr/analyses/decompiler/optimization_passes/optimization_pass.py +710 -0
  140. angr/analyses/decompiler/optimization_passes/peephole_simplifier.py +75 -0
  141. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +263 -0
  142. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier_adv.py +198 -0
  143. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
  144. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
  145. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +632 -0
  146. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
  147. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +166 -0
  148. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
  149. angr/analyses/decompiler/optimization_passes/static_vvar_rewriter.py +336 -0
  150. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +166 -0
  151. angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
  152. angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
  153. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +477 -0
  154. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
  155. angr/analyses/decompiler/peephole_optimizations/__init__.py +136 -0
  156. angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
  157. angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
  158. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
  159. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
  160. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
  161. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
  162. angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
  163. angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
  164. angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
  165. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
  166. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
  167. angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
  168. angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
  169. angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
  170. angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +182 -0
  171. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
  172. angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
  173. angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
  174. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
  175. angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
  176. angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
  177. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +436 -0
  178. angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
  179. angr/analyses/decompiler/peephole_optimizations/inlined_memcpy.py +78 -0
  180. angr/analyses/decompiler/peephole_optimizations/inlined_memset.py +262 -0
  181. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +217 -0
  182. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +106 -0
  183. angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy.py +256 -0
  184. angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy_consolidation.py +296 -0
  185. angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
  186. angr/analyses/decompiler/peephole_optimizations/modulo_simplifier.py +89 -0
  187. angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
  188. angr/analyses/decompiler/peephole_optimizations/optimized_div_simplifier.py +356 -0
  189. angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
  190. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
  191. angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
  192. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
  193. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +125 -0
  194. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +273 -0
  195. angr/analyses/decompiler/peephole_optimizations/remove_redundant_derefs.py +21 -0
  196. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
  197. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
  198. angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
  199. angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
  200. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
  201. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +115 -0
  202. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
  203. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
  204. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
  205. angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
  206. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
  207. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +143 -0
  208. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
  209. angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
  210. angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +28 -0
  211. angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
  212. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
  213. angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
  214. angr/analyses/decompiler/presets/__init__.py +22 -0
  215. angr/analyses/decompiler/presets/basic.py +36 -0
  216. angr/analyses/decompiler/presets/fast.py +66 -0
  217. angr/analyses/decompiler/presets/full.py +76 -0
  218. angr/analyses/decompiler/presets/malware.py +70 -0
  219. angr/analyses/decompiler/presets/preset.py +37 -0
  220. angr/analyses/decompiler/redundant_label_remover.py +141 -0
  221. angr/analyses/decompiler/region_identifier.py +1319 -0
  222. angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
  223. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
  224. angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
  225. angr/analyses/decompiler/region_simplifiers/expr_folding.py +838 -0
  226. angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
  227. angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
  228. angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
  229. angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
  230. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
  231. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +270 -0
  232. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
  233. angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
  234. angr/analyses/decompiler/region_walker.py +24 -0
  235. angr/analyses/decompiler/return_maker.py +72 -0
  236. angr/analyses/decompiler/semantic_naming/__init__.py +37 -0
  237. angr/analyses/decompiler/semantic_naming/array_index_naming.py +196 -0
  238. angr/analyses/decompiler/semantic_naming/boolean_naming.py +264 -0
  239. angr/analyses/decompiler/semantic_naming/call_result_naming.py +220 -0
  240. angr/analyses/decompiler/semantic_naming/naming_base.py +166 -0
  241. angr/analyses/decompiler/semantic_naming/orchestrator.py +107 -0
  242. angr/analyses/decompiler/semantic_naming/pointer_naming.py +334 -0
  243. angr/analyses/decompiler/semantic_naming/region_loop_counter_naming.py +246 -0
  244. angr/analyses/decompiler/semantic_naming/size_naming.py +137 -0
  245. angr/analyses/decompiler/seq_to_blocks.py +20 -0
  246. angr/analyses/decompiler/sequence_walker.py +261 -0
  247. angr/analyses/decompiler/ssailification/__init__.py +4 -0
  248. angr/analyses/decompiler/ssailification/rewriting.py +451 -0
  249. angr/analyses/decompiler/ssailification/rewriting_engine.py +1091 -0
  250. angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
  251. angr/analyses/decompiler/ssailification/ssailification.py +283 -0
  252. angr/analyses/decompiler/ssailification/traversal.py +127 -0
  253. angr/analyses/decompiler/ssailification/traversal_engine.py +323 -0
  254. angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
  255. angr/analyses/decompiler/stack_item.py +36 -0
  256. angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
  257. angr/analyses/decompiler/structured_codegen/base.py +193 -0
  258. angr/analyses/decompiler/structured_codegen/c.py +4257 -0
  259. angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
  260. angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
  261. angr/analyses/decompiler/structuring/__init__.py +30 -0
  262. angr/analyses/decompiler/structuring/dream.py +1217 -0
  263. angr/analyses/decompiler/structuring/phoenix.py +3636 -0
  264. angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
  265. angr/analyses/decompiler/structuring/sailr.py +120 -0
  266. angr/analyses/decompiler/structuring/structurer_base.py +1140 -0
  267. angr/analyses/decompiler/structuring/structurer_nodes.py +442 -0
  268. angr/analyses/decompiler/utils.py +1224 -0
  269. angr/analyses/deobfuscator/__init__.py +23 -0
  270. angr/analyses/deobfuscator/api_obf_finder.py +333 -0
  271. angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +80 -0
  272. angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
  273. angr/analyses/deobfuscator/data_transformation_embedder.py +633 -0
  274. angr/analyses/deobfuscator/hash_lookup_api_deobfuscator.py +156 -0
  275. angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
  276. angr/analyses/deobfuscator/scope_ops_analyzer.py +68 -0
  277. angr/analyses/deobfuscator/string_obf_finder.py +983 -0
  278. angr/analyses/deobfuscator/string_obf_opt_passes.py +136 -0
  279. angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
  280. angr/analyses/disassembly.py +1351 -0
  281. angr/analyses/disassembly_utils.py +101 -0
  282. angr/analyses/dominance_frontier.py +57 -0
  283. angr/analyses/fcp/__init__.py +4 -0
  284. angr/analyses/fcp/fcp.py +427 -0
  285. angr/analyses/find_objects_static.py +205 -0
  286. angr/analyses/flirt/__init__.py +47 -0
  287. angr/analyses/flirt/consts.py +160 -0
  288. angr/analyses/flirt/flirt.py +249 -0
  289. angr/analyses/flirt/flirt_function.py +20 -0
  290. angr/analyses/flirt/flirt_matcher.py +352 -0
  291. angr/analyses/flirt/flirt_module.py +32 -0
  292. angr/analyses/flirt/flirt_node.py +23 -0
  293. angr/analyses/flirt/flirt_sig.py +359 -0
  294. angr/analyses/flirt/flirt_utils.py +31 -0
  295. angr/analyses/forward_analysis/__init__.py +12 -0
  296. angr/analyses/forward_analysis/forward_analysis.py +619 -0
  297. angr/analyses/forward_analysis/job_info.py +64 -0
  298. angr/analyses/forward_analysis/visitors/__init__.py +14 -0
  299. angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
  300. angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
  301. angr/analyses/forward_analysis/visitors/graph.py +242 -0
  302. angr/analyses/forward_analysis/visitors/loop.py +29 -0
  303. angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
  304. angr/analyses/identifier/__init__.py +5 -0
  305. angr/analyses/identifier/custom_callable.py +137 -0
  306. angr/analyses/identifier/errors.py +10 -0
  307. angr/analyses/identifier/func.py +60 -0
  308. angr/analyses/identifier/functions/__init__.py +37 -0
  309. angr/analyses/identifier/functions/atoi.py +73 -0
  310. angr/analyses/identifier/functions/based_atoi.py +125 -0
  311. angr/analyses/identifier/functions/fdprintf.py +123 -0
  312. angr/analyses/identifier/functions/free.py +64 -0
  313. angr/analyses/identifier/functions/int2str.py +287 -0
  314. angr/analyses/identifier/functions/malloc.py +111 -0
  315. angr/analyses/identifier/functions/memcmp.py +67 -0
  316. angr/analyses/identifier/functions/memcpy.py +89 -0
  317. angr/analyses/identifier/functions/memset.py +43 -0
  318. angr/analyses/identifier/functions/printf.py +123 -0
  319. angr/analyses/identifier/functions/recv_until.py +312 -0
  320. angr/analyses/identifier/functions/skip_calloc.py +73 -0
  321. angr/analyses/identifier/functions/skip_realloc.py +97 -0
  322. angr/analyses/identifier/functions/skip_recv_n.py +105 -0
  323. angr/analyses/identifier/functions/snprintf.py +112 -0
  324. angr/analyses/identifier/functions/sprintf.py +116 -0
  325. angr/analyses/identifier/functions/strcasecmp.py +33 -0
  326. angr/analyses/identifier/functions/strcmp.py +113 -0
  327. angr/analyses/identifier/functions/strcpy.py +43 -0
  328. angr/analyses/identifier/functions/strlen.py +27 -0
  329. angr/analyses/identifier/functions/strncmp.py +104 -0
  330. angr/analyses/identifier/functions/strncpy.py +65 -0
  331. angr/analyses/identifier/functions/strtol.py +89 -0
  332. angr/analyses/identifier/identify.py +825 -0
  333. angr/analyses/identifier/runner.py +360 -0
  334. angr/analyses/init_finder.py +289 -0
  335. angr/analyses/loop_analysis/__init__.py +4 -0
  336. angr/analyses/loop_analysis/loop_analysis.py +464 -0
  337. angr/analyses/loop_analysis.py +349 -0
  338. angr/analyses/loop_unroller/__init__.py +4 -0
  339. angr/analyses/loop_unroller/loop_unroller.py +222 -0
  340. angr/analyses/loopfinder.py +171 -0
  341. angr/analyses/outliner/__init__.py +7 -0
  342. angr/analyses/outliner/outliner.py +402 -0
  343. angr/analyses/patchfinder.py +137 -0
  344. angr/analyses/pathfinder.py +282 -0
  345. angr/analyses/propagator/__init__.py +5 -0
  346. angr/analyses/propagator/engine_base.py +62 -0
  347. angr/analyses/propagator/engine_vex.py +297 -0
  348. angr/analyses/propagator/propagator.py +361 -0
  349. angr/analyses/propagator/top_checker_mixin.py +218 -0
  350. angr/analyses/propagator/values.py +117 -0
  351. angr/analyses/propagator/vex_vars.py +68 -0
  352. angr/analyses/proximity_graph.py +444 -0
  353. angr/analyses/purity/__init__.py +15 -0
  354. angr/analyses/purity/analysis.py +78 -0
  355. angr/analyses/purity/engine.py +593 -0
  356. angr/analyses/reaching_definitions/__init__.py +67 -0
  357. angr/analyses/reaching_definitions/call_trace.py +73 -0
  358. angr/analyses/reaching_definitions/dep_graph.py +433 -0
  359. angr/analyses/reaching_definitions/engine_ail.py +1128 -0
  360. angr/analyses/reaching_definitions/engine_vex.py +1128 -0
  361. angr/analyses/reaching_definitions/external_codeloc.py +0 -0
  362. angr/analyses/reaching_definitions/function_handler.py +639 -0
  363. angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
  364. angr/analyses/reaching_definitions/function_handler_library/stdio.py +269 -0
  365. angr/analyses/reaching_definitions/function_handler_library/stdlib.py +195 -0
  366. angr/analyses/reaching_definitions/function_handler_library/string.py +158 -0
  367. angr/analyses/reaching_definitions/function_handler_library/unistd.py +51 -0
  368. angr/analyses/reaching_definitions/heap_allocator.py +70 -0
  369. angr/analyses/reaching_definitions/rd_initializer.py +237 -0
  370. angr/analyses/reaching_definitions/rd_state.py +579 -0
  371. angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
  372. angr/analyses/reaching_definitions/subject.py +65 -0
  373. angr/analyses/reassembler.py +2900 -0
  374. angr/analyses/s_liveness.py +254 -0
  375. angr/analyses/s_propagator.py +575 -0
  376. angr/analyses/s_reaching_definitions/__init__.py +12 -0
  377. angr/analyses/s_reaching_definitions/s_rda_model.py +145 -0
  378. angr/analyses/s_reaching_definitions/s_rda_view.py +344 -0
  379. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +230 -0
  380. angr/analyses/smc.py +160 -0
  381. angr/analyses/soot_class_hierarchy.py +273 -0
  382. angr/analyses/stack_pointer_tracker.py +954 -0
  383. angr/analyses/static_hooker.py +53 -0
  384. angr/analyses/typehoon/__init__.py +5 -0
  385. angr/analyses/typehoon/dfa.py +118 -0
  386. angr/analyses/typehoon/lifter.py +133 -0
  387. angr/analyses/typehoon/simple_solver.py +2009 -0
  388. angr/analyses/typehoon/translator.py +283 -0
  389. angr/analyses/typehoon/typeconsts.py +439 -0
  390. angr/analyses/typehoon/typehoon.py +338 -0
  391. angr/analyses/typehoon/typevars.py +633 -0
  392. angr/analyses/typehoon/variance.py +11 -0
  393. angr/analyses/unpacker/__init__.py +6 -0
  394. angr/analyses/unpacker/obfuscation_detector.py +103 -0
  395. angr/analyses/unpacker/packing_detector.py +138 -0
  396. angr/analyses/variable_recovery/__init__.py +9 -0
  397. angr/analyses/variable_recovery/annotations.py +58 -0
  398. angr/analyses/variable_recovery/engine_ail.py +978 -0
  399. angr/analyses/variable_recovery/engine_base.py +1256 -0
  400. angr/analyses/variable_recovery/engine_vex.py +594 -0
  401. angr/analyses/variable_recovery/irsb_scanner.py +143 -0
  402. angr/analyses/variable_recovery/variable_recovery.py +574 -0
  403. angr/analyses/variable_recovery/variable_recovery_base.py +489 -0
  404. angr/analyses/variable_recovery/variable_recovery_fast.py +669 -0
  405. angr/analyses/veritesting.py +626 -0
  406. angr/analyses/vfg.py +1898 -0
  407. angr/analyses/vsa_ddg.py +420 -0
  408. angr/analyses/vtable.py +92 -0
  409. angr/analyses/xrefs.py +286 -0
  410. angr/angrdb/__init__.py +14 -0
  411. angr/angrdb/db.py +215 -0
  412. angr/angrdb/models.py +184 -0
  413. angr/angrdb/serializers/__init__.py +10 -0
  414. angr/angrdb/serializers/cfg_model.py +41 -0
  415. angr/angrdb/serializers/comments.py +60 -0
  416. angr/angrdb/serializers/funcs.py +61 -0
  417. angr/angrdb/serializers/kb.py +111 -0
  418. angr/angrdb/serializers/labels.py +59 -0
  419. angr/angrdb/serializers/loader.py +165 -0
  420. angr/angrdb/serializers/structured_code.py +167 -0
  421. angr/angrdb/serializers/variables.py +58 -0
  422. angr/angrdb/serializers/xrefs.py +48 -0
  423. angr/annocfg.py +317 -0
  424. angr/blade.py +431 -0
  425. angr/block.py +509 -0
  426. angr/callable.py +176 -0
  427. angr/calling_conventions.py +2613 -0
  428. angr/code_location.py +249 -0
  429. angr/codenode.py +145 -0
  430. angr/concretization_strategies/__init__.py +32 -0
  431. angr/concretization_strategies/any.py +17 -0
  432. angr/concretization_strategies/any_named.py +35 -0
  433. angr/concretization_strategies/base.py +81 -0
  434. angr/concretization_strategies/controlled_data.py +58 -0
  435. angr/concretization_strategies/eval.py +19 -0
  436. angr/concretization_strategies/logging.py +35 -0
  437. angr/concretization_strategies/max.py +25 -0
  438. angr/concretization_strategies/nonzero.py +16 -0
  439. angr/concretization_strategies/nonzero_range.py +22 -0
  440. angr/concretization_strategies/norepeats.py +37 -0
  441. angr/concretization_strategies/norepeats_range.py +37 -0
  442. angr/concretization_strategies/range.py +19 -0
  443. angr/concretization_strategies/signed_add.py +31 -0
  444. angr/concretization_strategies/single.py +15 -0
  445. angr/concretization_strategies/solutions.py +20 -0
  446. angr/concretization_strategies/unlimited_range.py +17 -0
  447. angr/distributed/__init__.py +9 -0
  448. angr/distributed/server.py +197 -0
  449. angr/distributed/worker.py +185 -0
  450. angr/emulator.py +144 -0
  451. angr/engines/__init__.py +69 -0
  452. angr/engines/ail/__init__.py +16 -0
  453. angr/engines/ail/callstack.py +58 -0
  454. angr/engines/ail/engine_light.py +903 -0
  455. angr/engines/ail/engine_successors.py +24 -0
  456. angr/engines/ail/setup.py +57 -0
  457. angr/engines/concrete.py +66 -0
  458. angr/engines/engine.py +29 -0
  459. angr/engines/failure.py +27 -0
  460. angr/engines/hook.py +93 -0
  461. angr/engines/icicle.py +294 -0
  462. angr/engines/light/__init__.py +23 -0
  463. angr/engines/light/data.py +681 -0
  464. angr/engines/light/engine.py +1297 -0
  465. angr/engines/pcode/__init__.py +9 -0
  466. angr/engines/pcode/behavior.py +998 -0
  467. angr/engines/pcode/cc.py +148 -0
  468. angr/engines/pcode/emulate.py +440 -0
  469. angr/engines/pcode/engine.py +242 -0
  470. angr/engines/pcode/lifter.py +1428 -0
  471. angr/engines/procedure.py +70 -0
  472. angr/engines/soot/__init__.py +5 -0
  473. angr/engines/soot/engine.py +410 -0
  474. angr/engines/soot/exceptions.py +17 -0
  475. angr/engines/soot/expressions/__init__.py +87 -0
  476. angr/engines/soot/expressions/arrayref.py +22 -0
  477. angr/engines/soot/expressions/base.py +21 -0
  478. angr/engines/soot/expressions/binop.py +28 -0
  479. angr/engines/soot/expressions/cast.py +22 -0
  480. angr/engines/soot/expressions/condition.py +35 -0
  481. angr/engines/soot/expressions/constants.py +47 -0
  482. angr/engines/soot/expressions/instanceOf.py +15 -0
  483. angr/engines/soot/expressions/instancefieldref.py +8 -0
  484. angr/engines/soot/expressions/invoke.py +114 -0
  485. angr/engines/soot/expressions/length.py +8 -0
  486. angr/engines/soot/expressions/local.py +8 -0
  487. angr/engines/soot/expressions/new.py +16 -0
  488. angr/engines/soot/expressions/newArray.py +54 -0
  489. angr/engines/soot/expressions/newMultiArray.py +86 -0
  490. angr/engines/soot/expressions/paramref.py +8 -0
  491. angr/engines/soot/expressions/phi.py +30 -0
  492. angr/engines/soot/expressions/staticfieldref.py +8 -0
  493. angr/engines/soot/expressions/thisref.py +7 -0
  494. angr/engines/soot/expressions/unsupported.py +7 -0
  495. angr/engines/soot/field_dispatcher.py +46 -0
  496. angr/engines/soot/method_dispatcher.py +46 -0
  497. angr/engines/soot/statements/__init__.py +44 -0
  498. angr/engines/soot/statements/assign.py +30 -0
  499. angr/engines/soot/statements/base.py +79 -0
  500. angr/engines/soot/statements/goto.py +14 -0
  501. angr/engines/soot/statements/identity.py +15 -0
  502. angr/engines/soot/statements/if_.py +19 -0
  503. angr/engines/soot/statements/invoke.py +12 -0
  504. angr/engines/soot/statements/return_.py +20 -0
  505. angr/engines/soot/statements/switch.py +41 -0
  506. angr/engines/soot/statements/throw.py +15 -0
  507. angr/engines/soot/values/__init__.py +38 -0
  508. angr/engines/soot/values/arrayref.py +122 -0
  509. angr/engines/soot/values/base.py +7 -0
  510. angr/engines/soot/values/constants.py +18 -0
  511. angr/engines/soot/values/instancefieldref.py +44 -0
  512. angr/engines/soot/values/local.py +18 -0
  513. angr/engines/soot/values/paramref.py +18 -0
  514. angr/engines/soot/values/staticfieldref.py +38 -0
  515. angr/engines/soot/values/strref.py +38 -0
  516. angr/engines/soot/values/thisref.py +149 -0
  517. angr/engines/successors.py +608 -0
  518. angr/engines/syscall.py +51 -0
  519. angr/engines/unicorn.py +490 -0
  520. angr/engines/vex/__init__.py +20 -0
  521. angr/engines/vex/claripy/__init__.py +5 -0
  522. angr/engines/vex/claripy/ccall.py +2097 -0
  523. angr/engines/vex/claripy/datalayer.py +141 -0
  524. angr/engines/vex/claripy/irop.py +1276 -0
  525. angr/engines/vex/heavy/__init__.py +16 -0
  526. angr/engines/vex/heavy/actions.py +231 -0
  527. angr/engines/vex/heavy/concretizers.py +403 -0
  528. angr/engines/vex/heavy/dirty.py +466 -0
  529. angr/engines/vex/heavy/heavy.py +370 -0
  530. angr/engines/vex/heavy/inspect.py +52 -0
  531. angr/engines/vex/heavy/resilience.py +85 -0
  532. angr/engines/vex/heavy/super_fastpath.py +34 -0
  533. angr/engines/vex/lifter.py +420 -0
  534. angr/engines/vex/light/__init__.py +11 -0
  535. angr/engines/vex/light/light.py +551 -0
  536. angr/engines/vex/light/resilience.py +74 -0
  537. angr/engines/vex/light/slicing.py +52 -0
  538. angr/errors.py +611 -0
  539. angr/exploration_techniques/__init__.py +53 -0
  540. angr/exploration_techniques/base.py +126 -0
  541. angr/exploration_techniques/bucketizer.py +94 -0
  542. angr/exploration_techniques/common.py +56 -0
  543. angr/exploration_techniques/dfs.py +37 -0
  544. angr/exploration_techniques/director.py +520 -0
  545. angr/exploration_techniques/driller_core.py +100 -0
  546. angr/exploration_techniques/explorer.py +152 -0
  547. angr/exploration_techniques/lengthlimiter.py +22 -0
  548. angr/exploration_techniques/local_loop_seer.py +65 -0
  549. angr/exploration_techniques/loop_seer.py +236 -0
  550. angr/exploration_techniques/manual_mergepoint.py +82 -0
  551. angr/exploration_techniques/memory_watcher.py +43 -0
  552. angr/exploration_techniques/oppologist.py +92 -0
  553. angr/exploration_techniques/slicecutor.py +118 -0
  554. angr/exploration_techniques/spiller.py +280 -0
  555. angr/exploration_techniques/spiller_db.py +27 -0
  556. angr/exploration_techniques/stochastic.py +56 -0
  557. angr/exploration_techniques/stub_stasher.py +19 -0
  558. angr/exploration_techniques/suggestions.py +159 -0
  559. angr/exploration_techniques/tech_builder.py +49 -0
  560. angr/exploration_techniques/threading.py +69 -0
  561. angr/exploration_techniques/timeout.py +34 -0
  562. angr/exploration_techniques/tracer.py +1098 -0
  563. angr/exploration_techniques/unique.py +106 -0
  564. angr/exploration_techniques/veritesting.py +37 -0
  565. angr/factory.py +413 -0
  566. angr/flirt/__init__.py +124 -0
  567. angr/flirt/build_sig.py +305 -0
  568. angr/graph_utils.py +0 -0
  569. angr/keyed_region.py +525 -0
  570. angr/knowledge_base.py +146 -0
  571. angr/knowledge_plugins/__init__.py +43 -0
  572. angr/knowledge_plugins/callsite_prototypes.py +95 -0
  573. angr/knowledge_plugins/cfg/__init__.py +18 -0
  574. angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
  575. angr/knowledge_plugins/cfg/cfg_model.py +1043 -0
  576. angr/knowledge_plugins/cfg/cfg_node.py +536 -0
  577. angr/knowledge_plugins/cfg/indirect_jump.py +131 -0
  578. angr/knowledge_plugins/cfg/memory_data.py +156 -0
  579. angr/knowledge_plugins/comments.py +16 -0
  580. angr/knowledge_plugins/custom_strings.py +38 -0
  581. angr/knowledge_plugins/data.py +22 -0
  582. angr/knowledge_plugins/debug_variables.py +216 -0
  583. angr/knowledge_plugins/functions/__init__.py +9 -0
  584. angr/knowledge_plugins/functions/function.py +1830 -0
  585. angr/knowledge_plugins/functions/function_manager.py +621 -0
  586. angr/knowledge_plugins/functions/function_parser.py +360 -0
  587. angr/knowledge_plugins/functions/soot_function.py +128 -0
  588. angr/knowledge_plugins/indirect_jumps.py +35 -0
  589. angr/knowledge_plugins/key_definitions/__init__.py +17 -0
  590. angr/knowledge_plugins/key_definitions/atoms.py +374 -0
  591. angr/knowledge_plugins/key_definitions/constants.py +29 -0
  592. angr/knowledge_plugins/key_definitions/definition.py +216 -0
  593. angr/knowledge_plugins/key_definitions/environment.py +96 -0
  594. angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
  595. angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
  596. angr/knowledge_plugins/key_definitions/live_definitions.py +1020 -0
  597. angr/knowledge_plugins/key_definitions/liveness.py +165 -0
  598. angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
  599. angr/knowledge_plugins/key_definitions/tag.py +78 -0
  600. angr/knowledge_plugins/key_definitions/undefined.py +70 -0
  601. angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
  602. angr/knowledge_plugins/key_definitions/uses.py +178 -0
  603. angr/knowledge_plugins/labels.py +110 -0
  604. angr/knowledge_plugins/obfuscations.py +40 -0
  605. angr/knowledge_plugins/patches.py +126 -0
  606. angr/knowledge_plugins/plugin.py +24 -0
  607. angr/knowledge_plugins/propagations/__init__.py +10 -0
  608. angr/knowledge_plugins/propagations/prop_value.py +191 -0
  609. angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
  610. angr/knowledge_plugins/propagations/propagation_model.py +80 -0
  611. angr/knowledge_plugins/propagations/states.py +552 -0
  612. angr/knowledge_plugins/structured_code.py +63 -0
  613. angr/knowledge_plugins/types.py +95 -0
  614. angr/knowledge_plugins/variables/__init__.py +8 -0
  615. angr/knowledge_plugins/variables/variable_access.py +113 -0
  616. angr/knowledge_plugins/variables/variable_manager.py +1375 -0
  617. angr/knowledge_plugins/xrefs/__init__.py +12 -0
  618. angr/knowledge_plugins/xrefs/xref.py +150 -0
  619. angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
  620. angr/knowledge_plugins/xrefs/xref_types.py +16 -0
  621. angr/misc/__init__.py +19 -0
  622. angr/misc/ansi.py +47 -0
  623. angr/misc/autoimport.py +90 -0
  624. angr/misc/bug_report.py +126 -0
  625. angr/misc/hookset.py +106 -0
  626. angr/misc/loggers.py +130 -0
  627. angr/misc/picklable_lock.py +46 -0
  628. angr/misc/plugins.py +289 -0
  629. angr/misc/telemetry.py +54 -0
  630. angr/misc/testing.py +24 -0
  631. angr/misc/ux.py +31 -0
  632. angr/procedures/__init__.py +12 -0
  633. angr/procedures/advapi32/__init__.py +0 -0
  634. angr/procedures/cgc/__init__.py +3 -0
  635. angr/procedures/cgc/_terminate.py +11 -0
  636. angr/procedures/cgc/allocate.py +75 -0
  637. angr/procedures/cgc/deallocate.py +67 -0
  638. angr/procedures/cgc/fdwait.py +65 -0
  639. angr/procedures/cgc/random.py +67 -0
  640. angr/procedures/cgc/receive.py +93 -0
  641. angr/procedures/cgc/transmit.py +65 -0
  642. angr/procedures/definitions/__init__.py +1043 -0
  643. angr/procedures/definitions/cgc.py +23 -0
  644. angr/procedures/definitions/common/glibc.json +3516 -0
  645. angr/procedures/definitions/gnulib.py +41 -0
  646. angr/procedures/definitions/libstdcpp.py +25 -0
  647. angr/procedures/definitions/linux_kernel.py +8382 -0
  648. angr/procedures/definitions/linux_loader.py +7 -0
  649. angr/procedures/definitions/macho_libsystem.py +18 -0
  650. angr/procedures/definitions/msvcr.py +25 -0
  651. angr/procedures/definitions/parse_glibc.py +77 -0
  652. angr/procedures/definitions/parse_syscalls_from_local_system.py +54 -0
  653. angr/procedures/definitions/parse_win32json.py +2540 -0
  654. angr/procedures/definitions/types_stl.py +22 -0
  655. angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-4.json +24 -0
  656. angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-6.json +18 -0
  657. angr/procedures/definitions/wdk/clfs.json +189 -0
  658. angr/procedures/definitions/wdk/fltmgr.json +813 -0
  659. angr/procedures/definitions/wdk/fwpkclnt.json +24 -0
  660. angr/procedures/definitions/wdk/fwpuclnt.json +453 -0
  661. angr/procedures/definitions/wdk/gdi32.json +528 -0
  662. angr/procedures/definitions/wdk/hal.json +96 -0
  663. angr/procedures/definitions/wdk/ksecdd.json +72 -0
  664. angr/procedures/definitions/wdk/ndis.json +336 -0
  665. angr/procedures/definitions/wdk/ntoskrnl.json +5158 -0
  666. angr/procedures/definitions/wdk/offreg.json +87 -0
  667. angr/procedures/definitions/wdk/pshed.json +33 -0
  668. angr/procedures/definitions/wdk/secur32.json +39 -0
  669. angr/procedures/definitions/wdk/vhfum.json +30 -0
  670. angr/procedures/definitions/win32/_types_win32.json +34480 -0
  671. angr/procedures/definitions/win32/aclui.json +24 -0
  672. angr/procedures/definitions/win32/activeds.json +81 -0
  673. angr/procedures/definitions/win32/advapi32.json +2505 -0
  674. angr/procedures/definitions/win32/advpack.json +165 -0
  675. angr/procedures/definitions/win32/amsi.json +36 -0
  676. angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-1.json +45 -0
  677. angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-3.json +30 -0
  678. angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-6.json +18 -0
  679. angr/procedures/definitions/win32/api-ms-win-core-apiquery-l2-1-0.json +18 -0
  680. angr/procedures/definitions/win32/api-ms-win-core-backgroundtask-l1-1-0.json +18 -0
  681. angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-1.json +18 -0
  682. angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-2.json +18 -0
  683. angr/procedures/definitions/win32/api-ms-win-core-enclave-l1-1-1.json +24 -0
  684. angr/procedures/definitions/win32/api-ms-win-core-errorhandling-l1-1-3.json +18 -0
  685. angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-0.json +30 -0
  686. angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-1.json +18 -0
  687. angr/procedures/definitions/win32/api-ms-win-core-file-fromapp-l1-1-0.json +48 -0
  688. angr/procedures/definitions/win32/api-ms-win-core-handle-l1-1-0.json +18 -0
  689. angr/procedures/definitions/win32/api-ms-win-core-ioring-l1-1-0.json +51 -0
  690. angr/procedures/definitions/win32/api-ms-win-core-marshal-l1-1-0.json +27 -0
  691. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-3.json +27 -0
  692. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-4.json +18 -0
  693. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-5.json +24 -0
  694. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-6.json +27 -0
  695. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-7.json +21 -0
  696. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-8.json +24 -0
  697. angr/procedures/definitions/win32/api-ms-win-core-path-l1-1-0.json +81 -0
  698. angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-0.json +21 -0
  699. angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-1.json +21 -0
  700. angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-1.json +24 -0
  701. angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-2.json +24 -0
  702. angr/procedures/definitions/win32/api-ms-win-core-slapi-l1-1-0.json +18 -0
  703. angr/procedures/definitions/win32/api-ms-win-core-state-helpers-l1-1-0.json +18 -0
  704. angr/procedures/definitions/win32/api-ms-win-core-synch-l1-2-0.json +24 -0
  705. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-0.json +18 -0
  706. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-3.json +21 -0
  707. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-4.json +21 -0
  708. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-6.json +18 -0
  709. angr/procedures/definitions/win32/api-ms-win-core-util-l1-1-1.json +21 -0
  710. angr/procedures/definitions/win32/api-ms-win-core-wow64-l1-1-1.json +24 -0
  711. angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-0.json +42 -0
  712. angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-1.json +30 -0
  713. angr/procedures/definitions/win32/api-ms-win-dx-d3dkmt-l1-1-0.json +18 -0
  714. angr/procedures/definitions/win32/api-ms-win-gaming-deviceinformation-l1-1-0.json +18 -0
  715. angr/procedures/definitions/win32/api-ms-win-gaming-expandedresources-l1-1-0.json +24 -0
  716. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-0.json +36 -0
  717. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-1.json +21 -0
  718. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-2.json +36 -0
  719. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-3.json +21 -0
  720. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-4.json +39 -0
  721. angr/procedures/definitions/win32/api-ms-win-mm-misc-l1-1-1.json +18 -0
  722. angr/procedures/definitions/win32/api-ms-win-net-isolation-l1-1-0.json +39 -0
  723. angr/procedures/definitions/win32/api-ms-win-security-base-l1-2-2.json +18 -0
  724. angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-0.json +18 -0
  725. angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-1.json +18 -0
  726. angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-3.json +18 -0
  727. angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-4.json +18 -0
  728. angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-5.json +21 -0
  729. angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-0.json +24 -0
  730. angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-1.json +33 -0
  731. angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-2.json +18 -0
  732. angr/procedures/definitions/win32/api-ms-win-wsl-api-l1-1-0.json +36 -0
  733. angr/procedures/definitions/win32/apphelp.json +18 -0
  734. angr/procedures/definitions/win32/authz.json +114 -0
  735. angr/procedures/definitions/win32/avicap32.json +27 -0
  736. angr/procedures/definitions/win32/avifil32.json +195 -0
  737. angr/procedures/definitions/win32/avrt.json +57 -0
  738. angr/procedures/definitions/win32/bcp47mrm.json +21 -0
  739. angr/procedures/definitions/win32/bcrypt.json +174 -0
  740. angr/procedures/definitions/win32/bcryptprimitives.json +21 -0
  741. angr/procedures/definitions/win32/bluetoothapis.json +138 -0
  742. angr/procedures/definitions/win32/bthprops_cpl.json +33 -0
  743. angr/procedures/definitions/win32/cabinet.json +81 -0
  744. angr/procedures/definitions/win32/certadm.json +69 -0
  745. angr/procedures/definitions/win32/certpoleng.json +39 -0
  746. angr/procedures/definitions/win32/cfgmgr32.json +732 -0
  747. angr/procedures/definitions/win32/chakra.json +270 -0
  748. angr/procedures/definitions/win32/cldapi.json +123 -0
  749. angr/procedures/definitions/win32/clfsw32.json +192 -0
  750. angr/procedures/definitions/win32/clusapi.json +855 -0
  751. angr/procedures/definitions/win32/comctl32.json +360 -0
  752. angr/procedures/definitions/win32/comdlg32.json +78 -0
  753. angr/procedures/definitions/win32/compstui.json +27 -0
  754. angr/procedures/definitions/win32/computecore.json +177 -0
  755. angr/procedures/definitions/win32/computenetwork.json +144 -0
  756. angr/procedures/definitions/win32/computestorage.json +51 -0
  757. angr/procedures/definitions/win32/comsvcs.json +36 -0
  758. angr/procedures/definitions/win32/credui.json +72 -0
  759. angr/procedures/definitions/win32/crypt32.json +702 -0
  760. angr/procedures/definitions/win32/cryptnet.json +30 -0
  761. angr/procedures/definitions/win32/cryptui.json +45 -0
  762. angr/procedures/definitions/win32/cryptxml.json +72 -0
  763. angr/procedures/definitions/win32/cscapi.json +27 -0
  764. angr/procedures/definitions/win32/d2d1.json +54 -0
  765. angr/procedures/definitions/win32/d3d10.json +96 -0
  766. angr/procedures/definitions/win32/d3d10_1.json +21 -0
  767. angr/procedures/definitions/win32/d3d11.json +24 -0
  768. angr/procedures/definitions/win32/d3d12.json +39 -0
  769. angr/procedures/definitions/win32/d3d9.json +48 -0
  770. angr/procedures/definitions/win32/d3dcompiler_47.json +93 -0
  771. angr/procedures/definitions/win32/d3dcsx.json +42 -0
  772. angr/procedures/definitions/win32/davclnt.json +69 -0
  773. angr/procedures/definitions/win32/dbgeng.json +27 -0
  774. angr/procedures/definitions/win32/dbghelp.json +663 -0
  775. angr/procedures/definitions/win32/dbgmodel.json +18 -0
  776. angr/procedures/definitions/win32/dciman32.json +75 -0
  777. angr/procedures/definitions/win32/dcomp.json +51 -0
  778. angr/procedures/definitions/win32/ddraw.json +36 -0
  779. angr/procedures/definitions/win32/deviceaccess.json +18 -0
  780. angr/procedures/definitions/win32/dflayout.json +18 -0
  781. angr/procedures/definitions/win32/dhcpcsvc.json +60 -0
  782. angr/procedures/definitions/win32/dhcpcsvc6.json +33 -0
  783. angr/procedures/definitions/win32/dhcpsapi.json +603 -0
  784. angr/procedures/definitions/win32/diagnosticdataquery.json +120 -0
  785. angr/procedures/definitions/win32/dinput8.json +18 -0
  786. angr/procedures/definitions/win32/directml.json +21 -0
  787. angr/procedures/definitions/win32/dmprocessxmlfiltered.json +18 -0
  788. angr/procedures/definitions/win32/dnsapi.json +207 -0
  789. angr/procedures/definitions/win32/drt.json +63 -0
  790. angr/procedures/definitions/win32/drtprov.json +42 -0
  791. angr/procedures/definitions/win32/drttransport.json +21 -0
  792. angr/procedures/definitions/win32/dsound.json +45 -0
  793. angr/procedures/definitions/win32/dsparse.json +72 -0
  794. angr/procedures/definitions/win32/dsprop.json +36 -0
  795. angr/procedures/definitions/win32/dssec.json +27 -0
  796. angr/procedures/definitions/win32/dsuiext.json +27 -0
  797. angr/procedures/definitions/win32/dwmapi.json +108 -0
  798. angr/procedures/definitions/win32/dwrite.json +18 -0
  799. angr/procedures/definitions/win32/dxcompiler.json +21 -0
  800. angr/procedures/definitions/win32/dxcore.json +18 -0
  801. angr/procedures/definitions/win32/dxgi.json +33 -0
  802. angr/procedures/definitions/win32/dxva2.json +129 -0
  803. angr/procedures/definitions/win32/eappcfg.json +57 -0
  804. angr/procedures/definitions/win32/eappprxy.json +69 -0
  805. angr/procedures/definitions/win32/efswrt.json +21 -0
  806. angr/procedures/definitions/win32/elscore.json +30 -0
  807. angr/procedures/definitions/win32/esent.json +702 -0
  808. angr/procedures/definitions/win32/evr.json +36 -0
  809. angr/procedures/definitions/win32/faultrep.json +27 -0
  810. angr/procedures/definitions/win32/fhsvcctl.json +36 -0
  811. angr/procedures/definitions/win32/firewallapi.json +24 -0
  812. angr/procedures/definitions/win32/fltlib.json +99 -0
  813. angr/procedures/definitions/win32/fontsub.json +21 -0
  814. angr/procedures/definitions/win32/forceinline.json +24 -0
  815. angr/procedures/definitions/win32/fwpuclnt.json +591 -0
  816. angr/procedures/definitions/win32/fxsutility.json +21 -0
  817. angr/procedures/definitions/win32/gdi32.json +1308 -0
  818. angr/procedures/definitions/win32/gdiplus.json +1902 -0
  819. angr/procedures/definitions/win32/glu32.json +171 -0
  820. angr/procedures/definitions/win32/gpedit.json +33 -0
  821. angr/procedures/definitions/win32/hhctrl_ocx.json +21 -0
  822. angr/procedures/definitions/win32/hid.json +150 -0
  823. angr/procedures/definitions/win32/hlink.json +99 -0
  824. angr/procedures/definitions/win32/hrtfapo.json +18 -0
  825. angr/procedures/definitions/win32/httpapi.json +144 -0
  826. angr/procedures/definitions/win32/icm32.json +78 -0
  827. angr/procedures/definitions/win32/icmui.json +21 -0
  828. angr/procedures/definitions/win32/icu.json +3090 -0
  829. angr/procedures/definitions/win32/ieframe.json +102 -0
  830. angr/procedures/definitions/win32/imagehlp.json +84 -0
  831. angr/procedures/definitions/win32/imgutil.json +42 -0
  832. angr/procedures/definitions/win32/imm32.json +261 -0
  833. angr/procedures/definitions/win32/infocardapi.json +66 -0
  834. angr/procedures/definitions/win32/inkobjcore.json +96 -0
  835. angr/procedures/definitions/win32/iphlpapi.json +618 -0
  836. angr/procedures/definitions/win32/iscsidsc.json +252 -0
  837. angr/procedures/definitions/win32/isolatedwindowsenvironmentutils.json +21 -0
  838. angr/procedures/definitions/win32/kernel32.json +4566 -0
  839. angr/procedures/definitions/win32/kernelbase.json +33 -0
  840. angr/procedures/definitions/win32/keycredmgr.json +27 -0
  841. angr/procedures/definitions/win32/ksproxy_ax.json +33 -0
  842. angr/procedures/definitions/win32/ksuser.json +39 -0
  843. angr/procedures/definitions/win32/ktmw32.json +132 -0
  844. angr/procedures/definitions/win32/licenseprotection.json +21 -0
  845. angr/procedures/definitions/win32/loadperf.json +51 -0
  846. angr/procedures/definitions/win32/magnification.json +72 -0
  847. angr/procedures/definitions/win32/mapi32.json +213 -0
  848. angr/procedures/definitions/win32/mdmlocalmanagement.json +24 -0
  849. angr/procedures/definitions/win32/mdmregistration.json +60 -0
  850. angr/procedures/definitions/win32/mf.json +201 -0
  851. angr/procedures/definitions/win32/mfcore.json +21 -0
  852. angr/procedures/definitions/win32/mfplat.json +450 -0
  853. angr/procedures/definitions/win32/mfplay.json +18 -0
  854. angr/procedures/definitions/win32/mfreadwrite.json +30 -0
  855. angr/procedures/definitions/win32/mfsensorgroup.json +45 -0
  856. angr/procedures/definitions/win32/mfsrcsnk.json +21 -0
  857. angr/procedures/definitions/win32/mgmtapi.json +42 -0
  858. angr/procedures/definitions/win32/mi.json +18 -0
  859. angr/procedures/definitions/win32/mmdevapi.json +18 -0
  860. angr/procedures/definitions/win32/mpr.json +156 -0
  861. angr/procedures/definitions/win32/mprapi.json +351 -0
  862. angr/procedures/definitions/win32/mqrt.json +117 -0
  863. angr/procedures/definitions/win32/mrmsupport.json +96 -0
  864. angr/procedures/definitions/win32/msacm32.json +141 -0
  865. angr/procedures/definitions/win32/msajapi.json +1656 -0
  866. angr/procedures/definitions/win32/mscms.json +252 -0
  867. angr/procedures/definitions/win32/mscoree.json +96 -0
  868. angr/procedures/definitions/win32/msctfmonitor.json +24 -0
  869. angr/procedures/definitions/win32/msdelta.json +63 -0
  870. angr/procedures/definitions/win32/msdmo.json +48 -0
  871. angr/procedures/definitions/win32/msdrm.json +267 -0
  872. angr/procedures/definitions/win32/msi.json +807 -0
  873. angr/procedures/definitions/win32/msimg32.json +24 -0
  874. angr/procedures/definitions/win32/mspatcha.json +63 -0
  875. angr/procedures/definitions/win32/mspatchc.json +42 -0
  876. angr/procedures/definitions/win32/msports.json +36 -0
  877. angr/procedures/definitions/win32/msrating.json +72 -0
  878. angr/procedures/definitions/win32/mssign32.json +45 -0
  879. angr/procedures/definitions/win32/mstask.json +21 -0
  880. angr/procedures/definitions/win32/msvfw32.json +144 -0
  881. angr/procedures/definitions/win32/mswsock.json +63 -0
  882. angr/procedures/definitions/win32/mtxdm.json +18 -0
  883. angr/procedures/definitions/win32/ncrypt.json +132 -0
  884. angr/procedures/definitions/win32/ndfapi.json +63 -0
  885. angr/procedures/definitions/win32/netapi32.json +633 -0
  886. angr/procedures/definitions/win32/netsh.json +39 -0
  887. angr/procedures/definitions/win32/netshell.json +21 -0
  888. angr/procedures/definitions/win32/newdev.json +48 -0
  889. angr/procedures/definitions/win32/ninput.json +105 -0
  890. angr/procedures/definitions/win32/normaliz.json +21 -0
  891. angr/procedures/definitions/win32/ntdll.json +234 -0
  892. angr/procedures/definitions/win32/ntdllk.json +18 -0
  893. angr/procedures/definitions/win32/ntdsapi.json +258 -0
  894. angr/procedures/definitions/win32/ntlanman.json +45 -0
  895. angr/procedures/definitions/win32/odbc32.json +477 -0
  896. angr/procedures/definitions/win32/odbcbcp.json +96 -0
  897. angr/procedures/definitions/win32/ole32.json +966 -0
  898. angr/procedures/definitions/win32/oleacc.json +66 -0
  899. angr/procedures/definitions/win32/oleaut32.json +1230 -0
  900. angr/procedures/definitions/win32/oledlg.json +84 -0
  901. angr/procedures/definitions/win32/ondemandconnroutehelper.json +30 -0
  902. angr/procedures/definitions/win32/opengl32.json +1080 -0
  903. angr/procedures/definitions/win32/opmxbox.json +24 -0
  904. angr/procedures/definitions/win32/p2p.json +339 -0
  905. angr/procedures/definitions/win32/p2pgraph.json +126 -0
  906. angr/procedures/definitions/win32/pdh.json +309 -0
  907. angr/procedures/definitions/win32/peerdist.json +99 -0
  908. angr/procedures/definitions/win32/powrprof.json +267 -0
  909. angr/procedures/definitions/win32/prntvpt.json +48 -0
  910. angr/procedures/definitions/win32/projectedfslib.json +72 -0
  911. angr/procedures/definitions/win32/propsys.json +669 -0
  912. angr/procedures/definitions/win32/psapi.json +96 -0
  913. angr/procedures/definitions/win32/quartz.json +21 -0
  914. angr/procedures/definitions/win32/query.json +27 -0
  915. angr/procedures/definitions/win32/qwave.json +48 -0
  916. angr/procedures/definitions/win32/rasapi32.json +267 -0
  917. angr/procedures/definitions/win32/rasdlg.json +33 -0
  918. angr/procedures/definitions/win32/resutils.json +375 -0
  919. angr/procedures/definitions/win32/rpcns4.json +198 -0
  920. angr/procedures/definitions/win32/rpcproxy.json +27 -0
  921. angr/procedures/definitions/win32/rpcrt4.json +1356 -0
  922. angr/procedures/definitions/win32/rstrtmgr.json +48 -0
  923. angr/procedures/definitions/win32/rtm.json +243 -0
  924. angr/procedures/definitions/win32/rtutils.json +138 -0
  925. angr/procedures/definitions/win32/rtworkq.json +114 -0
  926. angr/procedures/definitions/win32/sas.json +18 -0
  927. angr/procedures/definitions/win32/scarddlg.json +30 -0
  928. angr/procedures/definitions/win32/schannel.json +42 -0
  929. angr/procedures/definitions/win32/sechost.json +21 -0
  930. angr/procedures/definitions/win32/secur32.json +282 -0
  931. angr/procedures/definitions/win32/sensapi.json +24 -0
  932. angr/procedures/definitions/win32/sensorsutilsv2.json +135 -0
  933. angr/procedures/definitions/win32/setupapi.json +1017 -0
  934. angr/procedures/definitions/win32/sfc.json +33 -0
  935. angr/procedures/definitions/win32/shdocvw.json +24 -0
  936. angr/procedures/definitions/win32/shell32.json +747 -0
  937. angr/procedures/definitions/win32/shlwapi.json +1095 -0
  938. angr/procedures/definitions/win32/slc.json +111 -0
  939. angr/procedures/definitions/win32/slcext.json +27 -0
  940. angr/procedures/definitions/win32/slwga.json +18 -0
  941. angr/procedures/definitions/win32/snmpapi.json +93 -0
  942. angr/procedures/definitions/win32/spoolss.json +93 -0
  943. angr/procedures/definitions/win32/srclient.json +18 -0
  944. angr/procedures/definitions/win32/srpapi.json +48 -0
  945. angr/procedures/definitions/win32/sspicli.json +36 -0
  946. angr/procedures/definitions/win32/sti.json +18 -0
  947. angr/procedures/definitions/win32/t2embed.json +57 -0
  948. angr/procedures/definitions/win32/tapi32.json +762 -0
  949. angr/procedures/definitions/win32/tbs.json +57 -0
  950. angr/procedures/definitions/win32/tdh.json +96 -0
  951. angr/procedures/definitions/win32/tokenbinding.json +45 -0
  952. angr/procedures/definitions/win32/traffic.json +75 -0
  953. angr/procedures/definitions/win32/txfw32.json +42 -0
  954. angr/procedures/definitions/win32/ualapi.json +27 -0
  955. angr/procedures/definitions/win32/uiautomationcore.json +309 -0
  956. angr/procedures/definitions/win32/urlmon.json +246 -0
  957. angr/procedures/definitions/win32/user32.json +2298 -0
  958. angr/procedures/definitions/win32/userenv.json +147 -0
  959. angr/procedures/definitions/win32/usp10.json +135 -0
  960. angr/procedures/definitions/win32/uxtheme.json +246 -0
  961. angr/procedures/definitions/win32/verifier.json +18 -0
  962. angr/procedures/definitions/win32/version.json +57 -0
  963. angr/procedures/definitions/win32/vertdll.json +36 -0
  964. angr/procedures/definitions/win32/virtdisk.json +102 -0
  965. angr/procedures/definitions/win32/vmdevicehost.json +54 -0
  966. angr/procedures/definitions/win32/vmsavedstatedumpprovider.json +144 -0
  967. angr/procedures/definitions/win32/vssapi.json +18 -0
  968. angr/procedures/definitions/win32/wcmapi.json +30 -0
  969. angr/procedures/definitions/win32/wdsbp.json +36 -0
  970. angr/procedures/definitions/win32/wdsclientapi.json +126 -0
  971. angr/procedures/definitions/win32/wdsmc.json +33 -0
  972. angr/procedures/definitions/win32/wdspxe.json +108 -0
  973. angr/procedures/definitions/win32/wdstptc.json +54 -0
  974. angr/procedures/definitions/win32/webauthn.json +54 -0
  975. angr/procedures/definitions/win32/webservices.json +594 -0
  976. angr/procedures/definitions/win32/websocket.json +54 -0
  977. angr/procedures/definitions/win32/wecapi.json +60 -0
  978. angr/procedures/definitions/win32/wer.json +78 -0
  979. angr/procedures/definitions/win32/wevtapi.json +120 -0
  980. angr/procedures/definitions/win32/winbio.json +177 -0
  981. angr/procedures/definitions/win32/windows_ai_machinelearning.json +18 -0
  982. angr/procedures/definitions/win32/windows_media_mediacontrol.json +39 -0
  983. angr/procedures/definitions/win32/windows_networking.json +18 -0
  984. angr/procedures/definitions/win32/windows_ui_xaml.json +21 -0
  985. angr/procedures/definitions/win32/windowscodecs.json +42 -0
  986. angr/procedures/definitions/win32/winfax.json +183 -0
  987. angr/procedures/definitions/win32/winhttp.json +183 -0
  988. angr/procedures/definitions/win32/winhvemulation.json +27 -0
  989. angr/procedures/definitions/win32/winhvplatform.json +213 -0
  990. angr/procedures/definitions/win32/wininet.json +903 -0
  991. angr/procedures/definitions/win32/winml.json +18 -0
  992. angr/procedures/definitions/win32/winmm.json +543 -0
  993. angr/procedures/definitions/win32/winscard.json +225 -0
  994. angr/procedures/definitions/win32/winspool_drv.json +531 -0
  995. angr/procedures/definitions/win32/wintrust.json +195 -0
  996. angr/procedures/definitions/win32/winusb.json +117 -0
  997. angr/procedures/definitions/win32/wlanapi.json +195 -0
  998. angr/procedures/definitions/win32/wlanui.json +18 -0
  999. angr/procedures/definitions/win32/wldap32.json +744 -0
  1000. angr/procedures/definitions/win32/wldp.json +42 -0
  1001. angr/procedures/definitions/win32/wmvcore.json +48 -0
  1002. angr/procedures/definitions/win32/wnvapi.json +21 -0
  1003. angr/procedures/definitions/win32/wofutil.json +48 -0
  1004. angr/procedures/definitions/win32/ws2_32.json +495 -0
  1005. angr/procedures/definitions/win32/wscapi.json +33 -0
  1006. angr/procedures/definitions/win32/wsclient.json +24 -0
  1007. angr/procedures/definitions/win32/wsdapi.json +111 -0
  1008. angr/procedures/definitions/win32/wsmsvc.json +114 -0
  1009. angr/procedures/definitions/win32/wsnmp32.json +162 -0
  1010. angr/procedures/definitions/win32/wtsapi32.json +204 -0
  1011. angr/procedures/definitions/win32/xaudio2_8.json +27 -0
  1012. angr/procedures/definitions/win32/xinput1_4.json +36 -0
  1013. angr/procedures/definitions/win32/xmllite.json +33 -0
  1014. angr/procedures/definitions/win32/xolehlp.json +27 -0
  1015. angr/procedures/definitions/win32/xpsprint.json +21 -0
  1016. angr/procedures/glibc/__ctype_b_loc.py +21 -0
  1017. angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
  1018. angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
  1019. angr/procedures/glibc/__errno_location.py +7 -0
  1020. angr/procedures/glibc/__init__.py +3 -0
  1021. angr/procedures/glibc/__libc_init.py +37 -0
  1022. angr/procedures/glibc/__libc_start_main.py +301 -0
  1023. angr/procedures/glibc/dynamic_loading.py +20 -0
  1024. angr/procedures/glibc/scanf.py +19 -0
  1025. angr/procedures/glibc/sscanf.py +10 -0
  1026. angr/procedures/gnulib/__init__.py +3 -0
  1027. angr/procedures/gnulib/xalloc_die.py +14 -0
  1028. angr/procedures/gnulib/xstrtol_fatal.py +14 -0
  1029. angr/procedures/java/__init__.py +42 -0
  1030. angr/procedures/java/unconstrained.py +65 -0
  1031. angr/procedures/java_io/__init__.py +0 -0
  1032. angr/procedures/java_io/read.py +12 -0
  1033. angr/procedures/java_io/write.py +17 -0
  1034. angr/procedures/java_jni/__init__.py +482 -0
  1035. angr/procedures/java_jni/array_operations.py +312 -0
  1036. angr/procedures/java_jni/class_and_interface_operations.py +31 -0
  1037. angr/procedures/java_jni/field_access.py +173 -0
  1038. angr/procedures/java_jni/global_and_local_refs.py +57 -0
  1039. angr/procedures/java_jni/method_calls.py +365 -0
  1040. angr/procedures/java_jni/not_implemented.py +26 -0
  1041. angr/procedures/java_jni/object_operations.py +94 -0
  1042. angr/procedures/java_jni/string_operations.py +87 -0
  1043. angr/procedures/java_jni/version_information.py +12 -0
  1044. angr/procedures/java_lang/__init__.py +0 -0
  1045. angr/procedures/java_lang/character.py +30 -0
  1046. angr/procedures/java_lang/double.py +24 -0
  1047. angr/procedures/java_lang/exit.py +13 -0
  1048. angr/procedures/java_lang/getsimplename.py +18 -0
  1049. angr/procedures/java_lang/integer.py +43 -0
  1050. angr/procedures/java_lang/load_library.py +9 -0
  1051. angr/procedures/java_lang/math.py +15 -0
  1052. angr/procedures/java_lang/string.py +78 -0
  1053. angr/procedures/java_lang/stringbuilder.py +44 -0
  1054. angr/procedures/java_lang/system.py +18 -0
  1055. angr/procedures/java_util/__init__.py +0 -0
  1056. angr/procedures/java_util/collection.py +35 -0
  1057. angr/procedures/java_util/iterator.py +46 -0
  1058. angr/procedures/java_util/list.py +99 -0
  1059. angr/procedures/java_util/map.py +131 -0
  1060. angr/procedures/java_util/random.py +14 -0
  1061. angr/procedures/java_util/scanner_nextline.py +23 -0
  1062. angr/procedures/libc/__init__.py +3 -0
  1063. angr/procedures/libc/abort.py +9 -0
  1064. angr/procedures/libc/access.py +13 -0
  1065. angr/procedures/libc/atoi.py +14 -0
  1066. angr/procedures/libc/atol.py +13 -0
  1067. angr/procedures/libc/calloc.py +8 -0
  1068. angr/procedures/libc/closelog.py +10 -0
  1069. angr/procedures/libc/err.py +14 -0
  1070. angr/procedures/libc/error.py +54 -0
  1071. angr/procedures/libc/exit.py +11 -0
  1072. angr/procedures/libc/fclose.py +19 -0
  1073. angr/procedures/libc/feof.py +21 -0
  1074. angr/procedures/libc/fflush.py +16 -0
  1075. angr/procedures/libc/fgetc.py +27 -0
  1076. angr/procedures/libc/fgets.py +69 -0
  1077. angr/procedures/libc/fopen.py +63 -0
  1078. angr/procedures/libc/fprintf.py +25 -0
  1079. angr/procedures/libc/fputc.py +23 -0
  1080. angr/procedures/libc/fputs.py +24 -0
  1081. angr/procedures/libc/fread.py +24 -0
  1082. angr/procedures/libc/free.py +9 -0
  1083. angr/procedures/libc/fscanf.py +20 -0
  1084. angr/procedures/libc/fseek.py +34 -0
  1085. angr/procedures/libc/ftell.py +22 -0
  1086. angr/procedures/libc/fwrite.py +19 -0
  1087. angr/procedures/libc/getchar.py +13 -0
  1088. angr/procedures/libc/getdelim.py +99 -0
  1089. angr/procedures/libc/getegid.py +8 -0
  1090. angr/procedures/libc/geteuid.py +8 -0
  1091. angr/procedures/libc/getgid.py +8 -0
  1092. angr/procedures/libc/gets.py +68 -0
  1093. angr/procedures/libc/getuid.py +8 -0
  1094. angr/procedures/libc/malloc.py +12 -0
  1095. angr/procedures/libc/memcmp.py +69 -0
  1096. angr/procedures/libc/memcpy.py +45 -0
  1097. angr/procedures/libc/memset.py +72 -0
  1098. angr/procedures/libc/openlog.py +10 -0
  1099. angr/procedures/libc/perror.py +13 -0
  1100. angr/procedures/libc/printf.py +34 -0
  1101. angr/procedures/libc/putchar.py +13 -0
  1102. angr/procedures/libc/puts.py +19 -0
  1103. angr/procedures/libc/rand.py +8 -0
  1104. angr/procedures/libc/realloc.py +8 -0
  1105. angr/procedures/libc/rewind.py +12 -0
  1106. angr/procedures/libc/scanf.py +20 -0
  1107. angr/procedures/libc/setbuf.py +9 -0
  1108. angr/procedures/libc/setvbuf.py +7 -0
  1109. angr/procedures/libc/snprintf.py +36 -0
  1110. angr/procedures/libc/sprintf.py +25 -0
  1111. angr/procedures/libc/srand.py +7 -0
  1112. angr/procedures/libc/sscanf.py +13 -0
  1113. angr/procedures/libc/stpcpy.py +18 -0
  1114. angr/procedures/libc/strcat.py +14 -0
  1115. angr/procedures/libc/strchr.py +48 -0
  1116. angr/procedures/libc/strcmp.py +31 -0
  1117. angr/procedures/libc/strcpy.py +13 -0
  1118. angr/procedures/libc/strlen.py +114 -0
  1119. angr/procedures/libc/strncat.py +19 -0
  1120. angr/procedures/libc/strncmp.py +183 -0
  1121. angr/procedures/libc/strncpy.py +22 -0
  1122. angr/procedures/libc/strnlen.py +13 -0
  1123. angr/procedures/libc/strstr.py +101 -0
  1124. angr/procedures/libc/strtol.py +261 -0
  1125. angr/procedures/libc/strtoul.py +9 -0
  1126. angr/procedures/libc/system.py +13 -0
  1127. angr/procedures/libc/time.py +9 -0
  1128. angr/procedures/libc/tmpnam.py +20 -0
  1129. angr/procedures/libc/tolower.py +10 -0
  1130. angr/procedures/libc/toupper.py +10 -0
  1131. angr/procedures/libc/ungetc.py +20 -0
  1132. angr/procedures/libc/vsnprintf.py +17 -0
  1133. angr/procedures/libc/wchar.py +16 -0
  1134. angr/procedures/libstdcpp/__init__.py +0 -0
  1135. angr/procedures/libstdcpp/_unwind_resume.py +11 -0
  1136. angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
  1137. angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
  1138. angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
  1139. angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
  1140. angr/procedures/libstdcpp/std__terminate.py +13 -0
  1141. angr/procedures/linux_kernel/__init__.py +3 -0
  1142. angr/procedures/linux_kernel/access.py +18 -0
  1143. angr/procedures/linux_kernel/arch_prctl.py +34 -0
  1144. angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
  1145. angr/procedures/linux_kernel/brk.py +18 -0
  1146. angr/procedures/linux_kernel/cwd.py +28 -0
  1147. angr/procedures/linux_kernel/fstat.py +138 -0
  1148. angr/procedures/linux_kernel/fstat64.py +170 -0
  1149. angr/procedures/linux_kernel/futex.py +17 -0
  1150. angr/procedures/linux_kernel/getegid.py +17 -0
  1151. angr/procedures/linux_kernel/geteuid.py +17 -0
  1152. angr/procedures/linux_kernel/getgid.py +17 -0
  1153. angr/procedures/linux_kernel/getpid.py +14 -0
  1154. angr/procedures/linux_kernel/getrlimit.py +24 -0
  1155. angr/procedures/linux_kernel/gettid.py +9 -0
  1156. angr/procedures/linux_kernel/getuid.py +17 -0
  1157. angr/procedures/linux_kernel/iovec.py +47 -0
  1158. angr/procedures/linux_kernel/lseek.py +42 -0
  1159. angr/procedures/linux_kernel/mmap.py +16 -0
  1160. angr/procedures/linux_kernel/mprotect.py +42 -0
  1161. angr/procedures/linux_kernel/munmap.py +8 -0
  1162. angr/procedures/linux_kernel/openat.py +26 -0
  1163. angr/procedures/linux_kernel/set_tid_address.py +8 -0
  1164. angr/procedures/linux_kernel/sigaction.py +19 -0
  1165. angr/procedures/linux_kernel/sigprocmask.py +23 -0
  1166. angr/procedures/linux_kernel/stat.py +23 -0
  1167. angr/procedures/linux_kernel/sysinfo.py +59 -0
  1168. angr/procedures/linux_kernel/tgkill.py +10 -0
  1169. angr/procedures/linux_kernel/time.py +34 -0
  1170. angr/procedures/linux_kernel/uid.py +30 -0
  1171. angr/procedures/linux_kernel/uname.py +29 -0
  1172. angr/procedures/linux_kernel/unlink.py +22 -0
  1173. angr/procedures/linux_kernel/vsyscall.py +16 -0
  1174. angr/procedures/linux_loader/__init__.py +3 -0
  1175. angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
  1176. angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
  1177. angr/procedures/linux_loader/sim_loader.py +54 -0
  1178. angr/procedures/linux_loader/tls.py +40 -0
  1179. angr/procedures/msvcr/__getmainargs.py +16 -0
  1180. angr/procedures/msvcr/__init__.py +4 -0
  1181. angr/procedures/msvcr/_initterm.py +38 -0
  1182. angr/procedures/msvcr/fmode.py +31 -0
  1183. angr/procedures/ntdll/__init__.py +0 -0
  1184. angr/procedures/ntdll/exceptions.py +60 -0
  1185. angr/procedures/posix/__init__.py +3 -0
  1186. angr/procedures/posix/accept.py +29 -0
  1187. angr/procedures/posix/bind.py +13 -0
  1188. angr/procedures/posix/bzero.py +9 -0
  1189. angr/procedures/posix/chroot.py +27 -0
  1190. angr/procedures/posix/close.py +9 -0
  1191. angr/procedures/posix/closedir.py +7 -0
  1192. angr/procedures/posix/dup.py +56 -0
  1193. angr/procedures/posix/fcntl.py +10 -0
  1194. angr/procedures/posix/fdopen.py +76 -0
  1195. angr/procedures/posix/fileno.py +18 -0
  1196. angr/procedures/posix/fork.py +13 -0
  1197. angr/procedures/posix/getenv.py +35 -0
  1198. angr/procedures/posix/gethostbyname.py +43 -0
  1199. angr/procedures/posix/getpass.py +19 -0
  1200. angr/procedures/posix/getsockopt.py +11 -0
  1201. angr/procedures/posix/htonl.py +11 -0
  1202. angr/procedures/posix/htons.py +11 -0
  1203. angr/procedures/posix/inet_ntoa.py +59 -0
  1204. angr/procedures/posix/listen.py +13 -0
  1205. angr/procedures/posix/mmap.py +144 -0
  1206. angr/procedures/posix/open.py +18 -0
  1207. angr/procedures/posix/opendir.py +10 -0
  1208. angr/procedures/posix/poll.py +55 -0
  1209. angr/procedures/posix/pread64.py +46 -0
  1210. angr/procedures/posix/pthread.py +87 -0
  1211. angr/procedures/posix/pwrite64.py +46 -0
  1212. angr/procedures/posix/read.py +13 -0
  1213. angr/procedures/posix/readdir.py +62 -0
  1214. angr/procedures/posix/recv.py +13 -0
  1215. angr/procedures/posix/recvfrom.py +13 -0
  1216. angr/procedures/posix/select.py +48 -0
  1217. angr/procedures/posix/send.py +23 -0
  1218. angr/procedures/posix/setsockopt.py +9 -0
  1219. angr/procedures/posix/sigaction.py +23 -0
  1220. angr/procedures/posix/sim_time.py +48 -0
  1221. angr/procedures/posix/sleep.py +8 -0
  1222. angr/procedures/posix/socket.py +18 -0
  1223. angr/procedures/posix/strcasecmp.py +26 -0
  1224. angr/procedures/posix/strdup.py +18 -0
  1225. angr/procedures/posix/strtok_r.py +64 -0
  1226. angr/procedures/posix/syslog.py +15 -0
  1227. angr/procedures/posix/tz.py +9 -0
  1228. angr/procedures/posix/unlink.py +11 -0
  1229. angr/procedures/posix/usleep.py +8 -0
  1230. angr/procedures/posix/write.py +13 -0
  1231. angr/procedures/procedure_dict.py +50 -0
  1232. angr/procedures/stubs/CallReturn.py +13 -0
  1233. angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
  1234. angr/procedures/stubs/Nop.py +7 -0
  1235. angr/procedures/stubs/PathTerminator.py +9 -0
  1236. angr/procedures/stubs/Redirect.py +18 -0
  1237. angr/procedures/stubs/ReturnChar.py +11 -0
  1238. angr/procedures/stubs/ReturnUnconstrained.py +24 -0
  1239. angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
  1240. angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
  1241. angr/procedures/stubs/UserHook.py +18 -0
  1242. angr/procedures/stubs/__init__.py +3 -0
  1243. angr/procedures/stubs/b64_decode.py +15 -0
  1244. angr/procedures/stubs/caller.py +14 -0
  1245. angr/procedures/stubs/crazy_scanf.py +20 -0
  1246. angr/procedures/stubs/format_parser.py +669 -0
  1247. angr/procedures/stubs/syscall_stub.py +24 -0
  1248. angr/procedures/testing/__init__.py +3 -0
  1249. angr/procedures/testing/manyargs.py +9 -0
  1250. angr/procedures/testing/retreg.py +8 -0
  1251. angr/procedures/tracer/__init__.py +4 -0
  1252. angr/procedures/tracer/random.py +9 -0
  1253. angr/procedures/tracer/receive.py +23 -0
  1254. angr/procedures/tracer/transmit.py +26 -0
  1255. angr/procedures/uclibc/__init__.py +3 -0
  1256. angr/procedures/uclibc/__uClibc_main.py +10 -0
  1257. angr/procedures/win32/EncodePointer.py +7 -0
  1258. angr/procedures/win32/ExitProcess.py +9 -0
  1259. angr/procedures/win32/GetCommandLine.py +12 -0
  1260. angr/procedures/win32/GetCurrentProcessId.py +7 -0
  1261. angr/procedures/win32/GetCurrentThreadId.py +7 -0
  1262. angr/procedures/win32/GetLastInputInfo.py +40 -0
  1263. angr/procedures/win32/GetModuleHandle.py +29 -0
  1264. angr/procedures/win32/GetProcessAffinityMask.py +37 -0
  1265. angr/procedures/win32/InterlockedExchange.py +15 -0
  1266. angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
  1267. angr/procedures/win32/VirtualAlloc.py +114 -0
  1268. angr/procedures/win32/VirtualProtect.py +60 -0
  1269. angr/procedures/win32/__init__.py +3 -0
  1270. angr/procedures/win32/critical_section.py +12 -0
  1271. angr/procedures/win32/dynamic_loading.py +104 -0
  1272. angr/procedures/win32/file_handles.py +47 -0
  1273. angr/procedures/win32/gethostbyname.py +12 -0
  1274. angr/procedures/win32/heap.py +45 -0
  1275. angr/procedures/win32/is_bad_ptr.py +26 -0
  1276. angr/procedures/win32/local_storage.py +88 -0
  1277. angr/procedures/win32/mutex.py +11 -0
  1278. angr/procedures/win32/sim_time.py +135 -0
  1279. angr/procedures/win32/system_paths.py +35 -0
  1280. angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
  1281. angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
  1282. angr/procedures/win32_kernel/__fastfail.py +15 -0
  1283. angr/procedures/win32_kernel/__init__.py +3 -0
  1284. angr/procedures/win_user32/__init__.py +0 -0
  1285. angr/procedures/win_user32/chars.py +15 -0
  1286. angr/procedures/win_user32/keyboard.py +14 -0
  1287. angr/procedures/win_user32/messagebox.py +49 -0
  1288. angr/project.py +860 -0
  1289. angr/protos/__init__.py +19 -0
  1290. angr/protos/cfg_pb2.py +42 -0
  1291. angr/protos/function_pb2.py +38 -0
  1292. angr/protos/primitives_pb2.py +59 -0
  1293. angr/protos/variables_pb2.py +55 -0
  1294. angr/protos/xrefs_pb2.py +36 -0
  1295. angr/py.typed +1 -0
  1296. angr/rustylib.cpython-311-darwin.so +0 -0
  1297. angr/serializable.py +66 -0
  1298. angr/sim_manager.py +971 -0
  1299. angr/sim_options.py +436 -0
  1300. angr/sim_procedure.py +626 -0
  1301. angr/sim_state.py +926 -0
  1302. angr/sim_state_options.py +403 -0
  1303. angr/sim_type.py +4026 -0
  1304. angr/sim_variable.py +470 -0
  1305. angr/simos/__init__.py +47 -0
  1306. angr/simos/cgc.py +153 -0
  1307. angr/simos/javavm.py +458 -0
  1308. angr/simos/linux.py +509 -0
  1309. angr/simos/simos.py +444 -0
  1310. angr/simos/snimmuc_nxp.py +149 -0
  1311. angr/simos/userland.py +163 -0
  1312. angr/simos/windows.py +615 -0
  1313. angr/simos/xbox.py +32 -0
  1314. angr/slicer.py +352 -0
  1315. angr/state_hierarchy.py +262 -0
  1316. angr/state_plugins/__init__.py +84 -0
  1317. angr/state_plugins/callstack.py +478 -0
  1318. angr/state_plugins/cgc.py +155 -0
  1319. angr/state_plugins/debug_variables.py +192 -0
  1320. angr/state_plugins/filesystem.py +463 -0
  1321. angr/state_plugins/gdb.py +148 -0
  1322. angr/state_plugins/globals.py +65 -0
  1323. angr/state_plugins/heap/__init__.py +15 -0
  1324. angr/state_plugins/heap/heap_base.py +128 -0
  1325. angr/state_plugins/heap/heap_brk.py +136 -0
  1326. angr/state_plugins/heap/heap_freelist.py +213 -0
  1327. angr/state_plugins/heap/heap_libc.py +46 -0
  1328. angr/state_plugins/heap/heap_ptmalloc.py +620 -0
  1329. angr/state_plugins/heap/utils.py +22 -0
  1330. angr/state_plugins/history.py +564 -0
  1331. angr/state_plugins/inspect.py +375 -0
  1332. angr/state_plugins/javavm_classloader.py +134 -0
  1333. angr/state_plugins/jni_references.py +95 -0
  1334. angr/state_plugins/libc.py +1263 -0
  1335. angr/state_plugins/light_registers.py +168 -0
  1336. angr/state_plugins/log.py +84 -0
  1337. angr/state_plugins/loop_data.py +92 -0
  1338. angr/state_plugins/plugin.py +176 -0
  1339. angr/state_plugins/posix.py +703 -0
  1340. angr/state_plugins/preconstrainer.py +196 -0
  1341. angr/state_plugins/scratch.py +173 -0
  1342. angr/state_plugins/sim_action.py +326 -0
  1343. angr/state_plugins/sim_action_object.py +271 -0
  1344. angr/state_plugins/sim_event.py +59 -0
  1345. angr/state_plugins/solver.py +1128 -0
  1346. angr/state_plugins/symbolizer.py +291 -0
  1347. angr/state_plugins/trace_additions.py +738 -0
  1348. angr/state_plugins/uc_manager.py +94 -0
  1349. angr/state_plugins/unicorn_engine.py +1920 -0
  1350. angr/state_plugins/view.py +340 -0
  1351. angr/storage/__init__.py +15 -0
  1352. angr/storage/file.py +1210 -0
  1353. angr/storage/memory_mixins/__init__.py +317 -0
  1354. angr/storage/memory_mixins/actions_mixin.py +72 -0
  1355. angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
  1356. angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
  1357. angr/storage/memory_mixins/clouseau_mixin.py +137 -0
  1358. angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
  1359. angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
  1360. angr/storage/memory_mixins/default_filler_mixin.py +144 -0
  1361. angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
  1362. angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
  1363. angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
  1364. angr/storage/memory_mixins/keyvalue_memory_mixin.py +43 -0
  1365. angr/storage/memory_mixins/label_merger_mixin.py +31 -0
  1366. angr/storage/memory_mixins/memory_mixin.py +175 -0
  1367. angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
  1368. angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
  1369. angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
  1370. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
  1371. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
  1372. angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
  1373. angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
  1374. angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
  1375. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
  1376. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
  1377. angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
  1378. angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
  1379. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
  1380. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
  1381. angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
  1382. angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
  1383. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +529 -0
  1384. angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
  1385. angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
  1386. angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
  1387. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
  1388. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
  1389. angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
  1390. angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
  1391. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
  1392. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
  1393. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +442 -0
  1394. angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
  1395. angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
  1396. angr/storage/memory_mixins/simplification_mixin.py +15 -0
  1397. angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
  1398. angr/storage/memory_mixins/slotted_memory.py +140 -0
  1399. angr/storage/memory_mixins/smart_find_mixin.py +161 -0
  1400. angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
  1401. angr/storage/memory_mixins/top_merger_mixin.py +25 -0
  1402. angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
  1403. angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
  1404. angr/storage/memory_object.py +195 -0
  1405. angr/tablespecs.py +91 -0
  1406. angr/unicornlib.dylib +0 -0
  1407. angr/utils/__init__.py +46 -0
  1408. angr/utils/ail.py +176 -0
  1409. angr/utils/algo.py +34 -0
  1410. angr/utils/balancer.py +776 -0
  1411. angr/utils/bits.py +46 -0
  1412. angr/utils/constants.py +9 -0
  1413. angr/utils/cowdict.py +63 -0
  1414. angr/utils/cpp.py +17 -0
  1415. angr/utils/doms.py +150 -0
  1416. angr/utils/dynamic_dictlist.py +89 -0
  1417. angr/utils/endness.py +18 -0
  1418. angr/utils/enums_conv.py +97 -0
  1419. angr/utils/env.py +12 -0
  1420. angr/utils/formatting.py +128 -0
  1421. angr/utils/funcid.py +244 -0
  1422. angr/utils/graph.py +981 -0
  1423. angr/utils/lazy_import.py +13 -0
  1424. angr/utils/library.py +236 -0
  1425. angr/utils/loader.py +55 -0
  1426. angr/utils/mp.py +66 -0
  1427. angr/utils/orderedset.py +74 -0
  1428. angr/utils/ssa/__init__.py +455 -0
  1429. angr/utils/ssa/tmp_uses_collector.py +23 -0
  1430. angr/utils/ssa/vvar_uses_collector.py +36 -0
  1431. angr/utils/strings.py +20 -0
  1432. angr/utils/tagged_interval_map.py +112 -0
  1433. angr/utils/timing.py +74 -0
  1434. angr/utils/types.py +193 -0
  1435. angr/utils/vex.py +11 -0
  1436. angr/vaults.py +367 -0
  1437. angr-9.2.192.dist-info/METADATA +112 -0
  1438. angr-9.2.192.dist-info/RECORD +1442 -0
  1439. angr-9.2.192.dist-info/WHEEL +6 -0
  1440. angr-9.2.192.dist-info/entry_points.txt +2 -0
  1441. angr-9.2.192.dist-info/licenses/LICENSE +27 -0
  1442. angr-9.2.192.dist-info/top_level.txt +1 -0
@@ -0,0 +1,4257 @@
1
+ # pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument,no-self-use
2
+ from __future__ import annotations
3
+ from typing import cast, Any, TYPE_CHECKING
4
+
5
+ from collections.abc import Iterable
6
+ from collections.abc import Callable
7
+ from collections import defaultdict, Counter
8
+ import logging
9
+ import struct
10
+ import re
11
+
12
+ from angr.ailment import Block, Expr, Stmt, Tmp
13
+ from angr.ailment.constant import UNDETERMINED_SIZE
14
+ from angr.ailment.expression import StackBaseOffset, BinaryOp
15
+ from unique_log_filter import UniqueLogFilter
16
+
17
+ from angr.sim_type import (
18
+ SimTypeLongLong,
19
+ SimTypeInt,
20
+ SimTypeShort,
21
+ SimTypeChar,
22
+ SimTypeWideChar,
23
+ SimTypePointer,
24
+ SimStruct,
25
+ SimType,
26
+ SimTypeBottom,
27
+ SimTypeArray,
28
+ SimTypeFunction,
29
+ SimTypeFloat,
30
+ SimTypeDouble,
31
+ TypeRef,
32
+ SimTypeNum,
33
+ SimTypeFixedSizeArray,
34
+ SimTypeLength,
35
+ SimTypeReg,
36
+ SimTypeInt128,
37
+ SimTypeInt256,
38
+ SimTypeInt512,
39
+ SimCppClass,
40
+ )
41
+ from angr.knowledge_plugins.functions import Function
42
+ from angr.sim_variable import (
43
+ SimVariable,
44
+ SimTemporaryVariable,
45
+ SimStackVariable,
46
+ SimMemoryVariable,
47
+ SimRegisterVariable,
48
+ )
49
+ from angr.utils.constants import is_alignment_mask
50
+ from angr.utils.library import get_cpp_function_name
51
+ from angr.utils.loader import is_in_readonly_segment, is_in_readonly_section
52
+ from angr.utils.types import unpack_typeref, unpack_pointer_and_array, dereference_simtype_by_lib
53
+ from angr.utils.strings import decode_utf16_string
54
+ from angr.analyses.decompiler.utils import structured_node_is_simple_return
55
+ from angr.analyses.decompiler.notes.deobfuscated_strings import DeobfuscatedStringsNote
56
+ from angr.errors import UnsupportedNodeTypeError, AngrRuntimeError
57
+ from angr.knowledge_plugins.cfg.memory_data import MemoryData, MemoryDataSort
58
+ from angr.analyses import Analysis, register_analysis
59
+ from angr.analyses.decompiler.region_identifier import MultiNode
60
+ from angr.analyses.decompiler.structuring.structurer_nodes import (
61
+ SequenceNode,
62
+ CodeNode,
63
+ ConditionNode,
64
+ ConditionalBreakNode,
65
+ LoopNode,
66
+ BreakNode,
67
+ SwitchCaseNode,
68
+ IncompleteSwitchCaseNode,
69
+ ContinueNode,
70
+ CascadingConditionNode,
71
+ )
72
+ from .base import (
73
+ BaseStructuredCodeGenerator,
74
+ InstructionMapping,
75
+ PositionMapping,
76
+ PositionMappingElement,
77
+ IdentType,
78
+ CConstantType,
79
+ )
80
+
81
+ if TYPE_CHECKING:
82
+ import archinfo
83
+ import angr
84
+ from angr.knowledge_plugins.variables.variable_manager import VariableManagerInternal
85
+
86
+
87
+ l = logging.getLogger(name=__name__)
88
+ l.addFilter(UniqueLogFilter())
89
+
90
+
91
+ INDENT_DELTA = 4
92
+
93
+
94
+ def qualifies_for_simple_cast(ty1, ty2):
95
+ # converting ty1 to ty2 - can this happen precisely?
96
+ # used to decide whether to add explicit typecasts instead of doing *(int*)&v1
97
+ return (
98
+ ty1.size == ty2.size
99
+ and isinstance(ty1, (SimTypeInt, SimTypeChar, SimTypeNum, SimTypePointer))
100
+ and isinstance(ty2, (SimTypeInt, SimTypeChar, SimTypeNum, SimTypePointer))
101
+ )
102
+
103
+
104
+ def qualifies_for_implicit_cast(ty1, ty2):
105
+ # converting ty1 to ty2 - can this happen without a cast?
106
+ # used to decide whether to omit typecasts from output during promotion
107
+ # this function need to answer the question:
108
+ # when does having a cast vs having an implicit promotion affect the result?
109
+ # the answer: I DON'T KNOW
110
+ if not isinstance(ty1, (SimTypeInt, SimTypeChar, SimTypeNum)) or not isinstance(
111
+ ty2, (SimTypeInt, SimTypeChar, SimTypeNum)
112
+ ):
113
+ return False
114
+
115
+ return ty1.size <= ty2.size if ty1.size is not None and ty2.size is not None else False
116
+
117
+
118
+ def extract_terms(expr: CExpression) -> tuple[int, list[tuple[int, CExpression]]]:
119
+ # handle unnecessary type casts
120
+ if isinstance(expr, CTypeCast):
121
+ expr = MakeTypecastsImplicit.collapse(expr.dst_type, expr.expr)
122
+ if (
123
+ isinstance(expr, CTypeCast)
124
+ and isinstance(expr.dst_type, SimTypeInt)
125
+ and isinstance(expr.src_type, SimTypeInt)
126
+ and expr.dst_type.size == expr.src_type.size
127
+ and expr.dst_type.signed != expr.src_type.signed
128
+ ):
129
+ # (unsigned int)(a + 60) ==> a + 60, assuming a + 60 is an int
130
+ expr = expr.expr
131
+
132
+ if isinstance(expr, CConstant):
133
+ return expr.value, []
134
+ # elif isinstance(expr, CUnaryOp) and expr.op == 'Minus'
135
+ if isinstance(expr, CBinaryOp) and expr.op == "Add":
136
+ c1, t1 = extract_terms(expr.lhs)
137
+ c2, t2 = extract_terms(expr.rhs)
138
+ return c1 + c2, t1 + t2
139
+ if isinstance(expr, CBinaryOp) and expr.op == "Sub":
140
+ c1, t1 = extract_terms(expr.lhs)
141
+ c2, t2 = extract_terms(expr.rhs)
142
+ return c1 - c2, t1 + [(-c, t) for c, t in t2]
143
+ if isinstance(expr, CBinaryOp) and expr.op == "Mul":
144
+ if isinstance(expr.lhs, CConstant):
145
+ c, t = extract_terms(expr.rhs)
146
+ return c * expr.lhs.value, [(c1 * expr.lhs.value, t1) for c1, t1 in t]
147
+ if isinstance(expr.rhs, CConstant):
148
+ c, t = extract_terms(expr.lhs)
149
+ return c * expr.rhs.value, [(c1 * expr.rhs.value, t1) for c1, t1 in t]
150
+ return 0, [(1, expr)]
151
+ if isinstance(expr, CBinaryOp) and expr.op == "Shl":
152
+ if isinstance(expr.rhs, CConstant):
153
+ c, t = extract_terms(expr.lhs)
154
+ return c << expr.rhs.value, [(c1 << expr.rhs.value, t1) for c1, t1 in t]
155
+ return 0, [(1, expr)]
156
+ return 0, [(1, expr)]
157
+
158
+
159
+ def is_machine_word_size_type(type_: SimType, arch: archinfo.Arch) -> bool:
160
+ return isinstance(type_, SimTypeReg) and type_.size == arch.bits
161
+
162
+
163
+ def guess_value_type(value: int, project: angr.Project) -> SimType | None:
164
+ if project.kb.functions.contains_addr(value):
165
+ # might be a function pointer
166
+ return SimTypePointer(SimTypeBottom(label="void")).with_arch(project.arch)
167
+ if value > 4096:
168
+ sec = project.loader.find_section_containing(value)
169
+ if sec is not None and sec.is_readable:
170
+ return SimTypePointer(SimTypeBottom(label="void")).with_arch(project.arch)
171
+ seg = project.loader.find_segment_containing(value)
172
+ if seg is not None and seg.is_readable:
173
+ return SimTypePointer(SimTypeBottom(label="void")).with_arch(project.arch)
174
+ return None
175
+
176
+
177
+ def type_equals(t0: SimType, t1: SimType) -> bool:
178
+ # special logic for C++ classes
179
+ if isinstance(t0, SimCppClass) and isinstance(t1, SimCppClass): # noqa: SIM102
180
+ # TODO: Use the information (class names, etc.) in types_stl
181
+ if {t1.name, t0.name} == {
182
+ "std::string",
183
+ "class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>",
184
+ }:
185
+ return True
186
+ return t0 == t1
187
+
188
+
189
+ def type_to_c_repr_chunks(ty: SimType, name=None, name_type=None, full=False, indent_str=""):
190
+ """
191
+ Helper generator function to turn a SimType into generated tuples of (C-string, AST node).
192
+ """
193
+ if isinstance(ty, SimStruct):
194
+ if full:
195
+ # struct def preamble
196
+ yield indent_str, None
197
+ if isinstance(ty, SimCppClass):
198
+ yield "class ", None
199
+ else:
200
+ yield "typedef struct ", None
201
+ yield ty.name, ty
202
+ yield " {\n", None
203
+
204
+ # each of the fields
205
+ # fields should be indented
206
+ new_indent_str = (
207
+ " " * 4
208
+ ) + indent_str # TODO: hardcoded as 4 character space indents, which is same as SimStruct.c_repr
209
+ for k, v in ty.fields.items():
210
+ yield new_indent_str, None
211
+ yield from type_to_c_repr_chunks(v, name=k, name_type=CStructFieldNameDef(k), full=False, indent_str="")
212
+ yield ";\n", None
213
+
214
+ # struct def postamble
215
+ yield "} ", None
216
+ yield ty.name, ty
217
+ yield ";\n\n", None
218
+
219
+ else:
220
+ assert name
221
+ assert name_type
222
+ yield indent_str, None
223
+ yield ty.name, ty
224
+ yield " ", None
225
+ if name:
226
+ yield name, name_type
227
+ elif isinstance(ty, SimType):
228
+ assert name
229
+ assert name_type
230
+ raw_type_str = ty.c_repr(name=name)
231
+ assert name in raw_type_str
232
+
233
+ type_pre, type_post = raw_type_str.split(name, 1)
234
+
235
+ if type_pre.endswith(" "):
236
+ type_pre_spaces = " " * (len(type_pre) - len(type_pre.rstrip(" ")))
237
+ type_pre = type_pre.rstrip(" ")
238
+ else:
239
+ type_pre_spaces = ""
240
+
241
+ yield indent_str, None
242
+ yield type_pre, ty
243
+ if type_pre_spaces:
244
+ yield type_pre_spaces, None
245
+ yield name, name_type
246
+ yield type_post, CArrayTypeLength(type_post)
247
+ # This case was used when generating externs, apparently there can be cases where the name is not known
248
+ elif ty is None:
249
+ assert name
250
+ assert name_type
251
+ yield "<missing-type> ", None
252
+ yield name, name_type
253
+ else:
254
+ assert False
255
+
256
+
257
+ #
258
+ # C Representation Classes
259
+ #
260
+
261
+
262
+ class CConstruct:
263
+ """
264
+ Represents a program construct in C.
265
+ Acts as the base class for all other representation constructions.
266
+ """
267
+
268
+ __slots__ = ("codegen", "idx", "tags")
269
+
270
+ def __init__(self, codegen, tags=None):
271
+ self.tags = tags or {}
272
+ self.codegen: StructuredCodeGenerator = codegen
273
+ self.idx = codegen.next_idx(self.__class__.__name__)
274
+
275
+ def c_repr(self, initial_pos=0, indent=0, pos_to_node=None, pos_to_addr=None, addr_to_pos=None):
276
+ """
277
+ Creates the C representation of the code and displays it by
278
+ constructing a large string. This function is called by each program function that needs to be decompiled.
279
+ The map_pos_to_node and map_pos_to_addr act as position maps for the location of each variable and statement to
280
+ be tracked for later GUI operations. The map_pos_to_addr also contains expressions that are nested inside of
281
+ statements.
282
+ """
283
+
284
+ pending_stmt_comments = dict(self.codegen.stmt_comments)
285
+ pending_expr_comments = dict(self.codegen.expr_comments)
286
+
287
+ def mapper(chunks):
288
+ # start all positions at beginning of document
289
+ pos = initial_pos
290
+
291
+ last_insn_addr = None
292
+
293
+ # track all variables so we can tell if this is a declaration or not
294
+ used_vars = set()
295
+
296
+ # get each string and object representation of the chunks
297
+ for s, obj in chunks:
298
+ # filter out anything that is not a statement or expression object
299
+ if isinstance(obj, (CStatement, CExpression)):
300
+ # only add statements/expressions that can be address tracked into map_pos_to_addr
301
+ if hasattr(obj, "tags") and obj.tags is not None and "ins_addr" in obj.tags:
302
+ if isinstance(obj, CVariable) and obj not in used_vars:
303
+ used_vars.add(obj)
304
+ else:
305
+ last_insn_addr = obj.tags["ins_addr"]
306
+
307
+ # all valid statements and expressions should be added to map_pos_to_addr and
308
+ # tracked for instruction mapping from disassembly
309
+ if pos_to_addr is not None:
310
+ pos_to_addr.add_mapping(pos, len(s), obj)
311
+ if addr_to_pos is not None:
312
+ addr_to_pos.add_mapping(obj.tags["ins_addr"], pos)
313
+
314
+ # add all variables, constants, and function calls to map_pos_to_node for highlighting
315
+ # add ops to pos_to_node but NOT ast_to_pos
316
+ if (
317
+ isinstance(
318
+ obj,
319
+ (
320
+ CVariable,
321
+ CConstant,
322
+ CStructField,
323
+ CIndexedVariable,
324
+ CVariableField,
325
+ CBinaryOp,
326
+ CUnaryOp,
327
+ CAssignment,
328
+ CFunctionCall,
329
+ CLabel,
330
+ ),
331
+ )
332
+ and pos_to_node is not None
333
+ ):
334
+ pos_to_node.add_mapping(pos, len(s), obj)
335
+
336
+ # add (), {}, [], and [20] to mapping for highlighting as well as the full functions name
337
+ elif isinstance(obj, (CClosingObject, CFunction, CArrayTypeLength, CStructFieldNameDef)):
338
+ if s is None:
339
+ continue
340
+
341
+ if pos_to_node is not None:
342
+ pos_to_node.add_mapping(pos, len(s), obj)
343
+
344
+ elif isinstance(obj, SimType):
345
+ if pos_to_node is not None:
346
+ if isinstance(obj, TypeRef):
347
+ pos_to_node.add_mapping(pos, len(s), obj.type)
348
+ else:
349
+ pos_to_node.add_mapping(pos, len(s), obj)
350
+
351
+ if s.endswith("\n"):
352
+ text = pending_stmt_comments.pop(last_insn_addr, None) if isinstance(last_insn_addr, int) else None
353
+ if text is not None:
354
+ todo = " // " + text
355
+ pos += len(s) - 1
356
+ yield s[:-1]
357
+ pos += len(todo)
358
+ yield todo
359
+ s = "\n"
360
+
361
+ pos += len(s)
362
+ yield s
363
+
364
+ if isinstance(obj, CExpression):
365
+ text = pending_expr_comments.pop(last_insn_addr, None) if isinstance(last_insn_addr, int) else None
366
+ if text is not None:
367
+ todo = " /*" + text + "*/ "
368
+ pos += len(todo)
369
+ yield todo
370
+
371
+ if pending_expr_comments or pending_stmt_comments:
372
+ yield "// Orphaned comments\n"
373
+ for text in pending_stmt_comments.values():
374
+ yield "// " + text + "\n"
375
+ for text in pending_expr_comments.values():
376
+ yield "/* " + text + "*/\n"
377
+
378
+ # A special note about this line:
379
+ # Polymorphism allows that the c_repr_chunks() call will be called
380
+ # by the CFunction class, which will then call each statement within it and construct
381
+ # the chunks that get printed in qccode_edit in angr-management.
382
+ return "".join(mapper(self.c_repr_chunks(indent)))
383
+
384
+ def c_repr_chunks(self, indent=0, asexpr=False):
385
+ raise NotImplementedError
386
+
387
+ @staticmethod
388
+ def indent_str(indent=0):
389
+ return " " * indent
390
+
391
+
392
+ class CFunction(CConstruct): # pylint:disable=abstract-method
393
+ """
394
+ Represents a function in C.
395
+ """
396
+
397
+ __slots__ = (
398
+ "addr",
399
+ "arg_list",
400
+ "demangled_name",
401
+ "functy",
402
+ "name",
403
+ "omit_header",
404
+ "show_demangled_name",
405
+ "statements",
406
+ "unified_local_vars",
407
+ "variable_manager",
408
+ "variables_in_use",
409
+ )
410
+
411
+ def __init__(
412
+ self,
413
+ addr,
414
+ name,
415
+ functy: SimTypeFunction,
416
+ arg_list: list[CVariable],
417
+ statements,
418
+ variables_in_use,
419
+ variable_manager,
420
+ demangled_name=None,
421
+ show_demangled_name=True,
422
+ omit_header=False,
423
+ **kwargs,
424
+ ):
425
+ super().__init__(**kwargs)
426
+
427
+ self.addr = addr
428
+ self.name = name
429
+ self.functy = functy
430
+ self.arg_list = arg_list
431
+ self.statements = statements
432
+ self.variables_in_use = variables_in_use
433
+ self.variable_manager: VariableManagerInternal = variable_manager
434
+ self.demangled_name = demangled_name
435
+ self.unified_local_vars: dict[SimVariable, set[tuple[CVariable, SimType]]] = {}
436
+ self.show_demangled_name = show_demangled_name
437
+ self.omit_header = omit_header
438
+
439
+ self.refresh()
440
+
441
+ def refresh(self):
442
+ self.unified_local_vars = self.get_unified_local_vars()
443
+
444
+ def get_unified_local_vars(self) -> dict[SimVariable, set[tuple[CVariable, SimType]]]:
445
+ unified_to_var_and_types: dict[SimVariable, set[tuple[CVariable, SimType]]] = defaultdict(set)
446
+
447
+ arg_set: set[SimVariable] = set()
448
+ for arg in self.arg_list:
449
+ # TODO: Handle CIndexedVariable
450
+ if isinstance(arg, CVariable):
451
+ if arg.unified_variable is not None:
452
+ arg_set.add(arg.unified_variable)
453
+ else:
454
+ arg_set.add(arg.variable)
455
+
456
+ # output each variable and its type
457
+ for var, cvar in self.variables_in_use.items():
458
+ if isinstance(var, SimMemoryVariable) and not isinstance(var, SimStackVariable):
459
+ # Skip all global variables
460
+ continue
461
+
462
+ if var in arg_set or cvar.unified_variable in arg_set:
463
+ continue
464
+
465
+ unified_var = self.variable_manager.unified_variable(var)
466
+ if unified_var is not None:
467
+ key = unified_var
468
+ var_type = self.variable_manager.get_variable_type(var) # FIXME
469
+ else:
470
+ key = var
471
+ var_type = self.variable_manager.get_variable_type(var)
472
+
473
+ if var_type is None:
474
+ var_type = SimTypeBottom().with_arch(self.codegen.project.arch)
475
+
476
+ unified_to_var_and_types[key].add((cvar, var_type))
477
+
478
+ return unified_to_var_and_types
479
+
480
+ def variable_list_repr_chunks(self, indent=0):
481
+ indent_str = self.indent_str(indent)
482
+
483
+ for variable in self.sort_local_vars(self.unified_local_vars):
484
+ cvar_and_vartypes = self.unified_local_vars[variable]
485
+
486
+ yield indent_str, None
487
+
488
+ # pick the first cvariable
489
+ # picking any cvariable is enough since highlighting works on the unified variable
490
+ try:
491
+ cvariable = next(iter(cvar_and_vartypes))[0]
492
+ except StopIteration:
493
+ # this should never happen, but pylint complains
494
+ continue
495
+
496
+ if variable.name:
497
+ name = variable.name
498
+ elif isinstance(variable, SimTemporaryVariable):
499
+ name = f"tmp_{variable.tmp_id}"
500
+ else:
501
+ name = str(variable)
502
+
503
+ # sort by the following:
504
+ # * if it's a a non-basic type
505
+ # * the number of occurrences
506
+ # * the repr of the type itself
507
+ # TODO: The type selection should actually happen during variable unification
508
+ vartypes = [x[1] for x in cvar_and_vartypes]
509
+ count = Counter(vartypes)
510
+ vartypes = sorted(
511
+ count.copy(),
512
+ key=lambda x, ct=count: (isinstance(x, (SimTypeChar, SimTypeInt, SimTypeFloat)), ct[x], repr(x)),
513
+ )
514
+
515
+ for i, var_type in enumerate(vartypes):
516
+ if i == 0:
517
+ yield from type_to_c_repr_chunks(var_type, name=name, name_type=cvariable)
518
+ yield "; // ", None
519
+ yield variable.loc_repr(self.codegen.project.arch), None
520
+ # multiple types
521
+ else:
522
+ if i == 1:
523
+ yield ", Other Possible Types: ", None
524
+ else:
525
+ yield ", ", None
526
+ if isinstance(var_type, SimType):
527
+ yield var_type.c_repr(), var_type
528
+ else:
529
+ yield str(var_type), var_type
530
+ yield "\n", None
531
+
532
+ if self.unified_local_vars:
533
+ yield "\n", None
534
+
535
+ def c_repr_chunks(self, indent=0, asexpr=False):
536
+ if self.omit_header:
537
+ yield from self.headerless_c_repr_chunks(indent=indent)
538
+ else:
539
+ yield from self.full_c_repr_chunks(indent=indent, asexpr=asexpr)
540
+
541
+ def headerless_c_repr_chunks(self, indent=0):
542
+ yield from self.statements.c_repr_chunks(indent=indent)
543
+ yield "\n", None
544
+
545
+ def full_c_repr_chunks(self, indent=0, asexpr=False):
546
+ indent_str = self.indent_str(indent)
547
+ if self.codegen.show_local_types:
548
+ local_types = [unpack_typeref(ty) for ty in self.variable_manager.types.iter_own()]
549
+ name_to_structtypes = {}
550
+ for ty in local_types:
551
+ if isinstance(ty, SimStruct):
552
+ name_to_structtypes[ty.name] = ty
553
+ for field in ty.fields.values():
554
+ if isinstance(field, SimTypePointer):
555
+ if isinstance(field.pts_to, (SimTypeArray, SimTypeFixedSizeArray)):
556
+ field = field.pts_to.elem_type
557
+ else:
558
+ field = field.pts_to
559
+ if isinstance(field, SimStruct) and field not in local_types:
560
+ if field.name and not field.fields and field.name in name_to_structtypes:
561
+ # we use SimStruct types with empty fields to refer to already defined struct types
562
+ # for example, see how struct _IO_marker is defined in sim_type.py
563
+ continue
564
+ if field.name:
565
+ name_to_structtypes[field.name] = field
566
+ local_types.append(field)
567
+
568
+ yield from type_to_c_repr_chunks(ty, full=True, indent_str=indent_str)
569
+
570
+ if self.codegen.show_externs and self.codegen.cexterns:
571
+ for v in sorted(self.codegen.cexterns, key=lambda v: str(v.variable.name)):
572
+ if v.variable not in self.variables_in_use:
573
+ continue
574
+ varname = v.c_repr() if v.type is None else v.variable.name
575
+ yield "extern ", None
576
+ if v.type is None:
577
+ yield "<unknown-type>", None
578
+ else:
579
+ yield from type_to_c_repr_chunks(v.type, name=varname, name_type=v, full=False)
580
+ yield ";\n", None
581
+ yield "\n", None
582
+
583
+ yield indent_str, None
584
+
585
+ # header comments (if they exist)
586
+ assert self.codegen.cfunc is not None and self.codegen.cfunc.addr is not None
587
+ header_comments = self.codegen.kb.comments.get(self.codegen.cfunc.addr, [])
588
+ if header_comments:
589
+ header_cmt = self._line_wrap_comment("".join(header_comments))
590
+ yield header_cmt, None
591
+
592
+ if self.codegen._func.is_plt:
593
+ yield "// attributes: PLT stub\n", None
594
+
595
+ # return type
596
+ assert self.functy.returnty is not None
597
+ yield self.functy.returnty.c_repr(name="").strip(" "), self.functy.returnty
598
+ yield " ", None
599
+ # function name
600
+ if self.demangled_name and self.show_demangled_name:
601
+ normalized_name = get_cpp_function_name(self.demangled_name)
602
+ else:
603
+ normalized_name = self.name
604
+ yield normalized_name, self
605
+ # argument list
606
+ paren = CClosingObject("(")
607
+ brace = CClosingObject("{")
608
+ yield "(", paren
609
+ for i, (arg_type, cvariable) in enumerate(zip(self.functy.args, self.arg_list)):
610
+ if i:
611
+ yield ", ", None
612
+
613
+ variable = cvariable.unified_variable or cvariable.variable
614
+ yield from type_to_c_repr_chunks(arg_type, name=variable.name, name_type=cvariable, full=False)
615
+
616
+ yield ")", paren
617
+ # function body
618
+ if self.codegen.braces_on_own_lines:
619
+ yield "\n", None
620
+ yield indent_str, None
621
+ else:
622
+ yield " ", None
623
+ yield "{", brace
624
+ yield "\n", None
625
+ yield from self.variable_list_repr_chunks(indent=indent + INDENT_DELTA)
626
+ yield from self.statements.c_repr_chunks(indent=indent + INDENT_DELTA)
627
+ yield indent_str, None
628
+ yield "}", brace
629
+ yield "\n", None
630
+
631
+ @staticmethod
632
+ def _line_wrap_comment(comment: str, width=80) -> str:
633
+ lines = comment.splitlines()
634
+ wrapped_cmt = ""
635
+
636
+ for line in lines:
637
+ if len(line) < width:
638
+ wrapped_cmt += line + "\n"
639
+ continue
640
+
641
+ for i, c in enumerate(line):
642
+ if i % width == 0 and i != 0:
643
+ wrapped_cmt += "\n"
644
+ wrapped_cmt += c
645
+
646
+ wrapped_cmt += "\n"
647
+
648
+ return "".join([f"// {line}\n" for line in wrapped_cmt.splitlines()])
649
+
650
+ @staticmethod
651
+ def sort_local_vars(local_vars: Iterable[SimVariable]) -> list[SimVariable]:
652
+ # Order:
653
+ # - SimRegisterVariable, ordered based on their identifiers
654
+ # - SimStackVariables, ordered based on their stack offsets
655
+ # - SimMemoryVariable (but not stack variables) - we should not have global variables anyway
656
+ reg_vars, stack_vars, mem_vars = [], [], []
657
+ for var in local_vars:
658
+ match var:
659
+ case SimRegisterVariable():
660
+ reg_vars.append(var)
661
+ case SimStackVariable():
662
+ stack_vars.append(var)
663
+ case SimMemoryVariable():
664
+ mem_vars.append(var)
665
+ case _:
666
+ pass
667
+
668
+ reg_vars = sorted(reg_vars, key=lambda v: v.ident)
669
+ stack_vars = sorted(stack_vars, key=lambda v: (v.offset, v.ident))
670
+ mem_vars = sorted(mem_vars, key=lambda v: (v.addr if isinstance(v.addr, int) else -1, v.ident))
671
+ return reg_vars + stack_vars + mem_vars
672
+
673
+
674
+ class CStatement(CConstruct): # pylint:disable=abstract-method
675
+ """
676
+ Represents a statement in C.
677
+ """
678
+
679
+ def __init__(self, tags=None, codegen=None):
680
+ super().__init__(codegen=codegen, tags=tags)
681
+
682
+
683
+ class CExpression(CConstruct):
684
+ """
685
+ Base class for C expressions.
686
+ """
687
+
688
+ __slots__ = ("_type", "collapsed")
689
+
690
+ def __init__(self, collapsed=False, tags=None, codegen=None):
691
+ super().__init__(codegen=codegen, tags=tags)
692
+ self._type = None
693
+ self.collapsed = collapsed
694
+
695
+ @property
696
+ def type(self):
697
+ raise NotImplementedError(f"Class {type(self)} does not implement type().")
698
+
699
+ def set_type(self, v):
700
+ self._type = v
701
+
702
+ @staticmethod
703
+ def _try_c_repr_chunks(expr):
704
+ if hasattr(expr, "c_repr_chunks"):
705
+ yield from expr.c_repr_chunks()
706
+ else:
707
+ yield str(expr), expr
708
+
709
+
710
+ class CStatements(CStatement):
711
+ """
712
+ Represents a sequence of statements in C.
713
+ """
714
+
715
+ __slots__ = (
716
+ "addr",
717
+ "statements",
718
+ )
719
+
720
+ def __init__(self, statements, addr=None, **kwargs):
721
+ super().__init__(**kwargs)
722
+
723
+ self.statements = statements
724
+ self.addr = addr
725
+
726
+ def c_repr_chunks(self, indent=0, asexpr=False):
727
+ indent_str = self.indent_str(indent)
728
+ if self.codegen.display_block_addrs:
729
+ yield indent_str, None
730
+ yield f"/* Block {hex(self.addr) if self.addr is not None else 'unknown'} */", None
731
+ yield "\n", None
732
+ for stmt in self.statements:
733
+ yield from stmt.c_repr_chunks(indent=indent, asexpr=asexpr)
734
+ if asexpr:
735
+ yield ", ", None
736
+
737
+
738
+ class CAILBlock(CStatement):
739
+ """
740
+ Represents a block of AIL statements.
741
+ """
742
+
743
+ __slots__ = ("block",)
744
+
745
+ def __init__(self, block, **kwargs):
746
+ super().__init__(**kwargs)
747
+
748
+ self.block = block
749
+
750
+ def c_repr_chunks(self, indent=0, asexpr=False):
751
+ indent_str = self.indent_str(indent=indent)
752
+ r = str(self.block)
753
+ for stmt in r.split("\n"):
754
+ yield indent_str, None
755
+ yield stmt, None
756
+ yield "\n", None
757
+
758
+
759
+ class CLoop(CStatement): # pylint:disable=abstract-method
760
+ """
761
+ Represents a loop in C.
762
+ """
763
+
764
+ __slots__ = ()
765
+
766
+
767
+ class CWhileLoop(CLoop):
768
+ """
769
+ Represents a while loop in C.
770
+ """
771
+
772
+ __slots__ = (
773
+ "body",
774
+ "condition",
775
+ )
776
+
777
+ def __init__(self, condition, body, **kwargs):
778
+ super().__init__(**kwargs)
779
+
780
+ self.condition = condition
781
+ self.body = body
782
+
783
+ def c_repr_chunks(self, indent=0, asexpr=False):
784
+ indent_str = self.indent_str(indent=indent)
785
+
786
+ yield indent_str, None
787
+ yield "while ", None
788
+ paren = CClosingObject("(")
789
+ brace = CClosingObject("{")
790
+ yield "(", paren
791
+ if self.condition is None:
792
+ yield "true", self
793
+ else:
794
+ yield from self.condition.c_repr_chunks()
795
+ yield ")", paren
796
+ if self.codegen.braces_on_own_lines:
797
+ yield "\n", None
798
+ yield indent_str, None
799
+ else:
800
+ yield " ", None
801
+ if self.body is None:
802
+ yield ";", None
803
+ yield "\n", None
804
+ else:
805
+ yield "{", brace
806
+ yield "\n", None
807
+ yield from self.body.c_repr_chunks(indent=indent + INDENT_DELTA)
808
+ yield indent_str, None
809
+ yield "}", brace
810
+ yield "\n", None
811
+
812
+
813
+ class CDoWhileLoop(CLoop):
814
+ """
815
+ Represents a do-while loop in C.
816
+ """
817
+
818
+ __slots__ = (
819
+ "body",
820
+ "condition",
821
+ )
822
+
823
+ def __init__(self, condition, body, **kwargs):
824
+ super().__init__(**kwargs)
825
+
826
+ self.condition = condition
827
+ self.body = body
828
+
829
+ def c_repr_chunks(self, indent=0, asexpr=False):
830
+ indent_str = self.indent_str(indent=indent)
831
+ brace = CClosingObject("{")
832
+ paren = CClosingObject("(")
833
+
834
+ yield indent_str, None
835
+ yield "do", self
836
+ if self.codegen.braces_on_own_lines:
837
+ yield "\n", None
838
+ yield indent_str, None
839
+ else:
840
+ yield " ", None
841
+ if self.body is not None:
842
+ yield "{", brace
843
+ yield "\n", None
844
+ yield from self.body.c_repr_chunks(indent=indent + INDENT_DELTA)
845
+ yield indent_str, None
846
+ yield "}", brace
847
+ else:
848
+ yield "{", brace
849
+ yield " ", None
850
+ yield "}", brace
851
+ yield " ", None
852
+ yield "while ", self
853
+ yield "(", paren
854
+ if self.condition is None:
855
+ yield "true", self
856
+ else:
857
+ yield from self.condition.c_repr_chunks()
858
+ yield ")", paren
859
+ yield ";\n", self
860
+
861
+
862
+ class CForLoop(CStatement):
863
+ """
864
+ Represents a for-loop in C.
865
+ """
866
+
867
+ __slots__ = (
868
+ "body",
869
+ "condition",
870
+ "initializer",
871
+ "iterator",
872
+ )
873
+
874
+ def __init__(self, initializer, condition, iterator, body, **kwargs):
875
+ super().__init__(**kwargs)
876
+
877
+ self.initializer = initializer
878
+ self.condition = condition
879
+ self.iterator = iterator
880
+ self.body = body
881
+
882
+ def c_repr_chunks(self, indent=0, asexpr=False):
883
+ indent_str = self.indent_str(indent=indent)
884
+ brace = CClosingObject("{")
885
+ paren = CClosingObject("(")
886
+
887
+ yield indent_str, None
888
+ yield "for ", self
889
+ yield "(", paren
890
+ if self.initializer is not None:
891
+ yield from self.initializer.c_repr_chunks(indent=0, asexpr=True)
892
+ yield "; ", None
893
+ if self.condition is not None:
894
+ yield from self.condition.c_repr_chunks(indent=0)
895
+ yield "; ", None
896
+ if self.iterator is not None:
897
+ yield from self.iterator.c_repr_chunks(indent=0, asexpr=True)
898
+ yield ")", paren
899
+
900
+ if self.body is not None:
901
+ if self.codegen.braces_on_own_lines:
902
+ yield "\n", None
903
+ yield indent_str, None
904
+ else:
905
+ yield " ", None
906
+
907
+ yield "{", brace
908
+ yield "\n", None
909
+ yield from self.body.c_repr_chunks(indent=indent + INDENT_DELTA)
910
+ yield indent_str, None
911
+ yield "}", brace
912
+ else:
913
+ yield ";", None
914
+ yield "\n", None
915
+
916
+
917
+ class CIfElse(CStatement):
918
+ """
919
+ Represents an if-else construct in C.
920
+ """
921
+
922
+ __slots__ = (
923
+ "condition_and_nodes",
924
+ "cstyle_ifs",
925
+ "else_node",
926
+ "simplify_else_scope",
927
+ )
928
+
929
+ def __init__(
930
+ self,
931
+ condition_and_nodes: list[tuple[CExpression, CStatement | None]],
932
+ else_node=None,
933
+ simplify_else_scope=False,
934
+ cstyle_ifs=True,
935
+ **kwargs,
936
+ ):
937
+ super().__init__(**kwargs)
938
+
939
+ self.condition_and_nodes = condition_and_nodes
940
+ self.else_node = else_node
941
+ self.simplify_else_scope = simplify_else_scope
942
+ self.cstyle_ifs = cstyle_ifs
943
+
944
+ if not self.condition_and_nodes:
945
+ raise ValueError("You must specify at least one condition")
946
+
947
+ @staticmethod
948
+ def _is_single_stmt_node(node):
949
+ return (isinstance(node, CStatements) and len(node.statements) == 1) or isinstance(
950
+ node, (CBreak, CContinue, CReturn, CGoto)
951
+ )
952
+
953
+ def c_repr_chunks(self, indent=0, asexpr=False):
954
+ indent_str = self.indent_str(indent=indent)
955
+ paren = CClosingObject("(")
956
+ brace = CClosingObject("{")
957
+
958
+ first_node = True
959
+ first_node_is_single_stmt_if = False
960
+ for condition, node in self.condition_and_nodes:
961
+ # omit braces in the event that you want c-style if-statements that have only a single statement
962
+ # and have no else scope or an else with also a single statement
963
+ omit_braces = (
964
+ self.cstyle_ifs
965
+ and first_node
966
+ and len(self.condition_and_nodes) == 1
967
+ # no else-if tree can exist
968
+ and self._is_single_stmt_node(node)
969
+ # no else, else is also single-stmt, or else will not exist after pass
970
+ and (self.else_node is None or self._is_single_stmt_node(self.else_node) or self.simplify_else_scope)
971
+ )
972
+
973
+ if first_node:
974
+ first_node = False
975
+ first_node_is_single_stmt_if = omit_braces
976
+ yield indent_str, None
977
+ else:
978
+ if self.codegen.braces_on_own_lines:
979
+ yield "\n", None
980
+ yield indent_str, None
981
+ else:
982
+ yield " ", None
983
+ yield "else ", self
984
+
985
+ yield "if ", self
986
+ yield "(", paren
987
+ yield from condition.c_repr_chunks()
988
+ yield ")", paren
989
+ if omit_braces:
990
+ yield "\n", None
991
+ else:
992
+ if self.codegen.braces_on_own_lines:
993
+ yield "\n", None
994
+ yield indent_str, None
995
+ else:
996
+ yield " ", None
997
+
998
+ yield "{", brace
999
+ yield "\n", None
1000
+
1001
+ if node is not None:
1002
+ yield from node.c_repr_chunks(indent=INDENT_DELTA + indent)
1003
+
1004
+ if not omit_braces:
1005
+ yield indent_str, None
1006
+ yield "}", brace
1007
+
1008
+ single_stmt_else = first_node_is_single_stmt_if and len(self.condition_and_nodes) == 1
1009
+ if self.else_node is not None:
1010
+ brace = CClosingObject("{")
1011
+ if self.simplify_else_scope:
1012
+ if not single_stmt_else:
1013
+ yield "\n", None
1014
+ yield from self.else_node.c_repr_chunks(indent=indent)
1015
+ else:
1016
+ if single_stmt_else:
1017
+ yield indent_str, None
1018
+ elif self.codegen.braces_on_own_lines:
1019
+ yield "\n", None
1020
+ yield indent_str, None
1021
+ else:
1022
+ yield " ", None
1023
+
1024
+ yield "else", self
1025
+ if self.codegen.braces_on_own_lines or single_stmt_else:
1026
+ yield "\n", None
1027
+ yield indent_str, None
1028
+ else:
1029
+ yield " ", None
1030
+
1031
+ if single_stmt_else:
1032
+ yield from self.else_node.c_repr_chunks(indent=INDENT_DELTA)
1033
+ else:
1034
+ yield "{", brace
1035
+ yield "\n", None
1036
+ yield from self.else_node.c_repr_chunks(indent=indent + INDENT_DELTA)
1037
+ yield indent_str, None
1038
+ yield "}", brace
1039
+
1040
+ if not first_node_is_single_stmt_if and not self.simplify_else_scope:
1041
+ yield "\n", None
1042
+
1043
+
1044
+ class CIfBreak(CStatement):
1045
+ """
1046
+ Represents an if-break statement in C.
1047
+ """
1048
+
1049
+ __slots__ = (
1050
+ "condition",
1051
+ "cstyle_ifs",
1052
+ )
1053
+
1054
+ def __init__(self, condition, cstyle_ifs=True, **kwargs):
1055
+ super().__init__(**kwargs)
1056
+
1057
+ self.condition = condition
1058
+ self.cstyle_ifs = cstyle_ifs
1059
+
1060
+ def c_repr_chunks(self, indent=0, asexpr=False):
1061
+ indent_str = self.indent_str(indent=indent)
1062
+ paren = CClosingObject("(")
1063
+ brace = CClosingObject("{")
1064
+
1065
+ yield indent_str, None
1066
+ yield "if ", self
1067
+ yield "(", paren
1068
+ yield from self.condition.c_repr_chunks()
1069
+ yield ")", paren
1070
+ if self.codegen.braces_on_own_lines or self.cstyle_ifs:
1071
+ yield "\n", None
1072
+ yield indent_str, None
1073
+ else:
1074
+ yield " ", None
1075
+ if self.cstyle_ifs:
1076
+ yield self.indent_str(indent=INDENT_DELTA), self
1077
+ yield "break;\n", self
1078
+ else:
1079
+ yield "{", brace
1080
+ yield "\n", None
1081
+ yield self.indent_str(indent=indent + INDENT_DELTA), self
1082
+ yield "break;\n", self
1083
+ yield indent_str, None
1084
+ yield "}", brace
1085
+ if not self.cstyle_ifs:
1086
+ yield "\n", None
1087
+
1088
+
1089
+ class CBreak(CStatement):
1090
+ """
1091
+ Represents a break statement in C.
1092
+ """
1093
+
1094
+ __slots__ = ()
1095
+
1096
+ def __init__(self, **kwargs):
1097
+ super().__init__(**kwargs)
1098
+
1099
+ def c_repr_chunks(self, indent=0, asexpr=False):
1100
+ indent_str = self.indent_str(indent=indent)
1101
+
1102
+ yield indent_str, None
1103
+ yield "break;\n", self
1104
+
1105
+
1106
+ class CContinue(CStatement):
1107
+ """
1108
+ Represents a continue statement in C.
1109
+ """
1110
+
1111
+ __slots__ = ()
1112
+
1113
+ def __init__(self, **kwargs):
1114
+ super().__init__(**kwargs)
1115
+
1116
+ def c_repr_chunks(self, indent=0, asexpr=False):
1117
+ indent_str = self.indent_str(indent=indent)
1118
+
1119
+ yield indent_str, None
1120
+ yield "continue;\n", self
1121
+
1122
+
1123
+ class CSwitchCase(CStatement):
1124
+ """
1125
+ Represents a switch-case statement in C.
1126
+ """
1127
+
1128
+ __slots__ = ("cases", "default", "switch")
1129
+
1130
+ def __init__(self, switch, cases, default, **kwargs):
1131
+ super().__init__(**kwargs)
1132
+
1133
+ self.switch = switch
1134
+ self.cases: list[tuple[int | tuple[int], CStatements]] = cases
1135
+ self.default = default
1136
+
1137
+ def c_repr_chunks(self, indent=0, asexpr=False):
1138
+ indent_str = self.indent_str(indent=indent)
1139
+ paren = CClosingObject("(")
1140
+ brace = CClosingObject("{")
1141
+
1142
+ yield indent_str, None
1143
+ yield "switch ", self
1144
+ yield "(", paren
1145
+ yield from self.switch.c_repr_chunks()
1146
+ yield ")", paren
1147
+ if self.codegen.braces_on_own_lines:
1148
+ yield "\n", None
1149
+ yield indent_str, None
1150
+ else:
1151
+ yield " ", None
1152
+ yield "{", brace
1153
+ yield "\n", None
1154
+
1155
+ # cases
1156
+ for id_or_ids, case in self.cases:
1157
+ yield indent_str, None
1158
+ if isinstance(id_or_ids, int):
1159
+ yield f"case {id_or_ids}", self
1160
+ yield ":\n", None
1161
+ else:
1162
+ for i, case_id in enumerate(id_or_ids):
1163
+ yield f"case {case_id}", self
1164
+ yield ":", None
1165
+ if i != len(id_or_ids) - 1:
1166
+ yield " ", None
1167
+ yield "\n", None
1168
+ yield from case.c_repr_chunks(indent=indent + INDENT_DELTA)
1169
+
1170
+ if self.default is not None:
1171
+ yield indent_str, None
1172
+ yield "default:\n", self
1173
+ yield from self.default.c_repr_chunks(indent=indent + INDENT_DELTA)
1174
+
1175
+ yield indent_str, None
1176
+ yield "}", brace
1177
+ yield "\n", None
1178
+
1179
+
1180
+ class CIncompleteSwitchCase(CStatement):
1181
+ """
1182
+ Represents an incomplete switch-case construct; this only appear in the decompilation output when switch-case
1183
+ structuring fails (for whatever reason).
1184
+ """
1185
+
1186
+ __slots__ = ("cases", "head")
1187
+
1188
+ def __init__(self, head, cases, **kwargs):
1189
+ super().__init__(**kwargs)
1190
+
1191
+ self.head = head
1192
+ self.cases: list[tuple[int, CStatements]] = cases
1193
+
1194
+ def c_repr_chunks(self, indent=0, asexpr=False):
1195
+ indent_str = self.indent_str(indent=indent)
1196
+ paren = CClosingObject("(")
1197
+ brace = CClosingObject("{")
1198
+
1199
+ yield from self.head.c_repr_chunks(indent=indent)
1200
+ yield "\n", None
1201
+ yield indent_str, None
1202
+ yield "switch ", self
1203
+ yield "(", paren
1204
+ yield "/* incomplete */", None
1205
+ yield ")", paren
1206
+ if self.codegen.braces_on_own_lines:
1207
+ yield "\n", None
1208
+ yield indent_str, None
1209
+ else:
1210
+ yield " ", None
1211
+ yield "{", brace
1212
+ yield "\n", None
1213
+
1214
+ # cases
1215
+ for case_addr, case in self.cases:
1216
+ yield indent_str, None
1217
+ yield f"case {case_addr:#x}", self
1218
+ yield ":\n", None
1219
+ yield from case.c_repr_chunks(indent=indent + INDENT_DELTA)
1220
+
1221
+ yield indent_str, None
1222
+ yield "}", brace
1223
+ yield "\n", None
1224
+
1225
+
1226
+ class CAssignment(CStatement):
1227
+ """
1228
+ a = b
1229
+ """
1230
+
1231
+ __slots__ = ("lhs", "rhs")
1232
+
1233
+ def __init__(self, lhs, rhs, **kwargs):
1234
+ super().__init__(**kwargs)
1235
+
1236
+ self.lhs = lhs
1237
+ self.rhs = rhs
1238
+
1239
+ def c_repr_chunks(self, indent=0, asexpr=False):
1240
+ indent_str = self.indent_str(indent=indent)
1241
+
1242
+ yield indent_str, None
1243
+ yield from CExpression._try_c_repr_chunks(self.lhs)
1244
+
1245
+ compound_assignment_ops = {
1246
+ "Add": "+",
1247
+ "Sub": "-",
1248
+ "Mul": "*",
1249
+ "Div": "/",
1250
+ "And": "&",
1251
+ "Xor": "^",
1252
+ "Or": "|",
1253
+ "Shr": ">>",
1254
+ "Shl": "<<",
1255
+ "Sar": ">>",
1256
+ }
1257
+ commutative_ops = {"Add", "Mul", "And", "Xor", "Or"}
1258
+
1259
+ compound_expr_rhs = None
1260
+ if (
1261
+ self.codegen.use_compound_assignments
1262
+ and isinstance(self.lhs, CVariable)
1263
+ and isinstance(self.rhs, CBinaryOp)
1264
+ and self.rhs.op in compound_assignment_ops
1265
+ and self.lhs.unified_variable is not None
1266
+ ):
1267
+ if isinstance(self.rhs.lhs, CVariable) and self.lhs.unified_variable is self.rhs.lhs.unified_variable:
1268
+ compound_expr_rhs = self.rhs.rhs
1269
+ elif (
1270
+ self.rhs.op in commutative_ops
1271
+ and isinstance(self.rhs.rhs, CVariable)
1272
+ and self.lhs.unified_variable is self.rhs.rhs.unified_variable
1273
+ ):
1274
+ compound_expr_rhs = self.rhs.lhs
1275
+
1276
+ if compound_expr_rhs is not None:
1277
+ # a = a + x => a += x
1278
+ # a = x + a => a += x
1279
+ yield f" {compound_assignment_ops[self.rhs.op]}= ", self
1280
+ yield from CExpression._try_c_repr_chunks(compound_expr_rhs)
1281
+ else:
1282
+ yield " = ", self
1283
+ yield from CExpression._try_c_repr_chunks(self.rhs)
1284
+ if not asexpr:
1285
+ yield ";\n", self
1286
+
1287
+
1288
+ class CFunctionCall(CStatement, CExpression):
1289
+ """
1290
+ func(arg0, arg1)
1291
+
1292
+ :ivar Function callee_func: The function getting called.
1293
+ :ivar is_expr: True if the return value of the function is written to ret_expr; Essentially, ret_expr = call().
1294
+ """
1295
+
1296
+ __slots__ = (
1297
+ "args",
1298
+ "callee_func",
1299
+ "callee_target",
1300
+ "is_expr",
1301
+ "prettify_thiscall",
1302
+ "ret_expr",
1303
+ "returning",
1304
+ "show_demangled_name",
1305
+ "show_disambiguated_name",
1306
+ )
1307
+
1308
+ def __init__(
1309
+ self,
1310
+ callee_target,
1311
+ callee_func,
1312
+ args,
1313
+ returning=True,
1314
+ ret_expr=None,
1315
+ is_expr: bool = False,
1316
+ show_demangled_name=True,
1317
+ show_disambiguated_name: bool = True,
1318
+ prettify_thiscall: bool = True,
1319
+ tags=None,
1320
+ codegen=None,
1321
+ **kwargs,
1322
+ ):
1323
+ super().__init__(tags=tags, codegen=codegen, **kwargs)
1324
+ CConstruct.__init__(self, tags=tags, codegen=codegen)
1325
+
1326
+ self.callee_target = callee_target
1327
+ self.callee_func: Function | None = callee_func
1328
+ self.args = args if args is not None else []
1329
+ self.returning = returning
1330
+ self.ret_expr = ret_expr
1331
+ self.is_expr = is_expr
1332
+ self.show_demangled_name = show_demangled_name
1333
+ self.show_disambiguated_name = show_disambiguated_name
1334
+ self.prettify_thiscall = prettify_thiscall
1335
+
1336
+ @property
1337
+ def prototype(self) -> SimTypeFunction | None: # TODO there should be a prototype for each callsite!
1338
+ if self.callee_func is not None and self.callee_func.prototype is not None:
1339
+ proto = self.callee_func.prototype
1340
+ if self.callee_func.prototype_libname is not None:
1341
+ # we need to deref the prototype in case it uses SimTypeRef internally
1342
+ proto = cast(SimTypeFunction, dereference_simtype_by_lib(proto, self.callee_func.prototype_libname))
1343
+ return proto
1344
+ returnty = SimTypeInt(signed=False)
1345
+ return SimTypeFunction([arg.type for arg in self.args], returnty).with_arch(self.codegen.project.arch)
1346
+
1347
+ @property
1348
+ def type(self):
1349
+ if self.is_expr:
1350
+ return (self.prototype.returnty if self.prototype is not None else None) or SimTypeInt(
1351
+ signed=False
1352
+ ).with_arch(self.codegen.project.arch)
1353
+ raise AngrRuntimeError("CFunctionCall.type should not be accessed if the function call is used as a statement.")
1354
+
1355
+ def _is_target_ambiguous(self, func_name: str) -> bool:
1356
+ """
1357
+ Check for call target name ambiguity.
1358
+ """
1359
+ caller, callee = self.codegen._func, self.callee_func
1360
+
1361
+ assert self.codegen._variables_in_use is not None
1362
+
1363
+ for var in self.codegen._variables_in_use.values():
1364
+ if func_name == var.name:
1365
+ return True
1366
+
1367
+ # FIXME: Handle name mangle
1368
+ if callee is not None:
1369
+ for func in self.codegen.kb.functions.get_by_name(callee.name):
1370
+ if func is not callee and (caller.binary is not callee.binary or func.binary is callee.binary):
1371
+ return True
1372
+
1373
+ return False
1374
+
1375
+ @staticmethod
1376
+ def _is_func_likely_method(func_name: str, rust: bool) -> bool:
1377
+ if "::" not in func_name:
1378
+ return False
1379
+ chunks = func_name.split("::")
1380
+ if rust and re.match(r"[A-Z][a-zA-Z0-9_]*", chunks[-2]) is None:
1381
+ # let's say that rust structs are always UpperCamelCase
1382
+ return False
1383
+ return re.match(r"[a-zA-Z_][a-zA-Z0-9_]*", chunks[-1]) is not None
1384
+
1385
+ def c_repr_chunks(self, indent=0, asexpr: bool = False):
1386
+ """
1387
+
1388
+ :param indent: Number of whitespace indentation characters.
1389
+ :param asexpr: True if this call is used as an expression (which means we will skip the generation of
1390
+ semicolons and newlines at the end of the call).
1391
+ """
1392
+ indent_str = self.indent_str(indent=indent)
1393
+ yield indent_str, None
1394
+
1395
+ if not self.is_expr and self.ret_expr is not None:
1396
+ yield from CExpression._try_c_repr_chunks(self.ret_expr)
1397
+ yield " = ", None
1398
+
1399
+ if self.callee_func is not None:
1400
+ if self.callee_func.demangled_name and self.show_demangled_name:
1401
+ func_name = get_cpp_function_name(self.callee_func.demangled_name)
1402
+ else:
1403
+ func_name = self.callee_func.name
1404
+ if (
1405
+ self.prettify_thiscall
1406
+ and self.args
1407
+ and self._is_func_likely_method(func_name, self.callee_func.is_rust_function())
1408
+ ):
1409
+ func_name = self.callee_func.short_name
1410
+ yield from self._c_repr_chunks_thiscall(func_name, asexpr=asexpr)
1411
+ return
1412
+ if self.show_disambiguated_name and self._is_target_ambiguous(func_name):
1413
+ func_name = self.callee_func.get_unambiguous_name(display_name=func_name)
1414
+
1415
+ yield func_name, self
1416
+ elif isinstance(self.callee_target, str):
1417
+ yield self.callee_target, self
1418
+ else:
1419
+ chunks = list(CExpression._try_c_repr_chunks(self.callee_target))
1420
+ if isinstance(self.callee_target, (CUnaryOp, CBinaryOp)):
1421
+ yield "(", None
1422
+ yield from chunks
1423
+ if isinstance(self.callee_target, (CUnaryOp, CBinaryOp)):
1424
+ yield ")", None
1425
+
1426
+ paren = CClosingObject("(")
1427
+ yield "(", paren
1428
+
1429
+ for i, arg in enumerate(self.args):
1430
+ if i:
1431
+ yield ", ", None
1432
+ yield from CExpression._try_c_repr_chunks(arg)
1433
+
1434
+ yield ")", paren
1435
+
1436
+ if not self.is_expr and not asexpr:
1437
+ yield ";", None
1438
+ if not self.returning:
1439
+ yield " /* do not return */", None
1440
+ yield "\n", None
1441
+
1442
+ def _c_repr_chunks_thiscall(self, func_name: str, asexpr: bool = False):
1443
+ # The first argument is the `this` pointer
1444
+ assert self.args
1445
+ this_ref = self.args[0]
1446
+ if isinstance(this_ref, CUnaryOp) and this_ref.op == "Reference":
1447
+ yield from CExpression._try_c_repr_chunks(this_ref.operand)
1448
+ else:
1449
+ yield from CExpression._try_c_repr_chunks(this_ref)
1450
+
1451
+ if func_name != "<ctor>":
1452
+ yield ".", None
1453
+ yield func_name, self
1454
+
1455
+ # the remaining arguments
1456
+ paren = CClosingObject("(")
1457
+ yield "(", paren
1458
+
1459
+ for i, arg in enumerate(self.args):
1460
+ if i == 0:
1461
+ continue
1462
+ if i > 1:
1463
+ yield ", ", None
1464
+ yield from CExpression._try_c_repr_chunks(arg)
1465
+
1466
+ yield ")", paren
1467
+
1468
+ if not self.is_expr and not asexpr:
1469
+ yield ";", None
1470
+ if not self.returning:
1471
+ yield " /* do not return */", None
1472
+ yield "\n", None
1473
+
1474
+
1475
+ class CReturn(CStatement):
1476
+ __slots__ = ("retval",)
1477
+
1478
+ def __init__(self, retval, **kwargs):
1479
+ super().__init__(**kwargs)
1480
+
1481
+ self.retval = retval
1482
+
1483
+ def c_repr_chunks(self, indent=0, asexpr=False):
1484
+ indent_str = self.indent_str(indent=indent)
1485
+
1486
+ if not self.retval:
1487
+ yield indent_str, None
1488
+ yield "return;\n", self
1489
+ else:
1490
+ yield indent_str, None
1491
+ yield "return ", self
1492
+ yield from self.retval.c_repr_chunks()
1493
+ yield ";\n", self
1494
+
1495
+
1496
+ class CGoto(CStatement):
1497
+ __slots__ = (
1498
+ "target",
1499
+ "target_idx",
1500
+ )
1501
+
1502
+ def __init__(self, target, target_idx, **kwargs):
1503
+ super().__init__(**kwargs)
1504
+
1505
+ if isinstance(target, CConstant):
1506
+ # unpack target
1507
+ target = target.value
1508
+
1509
+ self.target: int | CExpression = target
1510
+ self.target_idx = target_idx
1511
+
1512
+ def c_repr_chunks(self, indent=0, asexpr=False):
1513
+ indent_str = self.indent_str(indent=indent)
1514
+ lbl = None
1515
+ if self.codegen is not None and isinstance(self.target, int):
1516
+ lbl = self.codegen.map_addr_to_label.get((self.target, self.target_idx))
1517
+
1518
+ yield indent_str, None
1519
+ if self.codegen.comment_gotos:
1520
+ yield "/* ", None
1521
+ yield "goto ", self
1522
+ if lbl is None:
1523
+ if isinstance(self.target, int):
1524
+ yield f"LABEL_{self.target:#x}", None
1525
+ else:
1526
+ yield from self.target.c_repr_chunks()
1527
+ else:
1528
+ yield lbl.name, lbl
1529
+ yield ";", self
1530
+ if self.codegen.comment_gotos:
1531
+ yield " */", None
1532
+ yield "\n", None
1533
+
1534
+
1535
+ class CUnsupportedStatement(CStatement):
1536
+ """
1537
+ A wrapper for unsupported AIL statement.
1538
+ """
1539
+
1540
+ __slots__ = ("stmt",)
1541
+
1542
+ def __init__(self, stmt, **kwargs):
1543
+ super().__init__(**kwargs)
1544
+
1545
+ self.stmt = stmt
1546
+
1547
+ def c_repr_chunks(self, indent=0, asexpr=False):
1548
+ indent_str = self.indent_str(indent=indent)
1549
+
1550
+ yield indent_str, None
1551
+ yield str(self.stmt), None
1552
+ yield "\n", None
1553
+
1554
+
1555
+ class CDirtyStatement(CExpression):
1556
+ __slots__ = ("dirty",)
1557
+
1558
+ def __init__(self, dirty: CDirtyExpression, **kwargs):
1559
+ super().__init__(**kwargs)
1560
+ self.dirty = dirty
1561
+
1562
+ @property
1563
+ def type(self):
1564
+ return SimTypeInt().with_arch(self.codegen.project.arch)
1565
+
1566
+ def c_repr_chunks(self, indent=0, asexpr=False):
1567
+ indent_str = self.indent_str(indent=indent)
1568
+
1569
+ yield indent_str, None
1570
+ yield from self.dirty.c_repr_chunks()
1571
+ yield "\n", None
1572
+
1573
+
1574
+ class CLabel(CStatement):
1575
+ """
1576
+ Represents a label in C code.
1577
+ """
1578
+
1579
+ __slots__ = ("name",)
1580
+
1581
+ def __init__(self, name: str, **kwargs):
1582
+ super().__init__(**kwargs)
1583
+ self.name = name
1584
+
1585
+ def c_repr_chunks(self, indent=0, asexpr=False):
1586
+ yield self.name, self
1587
+ yield ":", None
1588
+ yield "\n", None
1589
+
1590
+
1591
+ class CStructField(CExpression):
1592
+ __slots__ = (
1593
+ "field",
1594
+ "offset",
1595
+ "struct_type",
1596
+ )
1597
+
1598
+ def __init__(self, struct_type: SimStruct, offset, field, **kwargs):
1599
+ super().__init__(**kwargs)
1600
+
1601
+ self.struct_type = struct_type
1602
+ self.offset = offset
1603
+ self.field = field
1604
+
1605
+ @property
1606
+ def type(self):
1607
+ return self.struct_type.fields[self.field]
1608
+
1609
+ def c_repr_chunks(self, indent=0, asexpr=False):
1610
+ if self.collapsed:
1611
+ yield "...", self
1612
+ return
1613
+ yield str(self.field), self
1614
+
1615
+
1616
+ class CFakeVariable(CExpression):
1617
+ """
1618
+ An uninterpreted name to display in the decompilation output. Pretty much always represents an error?
1619
+ """
1620
+
1621
+ __slots__ = ("name",)
1622
+
1623
+ def __init__(self, name: str, ty: SimType, **kwargs):
1624
+ super().__init__(**kwargs)
1625
+ self.name = name
1626
+ self._type = ty.with_arch(self.codegen.project.arch)
1627
+
1628
+ @property
1629
+ def type(self):
1630
+ return self._type
1631
+
1632
+ def c_repr_chunks(self, indent=0, asexpr=False):
1633
+ yield self.name, self
1634
+
1635
+
1636
+ class CVariable(CExpression):
1637
+ """
1638
+ CVariable represents access to a variable with the specified type (`variable_type`).
1639
+
1640
+ `variable` must be a SimVariable.
1641
+ """
1642
+
1643
+ __slots__ = (
1644
+ "unified_variable",
1645
+ "variable",
1646
+ "variable_type",
1647
+ "vvar_id",
1648
+ )
1649
+
1650
+ def __init__(self, variable: SimVariable, unified_variable=None, variable_type=None, vvar_id=None, **kwargs):
1651
+ super().__init__(**kwargs)
1652
+
1653
+ self.variable: SimVariable = variable
1654
+ self.unified_variable: SimVariable | None = unified_variable
1655
+ self.variable_type: SimType | None = (
1656
+ variable_type.with_arch(self.codegen.project.arch) if variable_type is not None else None
1657
+ )
1658
+ self.vvar_id = vvar_id
1659
+
1660
+ @property
1661
+ def type(self):
1662
+ return self.variable_type
1663
+
1664
+ @property
1665
+ def name(self):
1666
+ v = self.variable if self.unified_variable is None else self.unified_variable
1667
+
1668
+ if v.name:
1669
+ return v.name
1670
+ if isinstance(v, SimTemporaryVariable):
1671
+ return f"tmp_{v.tmp_id}"
1672
+ return str(v)
1673
+
1674
+ def c_repr_chunks(self, indent=0, asexpr=False):
1675
+ yield self.name, self
1676
+ if self.codegen.display_vvar_ids:
1677
+ yield f"<vvar_{self.vvar_id}>", self
1678
+
1679
+
1680
+ class CIndexedVariable(CExpression):
1681
+ """
1682
+ Represent a variable (an array) that is indexed.
1683
+ """
1684
+
1685
+ def __init__(self, variable: CExpression, index: CExpression, variable_type=None, **kwargs):
1686
+ super().__init__(**kwargs)
1687
+ self.variable = variable
1688
+ self.index: CExpression = index
1689
+ self._type = variable_type
1690
+
1691
+ if self._type is None and self.variable.type is not None:
1692
+ u = unpack_typeref(self.variable.type)
1693
+ if isinstance(u, SimTypePointer):
1694
+ # special case: (&array)[x]
1695
+ u = u.pts_to.elem_type if isinstance(u.pts_to, (SimTypeArray, SimTypeFixedSizeArray)) else u.pts_to
1696
+ u = unpack_typeref(u)
1697
+ elif isinstance(u, (SimTypeArray, SimTypeFixedSizeArray)):
1698
+ u = u.elem_type
1699
+ u = unpack_typeref(u)
1700
+ else:
1701
+ u = None # this should REALLY be an assert false
1702
+ self._type = u
1703
+
1704
+ @property
1705
+ def type(self):
1706
+ return self._type
1707
+
1708
+ def c_repr_chunks(self, indent=0, asexpr=False):
1709
+ if self.collapsed:
1710
+ yield "...", self
1711
+ return
1712
+
1713
+ bracket = CClosingObject("[")
1714
+ if not isinstance(self.variable, (CVariable, CVariableField)):
1715
+ yield "(", None
1716
+ yield from self.variable.c_repr_chunks()
1717
+ if not isinstance(self.variable, (CVariable, CVariableField)):
1718
+ yield ")", None
1719
+ yield "[", bracket
1720
+ yield from CExpression._try_c_repr_chunks(self.index)
1721
+ yield "]", bracket
1722
+
1723
+
1724
+ class CVariableField(CExpression):
1725
+ """
1726
+ Represent a field of a variable.
1727
+ """
1728
+
1729
+ def __init__(self, variable: CExpression, field: CStructField, var_is_ptr: bool = False, **kwargs):
1730
+ super().__init__(**kwargs)
1731
+ self.variable = variable
1732
+ self.field = field
1733
+ self.var_is_ptr = var_is_ptr
1734
+
1735
+ @property
1736
+ def type(self):
1737
+ return self.field.type
1738
+
1739
+ def c_repr_chunks(self, indent=0, asexpr=False):
1740
+ if self.collapsed:
1741
+ yield "...", self
1742
+ return
1743
+ yield from self.variable.c_repr_chunks()
1744
+ if self.var_is_ptr:
1745
+ yield "->", self
1746
+ else:
1747
+ yield ".", self
1748
+ yield from self.field.c_repr_chunks()
1749
+
1750
+
1751
+ class CUnaryOp(CExpression):
1752
+ """
1753
+ Unary operations.
1754
+ """
1755
+
1756
+ __slots__ = (
1757
+ "op",
1758
+ "operand",
1759
+ )
1760
+
1761
+ def __init__(self, op, operand: CExpression, **kwargs):
1762
+ super().__init__(**kwargs)
1763
+
1764
+ self.op = op
1765
+ self.operand = operand
1766
+
1767
+ if operand.type is not None:
1768
+ var_type = unpack_typeref(operand.type)
1769
+ if op == "Reference":
1770
+ self._type = SimTypePointer(var_type).with_arch(self.codegen.project.arch)
1771
+ elif op == "Dereference":
1772
+ if isinstance(var_type, SimTypePointer):
1773
+ self._type = unpack_typeref(var_type.pts_to)
1774
+ elif isinstance(var_type, (SimTypeArray, SimTypeFixedSizeArray)):
1775
+ self._type = unpack_typeref(var_type.elem_type)
1776
+
1777
+ @property
1778
+ def type(self):
1779
+ if self._type is None and self.operand is not None and hasattr(self.operand, "type"):
1780
+ self._type = self.operand.type
1781
+ return self._type
1782
+
1783
+ def c_repr_chunks(self, indent=0, asexpr=False):
1784
+ if self.collapsed:
1785
+ yield "...", self
1786
+ return
1787
+
1788
+ OP_MAP = {
1789
+ "Not": self._c_repr_chunks_not,
1790
+ "Neg": self._c_repr_chunks_neg,
1791
+ "BitwiseNeg": self._c_repr_chunks_bitwiseneg,
1792
+ "Reference": self._c_repr_chunks_reference,
1793
+ "Dereference": self._c_repr_chunks_dereference,
1794
+ "Clz": self._c_repr_chunks_clz,
1795
+ }
1796
+
1797
+ handler = OP_MAP.get(self.op, None)
1798
+ if handler is not None:
1799
+ yield from handler()
1800
+ else:
1801
+ yield f"UnaryOp {self.op}", self
1802
+
1803
+ #
1804
+ # Handlers
1805
+ #
1806
+
1807
+ def _c_repr_chunks_not(self):
1808
+ paren = CClosingObject("(")
1809
+ yield "!", self
1810
+ yield "(", paren
1811
+ yield from CExpression._try_c_repr_chunks(self.operand)
1812
+ yield ")", paren
1813
+
1814
+ def _c_repr_chunks_bitwiseneg(self):
1815
+ paren = CClosingObject("(")
1816
+ yield "~", self
1817
+ yield "(", paren
1818
+ yield from CExpression._try_c_repr_chunks(self.operand)
1819
+ yield ")", paren
1820
+
1821
+ def _c_repr_chunks_neg(self):
1822
+ paren = CClosingObject("(")
1823
+ yield "-", self
1824
+ yield "(", paren
1825
+ yield from CExpression._try_c_repr_chunks(self.operand)
1826
+ yield ")", paren
1827
+
1828
+ def _c_repr_chunks_reference(self):
1829
+ yield "&", self
1830
+ yield from CExpression._try_c_repr_chunks(self.operand)
1831
+
1832
+ def _c_repr_chunks_dereference(self):
1833
+ paren = CClosingObject("(")
1834
+ yield "*", self
1835
+ yield "(", paren
1836
+ yield from CExpression._try_c_repr_chunks(self.operand)
1837
+ yield ")", paren
1838
+
1839
+ def _c_repr_chunks_clz(self):
1840
+ paren = CClosingObject("(")
1841
+ yield "Clz", self
1842
+ yield "(", paren
1843
+ yield from CExpression._try_c_repr_chunks(self.operand)
1844
+ yield ")", paren
1845
+
1846
+
1847
+ class CBinaryOp(CExpression):
1848
+ """
1849
+ Binary operations.
1850
+ """
1851
+
1852
+ __slots__ = ("_cstyle_null_cmp", "common_type", "lhs", "op", "rhs")
1853
+
1854
+ def __init__(self, op, lhs, rhs, **kwargs):
1855
+ super().__init__(**kwargs)
1856
+
1857
+ self.op = op
1858
+ self.lhs = lhs
1859
+ self.rhs = rhs
1860
+ self._cstyle_null_cmp = self.codegen.cstyle_null_cmp
1861
+
1862
+ self.common_type = self.compute_common_type(self.op, self.lhs.type, self.rhs.type)
1863
+ if self.op.startswith("Cmp"):
1864
+ self._type = SimTypeChar().with_arch(self.codegen.project.arch)
1865
+ else:
1866
+ self._type = self.common_type
1867
+
1868
+ @staticmethod
1869
+ def compute_common_type(op: str, lhs_ty: SimType, rhs_ty: SimType) -> SimType:
1870
+ # C spec https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf 6.3.1.8 Usual arithmetic conversions
1871
+ rhs_ptr = isinstance(rhs_ty, SimTypePointer)
1872
+ lhs_ptr = isinstance(lhs_ty, SimTypePointer)
1873
+ rhs_cls = isinstance(unpack_typeref(rhs_ty), SimCppClass)
1874
+ lhs_cls = isinstance(unpack_typeref(lhs_ty), SimCppClass)
1875
+
1876
+ if lhs_cls:
1877
+ return lhs_ty
1878
+ if rhs_cls:
1879
+ return rhs_ty
1880
+
1881
+ if op in ("Add", "Sub"):
1882
+ if lhs_ptr and rhs_ptr:
1883
+ return SimTypeLength().with_arch(rhs_ty._arch)
1884
+ if lhs_ptr:
1885
+ return lhs_ty
1886
+ if rhs_ptr:
1887
+ return rhs_ty
1888
+
1889
+ if lhs_ptr or rhs_ptr:
1890
+ # uh oh!
1891
+ return SimTypeLength().with_arch(rhs_ty._arch)
1892
+
1893
+ if lhs_ty == rhs_ty:
1894
+ return lhs_ty
1895
+
1896
+ lhs_signed = getattr(lhs_ty, "signed", None)
1897
+ rhs_signed = getattr(rhs_ty, "signed", None)
1898
+ # uhhhhhhhhhh idk
1899
+ if lhs_signed is None:
1900
+ return lhs_ty
1901
+ if rhs_signed is None:
1902
+ return rhs_ty
1903
+
1904
+ if lhs_signed == rhs_signed:
1905
+ if lhs_ty.size > rhs_ty.size:
1906
+ return lhs_ty
1907
+ return rhs_ty
1908
+
1909
+ if lhs_signed:
1910
+ signed_ty = lhs_ty
1911
+ unsigned_ty = rhs_ty
1912
+ else:
1913
+ signed_ty = rhs_ty
1914
+ unsigned_ty = lhs_ty
1915
+
1916
+ if unsigned_ty.size >= signed_ty.size:
1917
+ return unsigned_ty
1918
+ if signed_ty.size > unsigned_ty.size:
1919
+ return signed_ty
1920
+ # uh oh!!
1921
+ return signed_ty
1922
+
1923
+ @property
1924
+ def type(self):
1925
+ return self._type
1926
+
1927
+ @property
1928
+ def op_precedence(self):
1929
+ precedence_list = [
1930
+ # lowest precedence
1931
+ ["Concat"],
1932
+ ["LogicalOr"],
1933
+ ["LogicalXor"],
1934
+ ["LogicalAnd"],
1935
+ ["Or"],
1936
+ ["Xor"],
1937
+ ["And"],
1938
+ ["CmpEQ", "CmpNE"],
1939
+ ["CmpLE", "CmpLT", "CmpGT", "CmpGE"],
1940
+ ["Shl", "Shr", "Sar"],
1941
+ ["Add", "Sub"],
1942
+ ["Mul", "Div"],
1943
+ ["SBorrow", "SCarry", "Carry"],
1944
+ # highest precedence
1945
+ ]
1946
+ for i, sublist in enumerate(precedence_list):
1947
+ if self.op in sublist:
1948
+ return i
1949
+ return len(precedence_list)
1950
+
1951
+ def c_repr_chunks(self, indent=0, asexpr=False):
1952
+ if self.collapsed:
1953
+ yield "...", self
1954
+ return
1955
+
1956
+ OP_MAP = {
1957
+ "Add": self._c_repr_chunks_add,
1958
+ "Sub": self._c_repr_chunks_sub,
1959
+ "Mul": self._c_repr_chunks_mul,
1960
+ "Mull": self._c_repr_chunks_mull,
1961
+ "Div": self._c_repr_chunks_div,
1962
+ "Mod": self._c_repr_chunks_mod,
1963
+ "And": self._c_repr_chunks_and,
1964
+ "Xor": self._c_repr_chunks_xor,
1965
+ "Or": self._c_repr_chunks_or,
1966
+ "Shr": self._c_repr_chunks_shr,
1967
+ "Shl": self._c_repr_chunks_shl,
1968
+ "Sar": self._c_repr_chunks_sar,
1969
+ "LogicalAnd": self._c_repr_chunks_logicaland,
1970
+ "LogicalOr": self._c_repr_chunks_logicalor,
1971
+ "LogicalXor": self._c_repr_chunks_logicalxor,
1972
+ "CmpLE": self._c_repr_chunks_cmple,
1973
+ "CmpLEs": self._c_repr_chunks_cmple,
1974
+ "CmpLT": self._c_repr_chunks_cmplt,
1975
+ "CmpLTs": self._c_repr_chunks_cmplt,
1976
+ "CmpGT": self._c_repr_chunks_cmpgt,
1977
+ "CmpGTs": self._c_repr_chunks_cmpgt,
1978
+ "CmpGE": self._c_repr_chunks_cmpge,
1979
+ "CmpGEs": self._c_repr_chunks_cmpge,
1980
+ "CmpEQ": self._c_repr_chunks_cmpeq,
1981
+ "CmpNE": self._c_repr_chunks_cmpne,
1982
+ "Concat": self._c_repr_chunks_concat,
1983
+ "Rol": self._c_repr_chunks_rol,
1984
+ "Ror": self._c_repr_chunks_ror,
1985
+ }
1986
+
1987
+ handler = OP_MAP.get(self.op, None)
1988
+ if handler is not None:
1989
+ yield from handler()
1990
+ else:
1991
+ yield from self._c_repr_chunks_opfirst(self.op)
1992
+
1993
+ def _has_const_null_rhs(self) -> bool:
1994
+ return isinstance(self.rhs, CConstant) and self.rhs.value == 0
1995
+
1996
+ #
1997
+ # Handlers
1998
+ #
1999
+
2000
+ def _c_repr_chunks(self, op):
2001
+ skip_op_and_rhs = False
2002
+ if self._cstyle_null_cmp and self._has_const_null_rhs():
2003
+ if self.op == "CmpEQ":
2004
+ skip_op_and_rhs = True
2005
+ yield "!", None
2006
+ elif self.op == "CmpNE":
2007
+ skip_op_and_rhs = True
2008
+ # lhs
2009
+ if isinstance(self.lhs, CBinaryOp) and self.op_precedence > self.lhs.op_precedence:
2010
+ paren = CClosingObject("(")
2011
+ yield "(", paren
2012
+ yield from self._try_c_repr_chunks(self.lhs)
2013
+ yield ")", paren
2014
+ else:
2015
+ yield from self._try_c_repr_chunks(self.lhs)
2016
+
2017
+ if not skip_op_and_rhs:
2018
+ # operator
2019
+ yield op, self
2020
+ # rhs
2021
+ if isinstance(self.rhs, CBinaryOp) and self.op_precedence > self.rhs.op_precedence - (
2022
+ 1 if self.op in ["Sub", "Div"] else 0
2023
+ ):
2024
+ paren = CClosingObject("(")
2025
+ yield "(", paren
2026
+ yield from self._try_c_repr_chunks(self.rhs)
2027
+ yield ")", paren
2028
+ else:
2029
+ yield from self._try_c_repr_chunks(self.rhs)
2030
+
2031
+ def _c_repr_chunks_opfirst(self, op):
2032
+ yield op, self
2033
+ paren = CClosingObject("(")
2034
+ yield "(", paren
2035
+ yield from self._try_c_repr_chunks(self.lhs)
2036
+ yield ", ", None
2037
+ yield from self._try_c_repr_chunks(self.rhs)
2038
+ yield ")", paren
2039
+
2040
+ def _c_repr_chunks_add(self):
2041
+ yield from self._c_repr_chunks(" + ")
2042
+
2043
+ def _c_repr_chunks_sub(self):
2044
+ yield from self._c_repr_chunks(" - ")
2045
+
2046
+ def _c_repr_chunks_mul(self):
2047
+ yield from self._c_repr_chunks(" * ")
2048
+
2049
+ def _c_repr_chunks_mull(self):
2050
+ yield from self._c_repr_chunks(" * ")
2051
+
2052
+ def _c_repr_chunks_div(self):
2053
+ yield from self._c_repr_chunks(" / ")
2054
+
2055
+ def _c_repr_chunks_divmod(self):
2056
+ yield from self._c_repr_chunks(" /m ")
2057
+
2058
+ def _c_repr_chunks_mod(self):
2059
+ yield from self._c_repr_chunks(" % ")
2060
+
2061
+ def _c_repr_chunks_and(self):
2062
+ yield from self._c_repr_chunks(" & ")
2063
+
2064
+ def _c_repr_chunks_xor(self):
2065
+ yield from self._c_repr_chunks(" ^ ")
2066
+
2067
+ def _c_repr_chunks_or(self):
2068
+ yield from self._c_repr_chunks(" | ")
2069
+
2070
+ def _c_repr_chunks_shr(self):
2071
+ yield from self._c_repr_chunks(" >> ")
2072
+
2073
+ def _c_repr_chunks_shl(self):
2074
+ yield from self._c_repr_chunks(" << ")
2075
+
2076
+ def _c_repr_chunks_sar(self):
2077
+ yield from self._c_repr_chunks(" >> ")
2078
+
2079
+ def _c_repr_chunks_logicaland(self):
2080
+ yield from self._c_repr_chunks(" && ")
2081
+
2082
+ def _c_repr_chunks_logicalor(self):
2083
+ yield from self._c_repr_chunks(" || ")
2084
+
2085
+ def _c_repr_chunks_logicalxor(self):
2086
+ yield from self._c_repr_chunks(" ^ ")
2087
+
2088
+ def _c_repr_chunks_cmple(self):
2089
+ yield from self._c_repr_chunks(" <= ")
2090
+
2091
+ def _c_repr_chunks_cmplt(self):
2092
+ yield from self._c_repr_chunks(" < ")
2093
+
2094
+ def _c_repr_chunks_cmpgt(self):
2095
+ yield from self._c_repr_chunks(" > ")
2096
+
2097
+ def _c_repr_chunks_cmpge(self):
2098
+ yield from self._c_repr_chunks(" >= ")
2099
+
2100
+ def _c_repr_chunks_cmpeq(self):
2101
+ yield from self._c_repr_chunks(" == ")
2102
+
2103
+ def _c_repr_chunks_cmpne(self):
2104
+ yield from self._c_repr_chunks(" != ")
2105
+
2106
+ def _c_repr_chunks_concat(self):
2107
+ yield from self._c_repr_chunks(" CONCAT ")
2108
+
2109
+ def _c_repr_chunks_rol(self):
2110
+ yield "__ROL__", self
2111
+ paren = CClosingObject("(")
2112
+ yield "(", paren
2113
+ yield from self._try_c_repr_chunks(self.lhs)
2114
+ yield ", ", None
2115
+ yield from self._try_c_repr_chunks(self.rhs)
2116
+ yield ")", paren
2117
+
2118
+ def _c_repr_chunks_ror(self):
2119
+ yield "__ROR__", self
2120
+ paren = CClosingObject("(")
2121
+ yield "(", paren
2122
+ yield from self._try_c_repr_chunks(self.lhs)
2123
+ yield ", ", None
2124
+ yield from self._try_c_repr_chunks(self.rhs)
2125
+ yield ")", paren
2126
+
2127
+
2128
+ class CTypeCast(CExpression):
2129
+ __slots__ = (
2130
+ "dst_type",
2131
+ "expr",
2132
+ "src_type",
2133
+ )
2134
+
2135
+ def __init__(self, src_type: SimType | None, dst_type: SimType, expr: CExpression, **kwargs):
2136
+ super().__init__(**kwargs)
2137
+
2138
+ self.src_type = (src_type or expr.type).with_arch(self.codegen.project.arch)
2139
+ self.dst_type = dst_type.with_arch(self.codegen.project.arch)
2140
+ self.expr = expr
2141
+
2142
+ @property
2143
+ def type(self):
2144
+ if self._type is None:
2145
+ return self.dst_type
2146
+ return self._type
2147
+
2148
+ def c_repr_chunks(self, indent=0, asexpr=False):
2149
+ if self.collapsed:
2150
+ yield "...", self
2151
+ return
2152
+ paren = CClosingObject("(")
2153
+ if self.codegen.show_casts:
2154
+ yield "(", paren
2155
+ yield f"{self.dst_type.c_repr(name=None)}", self.dst_type
2156
+ yield ")", paren
2157
+
2158
+ if isinstance(self.expr, CBinaryOp):
2159
+ wrapping_paren = True
2160
+ yield "(", paren
2161
+ else:
2162
+ wrapping_paren = False
2163
+ yield from CExpression._try_c_repr_chunks(self.expr)
2164
+ if wrapping_paren:
2165
+ yield ")", paren
2166
+
2167
+
2168
+ class CConstant(CExpression):
2169
+ __slots__ = (
2170
+ "reference_values",
2171
+ "value",
2172
+ )
2173
+
2174
+ def __init__(self, value, type_: SimType, reference_values=None, **kwargs):
2175
+ super().__init__(**kwargs)
2176
+
2177
+ self.value: int | float | str = value
2178
+ self._type = type_.with_arch(self.codegen.project.arch)
2179
+ self.reference_values = reference_values
2180
+
2181
+ @property
2182
+ def _ident(self) -> IdentType:
2183
+ ins_addr = (self.tags or {}).get("ins_addr", -1)
2184
+ ty_enum = CConstantType.INT
2185
+ if isinstance(self.value, float):
2186
+ ty_enum = CConstantType.FLOAT
2187
+ elif isinstance(self.value, str):
2188
+ ty_enum = CConstantType.STRING
2189
+ return ins_addr, ty_enum.value, self.value
2190
+
2191
+ @property
2192
+ def fmt(self):
2193
+ return self.codegen.const_formats.get(self._ident, {})
2194
+
2195
+ @property
2196
+ def _fmt_setter(self):
2197
+ result = self.codegen.const_formats.get(self._ident, None)
2198
+ if result is None:
2199
+ result = {}
2200
+ self.codegen.const_formats[self._ident] = result
2201
+
2202
+ return result
2203
+
2204
+ @property
2205
+ def fmt_hex(self):
2206
+ result = self.fmt.get("hex", None)
2207
+ if result is None:
2208
+ result = False
2209
+ if isinstance(self.value, int):
2210
+ result = hex(self.value).endswith("00") or is_alignment_mask(self.value)
2211
+ return result
2212
+
2213
+ @fmt_hex.setter
2214
+ def fmt_hex(self, v):
2215
+ self._fmt_setter["hex"] = v
2216
+
2217
+ @property
2218
+ def fmt_neg(self):
2219
+ result = self.fmt.get("neg", None)
2220
+ if result is None:
2221
+ result = False
2222
+ # guess it
2223
+ if isinstance(self._type, (SimTypeInt, SimTypeChar)) and self._type.signed and isinstance(self.value, int):
2224
+ value_size = self._type.size if self._type is not None else None
2225
+ if (value_size == 32 and 0xF000_0000 <= self.value <= 0xFFFF_FFFF) or (
2226
+ value_size == 64 and 0xF000_0000_0000_0000 <= self.value <= 0xFFFF_FFFF_FFFF_FFFF
2227
+ ):
2228
+ result = True
2229
+
2230
+ return result
2231
+
2232
+ @fmt_neg.setter
2233
+ def fmt_neg(self, v):
2234
+ self._fmt_setter["neg"] = v
2235
+
2236
+ @property
2237
+ def fmt_char(self):
2238
+ return self.fmt.get("char", False)
2239
+
2240
+ @fmt_char.setter
2241
+ def fmt_char(self, v: bool):
2242
+ self._fmt_setter["char"] = v
2243
+
2244
+ @property
2245
+ def fmt_float(self):
2246
+ return self.fmt.get("float", False)
2247
+
2248
+ @fmt_float.setter
2249
+ def fmt_float(self, v: bool):
2250
+ self._fmt_setter["float"] = v
2251
+
2252
+ @property
2253
+ def fmt_double(self):
2254
+ return self.fmt.get("double", False)
2255
+
2256
+ @fmt_double.setter
2257
+ def fmt_double(self, v: bool):
2258
+ self._fmt_setter["double"] = v
2259
+
2260
+ @property
2261
+ def type(self):
2262
+ return self._type
2263
+
2264
+ @staticmethod
2265
+ def str_to_c_str(_str, prefix: str = "", maxlen: int | None = None) -> str:
2266
+ repr_str = repr(_str)
2267
+ base_str = repr_str[1:-1]
2268
+
2269
+ if maxlen is not None and len(base_str) > maxlen:
2270
+ base_str = base_str[:maxlen] + "..."
2271
+
2272
+ # check if there's double quotes in the body
2273
+ if repr_str[0] == "'" and '"' in base_str:
2274
+ base_str = base_str.replace('"', '\\"')
2275
+ return f'{prefix}"{base_str}"'
2276
+
2277
+ def c_repr_chunks(self, indent=0, asexpr=False):
2278
+
2279
+ def _default_output(v) -> str | None:
2280
+ if isinstance(v, MemoryData) and v.sort == MemoryDataSort.String:
2281
+ return CConstant.str_to_c_str(v.content.decode("utf-8"), maxlen=self.codegen.max_str_len)
2282
+ if isinstance(v, Function):
2283
+ return get_cpp_function_name(v.demangled_name)
2284
+ if isinstance(v, str):
2285
+ return CConstant.str_to_c_str(v, maxlen=self.codegen.max_str_len)
2286
+ if isinstance(v, bytes):
2287
+ return CConstant.str_to_c_str(v.replace(b"\x00", b"").decode("utf-8"), maxlen=self.codegen.max_str_len)
2288
+ return None
2289
+
2290
+ if self.collapsed:
2291
+ yield "...", self
2292
+ return
2293
+
2294
+ if self.reference_values is not None:
2295
+ if self._type is not None and self._type in self.reference_values:
2296
+ if isinstance(self._type, SimTypeInt):
2297
+ if isinstance(self.reference_values[self._type], int):
2298
+ yield self.fmt_int(self.reference_values[self._type]), self
2299
+ return
2300
+ yield hex(self.reference_values[self._type]), self
2301
+ return
2302
+ elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeChar):
2303
+ refval = self.reference_values[self._type]
2304
+ if isinstance(refval, MemoryData):
2305
+ v = refval.content.decode("utf-8")
2306
+ elif isinstance(refval, bytes):
2307
+ v = refval.decode("latin1")
2308
+ else:
2309
+ # it must be a string
2310
+ v = refval
2311
+ assert isinstance(v, str)
2312
+ yield CConstant.str_to_c_str(v, maxlen=self.codegen.max_str_len), self
2313
+ return
2314
+ elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeWideChar):
2315
+ refval = self.reference_values[self._type]
2316
+ v = (
2317
+ decode_utf16_string(refval.content)
2318
+ if isinstance(refval, MemoryData)
2319
+ else decode_utf16_string(refval)
2320
+ ) # it's a string
2321
+ yield CConstant.str_to_c_str(v, prefix="L", maxlen=self.codegen.max_str_len), self
2322
+ return
2323
+ else:
2324
+ if isinstance(self.reference_values[self._type], int):
2325
+ yield self.fmt_int(self.reference_values[self._type]), self
2326
+ return
2327
+ o = _default_output(self.reference_values[self.type])
2328
+ if o is not None:
2329
+ yield o, self
2330
+ return
2331
+
2332
+ # default priority: string references -> variables -> other reference values
2333
+ for _ty, v in self.reference_values.items(): # pylint:disable=unused-variable
2334
+ o = _default_output(v)
2335
+ if o is not None:
2336
+ yield o, self
2337
+ return
2338
+
2339
+ if isinstance(self.value, int) and self.value == 0 and isinstance(self.type, SimTypePointer):
2340
+ # print NULL instead
2341
+ yield "NULL", self
2342
+
2343
+ elif isinstance(self._type, SimTypePointer) and isinstance(self.value, int):
2344
+ # Print pointers in hex
2345
+ yield hex(self.value), self
2346
+
2347
+ elif isinstance(self.value, bool):
2348
+ # C doesn't have true or false, but whatever...
2349
+ yield "true" if self.value else "false", self
2350
+
2351
+ elif isinstance(self.value, int):
2352
+ str_value = self.fmt_int(self.value)
2353
+ yield str_value, self
2354
+ else:
2355
+ yield str(self.value), self
2356
+
2357
+ def fmt_int(self, value: int) -> str:
2358
+ """
2359
+ Format an integer using the format setup of the current node.
2360
+
2361
+ :param value: The integer value to format.
2362
+ :return: The formatted string.
2363
+ """
2364
+
2365
+ if self.fmt_float and 0 < value <= 0xFFFF_FFFF:
2366
+ return str(struct.unpack("f", struct.pack("I", value))[0])
2367
+
2368
+ if self.fmt_char:
2369
+ if value < 0:
2370
+ value += 2**self._type.size
2371
+ value &= 0xFF
2372
+ return repr(chr(value)) if value < 0x80 else f"'\\x{value:x}'"
2373
+
2374
+ if self.fmt_double and 0 < value <= 0xFFFF_FFFF_FFFF_FFFF:
2375
+ return str(struct.unpack("d", struct.pack("Q", value))[0])
2376
+
2377
+ if self.fmt_neg:
2378
+ if value > 0:
2379
+ value -= 2**self._type.size
2380
+ elif value < 0:
2381
+ value += 2**self._type.size
2382
+
2383
+ if self.fmt_hex:
2384
+ return hex(value)
2385
+
2386
+ return str(value)
2387
+
2388
+
2389
+ class CRegister(CExpression):
2390
+ __slots__ = ("reg",)
2391
+
2392
+ def __init__(self, reg, **kwargs):
2393
+ super().__init__(**kwargs)
2394
+
2395
+ self.reg = reg
2396
+
2397
+ @property
2398
+ def type(self):
2399
+ # FIXME
2400
+ return SimTypeInt().with_arch(self.codegen.project.arch)
2401
+
2402
+ def c_repr_chunks(self, indent=0, asexpr=False):
2403
+ yield str(self.reg), None
2404
+
2405
+
2406
+ class CITE(CExpression):
2407
+ __slots__ = (
2408
+ "cond",
2409
+ "iffalse",
2410
+ "iftrue",
2411
+ )
2412
+
2413
+ def __init__(self, cond, iftrue, iffalse, **kwargs):
2414
+ super().__init__(**kwargs)
2415
+ self.cond = cond
2416
+ self.iftrue = iftrue
2417
+ self.iffalse = iffalse
2418
+
2419
+ @property
2420
+ def type(self):
2421
+ return self.iftrue.type
2422
+
2423
+ def c_repr_chunks(self, indent=0, asexpr=False):
2424
+ if self.collapsed:
2425
+ yield "...", self
2426
+ return
2427
+ paren = CClosingObject("(")
2428
+ yield "(", paren
2429
+ yield from self.cond.c_repr_chunks()
2430
+ yield " ? ", self
2431
+ yield from self.iftrue.c_repr_chunks()
2432
+ yield " : ", self
2433
+ yield from self.iffalse.c_repr_chunks()
2434
+ yield ")", paren
2435
+
2436
+
2437
+ class CMultiStatementExpression(CExpression):
2438
+ """
2439
+ (stmt0, stmt1, stmt2, expr)
2440
+ """
2441
+
2442
+ __slots__ = (
2443
+ "expr",
2444
+ "stmts",
2445
+ )
2446
+
2447
+ def __init__(self, stmts: CStatements, expr: CExpression, **kwargs):
2448
+ super().__init__(**kwargs)
2449
+ self.stmts = stmts
2450
+ self.expr = expr
2451
+
2452
+ @property
2453
+ def type(self):
2454
+ return self.expr.type
2455
+
2456
+ def c_repr_chunks(self, indent=0, asexpr=False):
2457
+ paren = CClosingObject("(")
2458
+ yield "(", paren
2459
+ yield from self.stmts.c_repr_chunks(indent=0, asexpr=True)
2460
+ yield from self.expr.c_repr_chunks()
2461
+ yield ")", paren
2462
+
2463
+
2464
+ class CVEXCCallExpression(CExpression):
2465
+ """
2466
+ ccall_name(arg0, arg1, ...)
2467
+ """
2468
+
2469
+ __slots__ = (
2470
+ "callee",
2471
+ "operands",
2472
+ )
2473
+
2474
+ def __init__(self, callee: str, operands: list[CExpression], **kwargs):
2475
+ super().__init__(**kwargs)
2476
+ self.callee = callee
2477
+ self.operands = operands
2478
+
2479
+ @property
2480
+ def type(self):
2481
+ return SimTypeInt().with_arch(self.codegen.project.arch)
2482
+
2483
+ def c_repr_chunks(self, indent=0, asexpr=False):
2484
+ paren = CClosingObject("(")
2485
+ yield f"{self.callee}", self
2486
+ yield "(", paren
2487
+ for idx, operand in enumerate(self.operands):
2488
+ if idx != 0:
2489
+ yield ", ", None
2490
+ yield from operand.c_repr_chunks()
2491
+ yield ")", paren
2492
+
2493
+
2494
+ class CDirtyExpression(CExpression):
2495
+ """
2496
+ Ideally all dirty expressions should be handled and converted to proper conversions during conversion from VEX to
2497
+ AIL. Eventually this class should not be used at all.
2498
+ """
2499
+
2500
+ __slots__ = ("dirty",)
2501
+
2502
+ def __init__(self, dirty, **kwargs):
2503
+ super().__init__(**kwargs)
2504
+ self.dirty = dirty
2505
+
2506
+ @property
2507
+ def type(self):
2508
+ return SimTypeInt().with_arch(self.codegen.project.arch)
2509
+
2510
+ def c_repr_chunks(self, indent=0, asexpr=False):
2511
+ if self.collapsed:
2512
+ yield "...", self
2513
+ return
2514
+ yield str(self.dirty), None
2515
+
2516
+
2517
+ class CClosingObject:
2518
+ """
2519
+ A class to represent all objects that can be closed by it's correspodning character.
2520
+ Examples: (), {}, []
2521
+ """
2522
+
2523
+ __slots__ = ("opening_symbol",)
2524
+
2525
+ def __init__(self, opening_symbol):
2526
+ self.opening_symbol = opening_symbol
2527
+
2528
+
2529
+ class CArrayTypeLength:
2530
+ """
2531
+ A class to represent the type information of fixed-size array lengths.
2532
+ Examples: In "char foo[20]", this would be the "[20]".
2533
+ """
2534
+
2535
+ __slots__ = ("text",)
2536
+
2537
+ def __init__(self, text):
2538
+ self.text = text
2539
+
2540
+
2541
+ class CStructFieldNameDef:
2542
+ """A class to represent the name of a defined field in a struct.
2543
+ Needed because it's not a CVariable or a CStructField (because
2544
+ CStructField is the access of a CStructField).
2545
+ Example: In "struct foo { int bar; }, this would be "bar".
2546
+ """
2547
+
2548
+ __slots__ = ("name",)
2549
+
2550
+ def __init__(self, name):
2551
+ self.name = name
2552
+
2553
+
2554
+ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
2555
+ def __init__(
2556
+ self,
2557
+ func,
2558
+ sequence,
2559
+ indent=0,
2560
+ cfg=None,
2561
+ variable_kb=None,
2562
+ func_args: list[SimVariable] | None = None,
2563
+ binop_depth_cutoff: int = 16,
2564
+ show_casts=True,
2565
+ braces_on_own_lines=True,
2566
+ use_compound_assignments=True,
2567
+ show_local_types=True,
2568
+ comment_gotos=False,
2569
+ cstyle_null_cmp=True,
2570
+ flavor=None,
2571
+ stmt_comments=None,
2572
+ expr_comments=None,
2573
+ show_externs=True,
2574
+ externs=None,
2575
+ const_formats=None,
2576
+ show_demangled_name=True,
2577
+ show_disambiguated_name=True,
2578
+ ail_graph=None,
2579
+ simplify_else_scope=True,
2580
+ cstyle_ifs=True,
2581
+ omit_func_header=False,
2582
+ display_block_addrs=False,
2583
+ display_vvar_ids=False,
2584
+ min_data_addr: int = 0x400_000,
2585
+ notes=None,
2586
+ display_notes: bool = True,
2587
+ max_str_len: int | None = None,
2588
+ ):
2589
+ super().__init__(
2590
+ flavor=flavor,
2591
+ notes=notes,
2592
+ stmt_comments=stmt_comments,
2593
+ expr_comments=expr_comments,
2594
+ const_formats=const_formats,
2595
+ )
2596
+
2597
+ self._handlers = {
2598
+ CodeNode: self._handle_Code,
2599
+ SequenceNode: self._handle_Sequence,
2600
+ LoopNode: self._handle_Loop,
2601
+ ConditionNode: self._handle_Condition,
2602
+ CascadingConditionNode: self._handle_CascadingCondition,
2603
+ ConditionalBreakNode: self._handle_ConditionalBreak,
2604
+ MultiNode: self._handle_MultiNode,
2605
+ Block: self._handle_AILBlock,
2606
+ BreakNode: self._handle_Break,
2607
+ SwitchCaseNode: self._handle_SwitchCase,
2608
+ IncompleteSwitchCaseNode: self._handle_IncompleteSwitchCase,
2609
+ ContinueNode: self._handle_Continue,
2610
+ # AIL statements
2611
+ Stmt.Store: self._handle_Stmt_Store,
2612
+ Stmt.Assignment: self._handle_Stmt_Assignment,
2613
+ Stmt.WeakAssignment: self._handle_Stmt_WeakAssignment,
2614
+ Stmt.Call: self._handle_Stmt_Call,
2615
+ Stmt.Jump: self._handle_Stmt_Jump,
2616
+ Stmt.ConditionalJump: self._handle_Stmt_ConditionalJump,
2617
+ Stmt.Return: self._handle_Stmt_Return,
2618
+ Stmt.Label: self._handle_Stmt_Label,
2619
+ Stmt.DirtyStatement: self._handle_Stmt_Dirty,
2620
+ # AIL expressions
2621
+ Expr.Register: self._handle_Expr_Register,
2622
+ Expr.Load: self._handle_Expr_Load,
2623
+ Expr.Tmp: self._handle_Expr_Tmp,
2624
+ Expr.Const: self._handle_Expr_Const,
2625
+ Expr.UnaryOp: self._handle_Expr_UnaryOp,
2626
+ Expr.BinaryOp: self._handle_Expr_BinaryOp,
2627
+ Expr.Convert: self._handle_Expr_Convert,
2628
+ Expr.StackBaseOffset: self._handle_Expr_StackBaseOffset,
2629
+ Expr.VEXCCallExpression: self._handle_Expr_VEXCCallExpression,
2630
+ Expr.DirtyExpression: self._handle_Expr_Dirty,
2631
+ Expr.ITE: self._handle_Expr_ITE,
2632
+ Expr.Reinterpret: self._handle_Reinterpret,
2633
+ Expr.MultiStatementExpression: self._handle_MultiStatementExpression,
2634
+ Expr.VirtualVariable: self._handle_VirtualVariable,
2635
+ }
2636
+
2637
+ self._func = func
2638
+ self._func_args = func_args
2639
+ self._cfg = cfg
2640
+ self._sequence = sequence
2641
+ self._variable_kb = variable_kb if variable_kb is not None else self.kb
2642
+ self.binop_depth_cutoff = binop_depth_cutoff
2643
+
2644
+ self._variables_in_use: dict | None = None
2645
+ self._inlined_strings: set[SimMemoryVariable] = set()
2646
+ self._function_pointers: set[SimMemoryVariable] = set()
2647
+ self.ailexpr2cnode: dict[tuple[Expr.Expression, bool], CExpression] | None = None
2648
+ self.cnode2ailexpr: dict[CExpression, Expr.Expression] | None = None
2649
+ self._indent = indent
2650
+ self.show_casts = show_casts
2651
+ self.comment_gotos = comment_gotos
2652
+ self.braces_on_own_lines = braces_on_own_lines
2653
+ self.use_compound_assignments = use_compound_assignments
2654
+ self.show_local_types = show_local_types
2655
+ self.cstyle_null_cmp = cstyle_null_cmp
2656
+ self.externs = externs or set()
2657
+ self.show_externs = show_externs
2658
+ self.show_demangled_name = show_demangled_name
2659
+ self.show_disambiguated_name = show_disambiguated_name
2660
+ self.ail_graph = ail_graph
2661
+ self.simplify_else_scope = simplify_else_scope
2662
+ self.cstyle_ifs = cstyle_ifs
2663
+ self.omit_func_header = omit_func_header
2664
+ self.display_block_addrs = display_block_addrs
2665
+ self.display_vvar_ids = display_vvar_ids
2666
+ self.min_data_addr = min_data_addr
2667
+ self.text = None
2668
+ self.map_pos_to_node = None
2669
+ self.map_pos_to_addr = None
2670
+ self.map_addr_to_pos = None
2671
+ self.map_ast_to_pos: dict[SimVariable, set[PositionMappingElement]] | None = None
2672
+ self.map_addr_to_label: dict[tuple[int, int | None], CLabel] = {}
2673
+ self.cfunc: CFunction | None = None
2674
+ self.cexterns: set[CVariable] | None = None
2675
+ self.display_notes = display_notes
2676
+ self.max_str_len = max_str_len
2677
+
2678
+ self._analyze()
2679
+
2680
+ def reapply_options(self, options):
2681
+ for option, value in options:
2682
+ if option.param == "braces_on_own_lines":
2683
+ self.braces_on_own_lines = value
2684
+ elif option.param == "show_casts":
2685
+ self.show_casts = value
2686
+ elif option.param == "comment_gotos":
2687
+ self.comment_gotos = value
2688
+ elif option.param == "use_compound_assignments":
2689
+ self.use_compound_assignments = value
2690
+ elif option.param == "show_local_types":
2691
+ self.show_local_types = value
2692
+ elif option.param == "show_externs":
2693
+ self.show_externs = value
2694
+ elif option.param == "show_demangled_name":
2695
+ self.show_demangled_name = value
2696
+ elif option.param == "cstyle_null_cmp":
2697
+ self.cstyle_null_cmp = value
2698
+ elif option.param == "simplify_else_scope":
2699
+ self.simplify_else_scope = value
2700
+ elif option.param == "cstyle_ifs":
2701
+ self.cstyle_ifs = value
2702
+
2703
+ def _analyze(self):
2704
+ self._variables_in_use = {}
2705
+
2706
+ # memo
2707
+ self.ailexpr2cnode = {}
2708
+
2709
+ arg_list = [self._variable(arg, None) for arg in self._func_args] if self._func_args else []
2710
+
2711
+ self.reset_idx_counters()
2712
+ obj = self._handle(self._sequence)
2713
+
2714
+ self.cnode2ailexpr = {v: k[0] for k, v in self.ailexpr2cnode.items()}
2715
+
2716
+ self.cfunc = CFunction(
2717
+ self._func.addr,
2718
+ self._func.name,
2719
+ self._func.prototype,
2720
+ arg_list,
2721
+ obj,
2722
+ self._variables_in_use,
2723
+ self._variable_kb.variables[self._func.addr],
2724
+ demangled_name=self._func.demangled_name,
2725
+ show_demangled_name=self.show_demangled_name,
2726
+ codegen=self,
2727
+ omit_header=self.omit_func_header,
2728
+ )
2729
+ self.cfunc = FieldReferenceCleanup().handle(self.cfunc)
2730
+ self.cfunc = PointerArithmeticFixer().handle(self.cfunc)
2731
+ self.cfunc = MakeTypecastsImplicit().handle(self.cfunc)
2732
+
2733
+ # TODO store extern fallback size somewhere lol
2734
+ self.cexterns = {
2735
+ self._variable(v, 1, mark_used=False)
2736
+ for v in self.externs
2737
+ if v not in self._inlined_strings and v not in self._function_pointers
2738
+ }
2739
+
2740
+ self.regenerate_text()
2741
+
2742
+ def cleanup(self):
2743
+ """
2744
+ Remove existing rendering results.
2745
+ """
2746
+ self.map_pos_to_node = None
2747
+ self.map_pos_to_addr = None
2748
+ self.map_addr_to_pos = None
2749
+ self.map_ast_to_pos = None
2750
+ self.text = None
2751
+
2752
+ def regenerate_text(self) -> None:
2753
+ """
2754
+ Re-render text and re-generate all sorts of mapping information.
2755
+ """
2756
+ self.cleanup()
2757
+ (
2758
+ self.text,
2759
+ self.map_pos_to_node,
2760
+ self.map_pos_to_addr,
2761
+ self.map_addr_to_pos,
2762
+ self.map_ast_to_pos,
2763
+ ) = self.render_text(self.cfunc)
2764
+
2765
+ RENDER_TYPE = tuple[str, PositionMapping, PositionMapping, InstructionMapping, dict[Any, set[Any]]]
2766
+
2767
+ def render_text(self, cfunc: CFunction) -> RENDER_TYPE:
2768
+ pos_to_node = PositionMapping()
2769
+ pos_to_addr = PositionMapping()
2770
+ addr_to_pos = InstructionMapping()
2771
+ ast_to_pos = defaultdict(set)
2772
+
2773
+ text = cfunc.c_repr(
2774
+ initial_pos=0,
2775
+ indent=self._indent,
2776
+ pos_to_node=pos_to_node,
2777
+ pos_to_addr=pos_to_addr,
2778
+ addr_to_pos=addr_to_pos,
2779
+ )
2780
+
2781
+ if self.display_notes:
2782
+ notes = self.render_notes()
2783
+ pos_to_node, pos_to_addr, addr_to_pos = self.adjust_mapping_positions(
2784
+ len(notes), pos_to_node, pos_to_addr, addr_to_pos
2785
+ )
2786
+ text = notes + text
2787
+
2788
+ for elem, node in pos_to_node.items():
2789
+ if isinstance(node.obj, CConstant):
2790
+ ast_to_pos[node.obj.value].add(elem)
2791
+ elif isinstance(node.obj, CVariable):
2792
+ if node.obj.unified_variable is not None:
2793
+ ast_to_pos[node.obj.unified_variable].add(elem)
2794
+ else:
2795
+ ast_to_pos[node.obj.variable].add(elem)
2796
+ elif isinstance(node.obj, SimType):
2797
+ ast_to_pos[node.obj].add(elem)
2798
+ elif isinstance(node.obj, CFunctionCall):
2799
+ if node.obj.callee_func is not None:
2800
+ ast_to_pos[node.obj.callee_func].add(elem)
2801
+ else:
2802
+ ast_to_pos[node.obj.callee_target].add(elem)
2803
+ elif isinstance(node.obj, CStructField):
2804
+ key = (node.obj.struct_type, node.obj.offset)
2805
+ ast_to_pos[key].add(elem)
2806
+ else:
2807
+ ast_to_pos[node.obj].add(elem)
2808
+
2809
+ return text, pos_to_node, pos_to_addr, addr_to_pos, ast_to_pos
2810
+
2811
+ def render_notes(self) -> str:
2812
+ """
2813
+ Render decompilation notes.
2814
+
2815
+ :return: A string containing all notes.
2816
+ """
2817
+ if not self.notes:
2818
+ return ""
2819
+
2820
+ lines = []
2821
+ for note in self.notes.values():
2822
+ note_lines = str(note).split("\n")
2823
+ lines += [f"// {line}" for line in note_lines]
2824
+ return "\n".join(lines) + "\n\n"
2825
+
2826
+ def _get_variable_type(self, var, is_global=False):
2827
+ if is_global:
2828
+ return self._variable_kb.variables["global"].get_variable_type(var)
2829
+ return self._variable_kb.variables[self._func.addr].get_variable_type(var)
2830
+
2831
+ def _get_derefed_type(self, ty: SimType) -> SimType | None:
2832
+ if ty is None:
2833
+ return None
2834
+ ty = unpack_typeref(ty)
2835
+ if isinstance(ty, SimTypePointer):
2836
+ return unpack_typeref(ty.pts_to).with_arch(self.project.arch)
2837
+ if isinstance(ty, SimTypeArray):
2838
+ return unpack_typeref(ty.elem_type).with_arch(self.project.arch)
2839
+ return ty
2840
+
2841
+ def reload_variable_types(self) -> None:
2842
+ for var in self._variables_in_use.values():
2843
+ if isinstance(var, CVariable):
2844
+ var.variable_type = self._get_variable_type(
2845
+ var.variable,
2846
+ is_global=isinstance(var.variable, SimMemoryVariable)
2847
+ and not isinstance(var.variable, SimStackVariable),
2848
+ )
2849
+
2850
+ for var in self.cexterns:
2851
+ if isinstance(var, CVariable):
2852
+ var.variable_type = self._get_variable_type(var.variable, is_global=True)
2853
+
2854
+ for cvar in self.cfunc.arg_list:
2855
+ vartype = self._get_variable_type(
2856
+ cvar.variable,
2857
+ is_global=isinstance(cvar.variable, SimMemoryVariable)
2858
+ and not isinstance(cvar.variable, SimStackVariable),
2859
+ )
2860
+ if vartype is not None:
2861
+ cvar.variable_type = vartype.with_arch(self.project.arch)
2862
+
2863
+ #
2864
+ # Util methods
2865
+ #
2866
+
2867
+ def default_simtype_from_bits(self, n: int, signed: bool = True) -> SimType:
2868
+ _mapping = {
2869
+ 64: SimTypeLongLong,
2870
+ 32: SimTypeInt,
2871
+ 16: SimTypeShort,
2872
+ 8: SimTypeChar,
2873
+ }
2874
+ if n in _mapping:
2875
+ return _mapping.get(n)(signed=signed).with_arch(self.project.arch)
2876
+ return SimTypeNum(n, signed=signed).with_arch(self.project.arch)
2877
+
2878
+ def _variable(
2879
+ self, variable: SimVariable, fallback_type_size: int | None, vvar_id: int | None = None, mark_used: bool = True
2880
+ ) -> CVariable:
2881
+ # TODO: we need to fucking make sure that variable recovery and type inference actually generates a size
2882
+ # TODO: for each variable it links into the fucking ail. then we can remove fallback_type_size.
2883
+ unified = self._variable_kb.variables[self._func.addr].unified_variable(variable)
2884
+ variable_type = self._get_variable_type(
2885
+ variable, is_global=isinstance(variable, SimMemoryVariable) and not isinstance(variable, SimStackVariable)
2886
+ )
2887
+ if variable_type is None:
2888
+ variable_type = self.default_simtype_from_bits(
2889
+ (fallback_type_size or self.project.arch.bytes) * self.project.arch.byte_width
2890
+ )
2891
+ cvar = CVariable(variable, unified_variable=unified, variable_type=variable_type, codegen=self, vvar_id=vvar_id)
2892
+ if mark_used:
2893
+ self._variables_in_use[variable] = cvar
2894
+ return cvar
2895
+
2896
+ def _get_variable_reference(self, cvar: CVariable) -> CExpression:
2897
+ """
2898
+ Return a reference to a CVariable instance with special handling of arrays and array pointers.
2899
+
2900
+ :param cvar: The CVariable object.
2901
+ :return: A reference to a CVariable object.
2902
+ """
2903
+
2904
+ if isinstance(cvar.type, (SimTypeArray, SimTypeFixedSizeArray)):
2905
+ return cvar
2906
+ if isinstance(cvar.type, SimTypePointer) and isinstance(
2907
+ cvar.type.pts_to, (SimTypeArray, SimTypeFixedSizeArray)
2908
+ ):
2909
+ return cvar
2910
+ return CUnaryOp("Reference", cvar, codegen=self)
2911
+
2912
+ def _access_reference(self, expr: CExpression, data_type: SimType) -> CExpression:
2913
+ result = self._access(expr, data_type, True)
2914
+ if isinstance(result, CUnaryOp) and result.op == "Dereference":
2915
+ result = result.operand
2916
+ else:
2917
+ result = CUnaryOp("Reference", result, codegen=self)
2918
+ return result
2919
+
2920
+ def _access_constant_offset_reference(
2921
+ self, expr: CExpression, offset: int, data_type: SimType | None
2922
+ ) -> CExpression:
2923
+ result = self._access_constant_offset(expr, offset, data_type or SimTypeBottom(), True)
2924
+ if isinstance(result, CTypeCast) and data_type is None:
2925
+ result = result.expr
2926
+ if isinstance(result, CUnaryOp) and result.op == "Dereference":
2927
+ result = result.operand
2928
+ if isinstance(result, CTypeCast) and data_type is None:
2929
+ result = result.expr
2930
+ else:
2931
+ result = CUnaryOp("Reference", result, codegen=self)
2932
+ return result
2933
+
2934
+ def _access_constant_offset(
2935
+ self,
2936
+ expr: CExpression,
2937
+ offset: int,
2938
+ data_type: SimType,
2939
+ lvalue: bool,
2940
+ renegotiate_type: Callable[[SimType, SimType], SimType] = lambda old, proposed: old,
2941
+ ) -> CExpression:
2942
+ def _force_type_cast(src_type_: SimType, dst_type_: SimType, expr_: CExpression) -> CUnaryOp:
2943
+ src_type_ptr = SimTypePointer(src_type_).with_arch(self.project.arch)
2944
+ dst_type_ptr = SimTypePointer(dst_type_).with_arch(self.project.arch)
2945
+ return CUnaryOp(
2946
+ "Dereference",
2947
+ CTypeCast(
2948
+ src_type_ptr,
2949
+ dst_type_ptr,
2950
+ CUnaryOp("Reference", expr_, codegen=self),
2951
+ codegen=self,
2952
+ ),
2953
+ codegen=self,
2954
+ )
2955
+
2956
+ # expr must express a POINTER to the base
2957
+ # returns a value which has a simtype of data_type as if it were dereferenced out of expr
2958
+ data_type = unpack_typeref(data_type)
2959
+ base_type = unpack_typeref(unpack_pointer_and_array(expr.type))
2960
+ if base_type is None:
2961
+ # well, not much we can do
2962
+ if data_type is None:
2963
+ raise TypeError("CStructuredCodeGenerator programming error: no type whatsoever for dereference")
2964
+ if offset:
2965
+ expr = CBinaryOp("Add", expr, CConstant(offset, SimTypeInt(), codegen=self), codegen=self)
2966
+ return CUnaryOp(
2967
+ "Dereference",
2968
+ CTypeCast(expr.type, SimTypePointer(data_type).with_arch(self.project.arch), expr, codegen=self),
2969
+ codegen=self,
2970
+ )
2971
+
2972
+ base_expr = expr.operand if isinstance(expr, CUnaryOp) and expr.op == "Reference" else None
2973
+
2974
+ if offset == 0:
2975
+ data_type = renegotiate_type(data_type, base_type)
2976
+ if type_equals(base_type, data_type) or (
2977
+ base_type.size is not None and data_type.size is not None and base_type.size < data_type.size
2978
+ ):
2979
+ # case 1: we're done because we found it
2980
+ # case 2: we're done because we can never find it and we might as well stop early
2981
+ if base_expr:
2982
+ if not type_equals(base_type, data_type):
2983
+ return _force_type_cast(base_type, data_type, base_expr)
2984
+ return base_expr
2985
+
2986
+ if not type_equals(base_type, data_type):
2987
+ return _force_type_cast(base_type, data_type, expr)
2988
+ return CUnaryOp("Dereference", expr, codegen=self)
2989
+
2990
+ stride = 1 if base_type.size is None else base_type.size // self.project.arch.byte_width or 1
2991
+ index, remainder = divmod(offset, stride)
2992
+ if index != 0:
2993
+ index = CConstant(index, SimTypeInt(), codegen=self)
2994
+ kernel = expr
2995
+ # create a CIndexedVariable indicating the index access
2996
+ if base_expr and isinstance(base_expr, CIndexedVariable):
2997
+ old_index = base_expr.index
2998
+ kernel = base_expr.variable
2999
+ if not isinstance(old_index, CConstant) or old_index.value != 0:
3000
+ index = CBinaryOp("Add", old_index, index, codegen=self)
3001
+ result = CUnaryOp(
3002
+ "Reference", CIndexedVariable(kernel, index, variable_type=base_type, codegen=self), codegen=self
3003
+ )
3004
+ return self._access_constant_offset(result, remainder, data_type, lvalue, renegotiate_type)
3005
+
3006
+ if isinstance(base_type, SimStruct) and base_type.offsets:
3007
+ # find the field that we're accessing
3008
+ field_name, field_offset = max(
3009
+ ((x, y) for x, y in base_type.offsets.items() if y <= remainder), key=lambda x: x[1]
3010
+ )
3011
+ field = CStructField(base_type, field_offset, field_name, codegen=self)
3012
+ if base_expr:
3013
+ result = CUnaryOp("Reference", CVariableField(base_expr, field, False, codegen=self), codegen=self)
3014
+ else:
3015
+ result = CUnaryOp("Reference", CVariableField(expr, field, True, codegen=self), codegen=self)
3016
+ return self._access_constant_offset(result, remainder - field_offset, data_type, lvalue, renegotiate_type)
3017
+
3018
+ if isinstance(base_type, (SimTypeFixedSizeArray, SimTypeArray)):
3019
+ result = base_expr or expr # death to C
3020
+ if isinstance(result, CIndexedVariable):
3021
+ # unpack indexed variable
3022
+ var = result.variable
3023
+ result = CUnaryOp(
3024
+ "Reference",
3025
+ CIndexedVariable(var, result.index, variable_type=base_type.elem_type, codegen=self),
3026
+ codegen=self,
3027
+ )
3028
+ else:
3029
+ result = CUnaryOp(
3030
+ "Reference",
3031
+ CIndexedVariable(
3032
+ result,
3033
+ CConstant(0, SimTypeInt(), codegen=self),
3034
+ variable_type=base_type.elem_type,
3035
+ codegen=self,
3036
+ ),
3037
+ codegen=self,
3038
+ )
3039
+ return self._access_constant_offset(result, remainder, data_type, lvalue, renegotiate_type)
3040
+
3041
+ # TODO is it a big-endian downcast?
3042
+ # e.g. int x; *((char*)x + 3) is actually just (char)x
3043
+
3044
+ if remainder != 0:
3045
+ # pointer cast time!
3046
+ # TODO: BYTE2() and other ida-isms if we're okay with an rvalue
3047
+ if stride != 1:
3048
+ expr = CTypeCast(
3049
+ expr.type, SimTypePointer(SimTypeChar()).with_arch(self.project.arch), expr, codegen=self
3050
+ )
3051
+ expr_with_offset = CBinaryOp("Add", expr, CConstant(remainder, SimTypeInt(), codegen=self), codegen=self)
3052
+ return CUnaryOp(
3053
+ "Dereference",
3054
+ CTypeCast(
3055
+ expr_with_offset.type,
3056
+ SimTypePointer(data_type).with_arch(self.project.arch),
3057
+ expr_with_offset,
3058
+ codegen=self,
3059
+ ),
3060
+ codegen=self,
3061
+ )
3062
+
3063
+ # the case where we don't need a cast is handled at the start
3064
+ # if we've requested the result be an lvalue we have to do a pointer cast
3065
+ # if the value is not a trivial reference we have to do a pointer cast (?)
3066
+ if lvalue or not base_expr:
3067
+ return CUnaryOp(
3068
+ "Dereference", CTypeCast(expr.type, SimTypePointer(data_type), expr, codegen=self), codegen=self
3069
+ )
3070
+ # otherwise, normal cast
3071
+ return CTypeCast(base_type, data_type, base_expr, codegen=self)
3072
+
3073
+ def _access(
3074
+ self,
3075
+ expr: CExpression,
3076
+ data_type: SimType,
3077
+ lvalue: bool,
3078
+ renegotiate_type: Callable[[SimType, SimType], SimType] = lambda old, proposed: old,
3079
+ ) -> CExpression:
3080
+ # same rule as _access_constant_offset wrt pointer expressions
3081
+ data_type = unpack_typeref(data_type)
3082
+ base_type = unpack_pointer_and_array(expr.type)
3083
+ if base_type is None:
3084
+ # use the fallback from above
3085
+ return self._access_constant_offset(expr, 0, data_type, lvalue, renegotiate_type)
3086
+
3087
+ o_constant, o_terms = extract_terms(expr)
3088
+
3089
+ def bail_out():
3090
+ if len(o_terms) == 0:
3091
+ # probably a plain integer, return as is
3092
+ return expr
3093
+ result = None
3094
+ pointer_length_int_type = (
3095
+ SimTypeLongLong(signed=False) if self.project.arch.bits == 64 else SimTypeInt(signed=False)
3096
+ )
3097
+ for c, t in o_terms:
3098
+ op = "Add"
3099
+ if c == -1 and result is not None:
3100
+ op = "Sub"
3101
+ piece = (
3102
+ t
3103
+ if not isinstance(t.type, SimTypePointer)
3104
+ else CTypeCast(t.type, SimTypePointer(SimTypeChar()), t, codegen=self)
3105
+ )
3106
+ elif c == 1:
3107
+ piece = (
3108
+ t
3109
+ if not isinstance(t.type, SimTypePointer)
3110
+ else CTypeCast(t.type, SimTypePointer(SimTypeChar()), t, codegen=self)
3111
+ )
3112
+ else:
3113
+ piece = CBinaryOp(
3114
+ "Mul",
3115
+ CConstant(c, t.type, codegen=self),
3116
+ (
3117
+ t
3118
+ if not isinstance(t.type, SimTypePointer)
3119
+ else CTypeCast(t.type, pointer_length_int_type, t, codegen=self)
3120
+ ),
3121
+ codegen=self,
3122
+ )
3123
+ result = piece if result is None else CBinaryOp(op, result, piece, codegen=self)
3124
+ if o_constant != 0:
3125
+ result = CBinaryOp("Add", CConstant(o_constant, SimTypeInt(), codegen=self), result, codegen=self)
3126
+
3127
+ return CUnaryOp(
3128
+ "Dereference", CTypeCast(result.type, SimTypePointer(data_type), result, codegen=self), codegen=self
3129
+ )
3130
+
3131
+ # pain.
3132
+ # step 1 is split expr into a sum of terms, each of which is a product of a constant stride and an index
3133
+ # also identify the "kernel", the root of the expression
3134
+ constant, terms = o_constant, list(o_terms)
3135
+ if constant < 0:
3136
+ constant = -constant # TODO: This may not be correct. investigate later
3137
+
3138
+ i = 0
3139
+ kernel = None
3140
+ while i < len(terms):
3141
+ c, t = terms[i]
3142
+ if isinstance(unpack_typeref(t.type), (SimTypePointer, SimTypeArray)):
3143
+ if kernel is not None:
3144
+ l.warning("Summing two different pointers together. Uh oh!")
3145
+ return bail_out()
3146
+ if c == -1:
3147
+ # legit case: you can deduct a pointer from another pointer and get an integer as result in C
3148
+ return bail_out()
3149
+ if c != 1:
3150
+ l.warning("Multiplying a pointer by a constant??")
3151
+ return bail_out()
3152
+ kernel = t
3153
+ terms.pop(i)
3154
+ continue
3155
+ i += 1
3156
+
3157
+ if kernel is None:
3158
+ l.warning("Dereferencing a plain integer. Uh oh!")
3159
+ return bail_out()
3160
+
3161
+ terms.sort(key=lambda x: x[0])
3162
+
3163
+ # suffering.
3164
+ while terms:
3165
+ kernel_type = unpack_typeref(unpack_pointer_and_array(kernel.type))
3166
+ assert kernel_type
3167
+
3168
+ if kernel_type.size is None or kernel_type.size == 0:
3169
+ return bail_out()
3170
+ kernel_stride = kernel_type.size // self.project.arch.byte_width
3171
+ if kernel_stride == 0:
3172
+ return bail_out()
3173
+
3174
+ # if the constant offset is larger than the current fucker, uh, do something about that first
3175
+ if constant >= kernel_stride:
3176
+ index, remainder = divmod(constant, kernel_stride)
3177
+ kernel = CUnaryOp(
3178
+ "Reference",
3179
+ self._access_constant_offset(kernel, index * kernel_stride, kernel_type, True, renegotiate_type),
3180
+ codegen=self,
3181
+ )
3182
+ constant = remainder
3183
+ continue
3184
+
3185
+ # next, uh, check if there's an appropriately sized stride term that we can apply
3186
+ next_stride, next_term = terms[-1]
3187
+ if next_stride % kernel_stride == 0:
3188
+ index_multiplier = next_stride // kernel_stride
3189
+ if index_multiplier != 1:
3190
+ index = CBinaryOp(
3191
+ "Mul", CConstant(index_multiplier, SimTypeInt(), codegen=self), next_term, codegen=self
3192
+ )
3193
+ else:
3194
+ index = next_term
3195
+ if (
3196
+ isinstance(kernel, CUnaryOp)
3197
+ and kernel.op == "Reference"
3198
+ and isinstance(kernel.operand, CIndexedVariable)
3199
+ ):
3200
+ old_index = kernel.operand.index
3201
+ kernel = kernel.operand.variable
3202
+ if not isinstance(old_index, CConstant) or old_index.value != 0:
3203
+ index = CBinaryOp("Add", old_index, index, codegen=self)
3204
+ kernel = CUnaryOp("Reference", CIndexedVariable(kernel, index, codegen=self), codegen=self)
3205
+ terms.pop()
3206
+ continue
3207
+
3208
+ if next_stride > kernel_stride:
3209
+ l.warning("Oddly-sized array access stride. Uh oh!")
3210
+ return bail_out()
3211
+
3212
+ # nothing has the ability to escape the kernel
3213
+ # go in deeper
3214
+ if isinstance(kernel_type, SimStruct):
3215
+ field_name, field_offset = max(
3216
+ ((x, y) for x, y in kernel_type.offsets.items() if y <= constant), key=lambda x: x[1]
3217
+ )
3218
+ field_type = kernel_type.fields[field_name]
3219
+ kernel = CUnaryOp(
3220
+ "Reference",
3221
+ self._access_constant_offset(kernel, field_offset, field_type, True, renegotiate_type),
3222
+ codegen=self,
3223
+ )
3224
+ constant -= field_offset
3225
+ continue
3226
+
3227
+ if isinstance(kernel_type, (SimTypeArray, SimTypeFixedSizeArray)):
3228
+ inner = self._access_constant_offset(kernel, 0, kernel_type.elem_type, True, renegotiate_type)
3229
+ if isinstance(inner, CUnaryOp) and inner.op == "Dereference":
3230
+ # unpack
3231
+ kernel = inner.operand
3232
+ else:
3233
+ kernel = CUnaryOp("Reference", inner, codegen=self)
3234
+ if unpack_typeref(unpack_pointer_and_array(kernel.type)) == kernel_type:
3235
+ # we are not making progress
3236
+ pass
3237
+ else:
3238
+ continue
3239
+
3240
+ l.warning("There's a variable offset with stride shorter than the primitive type. What does this mean?")
3241
+ return bail_out()
3242
+
3243
+ return self._access_constant_offset(kernel, constant, data_type, lvalue, renegotiate_type)
3244
+
3245
+ #
3246
+ # Handlers
3247
+ #
3248
+
3249
+ def _handle(
3250
+ self,
3251
+ node,
3252
+ is_expr: bool = True,
3253
+ lvalue: bool = False,
3254
+ likely_signed=False,
3255
+ type_: SimType | None = None,
3256
+ ref: bool = False,
3257
+ ):
3258
+ if (node, is_expr) in self.ailexpr2cnode:
3259
+ return self.ailexpr2cnode[(node, is_expr)]
3260
+
3261
+ handler: Callable | None = self._handlers.get(node.__class__, None)
3262
+ if handler is not None:
3263
+ # special case for Call
3264
+ converted = (
3265
+ handler(node, is_expr=is_expr)
3266
+ if isinstance(node, Stmt.Call)
3267
+ else handler(node, lvalue=lvalue, likely_signed=likely_signed, type_=type_, ref=ref)
3268
+ )
3269
+ self.ailexpr2cnode[(node, is_expr)] = converted
3270
+ return converted
3271
+ raise UnsupportedNodeTypeError(f"Node type {type(node)} is not supported yet.")
3272
+
3273
+ def _handle_Code(self, node, **kwargs):
3274
+ return self._handle(node.node, is_expr=False)
3275
+
3276
+ def _handle_Sequence(self, seq, **kwargs):
3277
+ lines = []
3278
+
3279
+ for node in seq.nodes:
3280
+ lines.append(self._handle(node, is_expr=False))
3281
+
3282
+ return lines[0] if len(lines) == 1 else CStatements(lines, codegen=self, addr=seq.addr)
3283
+
3284
+ def _handle_Loop(self, loop_node, **kwargs):
3285
+ tags = {"ins_addr": loop_node.addr}
3286
+
3287
+ if loop_node.sort == "while":
3288
+ return CWhileLoop(
3289
+ None if loop_node.condition is None else self._handle(loop_node.condition),
3290
+ None if loop_node.sequence_node is None else self._handle(loop_node.sequence_node, is_expr=False),
3291
+ tags=tags,
3292
+ codegen=self,
3293
+ )
3294
+ if loop_node.sort == "do-while":
3295
+ return CDoWhileLoop(
3296
+ self._handle(loop_node.condition),
3297
+ None if loop_node.sequence_node is None else self._handle(loop_node.sequence_node, is_expr=False),
3298
+ tags=tags,
3299
+ codegen=self,
3300
+ )
3301
+ if loop_node.sort == "for":
3302
+ return CForLoop(
3303
+ None if loop_node.initializer is None else self._handle(loop_node.initializer),
3304
+ None if loop_node.condition is None else self._handle(loop_node.condition),
3305
+ None if loop_node.iterator is None else self._handle(loop_node.iterator),
3306
+ None if loop_node.sequence_node is None else self._handle(loop_node.sequence_node, is_expr=False),
3307
+ tags=tags,
3308
+ codegen=self,
3309
+ )
3310
+
3311
+ raise NotImplementedError
3312
+
3313
+ def _handle_Condition(self, condition_node: ConditionNode, **kwargs):
3314
+ tags = {"ins_addr": condition_node.addr}
3315
+
3316
+ condition_and_nodes = [
3317
+ (
3318
+ self._handle(condition_node.condition),
3319
+ self._handle(condition_node.true_node, is_expr=False) if condition_node.true_node else None,
3320
+ )
3321
+ ]
3322
+
3323
+ else_node = self._handle(condition_node.false_node, is_expr=False) if condition_node.false_node else None
3324
+
3325
+ return CIfElse(
3326
+ condition_and_nodes,
3327
+ else_node=else_node,
3328
+ simplify_else_scope=self.simplify_else_scope
3329
+ and structured_node_is_simple_return(condition_node.true_node, self.ail_graph)
3330
+ and else_node is not None,
3331
+ cstyle_ifs=self.cstyle_ifs,
3332
+ tags=tags,
3333
+ codegen=self,
3334
+ )
3335
+
3336
+ def _handle_CascadingCondition(self, cond_node: CascadingConditionNode, **kwargs):
3337
+ tags = {"ins_addr": cond_node.addr}
3338
+
3339
+ condition_and_nodes = [
3340
+ (self._handle(cond), self._handle(node, is_expr=False)) for cond, node in cond_node.condition_and_nodes
3341
+ ]
3342
+ else_node = self._handle(cond_node.else_node) if cond_node.else_node is not None else None
3343
+
3344
+ return CIfElse(
3345
+ condition_and_nodes,
3346
+ else_node=else_node,
3347
+ tags=tags,
3348
+ cstyle_ifs=self.cstyle_ifs,
3349
+ codegen=self,
3350
+ )
3351
+
3352
+ def _handle_ConditionalBreak(self, node, **kwargs):
3353
+ tags = {"ins_addr": node.addr}
3354
+
3355
+ return CIfBreak(self._handle(node.condition), cstyle_ifs=self.cstyle_ifs, tags=tags, codegen=self)
3356
+
3357
+ def _handle_Break(self, node, **kwargs):
3358
+ tags = {"ins_addr": node.addr}
3359
+
3360
+ return CBreak(tags=tags, codegen=self)
3361
+
3362
+ def _handle_MultiNode(self, node, **kwargs):
3363
+ lines = []
3364
+
3365
+ for n in node.nodes:
3366
+ r = self._handle(n, is_expr=False)
3367
+ lines.append(r)
3368
+
3369
+ return lines[0] if len(lines) == 1 else CStatements(lines, codegen=self, addr=node.addr)
3370
+
3371
+ def _handle_SwitchCase(self, node, **kwargs):
3372
+ """
3373
+
3374
+ :param SwitchCaseNode node:
3375
+ :return:
3376
+ """
3377
+
3378
+ switch_expr = self._handle(node.switch_expr)
3379
+ cases = [(idx, self._handle(case, is_expr=False)) for idx, case in node.cases.items()]
3380
+ default = self._handle(node.default_node, is_expr=False) if node.default_node is not None else None
3381
+ tags = {"ins_addr": node.addr}
3382
+ return CSwitchCase(switch_expr, cases, default=default, tags=tags, codegen=self)
3383
+
3384
+ def _handle_IncompleteSwitchCase(self, node: IncompleteSwitchCaseNode, **kwargs):
3385
+ head = self._handle(node.head, is_expr=False)
3386
+ cases = [(case.addr, self._handle(case, is_expr=False)) for case in node.cases]
3387
+ tags = {"ins_addr": node.addr}
3388
+ return CIncompleteSwitchCase(head, cases, tags=tags, codegen=self)
3389
+
3390
+ def _handle_Continue(self, node, **kwargs):
3391
+ tags = {"ins_addr": node.addr}
3392
+
3393
+ return CContinue(tags=tags, codegen=self)
3394
+
3395
+ def _handle_AILBlock(self, node, **kwargs):
3396
+ """
3397
+
3398
+ :param Block node:
3399
+ :return:
3400
+ """
3401
+
3402
+ # return CStatements([ CAILBlock(node) ])
3403
+ cstmts = []
3404
+ for stmt in node.statements:
3405
+ try:
3406
+ cstmt = self._handle(stmt, is_expr=False)
3407
+ except UnsupportedNodeTypeError:
3408
+ l.warning("Unsupported AIL statement or expression %s.", type(stmt), exc_info=True)
3409
+ cstmt = CUnsupportedStatement(stmt, codegen=self)
3410
+ cstmts.append(cstmt)
3411
+
3412
+ return CStatements(cstmts, codegen=self, addr=node.addr)
3413
+
3414
+ #
3415
+ # AIL statement handlers
3416
+ #
3417
+
3418
+ def _handle_Stmt_Store(self, stmt: Stmt.Store, **kwargs):
3419
+ cdata = self._handle(stmt.data)
3420
+
3421
+ if cdata.type.size != stmt.size * self.project.arch.byte_width:
3422
+ l.error("Store data lifted to a C type with a different size. Decompilation output will be wrong.")
3423
+
3424
+ def negotiate(old_ty, proposed_ty):
3425
+ # transfer casts from the dst to the src if possible
3426
+ # if we see something like *(size_t*)&v4 = x; where v4 is a pointer, change to v4 = (void*)x;
3427
+ nonlocal cdata
3428
+ if old_ty != proposed_ty and qualifies_for_simple_cast(old_ty, proposed_ty):
3429
+ cdata = CTypeCast(cdata.type, proposed_ty, cdata, codegen=self)
3430
+ return proposed_ty
3431
+ return old_ty
3432
+
3433
+ if stmt.variable is not None:
3434
+ if "struct_member_info" in stmt.tags:
3435
+ offset, var, _ = stmt.tags["struct_member_info"]
3436
+ cvar = self._variable(var, stmt.size)
3437
+ else:
3438
+ cvar = self._variable(stmt.variable, stmt.size)
3439
+ offset = stmt.offset or 0
3440
+ assert type(offset) is int # I refuse to deal with the alternative
3441
+
3442
+ cdst = self._access_constant_offset(self._get_variable_reference(cvar), offset, cdata.type, True, negotiate)
3443
+ else:
3444
+ addr_expr = self._handle(stmt.addr)
3445
+ cdst = self._access(addr_expr, cdata.type, True, negotiate)
3446
+
3447
+ return CAssignment(cdst, cdata, tags=stmt.tags, codegen=self)
3448
+
3449
+ def _handle_Stmt_Assignment(self, stmt, **kwargs):
3450
+ csrc = self._handle(stmt.src, lvalue=False)
3451
+ cdst = None
3452
+
3453
+ src_type = csrc.type
3454
+ dst_type = src_type
3455
+ if "tags" in stmt.tags:
3456
+ src_type = stmt.tags["type"].get("src")
3457
+ dst_type = stmt.tags["type"].get("dst")
3458
+
3459
+ if isinstance(stmt.dst, Expr.VirtualVariable) and stmt.dst.was_stack:
3460
+
3461
+ def negotiate(old_ty, proposed_ty):
3462
+ # transfer casts from the dst to the src if possible
3463
+ # if we see something like *(size_t*)&v4 = x; where v4 is a pointer, change to v4 = (void*)x;
3464
+ nonlocal csrc
3465
+ if not type_equals(old_ty, proposed_ty) and qualifies_for_simple_cast(old_ty, proposed_ty):
3466
+ csrc = CTypeCast(csrc.type, proposed_ty, csrc, codegen=self)
3467
+ return proposed_ty
3468
+ return old_ty
3469
+
3470
+ if stmt.dst.variable is not None:
3471
+ if "struct_member_info" in stmt.dst.tags:
3472
+ offset, var, _ = stmt.dst.tags["struct_member_info"]
3473
+ cvar = self._variable(var, stmt.dst.size, vvar_id=stmt.dst.varid)
3474
+ else:
3475
+ cvar = self._variable(stmt.dst.variable, stmt.dst.size, vvar_id=stmt.dst.varid)
3476
+ offset = stmt.dst.variable_offset or 0
3477
+ assert type(offset) is int # I refuse to deal with the alternative
3478
+
3479
+ cdst = self._access_constant_offset(
3480
+ self._get_variable_reference(cvar), offset, dst_type, True, negotiate
3481
+ )
3482
+
3483
+ if cdst is None:
3484
+ cdst = self._handle(stmt.dst, lvalue=True)
3485
+
3486
+ return CAssignment(cdst, csrc, tags=stmt.tags, codegen=self)
3487
+
3488
+ def _handle_Stmt_WeakAssignment(self, stmt, **kwargs):
3489
+ csrc = self._handle(stmt.src, lvalue=False)
3490
+ cdst = None
3491
+
3492
+ src_type = csrc.type
3493
+ dst_type = src_type
3494
+ if "type" in stmt.tags:
3495
+ src_type = stmt.tags["type"].get("src")
3496
+ dst_type = stmt.tags["type"].get("dst")
3497
+
3498
+ if isinstance(stmt.dst, Expr.VirtualVariable) and stmt.dst.was_stack:
3499
+
3500
+ def negotiate(old_ty, proposed_ty):
3501
+ # transfer casts from the dst to the src if possible
3502
+ # if we see something like *(size_t*)&v4 = x; where v4 is a pointer, change to v4 = (void*)x;
3503
+ nonlocal csrc
3504
+ if not type_equals(old_ty, proposed_ty) and qualifies_for_simple_cast(old_ty, proposed_ty):
3505
+ csrc = CTypeCast(csrc.type, proposed_ty, csrc, codegen=self)
3506
+ return proposed_ty
3507
+ return old_ty
3508
+
3509
+ if stmt.dst.variable is not None:
3510
+ if "struct_member_info" in stmt.dst.tags:
3511
+ offset, var, _ = stmt.dst.tags["struct_member_info"]
3512
+ cvar = self._variable(var, stmt.dst.size, vvar_id=stmt.dst.varid)
3513
+ else:
3514
+ cvar = self._variable(stmt.dst.variable, stmt.dst.size, vvar_id=stmt.dst.varid)
3515
+ offset = stmt.dst.variable_offset or 0
3516
+ assert type(offset) is int # I refuse to deal with the alternative
3517
+
3518
+ cdst = self._access_constant_offset(
3519
+ self._get_variable_reference(cvar), offset, dst_type, True, negotiate
3520
+ )
3521
+
3522
+ if cdst is None:
3523
+ cdst = self._handle(stmt.dst, lvalue=True)
3524
+
3525
+ return CAssignment(cdst, csrc, tags=stmt.tags, codegen=self)
3526
+
3527
+ def _handle_Stmt_Call(self, stmt: Stmt.Call, is_expr: bool = False, **kwargs):
3528
+ try:
3529
+ # Try to handle it as a normal function call
3530
+ target = self._handle(stmt.target, lvalue=True) if not isinstance(stmt.target, str) else stmt.target
3531
+ except UnsupportedNodeTypeError:
3532
+ target = stmt.target
3533
+
3534
+ if (
3535
+ isinstance(target, CUnaryOp)
3536
+ and target.op == "Reference"
3537
+ and isinstance(target.operand, CVariable)
3538
+ and isinstance(target.operand.variable, SimMemoryVariable)
3539
+ and not isinstance(target.operand.variable, SimStackVariable)
3540
+ and target.operand.variable.size == 1
3541
+ ):
3542
+ # special case: convert &global_var to just global_var if it's used as the call target
3543
+ target = target.operand
3544
+
3545
+ target_func = self.kb.functions.function(addr=target.value) if isinstance(target, CConstant) else None
3546
+
3547
+ args = []
3548
+ if stmt.args is not None:
3549
+ for i, arg in enumerate(stmt.args):
3550
+ type_ = None
3551
+ if (
3552
+ target_func is not None
3553
+ and target_func.prototype is not None
3554
+ and i < len(target_func.prototype.args)
3555
+ ):
3556
+ type_ = target_func.prototype.args[i].with_arch(self.project.arch)
3557
+ if target_func.prototype_libname is not None:
3558
+ type_ = dereference_simtype_by_lib(type_, target_func.prototype_libname)
3559
+
3560
+ if isinstance(arg, Expr.Const):
3561
+ if type_ is None or is_machine_word_size_type(type_, self.project.arch):
3562
+ type_ = guess_value_type(arg.value, self.project) or type_
3563
+
3564
+ new_arg = self._handle_Expr_Const(arg, type_=type_)
3565
+ else:
3566
+ new_arg = self._handle(arg, type_=type_)
3567
+ args.append(new_arg)
3568
+
3569
+ ret_expr = None
3570
+ if not is_expr and stmt.ret_expr is not None:
3571
+ ret_expr = self._handle(stmt.ret_expr)
3572
+
3573
+ result = CFunctionCall(
3574
+ target,
3575
+ target_func,
3576
+ args,
3577
+ returning=target_func.returning if target_func is not None else True,
3578
+ ret_expr=ret_expr,
3579
+ tags=stmt.tags,
3580
+ is_expr=is_expr,
3581
+ show_demangled_name=self.show_demangled_name,
3582
+ show_disambiguated_name=self.show_disambiguated_name,
3583
+ codegen=self,
3584
+ )
3585
+
3586
+ if result.is_expr and result.type.size != stmt.size * self.project.arch.byte_width:
3587
+ result = CTypeCast(
3588
+ result.type,
3589
+ self.default_simtype_from_bits(
3590
+ stmt.size * self.project.arch.byte_width, signed=getattr(result.type, "signed", False)
3591
+ ),
3592
+ result,
3593
+ codegen=self,
3594
+ )
3595
+
3596
+ return result
3597
+
3598
+ def _handle_Stmt_Jump(self, stmt: Stmt.Jump, **kwargs):
3599
+ return CGoto(self._handle(stmt.target), stmt.target_idx, tags=stmt.tags, codegen=self)
3600
+
3601
+ def _handle_Stmt_ConditionalJump(self, stmt: Stmt.ConditionalJump, **kwargs):
3602
+ else_node = (
3603
+ None
3604
+ if stmt.false_target is None
3605
+ else CGoto(self._handle(stmt.false_target), None, tags=stmt.tags, codegen=self)
3606
+ )
3607
+ return CIfElse(
3608
+ [(self._handle(stmt.condition), CGoto(self._handle(stmt.true_target), None, tags=stmt.tags, codegen=self))],
3609
+ else_node=else_node,
3610
+ cstyle_ifs=self.cstyle_ifs,
3611
+ tags=stmt.tags,
3612
+ codegen=self,
3613
+ )
3614
+
3615
+ def _handle_Stmt_Return(self, stmt: Stmt.Return, **kwargs):
3616
+ if not stmt.ret_exprs:
3617
+ return CReturn(None, tags=stmt.tags, codegen=self)
3618
+ if len(stmt.ret_exprs) == 1:
3619
+ ret_expr = stmt.ret_exprs[0]
3620
+ return CReturn(self._handle(ret_expr), tags=stmt.tags, codegen=self)
3621
+ # TODO: Multiple return expressions
3622
+ l.warning("StructuredCodeGen does not support multiple return expressions yet. Only picking the first one.")
3623
+ ret_expr = stmt.ret_exprs[0]
3624
+ return CReturn(self._handle(ret_expr), tags=stmt.tags, codegen=self)
3625
+
3626
+ def _handle_Stmt_Label(self, stmt: Stmt.Label, **kwargs):
3627
+ clabel = CLabel(stmt.name, tags=stmt.tags, codegen=self)
3628
+ if "ins_addr" in stmt.tags:
3629
+ self.map_addr_to_label[(stmt.tags["ins_addr"], stmt.tags.get("block_idx"))] = clabel
3630
+ return clabel
3631
+
3632
+ def _handle_Stmt_Dirty(self, stmt: Stmt.DirtyStatement, **kwargs):
3633
+ dirty = self._handle(stmt.dirty)
3634
+ return CDirtyStatement(dirty, codegen=self)
3635
+
3636
+ #
3637
+ # AIL expression handlers
3638
+ #
3639
+
3640
+ def _handle_Expr_Register(self, expr: Expr.Register, lvalue: bool = False, **kwargs):
3641
+ def negotiate(old_ty: SimType, proposed_ty: SimType) -> SimType:
3642
+ # we do not allow returning a struct for a primitive type
3643
+ if old_ty.size == proposed_ty.size and (
3644
+ not isinstance(proposed_ty, SimStruct) or isinstance(old_ty, SimStruct)
3645
+ ):
3646
+ return proposed_ty
3647
+ return old_ty
3648
+
3649
+ if expr.variable:
3650
+ cvar = self._variable(expr.variable, None)
3651
+ if expr.variable.size == expr.size:
3652
+ return cvar
3653
+ offset = 0 if expr.variable_offset is None else expr.variable_offset
3654
+ # FIXME: The type should be associated to the register expression itself
3655
+ type_ = self.default_simtype_from_bits(expr.bits, signed=False)
3656
+ return self._access_constant_offset(self._get_variable_reference(cvar), offset, type_, lvalue, negotiate)
3657
+ return CRegister(expr, tags=expr.tags, codegen=self)
3658
+
3659
+ def _handle_Expr_Load(self, expr: Expr.Load, **kwargs):
3660
+ if expr.size == UNDETERMINED_SIZE:
3661
+ # the size is undetermined; we force it to 1
3662
+ expr_size = 1
3663
+ expr_bits = 8
3664
+ else:
3665
+ expr_size = expr.size
3666
+ expr_bits = expr.bits
3667
+
3668
+ if expr.size > 100 and isinstance(expr.addr, Expr.Const):
3669
+ return self._handle_Expr_Const(expr.addr, type_=SimTypePointer(SimTypeChar()).with_arch(self.project.arch))
3670
+
3671
+ ty = self.default_simtype_from_bits(expr_bits)
3672
+
3673
+ def negotiate(old_ty: SimType, proposed_ty: SimType) -> SimType:
3674
+ # we do not allow returning a struct for a primitive type
3675
+ if (
3676
+ old_ty.size == proposed_ty.size
3677
+ and not isinstance(proposed_ty, SimStruct)
3678
+ and not isinstance(old_ty, SimStruct)
3679
+ ):
3680
+ return proposed_ty
3681
+ return old_ty
3682
+
3683
+ if expr.variable is not None:
3684
+ if "struct_member_info" in expr.tags:
3685
+ offset, var, _ = expr.tags["struct_member_info"]
3686
+ cvar = self._variable(var, var.size)
3687
+ else:
3688
+ cvar = self._variable(expr.variable, expr_size)
3689
+ offset = expr.variable_offset or 0
3690
+
3691
+ assert type(offset) is int # I refuse to deal with the alternative
3692
+ return self._access_constant_offset(CUnaryOp("Reference", cvar, codegen=self), offset, ty, False, negotiate)
3693
+
3694
+ addr_expr = self._handle(expr.addr)
3695
+ return self._access(addr_expr, ty, False, negotiate)
3696
+
3697
+ def _handle_Expr_Tmp(self, expr: Tmp, **kwargs):
3698
+ l.warning("FIXME: Leftover Tmp expressions are found.")
3699
+ return self._variable(SimTemporaryVariable(expr.tmp_idx, expr.bits), expr.size)
3700
+
3701
+ def _handle_Expr_Const(
3702
+ self,
3703
+ expr: Expr.Const,
3704
+ type_=None,
3705
+ reference_values: dict[SimType | str, str | bytes | int | float | Function | CExpression] | None = None,
3706
+ variable=None,
3707
+ likely_signed=True,
3708
+ **kwargs,
3709
+ ):
3710
+ inline_string = False
3711
+ function_pointer = False
3712
+
3713
+ if type_ is None and "type" in expr.tags:
3714
+ type_ = expr.tags["type"]
3715
+
3716
+ if reference_values is None and "reference_values" in expr.tags:
3717
+ reference_values = expr.tags["reference_values"].copy()
3718
+ if type_ is None and reference_values is not None and len(reference_values) == 1: # type: ignore
3719
+ type_ = next(iter(reference_values)) # type: ignore
3720
+
3721
+ if reference_values is None:
3722
+ reference_values = {}
3723
+ type_ = unpack_typeref(type_)
3724
+ if expr.value in self.kb.obfuscations.type1_deobfuscated_strings:
3725
+ deobf_str = self.kb.obfuscations.type1_deobfuscated_strings[expr.value]
3726
+ reference_values[SimTypePointer(SimTypeChar())] = deobf_str
3727
+ if "deobfuscated_strings" not in self.notes:
3728
+ self.notes["deobfuscated_strings"] = DeobfuscatedStringsNote()
3729
+ self.notes["deobfuscated_strings"].add_string("1", deobf_str, ref_addr=expr.value)
3730
+ inline_string = True
3731
+ elif expr.value in self.kb.obfuscations.type2_deobfuscated_strings:
3732
+ deobf_str = self.kb.obfuscations.type2_deobfuscated_strings[expr.value]
3733
+ reference_values[SimTypePointer(SimTypeChar())] = deobf_str
3734
+ if "deobfuscated_strings" not in self.notes:
3735
+ self.notes["deobfuscated_strings"] = DeobfuscatedStringsNote()
3736
+ self.notes["deobfuscated_strings"].add_string("2", deobf_str, ref_addr=expr.value)
3737
+ inline_string = True
3738
+ elif isinstance(type_, SimTypePointer) and isinstance(type_.pts_to, (SimTypeChar, SimTypeBottom)):
3739
+ # char* or void*
3740
+ # Try to get a string
3741
+ if (
3742
+ self._cfg is not None
3743
+ and expr.value in self._cfg.memory_data
3744
+ and self._cfg.memory_data[expr.value].sort == MemoryDataSort.String
3745
+ ):
3746
+ reference_values[type_] = self._cfg.memory_data[expr.value]
3747
+ inline_string = True
3748
+ elif isinstance(type_, SimTypeInt):
3749
+ # int
3750
+ reference_values[type_] = expr.value
3751
+
3752
+ # we don't know the type of this argument, or the type is not what we are expecting
3753
+ # edge cases: (void*)"this is a constant string pointer". in this case, the type_ will be a void*
3754
+ # (BOT*) instead of a char*.
3755
+
3756
+ if not reference_values and isinstance(expr.value, int):
3757
+ if expr.value in self.project.kb.functions:
3758
+ # It's a function pointer
3759
+ # We don't care about the actual prototype here
3760
+ type_ = SimTypePointer(SimTypeBottom(label="void")).with_arch(self.project.arch)
3761
+ reference_values[type_] = self.project.kb.functions[expr.value]
3762
+ function_pointer = True
3763
+
3764
+ # pure guessing: is it possible that it's a string?
3765
+ elif (
3766
+ self._cfg is not None
3767
+ and expr.bits == self.project.arch.bits
3768
+ and expr.value > 0x10000
3769
+ and expr.value in self._cfg.memory_data
3770
+ ):
3771
+ md = self._cfg.memory_data[expr.value]
3772
+ if md.sort == MemoryDataSort.String:
3773
+ type_ = SimTypePointer(SimTypeChar().with_arch(self.project.arch)).with_arch(self.project.arch)
3774
+ reference_values[type_] = self._cfg.memory_data[expr.value]
3775
+ # is it a constant string?
3776
+ if is_in_readonly_segment(self.project, expr.value) or is_in_readonly_section(
3777
+ self.project, expr.value
3778
+ ):
3779
+ inline_string = True
3780
+ elif md.sort == MemoryDataSort.UnicodeString:
3781
+ type_ = SimTypePointer(SimTypeWideChar().with_arch(self.project.arch)).with_arch(
3782
+ self.project.arch
3783
+ )
3784
+ reference_values[type_] = self._cfg.memory_data[expr.value]
3785
+ # is it a constant string?
3786
+ if is_in_readonly_segment(self.project, expr.value) or is_in_readonly_section(
3787
+ self.project, expr.value
3788
+ ):
3789
+ inline_string = True
3790
+
3791
+ if type_ is None:
3792
+ # default to int or unsigned int, determined by likely_signed
3793
+ type_ = self.default_simtype_from_bits(expr.bits, signed=likely_signed)
3794
+
3795
+ if variable is None and "reference_variable" in expr.tags and expr.tags["reference_variable"] is not None:
3796
+ variable = expr.tags["reference_variable"]
3797
+ if inline_string:
3798
+ self._inlined_strings.add(expr.tags["reference_variable"])
3799
+ elif function_pointer:
3800
+ self._function_pointers.add(expr.tags["reference_variable"])
3801
+
3802
+ var_access = None
3803
+ if variable is not None and not reference_values:
3804
+ cvar = self._variable(variable, None)
3805
+ offset = expr.tags.get("reference_variable_offset", 0)
3806
+ var_access = self._access_constant_offset_reference(self._get_variable_reference(cvar), offset, None)
3807
+
3808
+ if var_access is not None:
3809
+ if expr.value >= self.min_data_addr:
3810
+ return var_access
3811
+ reference_values["offset"] = var_access
3812
+ return CConstant(expr.value, type_, reference_values=reference_values, tags=expr.tags, codegen=self)
3813
+
3814
+ def _handle_Expr_UnaryOp(self, expr, type_: SimType | None = None, **kwargs):
3815
+ data_type = None
3816
+ ref = False
3817
+ if expr.op == "Reference":
3818
+ ref = True
3819
+ if isinstance(type_, SimTypePointer) and not isinstance(type_.pts_to, SimTypeBottom):
3820
+ data_type = type_.pts_to
3821
+
3822
+ operand = self._handle(expr.operand, lvalue=expr.op == "Reference", type_=data_type, ref=ref)
3823
+
3824
+ if expr.op == "Reference" and isinstance(operand, CUnaryOp) and operand.op == "Dereference":
3825
+ # cancel out
3826
+ return operand.operand
3827
+ return CUnaryOp(
3828
+ expr.op,
3829
+ operand,
3830
+ tags=expr.tags,
3831
+ codegen=self,
3832
+ )
3833
+
3834
+ def _handle_Expr_BinaryOp(self, expr: BinaryOp, **kwargs):
3835
+ if expr.variable is not None:
3836
+ cvar = self._variable(expr.variable, None)
3837
+ return self._access_constant_offset_reference(
3838
+ self._get_variable_reference(cvar), expr.variable_offset or 0, None
3839
+ )
3840
+
3841
+ lhs = self._handle(expr.operands[0])
3842
+ rhs = self._handle(expr.operands[1], likely_signed=expr.op not in {"And", "Or"})
3843
+
3844
+ return CBinaryOp(
3845
+ expr.op,
3846
+ lhs,
3847
+ rhs,
3848
+ tags=expr.tags,
3849
+ codegen=self,
3850
+ collapsed=expr.depth > self.binop_depth_cutoff,
3851
+ )
3852
+
3853
+ def _handle_Expr_Convert(self, expr: Expr.Convert, **kwargs):
3854
+ # width of converted type is easy
3855
+ dst_type: SimTypeInt | SimTypeChar
3856
+ if 512 >= expr.to_bits > 256:
3857
+ dst_type = SimTypeInt512()
3858
+ elif 256 >= expr.to_bits > 128:
3859
+ dst_type = SimTypeInt256()
3860
+ elif 128 >= expr.to_bits > 64:
3861
+ dst_type = SimTypeInt128()
3862
+ elif 64 >= expr.to_bits > 32:
3863
+ dst_type = SimTypeLongLong()
3864
+ elif 32 >= expr.to_bits > 16:
3865
+ dst_type = SimTypeInt()
3866
+ elif 16 >= expr.to_bits > 8:
3867
+ dst_type = SimTypeShort()
3868
+ elif 8 >= expr.to_bits > 1:
3869
+ dst_type = SimTypeChar()
3870
+ elif expr.to_bits == 1:
3871
+ dst_type = SimTypeChar() # FIXME: Add a SimTypeBit?
3872
+ else:
3873
+ raise UnsupportedNodeTypeError(f"Unsupported conversion bits {expr.to_bits}.")
3874
+
3875
+ # convert child
3876
+ child = self._handle(expr.operand)
3877
+ orig_child_signed = getattr(child.type, "signed", False)
3878
+
3879
+ # signedness of converted type is hard
3880
+ if expr.to_bits < expr.from_bits:
3881
+ # very sketchy. basically a guess
3882
+ # can we even generate signed downcasts?
3883
+ dst_type.signed = orig_child_signed | expr.is_signed
3884
+ else:
3885
+ dst_type.signed = expr.is_signed
3886
+
3887
+ # do we need an intermediate cast?
3888
+ if orig_child_signed != expr.is_signed and expr.to_bits > expr.from_bits:
3889
+ # this is a problem. sign-extension only happens when the SOURCE of the cast is signed
3890
+ child_ty = self.default_simtype_from_bits(child.type.size, expr.is_signed)
3891
+ child = CTypeCast(None, child_ty, child, codegen=self)
3892
+
3893
+ return CTypeCast(None, dst_type.with_arch(self.project.arch), child, tags=expr.tags, codegen=self)
3894
+
3895
+ def _handle_Expr_VEXCCallExpression(self, expr: Expr.VEXCCallExpression, **kwargs):
3896
+ operands = [self._handle(arg) for arg in expr.operands]
3897
+ return CVEXCCallExpression(expr.callee, operands, tags=expr.tags, codegen=self)
3898
+
3899
+ def _handle_Expr_Dirty(self, expr: Expr.DirtyExpression, **kwargs):
3900
+ return CDirtyExpression(expr, codegen=self)
3901
+
3902
+ def _handle_Expr_ITE(self, expr: Expr.ITE, **kwargs):
3903
+ return CITE(
3904
+ self._handle(expr.cond), self._handle(expr.iftrue), self._handle(expr.iffalse), tags=expr.tags, codegen=self
3905
+ )
3906
+
3907
+ def _handle_Reinterpret(self, expr: Expr.Reinterpret, **kwargs):
3908
+ def _to_type(bits, typestr):
3909
+ if typestr == "I":
3910
+ if bits == 32:
3911
+ r = SimTypeInt()
3912
+ elif bits == 64:
3913
+ r = SimTypeLongLong()
3914
+ else:
3915
+ raise TypeError(f"Unsupported integer type with bits {bits} in Reinterpret")
3916
+ elif typestr == "F":
3917
+ if bits == 32:
3918
+ r = SimTypeFloat()
3919
+ elif bits == 64:
3920
+ r = SimTypeDouble()
3921
+ else:
3922
+ raise TypeError(f"Unsupported floating-point type with bits {bits} in Reinterpret")
3923
+ else:
3924
+ raise TypeError(f"Unexpected reinterpret type {typestr}")
3925
+ return r.with_arch(self.project.arch)
3926
+
3927
+ src_type = _to_type(expr.from_bits, expr.from_type)
3928
+ dst_type = _to_type(expr.to_bits, expr.to_type)
3929
+ return CTypeCast(src_type, dst_type, self._handle(expr.operand), tags=expr.tags, codegen=self)
3930
+
3931
+ def _handle_MultiStatementExpression(self, expr: Expr.MultiStatementExpression, **kwargs):
3932
+ cstmts = CStatements([self._handle(stmt, is_expr=False) for stmt in expr.stmts], codegen=self)
3933
+ cexpr = self._handle(expr.expr)
3934
+ return CMultiStatementExpression(cstmts, cexpr, tags=expr.tags, codegen=self)
3935
+
3936
+ def _handle_VirtualVariable(
3937
+ self,
3938
+ expr: Expr.VirtualVariable,
3939
+ lvalue: bool = False,
3940
+ type_: SimType | None = None,
3941
+ ref: bool = False,
3942
+ **kwargs,
3943
+ ):
3944
+ def negotiate(old_ty: SimType, proposed_ty: SimType) -> SimType:
3945
+ # we do not allow returning a struct for a primitive type
3946
+ if old_ty.size == proposed_ty.size and (
3947
+ not isinstance(proposed_ty, SimStruct) or isinstance(old_ty, SimStruct)
3948
+ ):
3949
+ return proposed_ty
3950
+ return old_ty
3951
+
3952
+ if expr.variable is not None:
3953
+ if "struct_member_info" in expr.tags:
3954
+ offset, var, _ = expr.tags["struct_member_info"]
3955
+ if ref: # noqa:SIM108
3956
+ # this virtual variable is only used as the operand of a & operation, so the size is unreliable
3957
+ size = var.size // self.project.arch.byte_width
3958
+ else:
3959
+ size = expr.size
3960
+ cbasevar = self._variable(var, size, vvar_id=expr.varid)
3961
+ data_type = type_
3962
+ if data_type is None:
3963
+ # try to determine the type of this variable read
3964
+ data_type = cbasevar.type
3965
+ if data_type.size // self.project.arch.byte_width > expr.size:
3966
+ # fallback to a more suitable type
3967
+ data_type = (
3968
+ {
3969
+ 64: SimTypeLongLong(signed=False),
3970
+ 32: SimTypeInt(signed=False),
3971
+ 16: SimTypeShort(signed=False),
3972
+ 8: SimTypeChar(signed=False),
3973
+ }
3974
+ .get(expr.bits, data_type)
3975
+ .with_arch(self.project.arch)
3976
+ )
3977
+ if ref and offset == 0:
3978
+ cvar = cbasevar
3979
+ else:
3980
+ cvar = self._access_constant_offset(
3981
+ self._get_variable_reference(cbasevar), offset, data_type, lvalue, negotiate
3982
+ )
3983
+ else:
3984
+ cvar = self._variable(expr.variable, None, vvar_id=expr.varid)
3985
+
3986
+ if not lvalue and expr.variable.size != expr.size:
3987
+ l.warning(
3988
+ "VirtualVariable size (%d) and variable size (%d) do not match. Force a type cast.",
3989
+ expr.size,
3990
+ expr.variable.size,
3991
+ )
3992
+ src_type = cvar.type
3993
+ dst_type = {
3994
+ 64: SimTypeLongLong(signed=False),
3995
+ 32: SimTypeInt(signed=False),
3996
+ 16: SimTypeShort(signed=False),
3997
+ 8: SimTypeChar(signed=False),
3998
+ }.get(expr.bits, None)
3999
+ if dst_type is not None:
4000
+ dst_type = dst_type.with_arch(self.project.arch)
4001
+ return CTypeCast(src_type, dst_type, cvar, tags=expr.tags, codegen=self)
4002
+ return cvar
4003
+ return CDirtyExpression(expr, codegen=self)
4004
+
4005
+ def _handle_Expr_StackBaseOffset(self, expr: StackBaseOffset, **kwargs):
4006
+ if expr.variable is not None:
4007
+ var_thing = self._variable(expr.variable, expr.size)
4008
+ var_thing.tags = dict(expr.tags)
4009
+ if "def_at" in var_thing.tags and "ins_addr" not in var_thing.tags:
4010
+ var_thing.tags["ins_addr"] = var_thing.tags["def_at"].ins_addr
4011
+ return self._get_variable_reference(var_thing)
4012
+
4013
+ # FIXME
4014
+ stack_base = CFakeVariable("stack_base", SimTypePointer(SimTypeBottom()), codegen=self)
4015
+ return CBinaryOp("Add", stack_base, CConstant(expr.offset, SimTypeInt(), codegen=self), codegen=self)
4016
+
4017
+
4018
+ class CStructuredCodeWalker:
4019
+ def handle(self, obj):
4020
+ handler = getattr(self, "handle_" + type(obj).__name__, self.handle_default)
4021
+ return handler(obj)
4022
+
4023
+ def handle_default(self, obj):
4024
+ return obj
4025
+
4026
+ def handle_CFunction(self, obj):
4027
+ obj.statements = self.handle(obj.statements)
4028
+ return obj
4029
+
4030
+ def handle_CStatements(self, obj):
4031
+ obj.statements = [self.handle(stmt) for stmt in obj.statements]
4032
+ return obj
4033
+
4034
+ def handle_CWhileLoop(self, obj):
4035
+ obj.condition = self.handle(obj.condition)
4036
+ obj.body = self.handle(obj.body)
4037
+ return obj
4038
+
4039
+ def handle_CDoWhileLoop(self, obj):
4040
+ obj.condition = self.handle(obj.condition)
4041
+ obj.body = self.handle(obj.body)
4042
+ return obj
4043
+
4044
+ def handle_CForLoop(self, obj):
4045
+ obj.initializer = self.handle(obj.initializer)
4046
+ obj.condition = self.handle(obj.condition)
4047
+ obj.iterator = self.handle(obj.iterator)
4048
+ obj.body = self.handle(obj.body)
4049
+ return obj
4050
+
4051
+ def handle_CIfElse(self, obj):
4052
+ obj.condition_and_nodes = [
4053
+ (self.handle(condition), self.handle(node)) for condition, node in obj.condition_and_nodes
4054
+ ]
4055
+ obj.else_node = self.handle(obj.else_node)
4056
+ return obj
4057
+
4058
+ def handle_CIfBreak(self, obj):
4059
+ obj.condition = self.handle(obj.condition)
4060
+ return obj
4061
+
4062
+ def handle_CSwitchCase(self, obj):
4063
+ obj.switch = self.handle(obj.switch)
4064
+ obj.cases = [(case, self.handle(body)) for case, body in obj.cases]
4065
+ obj.default = self.handle(obj.default)
4066
+ return obj
4067
+
4068
+ def handle_CAssignment(self, obj):
4069
+ obj.lhs = self.handle(obj.lhs)
4070
+ obj.rhs = self.handle(obj.rhs)
4071
+ return obj
4072
+
4073
+ def handle_CFunctionCall(self, obj):
4074
+ obj.callee_target = self.handle(obj.callee_target)
4075
+ obj.args = [self.handle(arg) for arg in obj.args]
4076
+ obj.ret_expr = self.handle(obj.ret_expr)
4077
+ return obj
4078
+
4079
+ def handle_CReturn(self, obj):
4080
+ obj.retval = self.handle(obj.retval)
4081
+ return obj
4082
+
4083
+ def handle_CGoto(self, obj):
4084
+ obj.target = self.handle(obj.target)
4085
+ return obj
4086
+
4087
+ def handle_CIndexedVariable(self, obj):
4088
+ obj.variable = self.handle(obj.variable)
4089
+ obj.index = self.handle(obj.index)
4090
+ return obj
4091
+
4092
+ def handle_CVariableField(self, obj):
4093
+ obj.variable = self.handle(obj.variable)
4094
+ return obj
4095
+
4096
+ def handle_CUnaryOp(self, obj):
4097
+ obj.operand = self.handle(obj.operand)
4098
+ return obj
4099
+
4100
+ def handle_CBinaryOp(self, obj):
4101
+ obj.lhs = self.handle(obj.lhs)
4102
+ obj.rhs = self.handle(obj.rhs)
4103
+ return obj
4104
+
4105
+ def handle_CTypeCast(self, obj):
4106
+ obj.expr = self.handle(obj.expr)
4107
+ return obj
4108
+
4109
+ def handle_CITE(self, obj):
4110
+ obj.cond = self.handle(obj.cond)
4111
+ obj.iftrue = self.handle(obj.iftrue)
4112
+ obj.iffalse = self.handle(obj.iffalse)
4113
+ return obj
4114
+
4115
+
4116
+ class MakeTypecastsImplicit(CStructuredCodeWalker):
4117
+ @classmethod
4118
+ def collapse(cls, dst_ty: SimType, child: CExpression) -> CExpression:
4119
+ result = child
4120
+ if isinstance(child, CTypeCast):
4121
+ intermediate_ty = child.dst_type
4122
+ start_ty = child.src_type
4123
+
4124
+ # step 1: collapse pointer-integer casts of the same size
4125
+ if qualifies_for_simple_cast(intermediate_ty, dst_ty) and qualifies_for_simple_cast(start_ty, dst_ty):
4126
+ result = child.expr
4127
+ # step 2: collapse integer conversions which are redundant
4128
+ if (
4129
+ isinstance(dst_ty, (SimTypeChar, SimTypeInt, SimTypeNum))
4130
+ and isinstance(intermediate_ty, (SimTypeChar, SimTypeInt, SimTypeNum))
4131
+ and isinstance(start_ty, (SimTypeChar, SimTypeInt, SimTypeNum))
4132
+ ):
4133
+ assert dst_ty.size and start_ty.size and intermediate_ty.size
4134
+ if dst_ty.size <= start_ty.size and dst_ty.size <= intermediate_ty.size:
4135
+ # this is a down- or neutral-cast with an intermediate step that doesn't matter
4136
+ result = child.expr
4137
+ elif dst_ty.size >= intermediate_ty.size >= start_ty.size and intermediate_ty.signed == start_ty.signed:
4138
+ # this is an up- or neutral-cast which is monotonically ascending
4139
+ # we can leave out the dst_ty.signed check
4140
+ result = child.expr
4141
+ # more cases go here...
4142
+
4143
+ if result is not child:
4144
+ # TODO this is not the best since it prohibits things like the BinaryOp optimizer from working incrementally
4145
+ return cls.collapse(dst_ty, result)
4146
+ return result
4147
+
4148
+ def handle_CAssignment(self, obj):
4149
+ obj.rhs = self.collapse(obj.lhs.type, obj.rhs)
4150
+ return super().handle_CAssignment(obj)
4151
+
4152
+ def handle_CFunctionCall(self, obj: CFunctionCall):
4153
+ prototype_args = [] if obj.prototype is None else obj.prototype.args
4154
+ for i, (c_arg, arg_ty) in enumerate(zip(obj.args, prototype_args)):
4155
+ obj.args[i] = self.collapse(arg_ty, c_arg)
4156
+ return super().handle_CFunctionCall(obj)
4157
+
4158
+ def handle_CReturn(self, obj: CReturn):
4159
+ obj.retval = self.collapse(obj.codegen._func.prototype.returnty, obj.retval)
4160
+ return super().handle_CReturn(obj)
4161
+
4162
+ def handle_CBinaryOp(self, obj: CBinaryOp):
4163
+ obj = super().handle_CBinaryOp(obj)
4164
+ while True:
4165
+ new_lhs = self.collapse(obj.common_type, obj.lhs)
4166
+ if (
4167
+ new_lhs is not obj.lhs
4168
+ and CBinaryOp.compute_common_type(obj.op, new_lhs.type, obj.rhs.type) == obj.common_type
4169
+ ):
4170
+ obj.lhs = new_lhs
4171
+ else:
4172
+ new_rhs = self.collapse(obj.common_type, obj.rhs)
4173
+ if (
4174
+ new_rhs is not obj.rhs
4175
+ and CBinaryOp.compute_common_type(obj.op, obj.lhs.type, new_rhs.type) == obj.common_type
4176
+ ):
4177
+ obj.rhs = new_rhs
4178
+ else:
4179
+ break
4180
+ return obj
4181
+
4182
+ def handle_CTypeCast(self, obj: CTypeCast):
4183
+ # note that the expression that this method returns may no longer be a CTypeCast
4184
+ obj = super().handle_CTypeCast(obj)
4185
+ inner = self.collapse(obj.dst_type, obj.expr)
4186
+ if inner is not obj.expr:
4187
+ obj.src_type = inner.type
4188
+ obj.expr = inner
4189
+ if obj.src_type == obj.dst_type or qualifies_for_implicit_cast(obj.src_type, obj.dst_type):
4190
+ return obj.expr
4191
+ return obj
4192
+
4193
+
4194
+ class FieldReferenceCleanup(CStructuredCodeWalker):
4195
+ def handle_CTypeCast(self, obj):
4196
+ if isinstance(obj.dst_type, SimTypePointer) and not isinstance(obj.dst_type.pts_to, SimTypeBottom):
4197
+ new_obj = obj.codegen._access_reference(obj.expr, obj.dst_type.pts_to)
4198
+ if not isinstance(new_obj, CTypeCast):
4199
+ return self.handle(new_obj)
4200
+ return super().handle_CTypeCast(obj)
4201
+
4202
+
4203
+ class PointerArithmeticFixer(CStructuredCodeWalker):
4204
+ """
4205
+ Before calling this fixer class, pointer arithmetics are purely integer-based and ignoring the pointer type.
4206
+
4207
+ For example, in the following case:
4208
+
4209
+ struct A* a_ptr; // assume struct A is 24 bytes in size
4210
+ a_ptr = a_ptr + 24;
4211
+
4212
+ It means adding 24 to the address of a_ptr, without considering the size of struct A. This fixer class will make
4213
+ pointer arithmetics aware of the pointer type. In this case, the fixer class will convert the code to
4214
+ a_ptr = a_ptr + 1.
4215
+ """
4216
+
4217
+ def handle_CAssignment(self, obj: CAssignment):
4218
+ if "type" in obj.tags and "dst" in obj.tags["type"] and "src" in obj.tags["type"]:
4219
+ # HACK: do not attempt to fix pointer arithmetic if dst and src types are explicitly given
4220
+ # FIXME: Properly propagate dst and src types to lhs and rhs
4221
+ return obj
4222
+ return super().handle_CAssignment(obj)
4223
+
4224
+ def handle_CBinaryOp(self, obj: CBinaryOp): # type: ignore
4225
+ obj: CBinaryOp = super().handle_CBinaryOp(obj)
4226
+ if (
4227
+ obj.op in ("Add", "Sub")
4228
+ and isinstance(obj.type, SimTypePointer)
4229
+ and not isinstance(obj.type.pts_to, SimTypeBottom)
4230
+ ):
4231
+ out = obj.codegen._access_reference(obj, obj.type.pts_to)
4232
+ if (
4233
+ isinstance(out, CUnaryOp)
4234
+ and out.op == "Reference"
4235
+ and isinstance(out.operand, CIndexedVariable)
4236
+ and isinstance(out.operand.index, CConstant)
4237
+ ):
4238
+ # rewrite &a[1] to a + 1
4239
+ const = out.operand.index
4240
+ if isinstance(const.value, int) and const.value < 0:
4241
+ op = "Sub"
4242
+ const = CConstant(
4243
+ -const.value,
4244
+ const.type,
4245
+ reference_values=const.reference_values,
4246
+ tags=const.tags,
4247
+ codegen=const.codegen,
4248
+ )
4249
+ else:
4250
+ op = "Add"
4251
+ return CBinaryOp(op, out.operand.variable, const, tags=out.operand.tags, codegen=out.codegen)
4252
+ return out
4253
+ return obj
4254
+
4255
+
4256
+ StructuredCodeGenerator = CStructuredCodeGenerator
4257
+ register_analysis(StructuredCodeGenerator, "StructuredCodeGenerator")