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