angr 9.2.103__py3-none-macosx_11_0_arm64.whl

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

Potentially problematic release.


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

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