diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94707d2..82d044c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,16 +1,99 @@ IDAPython ========= + ### Contributing to IDAPython -This page really is only a read-only version of the source code we -host internally at http://www.hex-rays.com, and pull requests will -not be honored. +Anyone with a valid license is welcome to contribute to IDAPython, and pull +requests will be honored provided their nature matches the criteria below. -However, we will gladly accept patches & suggestions. Please send +If you prefer using patches over git/github+pull requests, please send those to . -Found a bug? ------------- -Users with an IDA license that is still under support are -encouraged to report bugs to . +### What can I contribute? + +We at Hex-Rays are currently maintaining the official IDAPython repository. + +Because we are not an infinite-sized company and thus have limited resources +([interested?](https://www.hex-rays.com/jobs.shtml)), we have to keep the +scope of IDAPython itself to a manageable size. + +Most of IDAPython consists of rather low-level, arguably non-pythonic APIs. +The reason for that is of course not that we have anything against pythonic +APIs, but we have found that: + +- what is idiomatic & pythonic to certain users, will not necessarily be + to the taste of others, +- when trying to provide pythonic/somewhat higher-level APIs, we often + ended up not providing the lower-level APIs, sometimes making it + impossible to build your own utilities should the APIs IDAPython provides + out-of-the box be insufficient, buggy or just not to your taste, +- users are better at coming up with their own layers anyway. + E.g., https://github.com/tmr232/Sark + +Therefore, the most important aspect of any contribution to IDAPython +should not be about making it more pythonic and/or higher-level, but +instead to make sure that its low-level API (which to a significant degree +are generated from the C/C++ IDA SDK by using SWiG) work fine, are +correctly documented, and tested. + +That is the approach we took in order to make sane & well-working +higher-level APIs possible at all. + + +### Should I write a test? + +If your changes touch the APIs from a functional perspective (e.g., fix +a bug, or make a new function available), yes. + +There is no such thing as a _code_ change in IDAPython, that is not +accompanied by a test, so please go through the trouble of writing one +so we don't have to do it ourselves. + +When it comes to other types of pull requests (e.g., documentation), +it should usually not be necessary to write a test. + + +### How to write tests? + +Pull requests that actually modify IDAPython code, and that come +together with a test script, have a better chance of being accepted, +because we do not happily push code to IDAPython without making sure +we have non-regression mechanisms into place. + +While we won't share our non-regression tools, it is enough to say +that many IDAPython APIs can be tested by mimicking the user entering +commands directly into IDA, and looking at the output. + +E.g., here is a part of an actual, real test currently running in +our non-regression environment, testing the `refwidth` property of a +`cexpr_t` instance: + +``` +Python>x = cexpr_t() +Python>x.refwidth +0 +Python>x.refwidth = 18 +Python>x.refwidth +18 +Python>x.refwidth = var_ref_t() +Traceback (most recent call last): + , , in + , , in + refwidth = property( lambda self: self._get_refwidth() if True else 0, lambda self, v: True and self._ensure_no_obj(self._get_refwidth(),"refwidth", False) and self._acquire_ownership(v, False) and self._set_refwidth(v)) + , , in _set_refwidth + return _ida_hexrays.cexpr_t__set_refwidth(self, *args) +TypeError: in method 'cexpr_t__set_refwidth', argument 2 of type 'int' +``` + +The key points are: + +- this represents a "dialog" with IDAPython: input is prepended with + "Python>", and output is inline +- this describes what should happen when those operations are performed + +Sending us similar testing 'scripts' alongside a pull request, will speed +up its integration significantly, since we'll be able to add the test to +our non-regression environment very quickly. + +Please also see [the best practices for developing on IDAPython](HOWTO.md) diff --git a/HOWTO.md b/HOWTO.md index 80b8373..a47812d 100644 --- a/HOWTO.md +++ b/HOWTO.md @@ -1,6 +1,6 @@ -# HOW-TO +# Developing IDAPython: best practices -### Whatever you do +### Rule of thumb If you are doing something non-trivial in IDAPython, or if you added something to the C++ SDK which will then be reflected in IDAPython, an *immensely* diff --git a/Scripts/msdnapihelp.py b/Scripts/msdnapihelp.py index 72881f9..8b9df34 100644 --- a/Scripts/msdnapihelp.py +++ b/Scripts/msdnapihelp.py @@ -17,6 +17,21 @@ try: except: ida_kernwin.warning('Feedparser package not installed') +def get_url(ident): + """ + Note: This code is left in a separate, toplevel function so that + tests can easily override it and provide a replacement file:// + URL and work on machines without an internet connection + """ + try: + # This is a 'hook' to enable testing on machines disconnected + # from the internet (we're not testing feedparser's HTTPS URL + # download capabilities anyway) + import sys + return sys.modules["__main__"].get_url(ident) + except: + return "https://social.msdn.microsoft.com/search/en-US/feed?query=%s&format=RSS&theme=feed%%2fen-us" % ident + # ----------------------------------------------------------------------- class msdnapihelp_plugin_t(ida_idaapi.plugin_t): flags = ida_idaapi.PLUGIN_UNL @@ -47,8 +62,7 @@ class msdnapihelp_plugin_t(ida_idaapi.plugin_t): ident = self.sanitize_name(ident) print "Looking up '%s' in MSDN online" % ident - qurl = "https://social.msdn.microsoft.com/search/en-US/feed?query=%s&format=RSS&theme=feed%%2fen-us" - d = feedparser.parse(qurl % ident) + d = feedparser.parse(get_url(ident)) if len(d['entries']) > 0: url = d['entries'][0].link if arg > 0: diff --git a/api_contents.txt b/api_contents.txt index 8c449a8..2211045 100644 --- a/api_contents.txt +++ b/api_contents.txt @@ -20,10 +20,45 @@ 'DBG_Hooks_dbg_trace', 'DBG_Hooks_hook', 'DBG_Hooks_unhook', + 'Hexrays_Hooks_close_pseudocode', + 'Hexrays_Hooks_cmt_changed', + 'Hexrays_Hooks_combine', + 'Hexrays_Hooks_create_hint', + 'Hexrays_Hooks_curpos', + 'Hexrays_Hooks_double_click', + 'Hexrays_Hooks_flowchart', + 'Hexrays_Hooks_func_printed', + 'Hexrays_Hooks_glbopt', + 'Hexrays_Hooks_hook', + 'Hexrays_Hooks_interr', + 'Hexrays_Hooks_keyboard', + 'Hexrays_Hooks_locopt', + 'Hexrays_Hooks_lvar_cmt_changed', + 'Hexrays_Hooks_lvar_mapping_changed', + 'Hexrays_Hooks_lvar_name_changed', + 'Hexrays_Hooks_lvar_type_changed', + 'Hexrays_Hooks_maturity', + 'Hexrays_Hooks_microcode', + 'Hexrays_Hooks_open_pseudocode', + 'Hexrays_Hooks_populating_popup', + 'Hexrays_Hooks_prealloc', + 'Hexrays_Hooks_preoptimized', + 'Hexrays_Hooks_print_func', + 'Hexrays_Hooks_prolog', + 'Hexrays_Hooks_refresh_pseudocode', + 'Hexrays_Hooks_resolve_stkaddrs', + 'Hexrays_Hooks_right_click', + 'Hexrays_Hooks_stkpnts', + 'Hexrays_Hooks_structural', + 'Hexrays_Hooks_switch_pseudocode', + 'Hexrays_Hooks_text_ready', + 'Hexrays_Hooks_unhook', 'IDB_Hooks_allsegs_moved', 'IDB_Hooks_auto_empty', 'IDB_Hooks_auto_empty_finally', + 'IDB_Hooks_bookmark_changed', 'IDB_Hooks_byte_patched', + 'IDB_Hooks_callee_addr_changed', 'IDB_Hooks_changing_cmt', 'IDB_Hooks_changing_enum_bf', 'IDB_Hooks_changing_enum_cmt', @@ -70,6 +105,7 @@ 'IDB_Hooks_func_updated', 'IDB_Hooks_hook', 'IDB_Hooks_idasgn_loaded', + 'IDB_Hooks_item_color_changed', 'IDB_Hooks_kernel_config_loaded', 'IDB_Hooks_loader_finished', 'IDB_Hooks_local_types_changed', @@ -94,6 +130,7 @@ 'IDB_Hooks_set_func_end', 'IDB_Hooks_set_func_start', 'IDB_Hooks_sgr_changed', + 'IDB_Hooks_sgr_deleted', 'IDB_Hooks_stkpnts_changed', 'IDB_Hooks_struc_align_changed', 'IDB_Hooks_struc_cmt_changed', @@ -238,6 +275,8 @@ 'TPointDouble_x_set', 'TPointDouble_y_get', 'TPointDouble_y_set', + 'TWidget__from_ptrval__', + 'UI_Hooks_create_desktop_widget', 'UI_Hooks_current_widget_changed', 'UI_Hooks_database_inited', 'UI_Hooks_debugger_menu_change', @@ -288,6 +327,7 @@ '_ask_long__varargs__', '_ask_seg', '_ask_seg__varargs__', + '_choose_get_embedded_chobj_pointer', '_decompile', '_kludge_use_TPopupMenu', '_ll_call_helper', @@ -303,7 +343,6 @@ 'action_ctx_base_t__get_form', 'action_ctx_base_t__get_form_title', 'action_ctx_base_t__get_form_type', - 'action_ctx_base_t__get_reg', 'action_ctx_base_t_action_get', 'action_ctx_base_t_action_set', 'action_ctx_base_t_chooser_selection_get', @@ -329,6 +368,8 @@ 'action_ctx_base_t_focus_get', 'action_ctx_base_t_focus_set', 'action_ctx_base_t_has_flag', + 'action_ctx_base_t_regname_get', + 'action_ctx_base_t_regname_set', 'action_ctx_base_t_reserved_get', 'action_ctx_base_t_reserved_set', 'action_ctx_base_t_reset', @@ -705,6 +746,10 @@ 'bgcolors_t_switch_color_set', 'bin_flag', 'bin_search', + 'bit_bound_t_nbits_get', + 'bit_bound_t_nbits_set', + 'bit_bound_t_sbits_get', + 'bit_bound_t_sbits_set', 'bitfield_type_data_t___eq__', 'bitfield_type_data_t___ge__', 'bitfield_type_data_t___gt__', @@ -909,6 +954,7 @@ 'calc_default_idaplace_flags', 'calc_dist', 'calc_fixup_size', + 'calc_func_size', 'calc_idasgn_state', 'calc_max_align', 'calc_max_item_end', @@ -921,6 +967,8 @@ 'calc_stkvar_struc_offset', 'calc_switch_cases', 'calc_target', + 'calc_target__SWIG_0', + 'calc_target__SWIG_1', 'calc_thunk_func_target', 'calc_tinfo_gaps', 'calc_type_size', @@ -1215,13 +1263,17 @@ 'cexpr_t_is_const_value', 'cexpr_t_is_cstr', 'cexpr_t_is_fpop', + 'cexpr_t_is_jumpout', 'cexpr_t_is_negative_const', 'cexpr_t_is_nice_cond', 'cexpr_t_is_nice_expr', + 'cexpr_t_is_non_negative_const', 'cexpr_t_is_non_zero_const', 'cexpr_t_is_odd_lvalue', 'cexpr_t_is_type_signed', 'cexpr_t_is_type_unsigned', + 'cexpr_t_is_undef_val', + 'cexpr_t_is_vftable', 'cexpr_t_is_zero_const', 'cexpr_t_maybe_ptr', 'cexpr_t_numval', @@ -1230,6 +1282,7 @@ 'cexpr_t_requires_lvalue', 'cexpr_t_set_cpadone', 'cexpr_t_set_v', + 'cexpr_t_set_vftable', 'cexpr_t_swap', 'cexpr_t_theother', 'cexpr_t_theother__SWIG_0', @@ -1262,6 +1315,8 @@ 'cfunc_t_entry_ea_get', 'cfunc_t_entry_ea_set', 'cfunc_t_find_item_coords', + 'cfunc_t_find_item_coords__SWIG_0', + 'cfunc_t_find_item_coords__SWIG_1', 'cfunc_t_find_label', 'cfunc_t_gather_derefs', 'cfunc_t_get_boundaries', @@ -1322,6 +1377,8 @@ 'cfuncptr_t_entry_ea_get', 'cfuncptr_t_entry_ea_set', 'cfuncptr_t_find_item_coords', + 'cfuncptr_t_find_item_coords__SWIG_0', + 'cfuncptr_t_find_item_coords__SWIG_1', 'cfuncptr_t_find_label', 'cfuncptr_t_gather_derefs', 'cfuncptr_t_get_boundaries', @@ -1411,8 +1468,6 @@ 'choose_enum_by_value', 'choose_find', 'choose_func', - 'choose_get_embedded', - 'choose_get_embedded_selection', 'choose_get_widget', 'choose_idasgn', 'choose_local_tinfo', @@ -1550,6 +1605,7 @@ 'citem_t__set_op', 'citem_t_cexpr_get', 'citem_t_cinsn_get', + 'citem_t_contains_expr', 'citem_t_contains_label', 'citem_t_ea_get', 'citem_t_ea_set', @@ -1627,6 +1683,10 @@ 'cnumber_t_value', 'code_flag', 'codegen_t_analyze_prolog', + 'codegen_t_emit', + 'codegen_t_emit__SWIG_0', + 'codegen_t_emit__SWIG_1', + 'codegen_t_emit_micro_mvm', 'codegen_t_gen_micro', 'codegen_t_ignore_micro_get', 'codegen_t_ignore_micro_set', @@ -1642,11 +1702,9 @@ 'compare', 'compare', 'compare', - 'compare__SWIG_17', + 'compare__SWIG_10', + 'compare__SWIG_11', 'compare__SWIG_19', - 'compare__SWIG_20', - 'compare__SWIG_21', - 'compare__SWIG_22', 'compare__SWIG_23', 'compare__SWIG_24', 'compare__SWIG_25', @@ -1663,14 +1721,16 @@ 'compare__SWIG_36', 'compare__SWIG_37', 'compare__SWIG_38', + 'compare__SWIG_39', + 'compare__SWIG_40', + 'compare__SWIG_41', + 'compare__SWIG_42', 'compare__SWIG_5', 'compare__SWIG_6', 'compare__SWIG_7', 'compare__SWIG_7', - 'compare__SWIG_8', 'compare__SWIG_9', 'compare_tinfo', - 'compare_typsrc', 'compile_idc_file', 'compile_idc_snippet', 'compile_idc_text', @@ -1702,6 +1762,7 @@ 'convert_pt_flags_to_hti', 'convert_to_user_call', 'copy_idcv', + 'copy_named_type', 'copy_sreg_ranges', 'copy_tinfo_t', 'create_16bit_data', @@ -1885,6 +1946,7 @@ 'data_format_t___get_id', 'data_format_t_hotkey_get', 'data_format_t_hotkey_set', + 'data_format_t_is_present_in_menus', 'data_format_t_menu_name_get', 'data_format_t_menu_name_set', 'data_format_t_name_get', @@ -1900,6 +1962,7 @@ 'data_type_t_asm_keyword_set', 'data_type_t_hotkey_get', 'data_type_t_hotkey_set', + 'data_type_t_is_present_in_menus', 'data_type_t_menu_name_get', 'data_type_t_menu_name_set', 'data_type_t_name_get', @@ -2037,6 +2100,7 @@ 'del_virt_module', 'delay_slot_insn', 'delete_DBG_Hooks', + 'delete_Hexrays_Hooks', 'delete_IDB_Hooks', 'delete_IDP_Hooks', 'delete_TPointDouble', @@ -2046,10 +2110,8 @@ 'delete___qsemaphore_t', 'delete___qthread_t', 'delete___qtimer_t', - 'delete_action_activation_ctx_t', 'delete_action_ctx_base_t', 'delete_action_desc_t', - 'delete_action_update_ctx_t', 'delete_addon_info_t', 'delete_aloc_visitor_t', 'delete_argloc_t', @@ -2060,6 +2122,7 @@ 'delete_asm_t', 'delete_auto_display_t', 'delete_bgcolors_t', + 'delete_bit_bound_t', 'delete_bitfield_type_data_t', 'delete_boolvec_t', 'delete_boundaries_iterator_t', @@ -2121,6 +2184,7 @@ 'delete_disasm_text_t', 'delete_ea_array', 'delete_ea_name_t', + 'delete_ea_name_vec_t', 'delete_ea_pointer', 'delete_eamap_iterator_t', 'delete_eamap_t', @@ -2173,7 +2237,6 @@ 'delete_imports', 'delete_insn_t', 'delete_instant_dbgopts_t', - 'delete_int64vec_t', 'delete_int_pointer', 'delete_interval_t', 'delete_intvec_t', @@ -2186,6 +2249,7 @@ 'delete_lochist_t', 'delete_lock_func', 'delete_lock_segment', + 'delete_longlongvec_t', 'delete_lowertype_helper_t', 'delete_lvar_locator_t', 'delete_lvar_mapping_iterator_t', @@ -2196,6 +2260,8 @@ 'delete_lvar_uservec_t', 'delete_lvars_t', 'delete_member_t', + 'delete_meminfo_vec_t', + 'delete_memory_info_t', 'delete_memreg_info_t', 'delete_memreg_infos_t', 'delete_menu', @@ -2218,6 +2284,7 @@ 'delete_plugin_info_t', 'delete_point_t', 'delete_pointseq_t', + 'delete_pointvec_t', 'delete_predicate_t', 'delete_printop_t', 'delete_process_info_t', @@ -2235,6 +2302,7 @@ 'delete_qvector_history_t', 'delete_qvector_lvar_t', 'delete_qvector_snapshotvec_t', + 'delete_range_array', 'delete_range_t', 'delete_rangeset_t', 'delete_rangevec_base_t', @@ -2247,6 +2315,7 @@ 'delete_regobj_t', 'delete_regobjs_t', 'delete_regval_t', + 'delete_regvar_array', 'delete_regvar_t', 'delete_renderer_info_pos_t', 'delete_renderer_info_t', @@ -2270,6 +2339,9 @@ 'delete_sizevec_t', 'delete_snapshot_t', 'delete_sreg_range_t', + 'delete_stkpnt_array', + 'delete_stkpnt_t', + 'delete_stkpnts_t', 'delete_strarray_t', 'delete_string_info_t', 'delete_strpath_ids_array', @@ -2282,7 +2354,11 @@ 'delete_sval_pointer', 'delete_switch_info_t', 'delete_switch_table', + 'delete_tev_info_reg_t', 'delete_tev_info_t', + 'delete_tev_reg_value_t', + 'delete_tev_reg_values_t', + 'delete_tevinforeg_vec_t', 'delete_text_sink_t', 'delete_thread_name_t', 'delete_tid_array', @@ -2308,6 +2384,8 @@ 'delete_udt_type_data_t', 'delete_udtmembervec_t', 'delete_ui_requests_t', + 'delete_uintvec_t', + 'delete_ulonglongvec_t', 'delete_unreferenced_stkvars', 'delete_user_cmts_iterator_t', 'delete_user_cmts_t', @@ -2322,7 +2400,6 @@ 'delete_user_unions_iterator_t', 'delete_user_unions_t', 'delete_uval_array', - 'delete_uvalvec_t', 'delete_valstr_t', 'delete_valstrs_t', 'delete_var_ref_t', @@ -2348,8 +2425,15 @@ 'detach_custom_data_format', 'detach_process', 'diff_trace_file', + 'disable_bblk_trace', + 'disable_bpt', + 'disable_bpt__SWIG_0', + 'disable_bpt__SWIG_1', 'disable_flags', + 'disable_func_trace', + 'disable_insn_trace', 'disable_script_timeout', + 'disable_step_trace', 'disasm_line_t_at_get', 'disasm_line_t_at_set', 'disasm_line_t_bg_color_get', @@ -2393,6 +2477,7 @@ 'disasm_text_t_swap', 'disasm_text_t_truncate', 'disown_DBG_Hooks', + 'disown_Hexrays_Hooks', 'disown_IDB_Hooks', 'disown_IDP_Hooks', 'disown_UI_Hooks', @@ -2434,6 +2519,38 @@ 'ea_name_t_ea_set', 'ea_name_t_name_get', 'ea_name_t_name_set', + 'ea_name_vec_t___getitem__', + 'ea_name_vec_t___len__', + 'ea_name_vec_t___setitem__', + 'ea_name_vec_t_at', + 'ea_name_vec_t_begin', + 'ea_name_vec_t_begin__SWIG_0', + 'ea_name_vec_t_begin__SWIG_1', + 'ea_name_vec_t_capacity', + 'ea_name_vec_t_clear', + 'ea_name_vec_t_empty', + 'ea_name_vec_t_end', + 'ea_name_vec_t_end__SWIG_0', + 'ea_name_vec_t_end__SWIG_1', + 'ea_name_vec_t_erase', + 'ea_name_vec_t_erase__SWIG_0', + 'ea_name_vec_t_erase__SWIG_1', + 'ea_name_vec_t_extract', + 'ea_name_vec_t_grow', + 'ea_name_vec_t_inject', + 'ea_name_vec_t_insert', + 'ea_name_vec_t_pop_back', + 'ea_name_vec_t_push_back', + 'ea_name_vec_t_push_back__SWIG_0', + 'ea_name_vec_t_push_back__SWIG_1', + 'ea_name_vec_t_qclear', + 'ea_name_vec_t_reserve', + 'ea_name_vec_t_resize', + 'ea_name_vec_t_resize__SWIG_0', + 'ea_name_vec_t_resize__SWIG_1', + 'ea_name_vec_t_size', + 'ea_name_vec_t_swap', + 'ea_name_vec_t_truncate', 'ea_pointer_assign', 'ea_pointer_cast', 'ea_pointer_frompointer', @@ -2615,6 +2732,7 @@ 'execute_sync', 'execute_ui_requests', 'exist', + 'exist_bpt', 'exists_fixup', 'exit_process', 'expand_struc', @@ -2623,7 +2741,9 @@ 'extract_module_from_archive', 'extract_name', 'f_any', + 'f_has_cmt', 'f_has_dummy_name', + 'f_has_extra_cmts', 'f_has_name', 'f_has_user_name', 'f_has_xref', @@ -2709,6 +2829,7 @@ 'fixup_data_t_set_type', 'fixup_data_t_set_type_and_flags', 'fixup_data_t_set_unused', + 'fixup_data_t_was_created', 'fixup_info_t_ea_get', 'fixup_info_t_ea_set', 'fixup_info_t_fd_get', @@ -2798,6 +2919,9 @@ 'func_parent_iterator_t_prev', 'func_parent_iterator_t_reset_fnt', 'func_parent_iterator_t_set', + 'func_t___get_points__', + 'func_t___get_regvars__', + 'func_t___get_tails__', 'func_t__from_ptrval__', 'func_t_analyzed_sp', 'func_t_argsize_get', @@ -2935,6 +3059,8 @@ 'gen_fix_fixups', 'gen_flow_graph', 'gen_gdl', + 'gen_idb_event', + 'gen_idb_event__varargs__', 'gen_simple_call_chart', 'gen_use_arg_tinfos', 'generate_disasm_line', @@ -2958,6 +3084,7 @@ 'get_action_state', 'get_action_tooltip', 'get_action_visibility', + 'get_active_modal_widget', 'get_addon_info', 'get_addon_info_idx', 'get_aflags', @@ -3019,10 +3146,13 @@ 'get_db_byte', 'get_dbg_byte', 'get_dbg_memory_info', + 'get_dbg_reg_info', 'get_debug_event', 'get_debug_name', 'get_debug_name_ea', 'get_debug_names', + 'get_debug_names__SWIG_0', + 'get_debug_names__SWIG_1', 'get_debugger_event_cond', 'get_default_encoding_idx', 'get_default_radix', @@ -3036,6 +3166,7 @@ 'get_ea_name', 'get_ea_viewer_history_info', 'get_effective_spd', + 'get_elf_debug_file_directory', 'get_encoding_bpu', 'get_encoding_name', 'get_encoding_qty', @@ -3182,6 +3313,8 @@ 'get_lookback', 'get_manual_insn', 'get_manual_regions', + 'get_manual_regions__SWIG_0', + 'get_manual_regions__SWIG_1', 'get_mapping', 'get_mappings_qty', 'get_mark_comment', @@ -3210,6 +3343,8 @@ 'get_name_value', 'get_named_type', 'get_named_type64', + 'get_navband_ea', + 'get_navband_pixel', 'get_next_bmask', 'get_next_cref_from', 'get_next_cref_to', @@ -3275,6 +3410,7 @@ 'get_prev_serial_enum_member', 'get_prev_sreg_range', 'get_prev_struc_idx', + 'get_printable_immvals', 'get_problem', 'get_problem_desc', 'get_problem_name', @@ -3288,6 +3424,8 @@ 'get_reg_info', 'get_reg_name', 'get_reg_val', + 'get_reg_val__SWIG_0', + 'get_reg_val__SWIG_1', 'get_reg_vals', 'get_registered_actions', 'get_ret_tev_return', @@ -3390,6 +3528,7 @@ 'get_widget_title', 'get_widget_type', 'get_widget_vdui', + 'get_window_id', 'get_word', 'get_zero_ranges', 'getn_bpt', @@ -3469,8 +3608,8 @@ 'has_user_name', 'has_value', 'has_xref', - 'have_set_options', 'hex_flag', + 'hexrays_alloc', 'hexrays_failure_t_code_get', 'hexrays_failure_t_code_set', 'hexrays_failure_t_desc', @@ -3478,6 +3617,7 @@ 'hexrays_failure_t_errea_set', 'hexrays_failure_t_str_get', 'hexrays_failure_t_str_set', + 'hexrays_free', 'hexwarn_t___eq__', 'hexwarn_t___ge__', 'hexwarn_t___gt__', @@ -3568,7 +3708,6 @@ 'idainfo_af2_set', 'idainfo_af_get', 'idainfo_af_set', - 'idainfo_allow_nonmatched_ops', 'idainfo_appcall_options_get', 'idainfo_appcall_options_set', 'idainfo_apptype_get', @@ -3582,7 +3721,6 @@ 'idainfo_bin_prefix_size_set', 'idainfo_cc_get', 'idainfo_cc_set', - 'idainfo_check_manual_ops', 'idainfo_comment_get', 'idainfo_comment_set', 'idainfo_database_change_count_get', @@ -3670,10 +3808,8 @@ 'idainfo_s_xrefflag_get', 'idainfo_s_xrefflag_set', 'idainfo_set_64bit', - 'idainfo_set_allow_nonmatched_ops', 'idainfo_set_auto_enabled', 'idainfo_set_be', - 'idainfo_set_check_manual_ops', 'idainfo_set_gen_lzero', 'idainfo_set_gen_null', 'idainfo_set_gen_tryblks', @@ -3872,6 +4008,7 @@ 'insn_t_insnpref_set', 'insn_t_ip_get', 'insn_t_ip_set', + 'insn_t_is_64bit', 'insn_t_is_canon_insn', 'insn_t_is_macro', 'insn_t_itype_get', @@ -3883,7 +4020,6 @@ 'insn_t_size_get', 'insn_t_size_set', 'install_command_interpreter', - 'install_hexrays_callback', 'install_microcode_filter', 'instant_dbgopts_t__pass_get', 'instant_dbgopts_t__pass_set', @@ -3901,45 +4037,6 @@ 'instant_dbgopts_t_pid_set', 'instant_dbgopts_t_port_get', 'instant_dbgopts_t_port_set', - 'int64vec_t___eq__', - 'int64vec_t___getitem__', - 'int64vec_t___len__', - 'int64vec_t___ne__', - 'int64vec_t___setitem__', - 'int64vec_t__del', - 'int64vec_t_add_unique', - 'int64vec_t_at', - 'int64vec_t_begin', - 'int64vec_t_begin__SWIG_0', - 'int64vec_t_begin__SWIG_1', - 'int64vec_t_capacity', - 'int64vec_t_clear', - 'int64vec_t_empty', - 'int64vec_t_end', - 'int64vec_t_end__SWIG_0', - 'int64vec_t_end__SWIG_1', - 'int64vec_t_erase', - 'int64vec_t_erase__SWIG_0', - 'int64vec_t_erase__SWIG_1', - 'int64vec_t_extract', - 'int64vec_t_find', - 'int64vec_t_find__SWIG_0', - 'int64vec_t_find__SWIG_1', - 'int64vec_t_has', - 'int64vec_t_inject', - 'int64vec_t_insert', - 'int64vec_t_pop_back', - 'int64vec_t_push_back', - 'int64vec_t_push_back__SWIG_0', - 'int64vec_t_push_back__SWIG_1', - 'int64vec_t_qclear', - 'int64vec_t_reserve', - 'int64vec_t_resize', - 'int64vec_t_resize__SWIG_0', - 'int64vec_t_resize__SWIG_1', - 'int64vec_t_size', - 'int64vec_t_swap', - 'int64vec_t_truncate', 'int_pointer_assign', 'int_pointer_cast', 'int_pointer_frompointer', @@ -3983,7 +4080,6 @@ 'intvec_t_find', 'intvec_t_find__SWIG_0', 'intvec_t_find__SWIG_1', - 'intvec_t_grow', 'intvec_t_has', 'intvec_t_inject', 'intvec_t_insert', @@ -3999,6 +4095,7 @@ 'intvec_t_size', 'intvec_t_swap', 'intvec_t_truncate', + 'invalidate_dbg_state', 'invalidate_dbgmem_config', 'invalidate_dbgmem_contents', 'is__bnot0', @@ -4139,6 +4236,7 @@ 'is_reg_float', 'is_reg_integer', 'is_relational', + 'is_request_running', 'is_restype_enum', 'is_restype_struct', 'is_restype_struni', @@ -4203,6 +4301,7 @@ 'is_type_struct', 'is_type_struni', 'is_type_sue', + 'is_type_tbyte', 'is_type_typedef', 'is_type_uchar', 'is_type_uint', @@ -4238,6 +4337,7 @@ 'is_yword', 'is_zstroff', 'is_zword', + 'jobj_wrapper_t_get_dict', 'jumpto', 'jumpto__SWIG_0', 'jumpto__SWIG_1', @@ -4325,6 +4425,45 @@ 'lock_segm', 'log2ceil', 'log2floor', + 'longlongvec_t___eq__', + 'longlongvec_t___getitem__', + 'longlongvec_t___len__', + 'longlongvec_t___ne__', + 'longlongvec_t___setitem__', + 'longlongvec_t__del', + 'longlongvec_t_add_unique', + 'longlongvec_t_at', + 'longlongvec_t_begin', + 'longlongvec_t_begin__SWIG_0', + 'longlongvec_t_begin__SWIG_1', + 'longlongvec_t_capacity', + 'longlongvec_t_clear', + 'longlongvec_t_empty', + 'longlongvec_t_end', + 'longlongvec_t_end__SWIG_0', + 'longlongvec_t_end__SWIG_1', + 'longlongvec_t_erase', + 'longlongvec_t_erase__SWIG_0', + 'longlongvec_t_erase__SWIG_1', + 'longlongvec_t_extract', + 'longlongvec_t_find', + 'longlongvec_t_find__SWIG_0', + 'longlongvec_t_find__SWIG_1', + 'longlongvec_t_has', + 'longlongvec_t_inject', + 'longlongvec_t_insert', + 'longlongvec_t_pop_back', + 'longlongvec_t_push_back', + 'longlongvec_t_push_back__SWIG_0', + 'longlongvec_t_push_back__SWIG_1', + 'longlongvec_t_qclear', + 'longlongvec_t_reserve', + 'longlongvec_t_resize', + 'longlongvec_t_resize__SWIG_0', + 'longlongvec_t_resize__SWIG_1', + 'longlongvec_t_size', + 'longlongvec_t_swap', + 'longlongvec_t_truncate', 'lookup_key_code', 'lower_type', 'lowertype_helper_t_func_has_stkframe_hole', @@ -4340,10 +4479,10 @@ 'lvar_locator_t_defea_set', 'lvar_locator_t_get_reg1', 'lvar_locator_t_get_reg2', - 'lvar_locator_t_get_regnum', 'lvar_locator_t_get_scattered', 'lvar_locator_t_get_scattered__SWIG_0', 'lvar_locator_t_get_scattered__SWIG_1', + 'lvar_locator_t_get_stkoff', 'lvar_locator_t_is_reg1', 'lvar_locator_t_is_reg2', 'lvar_locator_t_is_reg_var', @@ -4374,17 +4513,23 @@ 'lvar_saved_info_t___eq__', 'lvar_saved_info_t___ne__', 'lvar_saved_info_t_clear_keep', + 'lvar_saved_info_t_clr_forced_lvar', + 'lvar_saved_info_t_clr_noptr_lvar', 'lvar_saved_info_t_cmt_get', 'lvar_saved_info_t_cmt_set', 'lvar_saved_info_t_flags_get', 'lvar_saved_info_t_flags_set', 'lvar_saved_info_t_has_info', + 'lvar_saved_info_t_is_forced_lvar', 'lvar_saved_info_t_is_kept', + 'lvar_saved_info_t_is_noptr_lvar', 'lvar_saved_info_t_ll_get', 'lvar_saved_info_t_ll_set', 'lvar_saved_info_t_name_get', 'lvar_saved_info_t_name_set', + 'lvar_saved_info_t_set_forced_lvar', 'lvar_saved_info_t_set_keep', + 'lvar_saved_info_t_set_noptr_lvar', 'lvar_saved_info_t_size_get', 'lvar_saved_info_t_size_set', 'lvar_saved_info_t_type_get', @@ -4430,14 +4575,18 @@ 'lvar_saved_infos_t_swap', 'lvar_saved_infos_t_truncate', 'lvar_t_accepts_type', + 'lvar_t_append_list', 'lvar_t_clear_used', 'lvar_t_clr_arg_var', 'lvar_t_clr_fake_var', 'lvar_t_clr_floating_var', + 'lvar_t_clr_forced_var', 'lvar_t_clr_mapdst_var', 'lvar_t_clr_mreg_done', + 'lvar_t_clr_noptr_var', 'lvar_t_clr_overlapped_var', 'lvar_t_clr_spoiled_var', + 'lvar_t_clr_thisarg', 'lvar_t_clr_unknown_width', 'lvar_t_clr_user_info', 'lvar_t_clr_user_name', @@ -4451,16 +4600,21 @@ 'lvar_t_has_common', 'lvar_t_has_common_bit', 'lvar_t_has_nice_name', + 'lvar_t_has_regname', 'lvar_t_has_user_info', 'lvar_t_has_user_name', 'lvar_t_has_user_type', + 'lvar_t_is_aliasable', 'lvar_t_is_arg_var', 'lvar_t_is_fake_var', 'lvar_t_is_floating_var', + 'lvar_t_is_forced_var', 'lvar_t_is_mapdst_var', + 'lvar_t_is_noptr_var', 'lvar_t_is_overlapped_var', 'lvar_t_is_result_var', 'lvar_t_is_spoiled_var', + 'lvar_t_is_thisarg', 'lvar_t_is_unknown_width', 'lvar_t_mreg_done', 'lvar_t_name_get', @@ -4469,13 +4623,15 @@ 'lvar_t_set_fake_var', 'lvar_t_set_final_lvar_type', 'lvar_t_set_floating_var', + 'lvar_t_set_forced_var', 'lvar_t_set_lvar_type', 'lvar_t_set_mapdst_var', 'lvar_t_set_mreg_done', 'lvar_t_set_non_typed', + 'lvar_t_set_noptr_var', 'lvar_t_set_overlapped_var', - 'lvar_t_set_reg_name', 'lvar_t_set_spoiled_var', + 'lvar_t_set_thisarg', 'lvar_t_set_typed', 'lvar_t_set_unknown_width', 'lvar_t_set_used', @@ -4537,11 +4693,66 @@ 'member_t_has_union', 'member_t_id_get', 'member_t_id_set', + 'member_t_is_baseclass', + 'member_t_is_destructor', + 'member_t_is_dupname', 'member_t_props_get', 'member_t_props_set', 'member_t_soff_get', 'member_t_soff_set', 'member_t_unimem', + 'meminfo_vec_t___eq__', + 'meminfo_vec_t___getitem__', + 'meminfo_vec_t___len__', + 'meminfo_vec_t___ne__', + 'meminfo_vec_t___setitem__', + 'meminfo_vec_t__del', + 'meminfo_vec_t_add_unique', + 'meminfo_vec_t_at', + 'meminfo_vec_t_begin', + 'meminfo_vec_t_begin__SWIG_0', + 'meminfo_vec_t_begin__SWIG_1', + 'meminfo_vec_t_capacity', + 'meminfo_vec_t_clear', + 'meminfo_vec_t_empty', + 'meminfo_vec_t_end', + 'meminfo_vec_t_end__SWIG_0', + 'meminfo_vec_t_end__SWIG_1', + 'meminfo_vec_t_erase', + 'meminfo_vec_t_erase__SWIG_0', + 'meminfo_vec_t_erase__SWIG_1', + 'meminfo_vec_t_extract', + 'meminfo_vec_t_find', + 'meminfo_vec_t_find__SWIG_0', + 'meminfo_vec_t_find__SWIG_1', + 'meminfo_vec_t_grow', + 'meminfo_vec_t_has', + 'meminfo_vec_t_inject', + 'meminfo_vec_t_insert', + 'meminfo_vec_t_pop_back', + 'meminfo_vec_t_push_back', + 'meminfo_vec_t_push_back__SWIG_0', + 'meminfo_vec_t_push_back__SWIG_1', + 'meminfo_vec_t_qclear', + 'meminfo_vec_t_reserve', + 'meminfo_vec_t_resize', + 'meminfo_vec_t_resize__SWIG_0', + 'meminfo_vec_t_resize__SWIG_1', + 'meminfo_vec_t_size', + 'meminfo_vec_t_swap', + 'meminfo_vec_t_truncate', + 'memory_info_t___eq__', + 'memory_info_t___ne__', + 'memory_info_t_bitness_get', + 'memory_info_t_bitness_set', + 'memory_info_t_name_get', + 'memory_info_t_name_set', + 'memory_info_t_perm_get', + 'memory_info_t_perm_set', + 'memory_info_t_sbase_get', + 'memory_info_t_sbase_set', + 'memory_info_t_sclass_get', + 'memory_info_t_sclass_set', 'memreg_info_t_ea_get', 'memreg_info_t_ea_set', 'memreg_info_t_get_bytes', @@ -4610,6 +4821,7 @@ 'mutable_graph_t_empty', 'mutable_graph_t_exists', 'mutable_graph_t_get_custom_layout', + 'mutable_graph_t_get_edge', 'mutable_graph_t_get_first_subgraph_node', 'mutable_graph_t_get_graph_groups', 'mutable_graph_t_get_next_subgraph_node', @@ -4783,6 +4995,7 @@ 'netnode_valstr', 'netnode_value_exists', 'new_DBG_Hooks', + 'new_Hexrays_Hooks', 'new_IDB_Hooks', 'new_IDP_Hooks', 'new_TPointDouble', @@ -4795,10 +5008,8 @@ 'new___qsemaphore_t', 'new___qthread_t', 'new___qtimer_t', - 'new_action_activation_ctx_t', 'new_action_ctx_base_t', 'new_action_desc_t', - 'new_action_update_ctx_t', 'new_addon_info_t', 'new_aloc_visitor_t', 'new_argloc_t', @@ -4815,6 +5026,7 @@ 'new_asm_t', 'new_auto_display_t', 'new_bgcolors_t', + 'new_bit_bound_t', 'new_bitfield_type_data_t', 'new_boolvec_t', 'new_boolvec_t__SWIG_0', @@ -4923,6 +5135,9 @@ 'new_ea_name_t', 'new_ea_name_t__SWIG_0', 'new_ea_name_t__SWIG_1', + 'new_ea_name_vec_t', + 'new_ea_name_vec_t__SWIG_0', + 'new_ea_name_vec_t__SWIG_1', 'new_ea_pointer', 'new_eamap_iterator_t', 'new_eamap_t', @@ -5004,9 +5219,6 @@ 'new_idp_name_t', 'new_insn_t', 'new_instant_dbgopts_t', - 'new_int64vec_t', - 'new_int64vec_t__SWIG_0', - 'new_int64vec_t__SWIG_1', 'new_int_pointer', 'new_interval_t', 'new_interval_t__SWIG_0', @@ -5027,6 +5239,9 @@ 'new_lochist_t', 'new_lock_func', 'new_lock_segment', + 'new_longlongvec_t', + 'new_longlongvec_t__SWIG_0', + 'new_longlongvec_t__SWIG_1', 'new_lvar_locator_t', 'new_lvar_locator_t__SWIG_0', 'new_lvar_locator_t__SWIG_1', @@ -5039,6 +5254,10 @@ 'new_lvar_uservec_t', 'new_lvars_t', 'new_member_t', + 'new_meminfo_vec_t', + 'new_meminfo_vec_t__SWIG_0', + 'new_meminfo_vec_t__SWIG_1', + 'new_memory_info_t', 'new_memreg_info_t', 'new_memreg_infos_t', 'new_memreg_infos_t__SWIG_0', @@ -5066,6 +5285,9 @@ 'new_point_t__SWIG_0', 'new_point_t__SWIG_1', 'new_pointseq_t', + 'new_pointvec_t', + 'new_pointvec_t__SWIG_0', + 'new_pointvec_t__SWIG_1', 'new_predicate_t', 'new_printop_t', 'new_process_info_t', @@ -5101,6 +5323,7 @@ 'new_qvector_snapshotvec_t', 'new_qvector_snapshotvec_t__SWIG_0', 'new_qvector_snapshotvec_t__SWIG_1', + 'new_range_array', 'new_range_t', 'new_range_t__SWIG_0', 'new_range_t__SWIG_1', @@ -5127,6 +5350,7 @@ 'new_regval_t', 'new_regval_t__SWIG_0', 'new_regval_t__SWIG_1', + 'new_regvar_array', 'new_regvar_t', 'new_renderer_info_pos_t', 'new_renderer_info_t', @@ -5161,6 +5385,9 @@ 'new_sizevec_t__SWIG_1', 'new_snapshot_t', 'new_sreg_range_t', + 'new_stkpnt_array', + 'new_stkpnt_t', + 'new_stkpnts_t', 'new_strarray_t', 'new_string_info_t', 'new_string_info_t__SWIG_0', @@ -5174,7 +5401,15 @@ 'new_strwinsetup_t', 'new_sval_pointer', 'new_switch_info_t', + 'new_tev_info_reg_t', 'new_tev_info_t', + 'new_tev_reg_value_t', + 'new_tev_reg_values_t', + 'new_tev_reg_values_t__SWIG_0', + 'new_tev_reg_values_t__SWIG_1', + 'new_tevinforeg_vec_t', + 'new_tevinforeg_vec_t__SWIG_0', + 'new_tevinforeg_vec_t__SWIG_1', 'new_text_sink_t', 'new_thread_name_t', 'new_tid_array', @@ -5184,6 +5419,7 @@ 'new_tinfo_t', 'new_tinfo_t__SWIG_0', 'new_tinfo_t__SWIG_1', + 'new_tinfo_t__SWIG_2', 'new_tinfo_visitor_t', 'new_treeloc_t', 'new_try_handler_t', @@ -5215,6 +5451,12 @@ 'new_udtmembervec_t__SWIG_0', 'new_udtmembervec_t__SWIG_1', 'new_ui_requests_t', + 'new_uintvec_t', + 'new_uintvec_t__SWIG_0', + 'new_uintvec_t__SWIG_1', + 'new_ulonglongvec_t', + 'new_ulonglongvec_t__SWIG_0', + 'new_ulonglongvec_t__SWIG_1', 'new_user_cmts_iterator_t', 'new_user_cmts_t', 'new_user_iflags_iterator_t', @@ -5227,9 +5469,6 @@ 'new_user_unions_iterator_t', 'new_user_unions_t', 'new_uval_array', - 'new_uvalvec_t', - 'new_uvalvec_t__SWIG_0', - 'new_uvalvec_t__SWIG_1', 'new_valstr_t', 'new_valstrs_t', 'new_var_ref_t', @@ -5525,6 +5764,7 @@ 'outctx_base_t_retrieve_cmt', 'outctx_base_t_retrieve_name', 'outctx_base_t_set_comment_addr', + 'outctx_base_t_set_dlbind_opnd', 'outctx_base_t_set_gen_cmt', 'outctx_base_t_set_gen_demangled_label', 'outctx_base_t_set_gen_label', @@ -5560,6 +5800,8 @@ 'outctx_t_retrieve_cmt', 'outctx_t_retrieve_name', 'outctx_t_setup_outctx', + 'outctx_t_wif_get', + 'outctx_t_wif_set', 'oword_flag', 'pack_idcobj_to_bv', 'pack_idcobj_to_idb', @@ -5629,6 +5871,7 @@ 'plan_range', 'plan_to_apply_idasgn', 'plgform_close', + 'plgform_get_widget', 'plgform_new', 'plgform_show', 'plugin_info_t_arg_get', @@ -5662,6 +5905,46 @@ 'point_t_x_set', 'point_t_y_get', 'point_t_y_set', + 'pointvec_t___eq__', + 'pointvec_t___getitem__', + 'pointvec_t___len__', + 'pointvec_t___ne__', + 'pointvec_t___setitem__', + 'pointvec_t__del', + 'pointvec_t_add_unique', + 'pointvec_t_at', + 'pointvec_t_begin', + 'pointvec_t_begin__SWIG_0', + 'pointvec_t_begin__SWIG_1', + 'pointvec_t_capacity', + 'pointvec_t_clear', + 'pointvec_t_empty', + 'pointvec_t_end', + 'pointvec_t_end__SWIG_0', + 'pointvec_t_end__SWIG_1', + 'pointvec_t_erase', + 'pointvec_t_erase__SWIG_0', + 'pointvec_t_erase__SWIG_1', + 'pointvec_t_extract', + 'pointvec_t_find', + 'pointvec_t_find__SWIG_0', + 'pointvec_t_find__SWIG_1', + 'pointvec_t_grow', + 'pointvec_t_has', + 'pointvec_t_inject', + 'pointvec_t_insert', + 'pointvec_t_pop_back', + 'pointvec_t_push_back', + 'pointvec_t_push_back__SWIG_0', + 'pointvec_t_push_back__SWIG_1', + 'pointvec_t_qclear', + 'pointvec_t_reserve', + 'pointvec_t_resize', + 'pointvec_t_resize__SWIG_0', + 'pointvec_t_resize__SWIG_1', + 'pointvec_t_size', + 'pointvec_t_swap', + 'pointvec_t_truncate', 'predicate_t_should_display', 'prev_addr', 'prev_chunk', @@ -5733,9 +6016,14 @@ 'ptr_type_data_t_based_ptr_size_set', 'ptr_type_data_t_closure_get', 'ptr_type_data_t_closure_set', + 'ptr_type_data_t_delta_get', + 'ptr_type_data_t_delta_set', 'ptr_type_data_t_is_code_ptr', + 'ptr_type_data_t_is_shifted', 'ptr_type_data_t_obj_type_get', 'ptr_type_data_t_obj_type_set', + 'ptr_type_data_t_parent_get', + 'ptr_type_data_t_parent_set', 'ptr_type_data_t_swap', 'ptr_type_data_t_taptr_bits_get', 'ptr_type_data_t_taptr_bits_set', @@ -5870,6 +6158,8 @@ 'qlist_cinsn_t_insert__SWIG_0', 'qlist_cinsn_t_insert__SWIG_1', 'qlist_cinsn_t_insert__SWIG_3', + 'qlist_cinsn_t_iterator___eq__', + 'qlist_cinsn_t_iterator___ne__', 'qlist_cinsn_t_iterator_cur_get', 'qlist_cinsn_t_iterator_next', 'qlist_cinsn_t_pop_back', @@ -6113,6 +6403,11 @@ 'qvector_snapshotvec_t_swap', 'qvector_snapshotvec_t_truncate', 'qword_flag', + 'range_array___getitem__', + 'range_array___len__', + 'range_array___setitem__', + 'range_array_count_get', + 'range_array_data_get', 'range_t___eq__', 'range_t___gt__', 'range_t___lt__', @@ -6393,6 +6688,11 @@ 'regval_t_set_float', 'regval_t_set_int', 'regval_t_swap', + 'regvar_array___getitem__', + 'regvar_array___len__', + 'regvar_array___setitem__', + 'regvar_array_count_get', + 'regvar_array_data_get', 'regvar_t_canon_get', 'regvar_t_canon_set', 'regvar_t_cmt_get', @@ -6407,7 +6707,6 @@ 'remove_abi_opts', 'remove_command_interpreter', 'remove_func_tail', - 'remove_hexrays_callback', 'remove_pointer', 'remove_tinfo_pointer', 'rename_bptgrp', @@ -6443,6 +6742,7 @@ 'renderer_pos_info_t_sx_set', 'reorder_dummy_names', 'repaint_custom_viewer', + 'replace_ordinal_typerefs', 'replace_wait_box', 'replace_wait_box__varargs__', 'request_add_bpt', @@ -6455,6 +6755,13 @@ 'request_del_bpt__SWIG_0', 'request_del_bpt__SWIG_1', 'request_detach_process', + 'request_disable_bblk_trace', + 'request_disable_bpt', + 'request_disable_bpt__SWIG_0', + 'request_disable_bpt__SWIG_1', + 'request_disable_func_trace', + 'request_disable_insn_trace', + 'request_disable_step_trace', 'request_enable_bblk_trace', 'request_enable_bpt', 'request_enable_bpt__SWIG_0', @@ -6705,10 +7012,6 @@ 'set_custom_data_type_ids', 'set_custom_viewer_qt_aware', 'set_database_flag', - 'set_dbg_default_options', - 'set_dbg_options', - 'set_dbg_options__SWIG_0', - 'set_dbg_options__SWIG_1', 'set_debug_event_code', 'set_debug_name', 'set_debugger_event_cond', @@ -6757,13 +7060,13 @@ 'set_imagebase', 'set_immd', 'set_insn_trace_options', - 'set_int_dbg_options', 'set_item_color', 'set_libitem', 'set_lzero', 'set_lzero0', 'set_lzero1', 'set_manual_insn', + 'set_manual_regions', 'set_member_cmt', 'set_member_name', 'set_member_tinfo', @@ -6790,6 +7093,7 @@ 'set_reg_val', 'set_reg_val__SWIG_0', 'set_reg_val__SWIG_1', + 'set_reg_val__SWIG_2', 'set_regvar_cmt', 'set_remote_debugger', 'set_resume_mode', @@ -6943,6 +7247,16 @@ 'step_into', 'step_over', 'step_until_ret', + 'stkpnt_array___getitem__', + 'stkpnt_array___len__', + 'stkpnt_array___setitem__', + 'stkpnt_array_count_get', + 'stkpnt_array_data_get', + 'stkpnt_t___lt__', + 'stkpnt_t_ea_get', + 'stkpnt_t_ea_set', + 'stkpnt_t_spd_get', + 'stkpnt_t_spd_set', 'stkvar_flag', 'store_exceptions', 'store_til', @@ -7055,6 +7369,7 @@ 'sval_pointer_frompointer', 'sval_pointer_value', 'swap_idcvs', + 'swapped_relation', 'switch_info_t__from_ptrval__', 'switch_info_t__get_values_lowcase', 'switch_info_t__set_values_lowcase', @@ -7116,12 +7431,84 @@ 'take_memory_snapshot', 'tbyte_flag', 'term_hexrays_plugin', + 'tev_info_reg_t_info_get', + 'tev_info_reg_t_info_set', + 'tev_info_reg_t_registers_get', + 'tev_info_reg_t_registers_set', 'tev_info_t_ea_get', 'tev_info_t_ea_set', 'tev_info_t_tid_get', 'tev_info_t_tid_set', 'tev_info_t_type_get', 'tev_info_t_type_set', + 'tev_reg_value_t_reg_idx_get', + 'tev_reg_value_t_reg_idx_set', + 'tev_reg_value_t_value_get', + 'tev_reg_value_t_value_set', + 'tev_reg_values_t___getitem__', + 'tev_reg_values_t___len__', + 'tev_reg_values_t___setitem__', + 'tev_reg_values_t_at', + 'tev_reg_values_t_begin', + 'tev_reg_values_t_begin__SWIG_0', + 'tev_reg_values_t_begin__SWIG_1', + 'tev_reg_values_t_capacity', + 'tev_reg_values_t_clear', + 'tev_reg_values_t_empty', + 'tev_reg_values_t_end', + 'tev_reg_values_t_end__SWIG_0', + 'tev_reg_values_t_end__SWIG_1', + 'tev_reg_values_t_erase', + 'tev_reg_values_t_erase__SWIG_0', + 'tev_reg_values_t_erase__SWIG_1', + 'tev_reg_values_t_extract', + 'tev_reg_values_t_grow', + 'tev_reg_values_t_inject', + 'tev_reg_values_t_insert', + 'tev_reg_values_t_pop_back', + 'tev_reg_values_t_push_back', + 'tev_reg_values_t_push_back__SWIG_0', + 'tev_reg_values_t_push_back__SWIG_1', + 'tev_reg_values_t_qclear', + 'tev_reg_values_t_reserve', + 'tev_reg_values_t_resize', + 'tev_reg_values_t_resize__SWIG_0', + 'tev_reg_values_t_resize__SWIG_1', + 'tev_reg_values_t_size', + 'tev_reg_values_t_swap', + 'tev_reg_values_t_truncate', + 'tevinforeg_vec_t___getitem__', + 'tevinforeg_vec_t___len__', + 'tevinforeg_vec_t___setitem__', + 'tevinforeg_vec_t_at', + 'tevinforeg_vec_t_begin', + 'tevinforeg_vec_t_begin__SWIG_0', + 'tevinforeg_vec_t_begin__SWIG_1', + 'tevinforeg_vec_t_capacity', + 'tevinforeg_vec_t_clear', + 'tevinforeg_vec_t_empty', + 'tevinforeg_vec_t_end', + 'tevinforeg_vec_t_end__SWIG_0', + 'tevinforeg_vec_t_end__SWIG_1', + 'tevinforeg_vec_t_erase', + 'tevinforeg_vec_t_erase__SWIG_0', + 'tevinforeg_vec_t_erase__SWIG_1', + 'tevinforeg_vec_t_extract', + 'tevinforeg_vec_t_grow', + 'tevinforeg_vec_t_inject', + 'tevinforeg_vec_t_insert', + 'tevinforeg_vec_t_pop_back', + 'tevinforeg_vec_t_push_back', + 'tevinforeg_vec_t_push_back__SWIG_0', + 'tevinforeg_vec_t_push_back__SWIG_1', + 'tevinforeg_vec_t_qclear', + 'tevinforeg_vec_t_reserve', + 'tevinforeg_vec_t_resize', + 'tevinforeg_vec_t_resize__SWIG_0', + 'tevinforeg_vec_t_resize__SWIG_1', + 'tevinforeg_vec_t_size', + 'tevinforeg_vec_t_swap', + 'tevinforeg_vec_t_truncate', 'text_sink_t__print', 'textctrl_info_t_assign', 'textctrl_info_t_create', @@ -7210,7 +7597,6 @@ 'tinfo_t_deserialize__SWIG_0', 'tinfo_t_deserialize__SWIG_1', 'tinfo_t_deserialize__SWIG_2', - 'tinfo_t_deserialize__SWIG_3', 'tinfo_t_dstr', 'tinfo_t_empty', 'tinfo_t_equals_to', @@ -7251,6 +7637,8 @@ 'tinfo_t_get_udt_nmembers', 'tinfo_t_get_unpadded_size', 'tinfo_t_has_details', + 'tinfo_t_has_vftable', + 'tinfo_t_is_anonymous_udt', 'tinfo_t_is_arithmetic', 'tinfo_t_is_array', 'tinfo_t_is_bitfield', @@ -7283,6 +7671,7 @@ 'tinfo_t_is_decl_ptr', 'tinfo_t_is_decl_struct', 'tinfo_t_is_decl_sue', + 'tinfo_t_is_decl_tbyte', 'tinfo_t_is_decl_typedef', 'tinfo_t_is_decl_uchar', 'tinfo_t_is_decl_udt', @@ -7323,11 +7712,13 @@ 'tinfo_t_is_purging_cc', 'tinfo_t_is_pvoid', 'tinfo_t_is_scalar', + 'tinfo_t_is_shifted_ptr', 'tinfo_t_is_signed', 'tinfo_t_is_small_udt', 'tinfo_t_is_sse_type', 'tinfo_t_is_struct', 'tinfo_t_is_sue', + 'tinfo_t_is_tbyte', 'tinfo_t_is_typeref', 'tinfo_t_is_uchar', 'tinfo_t_is_udt', @@ -7341,12 +7732,14 @@ 'tinfo_t_is_unsigned', 'tinfo_t_is_user_cc', 'tinfo_t_is_vararg_cc', + 'tinfo_t_is_vftable', 'tinfo_t_is_void', 'tinfo_t_is_volatile', 'tinfo_t_is_well_defined', 'tinfo_t_present', 'tinfo_t_read_bitfield_value', 'tinfo_t_remove_ptr_or_array', + 'tinfo_t_requires_qualifier', 'tinfo_t_serialize', 'tinfo_t_set_attr', 'tinfo_t_set_attrs', @@ -7532,6 +7925,7 @@ 'udt_member_t_begin', 'udt_member_t_clr_baseclass', 'udt_member_t_clr_unaligned', + 'udt_member_t_clr_vftable', 'udt_member_t_clr_virtbase', 'udt_member_t_cmt_get', 'udt_member_t_cmt_set', @@ -7540,9 +7934,11 @@ 'udt_member_t_end', 'udt_member_t_fda_get', 'udt_member_t_fda_set', + 'udt_member_t_is_anonymous_udm', 'udt_member_t_is_baseclass', 'udt_member_t_is_bitfield', 'udt_member_t_is_unaligned', + 'udt_member_t_is_vftable', 'udt_member_t_is_virtbase', 'udt_member_t_is_zero_bitfield', 'udt_member_t_name_get', @@ -7551,6 +7947,7 @@ 'udt_member_t_offset_set', 'udt_member_t_set_baseclass', 'udt_member_t_set_unaligned', + 'udt_member_t_set_vftable', 'udt_member_t_set_virtbase', 'udt_member_t_size_get', 'udt_member_t_size_set', @@ -7567,6 +7964,7 @@ 'udt_type_data_t_is_unaligned', 'udt_type_data_t_is_union_get', 'udt_type_data_t_is_union_set', + 'udt_type_data_t_is_vftable', 'udt_type_data_t_pack_get', 'udt_type_data_t_pack_set', 'udt_type_data_t_sda_get', @@ -7620,6 +8018,84 @@ 'udtmembervec_t_truncate', 'ui_load_new_file', 'ui_run_debugger', + 'uintvec_t___eq__', + 'uintvec_t___getitem__', + 'uintvec_t___len__', + 'uintvec_t___ne__', + 'uintvec_t___setitem__', + 'uintvec_t__del', + 'uintvec_t_add_unique', + 'uintvec_t_at', + 'uintvec_t_begin', + 'uintvec_t_begin__SWIG_0', + 'uintvec_t_begin__SWIG_1', + 'uintvec_t_capacity', + 'uintvec_t_clear', + 'uintvec_t_empty', + 'uintvec_t_end', + 'uintvec_t_end__SWIG_0', + 'uintvec_t_end__SWIG_1', + 'uintvec_t_erase', + 'uintvec_t_erase__SWIG_0', + 'uintvec_t_erase__SWIG_1', + 'uintvec_t_extract', + 'uintvec_t_find', + 'uintvec_t_find__SWIG_0', + 'uintvec_t_find__SWIG_1', + 'uintvec_t_has', + 'uintvec_t_inject', + 'uintvec_t_insert', + 'uintvec_t_pop_back', + 'uintvec_t_push_back', + 'uintvec_t_push_back__SWIG_0', + 'uintvec_t_push_back__SWIG_1', + 'uintvec_t_qclear', + 'uintvec_t_reserve', + 'uintvec_t_resize', + 'uintvec_t_resize__SWIG_0', + 'uintvec_t_resize__SWIG_1', + 'uintvec_t_size', + 'uintvec_t_swap', + 'uintvec_t_truncate', + 'ulonglongvec_t___eq__', + 'ulonglongvec_t___getitem__', + 'ulonglongvec_t___len__', + 'ulonglongvec_t___ne__', + 'ulonglongvec_t___setitem__', + 'ulonglongvec_t__del', + 'ulonglongvec_t_add_unique', + 'ulonglongvec_t_at', + 'ulonglongvec_t_begin', + 'ulonglongvec_t_begin__SWIG_0', + 'ulonglongvec_t_begin__SWIG_1', + 'ulonglongvec_t_capacity', + 'ulonglongvec_t_clear', + 'ulonglongvec_t_empty', + 'ulonglongvec_t_end', + 'ulonglongvec_t_end__SWIG_0', + 'ulonglongvec_t_end__SWIG_1', + 'ulonglongvec_t_erase', + 'ulonglongvec_t_erase__SWIG_0', + 'ulonglongvec_t_erase__SWIG_1', + 'ulonglongvec_t_extract', + 'ulonglongvec_t_find', + 'ulonglongvec_t_find__SWIG_0', + 'ulonglongvec_t_find__SWIG_1', + 'ulonglongvec_t_has', + 'ulonglongvec_t_inject', + 'ulonglongvec_t_insert', + 'ulonglongvec_t_pop_back', + 'ulonglongvec_t_push_back', + 'ulonglongvec_t_push_back__SWIG_0', + 'ulonglongvec_t_push_back__SWIG_1', + 'ulonglongvec_t_qclear', + 'ulonglongvec_t_reserve', + 'ulonglongvec_t_resize', + 'ulonglongvec_t_resize__SWIG_0', + 'ulonglongvec_t_resize__SWIG_1', + 'ulonglongvec_t_size', + 'ulonglongvec_t_swap', + 'ulonglongvec_t_truncate', 'unhide_border', 'unhide_item', 'unmark_selection', @@ -7750,45 +8226,6 @@ 'uval_array___setitem__', 'uval_array_cast', 'uval_array_frompointer', - 'uvalvec_t___eq__', - 'uvalvec_t___getitem__', - 'uvalvec_t___len__', - 'uvalvec_t___ne__', - 'uvalvec_t___setitem__', - 'uvalvec_t__del', - 'uvalvec_t_add_unique', - 'uvalvec_t_at', - 'uvalvec_t_begin', - 'uvalvec_t_begin__SWIG_0', - 'uvalvec_t_begin__SWIG_1', - 'uvalvec_t_capacity', - 'uvalvec_t_clear', - 'uvalvec_t_empty', - 'uvalvec_t_end', - 'uvalvec_t_end__SWIG_0', - 'uvalvec_t_end__SWIG_1', - 'uvalvec_t_erase', - 'uvalvec_t_erase__SWIG_0', - 'uvalvec_t_erase__SWIG_1', - 'uvalvec_t_extract', - 'uvalvec_t_find', - 'uvalvec_t_find__SWIG_0', - 'uvalvec_t_find__SWIG_1', - 'uvalvec_t_has', - 'uvalvec_t_inject', - 'uvalvec_t_insert', - 'uvalvec_t_pop_back', - 'uvalvec_t_push_back', - 'uvalvec_t_push_back__SWIG_0', - 'uvalvec_t_push_back__SWIG_1', - 'uvalvec_t_qclear', - 'uvalvec_t_reserve', - 'uvalvec_t_resize', - 'uvalvec_t_resize__SWIG_0', - 'uvalvec_t_resize__SWIG_1', - 'uvalvec_t_size', - 'uvalvec_t_swap', - 'uvalvec_t_truncate', 'validate_idb_names', 'validate_name', 'valstr_t_info_get', @@ -7824,7 +8261,15 @@ 'vd_printer_t__print__varargs__', 'vd_printer_t_hdrlines_get', 'vd_printer_t_hdrlines_set', + 'vdloc_t___eq__', + 'vdloc_t___ge__', + 'vdloc_t___gt__', + 'vdloc_t___le__', + 'vdloc_t___lt__', + 'vdloc_t___ne__', 'vdloc_t__set_reg1', + 'vdloc_t_compare', + 'vdloc_t_is_aliasable', 'vdloc_t_reg1', 'vdloc_t_set_reg1', 'vdui_t_calc_cmt_type', @@ -7871,6 +8316,7 @@ 'vdui_t_set_locked', 'vdui_t_set_lvar_cmt', 'vdui_t_set_lvar_type', + 'vdui_t_set_noptr_lvar', 'vdui_t_set_num_enum', 'vdui_t_set_num_radix', 'vdui_t_set_num_stroff', diff --git a/build.py b/build.py index de13fc3..89d15d3 100644 --- a/build.py +++ b/build.py @@ -16,40 +16,27 @@ import os, sys, argparse parser = argparse.ArgumentParser(epilog=""" A very specific version of SWiG is expected in order to produce reliable bindings. If your platform doesn't provide that version by default and you -had to build/install it yourself, you will have to specify '--swig-bin' and -'--swig-inc' arguments. +had to build/install it yourself, you will have to specify '--swig-home'. What follows, are example build commands ### Windows (assume SWiG is installed in C:\swigwin-2.0.12, and IDA is in C:\Program Files\IDA7) python build.py \\ - --swig-bin C:/swigwin-2.0.12/swig.exe \\ - --swig-inc "C:/swigwin-2.0.12/Lib/python;C:/swigwin-2.0.12/Lib" \\ + --with-hexrays \\ + --swig-home C:/swigwin-2.0.12 \\ --idc "c:/Program\ Files/IDA_7.0-171130-tests/idc/idc.idc" - (note the argument quoting) - -### Linux/OSX (assume SWiG is installed in /opt/my-swig/, and IDA is in /opt/my-ida-install) +### Linux/OSX (assume SWiG is installed in /opt/swiglinux-2.0.12, and IDA is in /opt/my-ida-install) python build.py \\ - --swig-bin /opt/my-swig/bin/swig \\ - --swig-inc /opt/my-swig/share/swig/2.0.12/python/:/opt/my-swig/share/swig/2.0.12 \\ + --with-hexrays \\ + --swig-home /opt/swiglinux-2.0.12 \\ --idc /opt/my-ida-install/idc/idc.idc - - -Notes: - * '--swig-inc' here has 2 path components, separated by the platform's - path separator; i.e., ':' in this case (if you were building on Windows, - you would have to use ';'.) - * SWiG can be tricky to deal with when specifying input paths. The path - to the '.../2.0.12/python/' subdirectory should be placed before the - more global '.../2.0.12/' directory. """, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument("--swig-bin", type=str, help="Path to the SWIG binary", default=None) -parser.add_argument("--swig-inc", type=str, help="Path(s) to the SWIG includes directory(ies)", default=None) +parser.add_argument("--swig-home", type=str, help="Path to the SWIG installation", default=None) parser.add_argument("--with-hexrays", help="Build Hex-Rays decompiler bindings (requires the 'hexrays.hpp' header to be present in the SDK's include/ directory)", default=False, action="store_true") parser.add_argument("--debug", help="Build debug version of the plugin", default=False, action="store_true") if "linux" in sys.platform: @@ -80,14 +67,12 @@ def main(): env = { "OUT_OF_TREE_BUILD" : "1" } - if args.swig_bin: - env["SWIG"] = args.swig_bin - if args.swig_inc: - env["SWIGINCLUDES"] = " ".join(map(lambda p: "-I%s" % p, args.swig_inc.split(os.pathsep))) + if args.swig_home: + env["SWIG_HOME"] = args.swig_home if args.with_hexrays: env["HAS_HEXRAYS"] = "1" if args.debug: - env["__VC__"] = "1" # to enable PDB flags + env["__NT__"] = "1" # to enable PDB flags else: env["NDEBUG"] = "1" try: diff --git a/examples/ex_askusingform.py b/examples/ex_askusingform.py index d9c9e2f..b49cd2b 100644 --- a/examples/ex_askusingform.py +++ b/examples/ex_askusingform.py @@ -32,7 +32,6 @@ class TestEmbeddedChooserClass(Choose): class MyForm(Form): def __init__(self): self.invert = False - self.EChooser = TestEmbeddedChooserClass("E1", flags=Choose.CH_MULTI) Form.__init__(self, r"""STARTITEM {id:rNormal} BUTTON YES* Yeah BUTTON NO Nope @@ -85,7 +84,7 @@ The end! 'cGroup1': Form.ChkGroupControl(("rNormal", "rError", "rWarnings")), 'cGroup2': Form.RadGroupControl(("rRed", "rGreen", "rBlue")), 'FormChangeCb': Form.FormChangeCb(self.OnFormChange), - 'cEChooser' : Form.EmbeddedChooserControl(self.EChooser) + 'cEChooser' : Form.EmbeddedChooserControl(TestEmbeddedChooserClass("E1", flags=Choose.CH_MULTI)) }) @@ -152,6 +151,7 @@ def ida_main(): f.iColor1.value = 0x5bffff f.iDir.value = os.getcwd() + f.iChar.value = ord("a") f.rNormal.checked = True f.rWarnings.checked = True f.rGreen.selected = True @@ -174,8 +174,7 @@ def ida_main(): print("f.addr=%x" % f.iAddr.value) print("f.cGroup1=%x" % f.cGroup1.value) print("f.cGroup2=%x" % f.cGroup2.value) - - sel = f.EChooser.GetEmbSelection() + sel = f.cEChooser.selection if sel is None: print("No selection") else: diff --git a/examples/ex_auto_instantiate_widget_plugin.py b/examples/ex_auto_instantiate_widget_plugin.py new file mode 100644 index 0000000..ea52fed --- /dev/null +++ b/examples/ex_auto_instantiate_widget_plugin.py @@ -0,0 +1,110 @@ + +import ida_idaapi +import ida_kernwin + +title = "Auto-instantiable at IDA startup" + +# ----------------------------------------------------------------------- +class auto_inst_t(ida_kernwin.simplecustviewer_t): + def __init__(self): + ida_kernwin.simplecustviewer_t.__init__(self) + + def Create(self): + if not ida_kernwin.simplecustviewer_t.Create(self, title): + return False + + text = r""" +This is an example demonstrating how one can create widgets from a plugin, +and have them re-created automatically at IDA startup-time or at desktop load-time. + +This example should be placed in the 'plugins' directory of the +IDA installation, for it to work. + +There are 2 ways to use this example: +1) reloading an IDB, where the widget was opened + - open the widget ('View > Open subview > """ + title + """') + - save this IDB, and close IDA + - restart IDA with this IDB + => the widget will be visible + +2) reloading a desktop, where the widget was opened + - open the widget ('View > Open subview > """ + title + """') + - save the desktop ('Windows > Save desktop...') under, say, the name 'with_auto' + - start another IDA instance with some IDB, and load that desktop + => the widget will be visible +""" + for l in text.split("\n"): + self.AddLine(l) + return True + +# ----------------------------------------------------------------------- +auto_inst = None + +# ----------------------------------------------------------------------- +def register_open_action(): + """ + Provide the action that will create the widget + when the user asks for it. + """ + class create_widget_t(ida_kernwin.action_handler_t): + def activate(self, ctx): + if ida_kernwin.find_widget(title) is None: + global auto_inst + auto_inst = auto_inst_t() + assert(auto_inst.Create()) + assert(auto_inst.Show()) + + def update(self, ctx): + return ida_kernwin.AST_ENABLE_ALWAYS + + action_name = "autoinst:create" + ida_kernwin.register_action( + ida_kernwin.action_desc_t( + action_name, + title, + create_widget_t())) + ida_kernwin.attach_action_to_menu( + "View/Open subviews/Strings", + action_name, + ida_kernwin.SETMENU_APP) + +# ----------------------------------------------------------------------- +auto_inst_hooks = None +def register_autoinst_hooks(): + """ + Register hooks that will create the widget when IDA + requires it because of the IDB/desktop + """ + class auto_inst_hooks_t(ida_kernwin.UI_Hooks): + def create_desktop_widget(self, ttl, cfg): + if ttl == title: + global auto_inst + auto_inst = auto_inst_t() + assert(auto_inst.Create()) + return auto_inst.GetWidget() + + global auto_inst_hooks + auto_inst_hooks = auto_inst_hooks_t() + auto_inst_hooks.hook() + +# ----------------------------------------------------------------------- +class auto_inst_plugin_t(ida_idaapi.plugin_t): + flags = 0 + comment = "This plugin creates a widget that will be recreated automatically if needed, either at startup or when loading a desktop that requires it" + help = "No help, really" + wanted_name = "autoinst" + wanted_hotkey = "" + + def init(self): + register_open_action() + register_autoinst_hooks() + + def run(self, arg): + pass + + def term(self): + pass + + +def PLUGIN_ENTRY(): + return auto_inst_plugin_t() diff --git a/examples/ex_choose.py b/examples/ex_choose.py index 592ee88..82a074a 100644 --- a/examples/ex_choose.py +++ b/examples/ex_choose.py @@ -27,7 +27,8 @@ class MyChoose(Choose): self, title, [ ["Address", 10], ["Name", 30] ], - flags = flags | (Choose.CH_CAN_INS + flags = flags | Choose.CH_RESTORE + | (Choose.CH_CAN_INS | Choose.CH_CAN_DEL | Choose.CH_CAN_EDIT | Choose.CH_CAN_REFRESH), diff --git a/examples/ex_custdata.py b/examples/ex_custdata.py index 99aaa88..8339094 100644 --- a/examples/ex_custdata.py +++ b/examples/ex_custdata.py @@ -21,11 +21,11 @@ class pascal_data_type(data_type_t): def calc_item_size(self, ea, maxsize): # Custom data types may be used in structure definitions. If this case # ea is a member id. Check for this situation and return 1 - if _idaapi.is_member_id(ea): + if idaapi.is_member_id(ea): return 1 # get the length byte - n = _idaapi.get_byte(ea) + n = idaapi.get_byte(ea) # string too big? if n > maxsize: @@ -71,10 +71,10 @@ class simplevm_data_type(data_type_t): asm_keyword) def calc_item_size(self, ea, maxsize): - if _idaapi.is_member_id(ea): + if idaapi.is_member_id(ea): return 1 # get the opcode and see if it has an imm - n = 5 if (_idaapi.get_byte(ea) & 3) == 0 else 1 + n = 5 if (idaapi.get_byte(ea) & 3) == 0 else 1 # string too big? if n > maxsize: return 0 diff --git a/examples/ex_custview.py b/examples/ex_custview.py index 2a11a40..6150a67 100644 --- a/examples/ex_custview.py +++ b/examples/ex_custview.py @@ -21,24 +21,28 @@ class say_something_handler_t(idaapi.action_handler_t): # ----------------------------------------------------------------------- class mycv_t(simplecustviewer_t): - def Create(self, sn=None): + def Create(self, sn=None, use_colors=True): # Form the title title = "Simple custom view test" if sn: title += " %d" % sn + self.use_colors = use_colors # Create the customviewer if not simplecustviewer_t.Create(self, title): return False for i in xrange(0, 100): - fg, bg = idaapi.COLOR_PREFIX, None + prefix, bg = idaapi.COLOR_DEFAULT, None # make every 10th line a bit special if i % 10 == 0: - fg = idaapi.COLOR_DEFAULT # i.e., white... - bg = 0xFFFF00 # ...on cyan + prefix = idaapi.COLOR_DNAME # i.e., dark yellow... + bg = 0xFFFF00 # ...on cyan pfx = idaapi.COLSTR("%3d" % i, idaapi.SCOLOR_PREFIX) - self.AddLine("%s: Line %d" % (pfx, i), fgcolor=fg, bgcolor=bg) + if self.use_colors: + self.AddLine("%s: Line %d" % (pfx, i), fgcolor=prefix, bgcolor=bg) + else: + self.AddLine("%s: Line %d" % (pfx, i)) return True @@ -51,6 +55,12 @@ class mycv_t(simplecustviewer_t): print "OnClick, shift=%d" % shift return True + def OnPopup(self, form, popup_handle): + for thing in ["Hello", "World"]: + actname = "custview:say_%s" % thing + desc = ida_kernwin.action_desc_t(actname, "Say %s" % thing, say_something_handler_t(thing)) + ida_kernwin.attach_dynamic_action_to_popup(form, popup_handle, desc) + def OnDblClick(self, shift): """ User dbl-clicked in the view @@ -161,13 +171,6 @@ def show_win(): return None x.Show() tcc = x.GetWidget() - - # Register actions - for thing in ["Hello", "World"]: - actname = "custview:say_%s" % thing - idaapi.register_action( - idaapi.action_desc_t(actname, "Say %s" % thing, say_something_handler_t(thing))) - idaapi.attach_action_to_popup(tcc, None, actname) return x mycv = show_win() diff --git a/examples/ex_idphook_asm.py b/examples/ex_idphook_asm.py index b364212..5cc4656 100644 --- a/examples/ex_idphook_asm.py +++ b/examples/ex_idphook_asm.py @@ -2,7 +2,7 @@ import idaapi import idautils """ - This is a sample plugin for extending the assemble(). + This is a sample script for extending the assemble() hook. We add support for assembling the following pseudo instructions: - "zero eax" -> xor eax, eax diff --git a/examples/ex_paint_over_navbar.py b/examples/ex_paint_over_navbar.py new file mode 100644 index 0000000..d9e56f3 --- /dev/null +++ b/examples/ex_paint_over_navbar.py @@ -0,0 +1,66 @@ + +import random + +from PyQt5 import QtCore +from PyQt5 import QtGui +from PyQt5 import QtWidgets + +import ida_kernwin +import ida_segment + +import idc + +class painter_t(QtCore.QObject): + def __init__(self): + QtCore.QObject.__init__(self) + self.target = ida_kernwin.PluginForm.FormToPyQtWidget(ida_kernwin.open_navband_window(idc.here(), 1)) + self.target.installEventFilter(self) + self.items = [] + self.painting = False + + def add_item(self, ea, radius, color): + self.items.append((ea, radius, color)) + self.target.update() + + def add_random_item(self): + R = random.random + s = ida_segment.getnseg(int(ida_segment.get_segm_qty() * R())) + ea = s.start_ea + long((s.end_ea - s.start_ea) * R()) + radius = 4 + long(R() * 8) + color = QtGui.QColor(long(255 * R()), long(255 * R()), long(255 * R())) + self.add_item(ea, radius, color) + + def eventFilter(self, receiver, event): + if not self.painting and \ + self.target == receiver and \ + event.type() == QtCore.QEvent.Paint: + + # Send a paint event that we won't intercept + self.painting = True + try: + pev = QtGui.QPaintEvent(self.target.rect()) + QtWidgets.QApplication.instance().sendEvent(self.target, pev) + finally: + self.painting = False + + # now we can paint our items + for ea, radius, color in self.items: + painter = QtGui.QPainter(receiver) + painter.setRenderHints(QtGui.QPainter.Antialiasing) + pxl, is_vertical = ida_kernwin.get_navband_pixel(ea) + if pxl >= 0: + x = (self.target.width() / 2) if is_vertical else pxl + y = pxl if is_vertical else (self.target.height() / 2) + painter.setPen(color) + painter.setBrush(color) + painter.drawEllipse(QtCore.QPoint(x, y), radius, radius) + painter.end() + + # ...and prevent the widget form painting itself again + return True + return QtCore.QObject.eventFilter(self, receiver, event) + +painter = painter_t() + +# Try the following: +# for i in xrange(100): painter.add_random_item() diff --git a/examples/ex_pyqt.py b/examples/ex_pyqt.py index 6a0914d..e8fe27b 100644 --- a/examples/ex_pyqt.py +++ b/examples/ex_pyqt.py @@ -6,7 +6,7 @@ import sip class MyPluginFormClass(PluginForm): def OnCreate(self, form): """ - Called when the plugin form is created + Called when the widget is created """ # Get parent widget @@ -28,7 +28,7 @@ class MyPluginFormClass(PluginForm): def OnClose(self, form): """ - Called when the plugin form is closed + Called when the widget is closed """ pass diff --git a/examples/ex_uihook.py b/examples/ex_uihook.py index f9dfd8e..9186999 100644 --- a/examples/ex_uihook.py +++ b/examples/ex_uihook.py @@ -44,7 +44,7 @@ class MyUiHook(idaapi.UI_Hooks): IDA is terminated and the database is already closed. The UI may close its windows in this callback. - This callback is best used with a plugin_t with flags PLUGIN_FIX + This callback is best used within the context of a plugin_t with PLUGIN_FIX flags """ print("IDA terminated") @@ -57,6 +57,20 @@ class MyUiHook(idaapi.UI_Hooks): """ print("get_ea_hint(%x)" % ea) + def populating_widget_popup(self, widget, popup, ctx): + """ + The UI is currently populating the widget popup. Now is a good time to + attach actions. + """ + print("populating_widget_popup; title: %s" % (ctx.widget_title,)) + + def finish_populating_widget_popup(self, widget, popup, ctx): + """ + The UI is done populating the widget popup. Now is the last chance to + attach actions. + """ + print("finish_populating_widget_popup; title: %s" % (ctx.widget_title,)) + #--------------------------------------------------------------------- # Remove an existing hook on second run diff --git a/examples/vds3.py b/examples/vds3.py index c4fa8fb..d9dccb0 100644 --- a/examples/vds3.py +++ b/examples/vds3.py @@ -168,19 +168,22 @@ class hexrays_callback_info(object): return - def event_callback(self, event, *args): - if event == idaapi.hxe_populating_popup: - widget, phandle, vu = args - res = idaapi.attach_action_to_popup(vu.ct, None, inverter_actname) - - elif event == idaapi.hxe_maturity: - cfunc, maturity = args - if maturity == idaapi.CMAT_FINAL: - self.restore(cfunc) +class vds3_hooks_t(idaapi.Hexrays_Hooks): + def __init__(self, i): + idaapi.Hexrays_Hooks.__init__(self) + self.i = i + def populating_popup(self, widget, phandle, vu): + idaapi.attach_action_to_popup(vu.ct, None, inverter_actname) return 0 + def maturity(self, cfunc, maturity): + if maturity == idaapi.CMAT_FINAL: + self.i.restore(cfunc) + return 0 + + if idaapi.init_hexrays_plugin(): i = hexrays_callback_info() idaapi.register_action( @@ -189,7 +192,8 @@ if idaapi.init_hexrays_plugin(): "Invert then/else", invert_action_handler_t(i), "I")) - idaapi.install_hexrays_callback(i.event_callback) + vds3_hooks = vds3_hooks_t(i) + vds3_hooks.hook() else: print 'invert-if: hexrays is not available.' diff --git a/examples/vds4.py b/examples/vds4.py index b19cff0..0630823 100644 --- a/examples/vds4.py +++ b/examples/vds4.py @@ -41,8 +41,8 @@ def run(): iflags = idaapi.restore_user_iflags(entry_ea) if iflags is not None: print "------- %u user defined citem iflags" % (len(iflags), ) - for cl, t in iflags.iteritems(): - print "%a(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & CIT_COLLAPSED else "") + for cl, f in iflags.iteritems(): + print "%x(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & idaapi.CIT_COLLAPSED else "") idaapi.user_iflags_free(iflags) # Display user defined number formats diff --git a/examples/vds5.py b/examples/vds5.py index dca3710..e057c29 100644 --- a/examples/vds5.py +++ b/examples/vds5.py @@ -290,12 +290,10 @@ class display_graph_ah_t(ida_kernwin.action_handler_t): ida_kernwin.AST_DISABLE_FOR_WIDGET -def cb(event, *args): - if event == ida_hexrays.hxe_populating_popup: - widget, phandle, vu = args - res = idaapi.attach_action_to_popup(vu.ct, None, ACTION_NAME) - return 0 - +class vds5_hooks_t(ida_hexrays.Hexrays_Hooks): + def populating_popup(self, widget, handle, vu): + idaapi.attach_action_to_popup(vu.ct, None, ACTION_NAME) + return 0 if ida_hexrays.init_hexrays_plugin(): ida_kernwin.register_action( @@ -304,6 +302,8 @@ if ida_hexrays.init_hexrays_plugin(): "Hex-Rays show C graph (IDAPython)", display_graph_ah_t(), ACTION_SHORTCUT)) - idaapi.install_hexrays_callback(cb) + vds5_hooks = vds5_hooks_t() + vds5_hooks.hook() else: print 'hexrays-graph: hexrays is not available.' + diff --git a/examples/vds6.py b/examples/vds6.py index eac7657..8456414 100644 --- a/examples/vds6.py +++ b/examples/vds6.py @@ -80,14 +80,15 @@ def remove_spaces(sl): sl.line = "".join(out) -def cb(event, *args): - if event == ida_hexrays.hxe_func_printed: - cf = args[0] - for sl in cf.get_pseudocode(): + +class vds6_hooks_t(ida_hexrays.Hexrays_Hooks): + def func_printed(self, cfunc): + for sl in cfunc.get_pseudocode(): remove_spaces(sl); - return 0 + return 0 if ida_hexrays.init_hexrays_plugin(): - ida_hexrays.install_hexrays_callback(cb) + vds6_hooks = vds6_hooks_t() + vds6_hooks.hook() else: print 'remove spaces: hexrays is not available.' diff --git a/examples/vds7.py b/examples/vds7.py index bb2dd11..b73cfc1 100644 --- a/examples/vds7.py +++ b/examples/vds7.py @@ -35,28 +35,17 @@ class cblock_visitor_t(idaapi.ctree_visitor_t): return -class hexrays_callback_info(object): - - def __init__(self): - return - - def event_callback(self, event, *args): - - try: - if event == idaapi.hxe_maturity: - cfunc, maturity = args - - if maturity == idaapi.CMAT_BUILT: - cbv = cblock_visitor_t() - cbv.apply_to(cfunc.body, None) - - except: - traceback.print_exc() +class vds7_hooks_t(idaapi.Hexrays_Hooks): + def maturity(self, cfunc, maturity): + if maturity == idaapi.CMAT_BUILT: + cbv = cblock_visitor_t() + cbv.apply_to(cfunc.body, None) return 0 + if idaapi.init_hexrays_plugin(): - i = hexrays_callback_info() - idaapi.install_hexrays_callback(i.event_callback) + vds7_hooks = vds7_hooks_t() + vds7_hooks.hook() else: print 'cblock visitor: hexrays is not available.' diff --git a/examples/vds8.py b/examples/vds8.py index ffe1ac8..2ee13bf 100644 --- a/examples/vds8.py +++ b/examples/vds8.py @@ -3,10 +3,10 @@ # Copyright (c) 2007-2018 by Hex-Rays, support@hex-rays.com # ALL RIGHTS RESERVED. # -# Sample plugin for Hex-Rays Decompiler usage of udc_filter_t +# Sample script for Hex-Rays Decompiler usage of udc_filter_t # class: decompile svc 0x900001 and svc 0x9000F8 as function calls to # svc_exit() and svc_exit_group() respectively. -# NOTE: You will need to have an ARM + Linux IDB for this plugin to be usable +# NOTE: You will need to have an ARM + Linux IDB for this script to be usable # # It is also added into the right-click menu as "vds8.py:Toggle UDC" diff --git a/examples/vds_create_hint.py b/examples/vds_create_hint.py index 860013d..404d8b0 100644 --- a/examples/vds_create_hint.py +++ b/examples/vds_create_hint.py @@ -1,6 +1,6 @@ -"""'Hints' plugin for Hexrays Decompiler +"""'Hints' example for Hexrays Decompiler -Hijack the 'hxe_create_hint' notification, to return our own. +Handle 'hxe_create_hint' notification using hooks, to return our own. If the object under the cursor is: - a function call, prefix the original decompiler hint with "==> " - a local variable declaration, replace the hint with our own in the form of "!{varname}" (where '{varname}' is replaced w/ the variable name) @@ -9,9 +9,8 @@ If the object under the cursor is: import ida_hexrays -def create_hint_cb(event, *args): - if event == ida_hexrays.hxe_create_hint: - vu = args[0] +class hint_hooks_t(ida_hexrays.Hexrays_Hooks): + def create_hint(self, vu): if vu.get_current_item(ida_hexrays.USE_MOUSE): cit = vu.item.citype if cit == ida_hexrays.VDI_LVAR: @@ -22,11 +21,7 @@ def create_hint_cb(event, *args): return 2, "==> ", 1 if ce.op == ida_hexrays.cit_if: return 1, "condition", 1 - return 0 - return 0 - -if ida_hexrays.init_hexrays_plugin(): - ida_hexrays.install_hexrays_callback(create_hint_cb) -else: - print 'hexrays is not available.' + return 0 +vds_hooks = hint_hooks_t() +vds_hooks.hook() diff --git a/examples/vds_hooks.py b/examples/vds_hooks.py new file mode 100644 index 0000000..6c34bb9 --- /dev/null +++ b/examples/vds_hooks.py @@ -0,0 +1,128 @@ +""" +Various hooks for Hexrays Decompiler +""" + +import ida_typeinf +import ida_hexrays + +class vds_hooks_t(ida_hexrays.Hexrays_Hooks): + def _shorten(self, cfunc): + raw = str(cfunc) + if len(raw) > 20: + raw = raw[0:20] + "[...snipped...]" + return raw + + def _format_lvar(self, v): + parts = [] + if v: + if v.name: + parts.append("name=%s" % v.name) + if v.cmt: + parts.append("cmt=%s" % v.cmt) + parts.append("width=%s" % v.width) + parts.append("defblk=%s" % v.defblk) + parts.append("divisor=%s" % v.divisor) + return "{%s}" % ", ".join(parts) + + def _log(self, msg): + print("### %s" % msg) + return 0 + + def flowchart(self, fc): + return self._log("flowchart: fc=%s" % fc) + + def stkpnts(self, mba, stkpnts): + return self._log("stkpnts: mba=%s, stkpnts=%s" % (mba, stkpnts)) + + def prolog(self, mba, fc, reachable_blocks): + return self._log("prolog: mba=%s, fc=%s, reachable_blocks=%s" % (mba, fc, reachable_blocks)) + + def microcode(self, mba): + return self._log("microcode: mba=%s" % (mba,)) + + def preoptimized(self, mba): + return self._log("preoptimized: mba=%s" % (mba,)) + + def locopt(self, mba): + return self._log("locopt: mba=%s" % (mba,)) + + def prealloc(self, mba): + return self._log("prealloc: mba=%s" % (mba,)) + + def glbopt(self, mba): + return self._log("glbopt: mba=%s" % (mba,)) + + def structural(self, ctrl_graph): + return self._log("structural: ctrl_graph: %s" % (ctrl_graph,)) + + def maturity(self, cfunc, maturity): + return self._log("maturity: cfunc=%s, maturity=%s" % (self._shorten(cfunc), maturity)) + + def interr(self, code): + return self._log("interr: code=%s" % (code,)) + + def combine(self, blk, insn): + return self._log("combine: blk=%s, insn=%s" % (blk, insn)) + + def print_func(self, cfunc, printer): + # Note: we can't print/str()-ify 'cfunc' here, + # because that'll call print_func() us recursively. + return self._log("print_func: cfunc=..., printer=%s" % (printer,)) + + def func_printed(self, cfunc): + return self._log("func_printed: cfunc=%s" % (cfunc,)) + + def resolve_stkaddrs(self, mba): + return self._log("resolve_stkaddrs: mba=%s" % (mba,)) + + def open_pseudocode(self, vu): + return self._log("open_pseudocode: vu=%s" % (vu,)) + + def switch_pseudocode(self, vu): + return self._log("switch_pseudocode: vu=%s" % (vu,)) + + def refresh_pseudocode(self, vu): + return self._log("refresh_pseudocode: vu=%s" % (vu,)) + + def close_pseudocode(self, vu): + return self._log("close_pseudocode: vu=%s" % (vu,)) + + def keyboard(self, vu, key_code, shift_state): + return self._log("keyboard: vu=%s, key_code=%s, shift_state=%s" % (vu, key_code, shift_state)) + + def right_click(self, vu): + return self._log("right_click: vu=%s" % (vu,)) + + def double_click(self, vu, shift_state): + return self._log("double_click: vu=%s, shift_state=%s" % (vu, shift_state)) + + def curpos(self, vu): + return self._log("curpos: vu=%s" % (vu,)) + + def create_hint(self, vu): + return self._log("create_hint: vu=%s: " % (vu,)) + + def text_ready(self, vu): + return self._log("text_ready: vu=%s" % (vu,)) + + def populating_popup(self, widget, popup, vu): + return self._log("populating_popup: widget=%s, popup=%s, vu=%s" % (widget, popup, vu)) + + def lvar_name_changed(self, vu, v, name, is_user_name): + return self._log("lvar_name_changed: vu=%s, v=%s, name=%s, is_user_name=%s" % (vu, self._format_lvar(v), name, is_user_name)) + + def lvar_type_changed(self, vu, v, tif): + return self._log("lvar_type_changed: vu=%s, v=%s, tinfo=%s" % (vu, self._format_lvar(v), tif._print())) + + def lvar_cmt_changed(self, vu, v, cmt): + return self._log("lvar_cmt_changed: vu=%s, v=%s, cmt=%s" % (vu, self._format_lvar(v), cmt)) + + def lvar_mapping_changed(self, vu, _from, to): + return self._log("lvar_mapping_changed: vu=%s, from=%s, to=%s" % (vu, _from, to)) + + def cmt_changed(self, cfunc, loc, cmt): + return self._log("cmt_changed: cfunc=%s, loc=%s, cmt=%s" % (self._shorten(cfunc),loc, cmt)) + +vds_hooks = vds_hooks_t() +vds_hooks.hook() + diff --git a/examples/vds_xrefs.py b/examples/vds_xrefs.py index 1fb55cb..f834b4c 100644 --- a/examples/vds_xrefs.py +++ b/examples/vds_xrefs.py @@ -1,4 +1,4 @@ -""" Xref plugin for Hexrays Decompiler +""" Xref script for Hexrays Decompiler Author: EiNSTeiN_ @@ -283,27 +283,18 @@ class show_xrefs_ah_t(idaapi.action_handler_t): return idaapi.AST_ENABLE if self.sel else idaapi.AST_DISABLE -class hexrays_callback_info(object): - - def __init__(self): - return - - def event_callback(self, event, *args): - - try: - if event == idaapi.hxe_populating_popup: - widget, phandle, vu = args - idaapi.attach_action_to_popup(widget, phandle, "vdsxrefs:show", None) - except: - traceback.print_exc() +class vds_xrefs_hooks_t(idaapi.Hexrays_Hooks): + def populating_popup(self, widget, phandle, vu): + idaapi.attach_action_to_popup(widget, phandle, "vdsxrefs:show", None) return 0 + if idaapi.init_hexrays_plugin(): adesc = idaapi.action_desc_t('vdsxrefs:show', 'Show xrefs', show_xrefs_ah_t(), "Ctrl+X") if idaapi.register_action(adesc): - i = hexrays_callback_info() - idaapi.install_hexrays_callback(i.event_callback) + vds_xrefs_hooks = vds_xrefs_hooks_t() + vds_xrefs_hooks.hook() else: print "Couldn't register action." else: diff --git a/idapython.script b/idapython.script new file mode 100644 index 0000000..6a9df92 --- /dev/null +++ b/idapython.script @@ -0,0 +1,75 @@ +{ +global: + PLUGIN; + PyWStringOrNone_Check; + PyW_CreateIdcException; + PyW_GetError; + PyW_GetNumber; + PyW_GetNumberAsIDC; + PyW_GetStringAttr; + PyW_IsSequenceType; + PyW_ObjectToString; + PyW_PyListToEaVec; + PyW_PyListToSizeVec; + PyW_PyListToStrVec; + PyW_ShowCbErr; + PyW_SizeVecToPyList; + PyW_UvalVecToPyList; + PyW_TryGetAttrString; + PyW_TryImportModule; + PyW_register_compiled_form; + PyW_unregister_compiled_form; + add_notify_when; + create_linked_class_instance; + disable_script_timeout; + enable_extlang_python; + enable_python_cli; + idapython_hook_to_notification_point; + idapython_unhook_from_notification_point; + idcvar_to_pyvar; + lookup_info_t_commit; + lookup_info_t_del_by_py_view; + lookup_info_t_find_by_py_view; + lookup_info_t_find_by_view; + lookup_info_t_new_entry; + meminfo_vec_t_to_py; + prepare_programmatic_plugin_load; + py_customidamemo_t_bind; + py_customidamemo_t_collect_class_callbacks_ids; + py_customidamemo_t_collect_pyobject_callbacks; + py_customidamemo_t_create_groups; + py_customidamemo_t_del_nodes_infos; + py_customidamemo_t_delete_groups; + py_customidamemo_t_get_current_renderer_type; + py_customidamemo_t_get_node_info; + py_customidamemo_t_set_current_renderer_type; + py_customidamemo_t_set_groups_visibility; + py_customidamemo_t_set_node_info; + py_customidamemo_t_set_nodes_infos; + py_customidamemo_t_unbind; + pycim_lookup_info; + pyobj_get_clink; + python_timer_del; + python_timer_new; + pyvar_to_idcvar; + pyvar_to_idcvar_or_error; + pyvar_walk_list; + pyw_convert_idc_args; + register_module_lifecycle_callbacks; + set_script_timeout; + set_interruptible_state; + til_deregister_python_array_type_data_t_instance; + til_deregister_python_func_type_data_t_instance; + til_deregister_python_ptr_type_data_t_instance; + til_deregister_python_tinfo_t_instance; + til_deregister_python_udt_type_data_t_instance; + til_register_python_array_type_data_t_instance; + til_register_python_func_type_data_t_instance; + til_register_python_ptr_type_data_t_instance; + til_register_python_tinfo_t_instance; + til_register_python_udt_type_data_t_instance; + try_create_swig_wrapper; + get_callable_arg_count; +local: + *; +}; diff --git a/idapython.sln b/idapython.sln deleted file mode 100644 index 863f73e..0000000 --- a/idapython.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "idapython", "idapython.vcxproj", "{F43D6BB8-B7D6-486A-82E5-BABBA9848525}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug64|Win32 = Debug64|Win32 - Release|Win32 = Release|Win32 - SemiDebug|Win32 = SemiDebug|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.ActiveCfg = Debug|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.Build.0 = Debug|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug64|Win32.ActiveCfg = Debug64|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug64|Win32.Build.0 = Debug64|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.ActiveCfg = Release|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.Build.0 = Release|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.ActiveCfg = SemiDebug|Win32 - {F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.Build.0 = SemiDebug|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/idapython.vcxproj b/idapython.vcxproj deleted file mode 100644 index 9393c48..0000000 --- a/idapython.vcxproj +++ /dev/null @@ -1,455 +0,0 @@ - - - - - Debug64 - Win32 - - - Debug - Win32 - - - Release - Win32 - - - SemiDebug - Win32 - - - - {F43D6BB8-B7D6-486A-82E5-BABBA9848525} - idapython - - - - DynamicLibrary - false - MultiByte - v140 - - - DynamicLibrary - false - MultiByte - v140 - - - DynamicLibrary - false - MultiByte - v140 - - - DynamicLibrary - false - MultiByte - v140 - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - .\Debug\ - .\Debug64\ - .\Debug\ - .\Debug64\ - true - true - .\Release\ - .\Release\ - false - false - $(Configuration)\ - $(Configuration)\ - true - false - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\Debug/idapython.tlb - - - - - Disabled - .\pywraps;..\..\include;c:\python27\include;%(AdditionalIncludeDirectories) - WITH_HEXRAYS;NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=3;PLUGINFIX;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - .\Debug/idapython.pch - .\Debug/ - .\Debug/ - .\Debug/ - Level3 - true - EditAndContinue - Cdecl - 4102;4804;4800;4018;4005;%(DisableSpecificWarnings) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - /export:PLUGIN %(AdditionalOptions) - ida.lib;%(AdditionalDependencies) - c:\temp\ida\plugins\python.plw - true - \Python27\libs;..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) - true - .\Debug/idapython.pdb - - - - - .\Debug/idapython.lib - MachineX86 - - - true - .\Debug/idapython.bsc - - - - - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\Debug/idapython.tlb - - - - - Disabled - .\pywraps;..\..\include;c:\python26\include;%(AdditionalIncludeDirectories) - NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=0;PLUGINFIX;%(PreprocessorDefinitions);__EA64__ - true - EnableFastChecks - MultiThreadedDebug - .\Debug/idapython.pch - .\Debug/ - .\Debug/ - .\Debug/ - Level3 - true - EditAndContinue - Cdecl - 4804;4800;4018;4005;%(DisableSpecificWarnings) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - /export:PLUGIN %(AdditionalOptions) - ida.lib;%(AdditionalDependencies) - ..\..\bin\x86_win_vc\plugins\python.p64 - true - C:\Python26\libs;..\..\lib\x86_win_vc_64;%(AdditionalLibraryDirectories) - true - .\Debug/idapython.pdb - - - - - .\Debug/idapython.lib - MachineX86 - - - true - .\Debug/idapython.bsc - - - copy ..\..\bin\x86_win_vc\plugins\python.p64 ..\..\bin\x86_win_bcc\plugins\python.p64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\Release/idapython.tlb - - - - - Disabled - OnlyExplicitInline - .\pywraps;..\..\include;c:\python27\include;..\;%(AdditionalIncludeDirectories) - NO_OBSOLETE_FUNCS;NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=3;VER_PATCH=7;PLUGINFIX;4804;%(PreprocessorDefinitions) - true - MultiThreaded - true - .\Release/idapython.pch - .\Release/ - .\Release/ - .\Release/ - Level3 - true - ProgramDatabase - Cdecl - 4102;4005;4804;4018;4800;%(DisableSpecificWarnings) - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0419 - - - /export:PLUGIN %(AdditionalOptions) - ida.lib;%(AdditionalDependencies) - C:\temp\ida\plugins\python.plw - true - \Python27\libs;..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) - true - .\Release/idapython.pdb - - - - - .\Release/idapython.lib - MachineX86 - - - true - .\Release/idapython.bsc - - - copy ..\..\bin\x86_win_vc\plugins\python.plw ..\..\bin\x86_win_bcc\plugins\python.plw - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\Debug/idapython.tlb - - - - - Disabled - .\pywraps;..\..\include;c:\python27\include;%(AdditionalIncludeDirectories) - NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=3;VER_PATCH=7;PLUGINFIX;%(PreprocessorDefinitions) - true - true - EnableFastChecks - MultiThreaded - false - .\Debug/idapython.pch - .\Debug/ - .\Debug/ - .\Debug/ - Level3 - true - EditAndContinue - Cdecl - 4102;4804;4800;4018;%(DisableSpecificWarnings) - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - /export:PLUGIN %(AdditionalOptions) - ida.lib;%(AdditionalDependencies) - ../../bin/x86_win_vc/plugins/python.plw - true - C:\Python27\libs;..\..\lib\x86_win_vc_32;%(AdditionalLibraryDirectories) - true - .\Debug/idapython.pdb - - - - - .\Debug/idapython.lib - MachineX86 - - - true - .\Debug/idapython.bsc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Document - true - true - true - true - - - Document - true - true - true - true - - - Document - true - true - true - - - Document - true - true - - - Document - true - true - true - true - - - Document - true - true - true - - - - - - diff --git a/idapython.vcxproj.filters b/idapython.vcxproj.filters deleted file mode 100644 index 886433a..0000000 --- a/idapython.vcxproj.filters +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - autogen - - - - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - autogen - - - - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - autogen - - - swig_i - - - swig_i - - - swig_i - - - py - - - py - - - py - - - py - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - pywraps - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - swig_i - - - TEXT - - - TEXT - - - pywraps - - - TEXT - - - TEXT - - - swig_i - - - py - - - - - {16b55e12-2b1e-4d6d-a1bf-df3400f06d21} - - - {f733d65b-1c25-4587-8566-7000875727ff} - - - {e2ec193c-4803-45b0-96c8-bfdc173c14ff} - - - {01459f9f-5d55-4797-aab4-81876a9163d3} - - - {b581ad45-b3f6-4591-baf0-306dab4e0590} - - - diff --git a/tools/idapython_implib.def.in b/idapython_implib.def similarity index 96% rename from tools/idapython_implib.def.in rename to idapython_implib.def index 5b56539..10ff797 100644 --- a/tools/idapython_implib.def.in +++ b/idapython_implib.def @@ -1,4 +1,3 @@ -LIBRARY %LIBNAME% EXPORTS PyWStringOrNone_Check PyW_CreateIdcException @@ -7,6 +6,7 @@ EXPORTS PyW_GetNumberAsIDC PyW_GetStringAttr PyW_SizeVecToPyList + PyW_UvalVecToPyList PyW_IsSequenceType PyW_ObjectToString PyW_PyListToEaVec @@ -62,8 +62,9 @@ EXPORTS til_register_python_tinfo_t_instance til_register_python_udt_type_data_t_instance try_create_swig_wrapper + get_callable_arg_count idapython_hook_to_notification_point idapython_unhook_from_notification_point register_module_lifecycle_callbacks + prepare_programmatic_plugin_load pycim_lookup_info DATA - %PLUGIN_DATA_EXP% diff --git a/makefile b/makefile index 50dbffa..cf9dbc0 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,6 @@ +include ../../allmake.mak -# +#---------------------------------------------------------------------- # WARNING: Many rules in this file use pattern matching, where 'make' # first considers rules as simple strings, not paths. Consequently, # it is necessary that we don't end up with 'some_dir//some_file'. @@ -13,71 +14,103 @@ # non-hexrays people looking at the file, it also allows us to work in # a more natural manner with other tools (such as the build.py wrapper, that # uses os.path.join()) -# -PROC=python -API_CONTENTS=api_contents.txt -PYDOC_INJECTIONS=pydoc_injections.txt +#---------------------------------------------------------------------- +# default goals +.PHONY: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections public_tree test_idc docs +all: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections # public_tree test_idc docs -BC695=1 +#---------------------------------------------------------------------- +# configurable variables for this makefile +BC695 = 1 ifdef BC695 - BC695_CFLAGS=-DBC695 - BC695_SWIGFLAGS=-DBC695 - BC695_DEPLOYFLAGS=--bc695 + BC695_CC_DEF = BC695 + BC695_SWIGFLAGS = -DBC695 + BC695_DEPLOYFLAGS = --bc695 endif -IDA_INCLUDE=../../include +#---------------------------------------------------------------------- +# Build system hacks -DIST=$(F)dist - -ifdef __NT__ - SYSNAME=win - MSRUNTIME=/MD - MSCLOPTS=/nologo - MSLDOPTS=/nologo +# HACK HIJACK the $(I) variable to point to our staging SDK +# (but don't let mkdep know about it) +IDA_INCLUDE = ../../include +ifeq ($(OUT_OF_TREE_BUILD),) + ST_SDK = $(F)idasdk +else + ST_SDK = $(IDA_INCLUDE) +endif +ifndef __MKDEP__ + I = $(ST_SDK)/ +else + # HACK for mkdep to add dependencies for $(F)python$(O) + OBJS += $(F)python$(O) endif -ifdef __LINUX__ - SYSNAME=linux - DEFS=-D__LINUX__ - PYTHON32_LIBRARY_PATH?=/usr/lib - PYTHON32_LIBRARY_INCLUDE=-L$(PYTHON32_LIBRARY_PATH) -endif - -ifdef __MAC__ - SYSNAME=mac - DEFS=-D__MAC__ -endif - -DONT_ERASE_LIB=1 - -include ../plugin.mak -include ../pyplg.mak - -# allmake.unx defines 'CP' as 'qcp.sh' which is an internal tool providing +# allmake.mak defines 'CP' as 'qcp.sh' which is an internal tool providing # support for the '-u' flag on OSX. However, since this makefile is part # of the public release of IDAPython, we cannot rely on it (we do not use # that flag in IDAPython anyway) ifdef __MAC__ - CP=cp -f + CP = cp -f endif -PLUGIN_SCRIPT= +#---------------------------------------------------------------------- +# the 'configs' target is in $(IDA)module.mak +CONFIGS += python.cfg + +#---------------------------------------------------------------------- +# the 'modules' target is in $(IDA)module.mak +MODULE = $(call module_dll,python) +MODULES += $(MODULE) + +#---------------------------------------------------------------------- +# we explicitly added our module targets +NO_DEFAULT_MODULE = 1 +DONT_ERASE_LIB = 1 + +# NOTE: all MODULES must be defined before including plugin.mak. +include ../plugin.mak +include ../pyplg.mak +# NOTE: target-specific rules and dependencies that use variable +# expansion to name the target (such as "$(MODULE): [...]") must +# come after including plugin.mak + +#---------------------------------------------------------------------- +PYTHON_OBJS += $(F)python$(O) +$(MODULE): MODULE_OBJS += $(PYTHON_OBJS) +$(MODULE): $(PYTHON_OBJS) +ifdef __NT__ + $(MODULE): LDFLAGS += /DEF:$(IDAPYTHON_IMPLIB_DEF) /IMPLIB:$(IDAPYTHON_IMPLIB_PATH) +endif + +# TODO these should apply only to $(MODULE) +DEFFILE = idapython.script +INSTALL_NAME = @executable_path/plugins/$(notdir $(MODULE)) ifdef __LINUX__ - OUTDLLOPTS=-Wl,-soname,$(notdir $(BINARY)) -else - ifdef __MAC__ - OUTDLLOPTS=-Wl,-install_name,@executable_path/plugins/$(notdir $(BINARY)) - endif + LDFLAGS += -Wl,-soname,$(notdir $(MODULE)) endif -IDA_CMD=TVHEADLESS=1 $(R)idat$(X64SUFF)$(SUFF64) -ST_SWIG=$(F)swig -ifeq ($(OUT_OF_TREE_BUILD),) - ST_SDK=$(F)idasdk -else - ST_SDK=$(IDA_INCLUDE) +#---------------------------------------------------------------------- +# TODO move this below, but it might be necessary before the defines-* +ifdef DO_IDAMAKE_SIMPLIFY + QCHKAPI = @echo $(call qcolor,chkapi) && # + QDEPLOY = @echo $(call qcolor,deploy) $$< && # + QGENDOXYCFG = @echo $(call qcolor,gendoxycfg) $@ && # + QGENHOOKS = @echo $(call qcolor,genhooks) $< && # + QGENIDAAPI = @echo $(call qcolor,genidaapi) $< && # + QGENSWIGHEADER = @echo $(call qcolor,genswigheader) $< && # + QGEN_IDC_BC695 = @echo $(call qcolor,gen_idc_bc695) $< && # + QINJECT_PLFM = @echo $(call qcolor,inject_plfm) $< && # + QINJECT_PYDOC = @echo $(call qcolor,inject_pydoc) $$< && # + QPATCH_CODEGEN = @echo $(call qcolor,patch_codegen) $$< && # + QSWIG = @echo $(call qcolor,swig) $$< && # + QUPATE_SDK = @echo $(call qcolor,update_sdk) $< && # endif + +#---------------------------------------------------------------------- +IDA_CMD=TVHEADLESS=1 $(R)idat$(SUFF64) +ST_SWIG=$(F)swig ST_PYW=$(F)pywraps ST_WRAP=$(F)wrappers ST_PARSED_HEADERS_NOXML=$(F)parsed_notifications @@ -85,8 +118,6 @@ ST_PARSED_HEADERS=$(ST_PARSED_HEADERS_NOXML)/xml ifeq ($(OUT_OF_TREE_BUILD),) ST_PARSED_HEADERS_CONFIG=$(ST_PARSED_HEADERS_NOXML)/doxy_gen_notifs.cfg endif -ST_API_CONTENTS=$(F)api_contents.txt.new -ST_PYDOC_INJECTIONS=$(F)pydoc_injections.txt # output directory for python scripts DEPLOY_PYDIR=$(R)python @@ -98,32 +129,24 @@ DEPLOY_IDAAPI_PY=$(DEPLOY_PYDIR)/idaapi.py DEPLOY_IDADEX_PY=$(DEPLOY_PYDIR)/idadex.py ifeq ($(OUT_OF_TREE_BUILD),) TEST_IDC=test_idc - DBLZIP_SCRIPT:=$(abspath ../../ida/build/dblzip.py) - PKGBIN_SCRIPT:=$(abspath ../../ida/build/pkgbin.py) IDC_BC695_IDC_SOURCE?=$(DEPLOY_PYDIR)/../idc/idc.idc endif # SDK_SOURCES=$(wildcard $(IDA_INCLUDE)/*.h) $(wildcard $(IDA_INCLUDE)/*.hpp) ifeq ($(OUT_OF_TREE_BUILD),) - ST_SDK_TARGETS=$(SDK_SOURCES:$(IDA_INCLUDE)/%=$(ST_SDK)/%) + ST_SDK_TARGETS = $(SDK_SOURCES:$(IDA_INCLUDE)/%=$(ST_SDK)/%) else - ST_SDK_TARGETS=$(SDK_SOURCES) + ST_SDK_TARGETS = $(SDK_SOURCES) endif PYTHON_DYNLOAD=$(BIN_PATH)../python/lib/python2.7/lib-dynload DEPLOY_LIBDIR=$(PYTHON_DYNLOAD)/ida_$(ADRSIZE) -$(DEPLOY_LIBDIR): - -@if [ ! -d "$(DEPLOY_LIBDIR)" ] ; then mkdir -p 2>/dev/null $(DEPLOY_LIBDIR) ; fi - -$(DEPLOY_PYDIR): - -@if [ ! -d "$(DEPLOY_PYDIR)" ] ; then mkdir -p 2>/dev/null $(DEPLOY_PYDIR) ; fi - ifdef __NT__ - MODULE_SFX=.pyd + MODULE_SFX = .pyd else - MODULE_SFX=.so + MODULE_SFX = .so endif ifneq ($(OUT_OF_TREE_BUILD),) @@ -132,86 +155,85 @@ else HAS_HEXRAYS=1 # force hexrays bindings endif ifneq ($(HAS_HEXRAYS),) - WITH_HEXRAYS=-DWITH_HEXRAYS + WITH_HEXRAYS_DEF = WITH_HEXRAYS WITH_HEXRAYS_CHKAPI=--with-hexrays HEXRAYS_MODNAME=hexrays endif -# We are building 'MODULES_NAMES' from subvars because it appears some versions -# of make do not deal too well with '\'s, and introduce spaces, which later is -# problematic when substituting ' ' for ',' & passing modules list to scripts -MNAMES_0=allins range auto bytes dbg diskio entry enum expr fixup -MNAMES_1=fpro frame funcs gdl graph $(HEXRAYS_MODNAME) ida idaapi idd idp -MNAMES_2=kernwin lines loader moves nalt name netnode offset pro problems -MNAMES_3=registry search segment segregs strlist struct typeinf tryblks ua xref -MNAMES_EXTRA=idc -MODULES_NAMES=$(MNAMES_0) $(MNAMES_1) $(MNAMES_2) $(MNAMES_3) $(MNAMES_EXTRA) +#---------------------------------------------------------------------- +MODULES_NAMES += $(HEXRAYS_MODNAME) +MODULES_NAMES += allins +MODULES_NAMES += auto +MODULES_NAMES += bytes +MODULES_NAMES += dbg +MODULES_NAMES += diskio +MODULES_NAMES += entry +MODULES_NAMES += enum +MODULES_NAMES += expr +MODULES_NAMES += fixup +MODULES_NAMES += fpro +MODULES_NAMES += frame +MODULES_NAMES += funcs +MODULES_NAMES += gdl +MODULES_NAMES += graph +MODULES_NAMES += ida +MODULES_NAMES += idaapi +MODULES_NAMES += idc +MODULES_NAMES += idd +MODULES_NAMES += idp +MODULES_NAMES += kernwin +MODULES_NAMES += lines +MODULES_NAMES += loader +MODULES_NAMES += moves +MODULES_NAMES += nalt +MODULES_NAMES += name +MODULES_NAMES += netnode +MODULES_NAMES += offset +MODULES_NAMES += pro +MODULES_NAMES += problems +MODULES_NAMES += range +MODULES_NAMES += registry +MODULES_NAMES += search +MODULES_NAMES += segment +MODULES_NAMES += segregs +MODULES_NAMES += strlist +MODULES_NAMES += struct +MODULES_NAMES += tryblks +MODULES_NAMES += typeinf +MODULES_NAMES += ua +MODULES_NAMES += xref -MODULES=$(MODULES_NAMES:%=$(F)_ida_%$(MODULE_SFX)) -DEPLOYED_MODULES=$(MODULES_NAMES:%=$(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX)) -MODULES_OBJECTS=$(MODULES_NAMES:%=$(F)%$(O)) +ALL_ST_WRAP_CPP = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/$(mod).cpp) +ALL_ST_WRAP_PY = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/ida_$(mod).py) +DEPLOYED_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(MODULE_SFX)) +IDAPYTHON_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_PYDIR)/ida_$(mod).py) +PYTHON_BINARY_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(MODULE_SFX)) -ALL_ST_SWIG=$(foreach mod,$(MODULES_NAMES),$(ST_SWIG)/$(mod).i) -ALL_ST_WRAP_CPP=$(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/$(mod).cpp) -ALL_ST_WRAP_PY=$(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/ida_$(mod).py) - -PYTHON_MODULES=$(MODULES_NAMES:%=$(DEPLOY_PYDIR)/ida_%.py) -PYTHON_BINARY_MODULES=$(MODULES_NAMES:%=$(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX)) +#---------------------------------------------------------------------- +idapython_modules: $(IDAPYTHON_MODULES) +deployed_modules: $(DEPLOYED_MODULES) ifdef __NT__ - MODULE_LINKIDA= - CREATE_IMPLIB=$(RS)lib32.bat - IDAPYTHON_IMPLIB_DEF=$(F)idapython_implib.def - IDAPYTHON_IMPLIB_DEF_IN=tools/idapython_implib.def.in + IDAPYTHON_IMPLIB_DEF=idapython_implib.def IDAPYTHON_IMPLIB_PATH=$(F)python.lib - BINARY_LINKOPTS=/def:$(IDAPYTHON_IMPLIB_DEF) /IMPLIB:$(IDAPYTHON_IMPLIB_PATH) - RESFILES=$(IDAPYTHON_IMPLIB_DEF) + LINKIDAPYTHON = $(IDAPYTHON_IMPLIB_PATH) else - ifeq ($(OUT_OF_TREE_BUILD),) - LIBIDA_DIR:=$(R) - else - LIBIDA_DIR:=$(L) - endif - MODULE_LINKIDA=-L$(LIBIDA_DIR) $(LINKIDA) $(BINARY) -endif - -all: objdir pyfiles config $(DEPLOYED_MODULES) $(PYTHON_MODULES) $(ST_API_CONTENTS) $(IDAPYTHON_IMPLIB) $(ST_PYDOC_INJECTIONS) #$(TEST_IDC) - -# IDAPython version -IDAPYTHON_VERSION_MAJOR=6 -IDAPYTHON_VERSION_MINOR=9 -IDAPYTHON_VERSION_PATCH=5 -PACKAGE_NAME=idapython-$(IDAPYTHON_VERSION_MAJOR).$(IDAPYTHON_VERSION_MINOR).$(IDAPYTHON_VERSION_PATCH)-python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)-$(SYSNAME) - - -# HIJACK the $(I) variable to point to our staging SDK -I=$(ST_SDK)/ - -ifdef __CODE_CHECKER__ - ADDITIONAL_GOALS:=$(filter-out pyfiles config $(TEST_IDC),$(ADDITIONAL_GOALS)) - OBJS:=$(filter-out $(OBJ1),$(OBJS)) + LINKIDAPYTHON = $(MODULE) endif ifdef __NT__ # os and compiler specific flags - ifneq ($(UCRT_INCLUDE),) - I_UCRT_INCLUDE=/I$(UCRT_INCLUDE) - endif - IDAPYTHON_CFLAGS=$(PYTHON_CFLAGS) -w -Z7 /bigobj /I$(MSVCDIR)Include $(I_UCRT_INCLUDE) - _SWIGFLAGS=-D__NT__ -DWIN32 -D_USRDLL -I$(PYTHON_DIR)/include - SWIGINCLUDES?= # nothing - # FIXME: Cannot enable the .cfg file ATM, because there's just too many errors if I do. - PLATFORM_CFLAGS=$(_SWIGFLAGS) -UNO_OBSOLETE_FUNCS + _SWIGFLAGS = -D__NT__ -DWIN32 -D_USRDLL -I$(PYTHON_DIR)/include + CFLAGS += /bigobj $(_SWIGFLAGS) -I$(ST_SDK) /U_DEBUG + # override runtime libs in CFLAGS + RUNTIME_LIBSW = /MD else # unix/mac ifdef __LINUX__ PYTHON_LDFLAGS_RPATH_MAIN=-Wl,-rpath='$$ORIGIN/..' - PYTHON_LDFLAGS_RPATH_MODULE=-Wl,-rpath='$$$$ORIGIN/../../..' - else - MACDEFINES=-DMACSDKVER=$(MACSDKVER) + PYTHON_LDFLAGS_RPATH_MODULE=-Wl,-rpath='$$ORIGIN/../../..' + _SWIGFLAGS = -D__LINUX__ + else ifdef __MAC__ + _SWIGFLAGS = -D__MAC__ endif - IDAPYTHON_CFLAGS=-w -g - PLATFORM_CFLAGS=$(SYS) -g $(PYTHON_CFLAGS) $(ARCH_CFLAGS) $(PIC) -UNO_OBSOLETE_FUNCS # gcc flags - _SWIGFLAGS=$(DEFS) - SWIGINCLUDES?=-I$(SWIGDIR)share/swig/$(SWIG_VERSION)/python -I$(SWIGDIR)share/swig/$(SWIG_VERSION) endif # Apparently that's not needed, but I don't understand why ATM, since doc says: # ...Then, only modules compiled with SWIG_TYPE_TABLE set to myprojectname @@ -219,184 +241,186 @@ endif # should be compiled with -DSWIG_TYPE_TABLE=myprojectname, and then these # three modules will share type information. But any other project's # types will not interfere or clash with the types in your module. -DEF_TYPE_TABLE=-DSWIG_TYPE_TABLE=idaapi -SWIGFLAGS=$(_SWIGFLAGS) -Itools/typemaps-supplement $(SWIGINCLUDES) $(DEF_TYPE_TABLE) -D__IDP__ -D__PLUGIN__ $(BC695_SWIGFLAGS) +DEF_TYPE_TABLE = SWIG_TYPE_TABLE=idaapi +SWIGFLAGS=$(_SWIGFLAGS) -Itools/typemaps-supplement $(SWIG_INCLUDES) $(addprefix -D,$(DEF_TYPE_TABLE)) $(BC695_SWIGFLAGS) -ADDITIONAL_LIBS=$(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MAIN) -ifdef __LINUX__ - ADDITIONAL_LIBS_MODULE=$(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MODULE) -else - ADDITIONAL_LIBS_MODULE=$(ADDITIONAL_LIBS) -endif - -PUBTREE_DIR=$(F)/public_tree - -.PHONY: pyfiles docs $(TEST_IDC) staging_dirs clean check_python package public_tree -config: $(C)python.cfg - -clean:: - rm -rf obj/ +LDFLAGS += $(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MAIN) pyfiles: $(DEPLOY_IDAUTILS_PY) \ - $(DEPLOY_IDC_PY) \ - $(DEPLOY_IDC_BC695_PY) \ - $(DEPLOY_INIT_PY) \ - $(DEPLOY_IDAAPI_PY) \ - $(DEPLOY_IDADEX_PY) + $(DEPLOY_IDC_PY) \ + $(DEPLOY_IDC_BC695_PY) \ + $(DEPLOY_INIT_PY) \ + $(DEPLOY_IDAAPI_PY) \ + $(DEPLOY_IDADEX_PY) GENHOOKS=tools/genhooks/ -_SPACE := $(null) # -_COMMA := , -$(DEPLOY_INIT_PY): python/init.py | $(DEPLOY_PYDIR) +$(DEPLOY_INIT_PY): python/init.py $(CP) $? $@ -$(DEPLOY_IDC_PY): python/idc.py | $(DEPLOY_PYDIR) +$(DEPLOY_IDC_PY): python/idc.py $(CP) $? $@ -$(DEPLOY_IDAUTILS_PY): python/idautils.py | $(DEPLOY_PYDIR) +$(DEPLOY_IDAUTILS_PY): python/idautils.py $(CP) $? $@ -$(DEPLOY_IDC_BC695_PY): $(IDC_BC695_IDC_SOURCE) python/idc.py tools/gen_idc_bc695.py | $(DEPLOY_PYDIR) - $(PYTHON) tools/gen_idc_bc695.py --idc $(IDC_BC695_IDC_SOURCE) --output $@ +$(DEPLOY_IDC_BC695_PY): $(IDC_BC695_IDC_SOURCE) python/idc.py tools/gen_idc_bc695.py + $(QGEN_IDC_BC695)$(PYTHON) tools/gen_idc_bc695.py --idc $(IDC_BC695_IDC_SOURCE) --output $@ -$(DEPLOY_PYDIR)/idaapi.py: python/idaapi.py tools/genidaapi.py $(PYTHON_MODULES) | $(DEPLOY_PYDIR) - $(PYTHON) tools/genidaapi.py -i $< -o $@ -m $(subst $(_SPACE),$(_COMMA),$(MODULES_NAMES)) +$(DEPLOY_IDAAPI_PY): python/idaapi.py tools/genidaapi.py $(IDAPYTHON_MODULES) + $(QGENIDAAPI)$(PYTHON) tools/genidaapi.py -i $< -o $@ -m $(subst $(space),$(comma),$(MODULES_NAMES)) -$(DEPLOY_PYDIR)/idadex.py: python/idadex.py | $(DEPLOY_PYDIR) +$(DEPLOY_IDADEX_PY): python/idadex.py $(CP) $? $@ $(DEPLOY_PYDIR)/lib/%: precompiled/lib/% - mkdir -p $(@D) cp $< $@ - @chmod +w $@ + $(Q)chmod +w $@ -$(C)python.cfg: python.cfg - $(CP) $? $@ - -$(R)$(LIBPYTHON_NAME): $(PRECOMPILED_DIR)/$(LIBPYTHON_NAME) - $(CP) $? $@ - -# ------------------------------------------------------------------------- +#---------------------------------------------------------------------- # Hooks generation # http://stackoverflow.com/questions/11032280/specify-doxygen-parameters-through-command-line -$(ST_PARSED_HEADERS_CONFIG): $(GENHOOKS)doxy_gen_notifs.cfg.in $(ST_SDK_TARGETS) $(GENHOOKS)gendoxycfg.py | staging_dirs - @$(PYTHON) $(GENHOOKS)gendoxycfg.py -i $< -o $@ --includes $(subst $(_SPACE),$(_COMMA),$(ST_SDK_TARGETS)) +$(ST_PARSED_HEADERS_CONFIG): $(GENHOOKS)doxy_gen_notifs.cfg.in $(ST_SDK_TARGETS) $(GENHOOKS)gendoxycfg.py + $(QGENDOXYCFG)$(PYTHON) $(GENHOOKS)gendoxycfg.py -i $< -o $@ --includes $(subst $(space),$(comma),$(ST_SDK_TARGETS)) PARSED_HEADERS_MARKER=$(ST_PARSED_HEADERS)/headers_generated.marker $(PARSED_HEADERS_MARKER): $(ST_SDK_TARGETS) $(ST_PARSED_HEADERS_CONFIG) $(ST_SDK_TARGETS) ifeq ($(OUT_OF_TREE_BUILD),) - @( cat $(ST_PARSED_HEADERS_CONFIG); echo "OUTPUT_DIRECTORY=$(ST_PARSED_HEADERS_NOXML)" ) | $(DOXYGEN_BIN) - + $(Q)( cat $(ST_PARSED_HEADERS_CONFIG); echo "OUTPUT_DIRECTORY=$(ST_PARSED_HEADERS_NOXML)" ) | $(DOXYGEN_BIN) - >/dev/null else (cd $(F) && unzip ../../out_of_tree/parsed_notifications.zip) endif - @touch $@ + $(Q)touch $@ -# -staging_dirs: - -@if [ ! -d "$(ST_SDK)" ] ; then mkdir -p 2>/dev/null $(ST_SDK) ; fi - -@if [ ! -d "$(ST_SWIG)" ] ; then mkdir -p 2>/dev/null $(ST_SWIG) ; fi - -@if [ ! -d "$(ST_PYW)" ] ; then mkdir -p 2>/dev/null $(ST_PYW) ; fi - -@if [ ! -d "$(ST_WRAP)" ] ; then mkdir -p 2>/dev/null $(ST_WRAP) ; fi - -@if [ ! -d "$(ST_PARSED_HEADERS)" ] ; then mkdir -p 2>/dev/null $(ST_PARSED_HEADERS) ; fi +#---------------------------------------------------------------------- +# Create directories in the first phase of makefile parsing. +DIRLIST += $(DEPLOY_LIBDIR) +DIRLIST += $(DEPLOY_PYDIR) +DIRLIST += $(DEPLOY_PYDIR)/lib +DIRLIST += $(ST_PARSED_HEADERS) +DIRLIST += $(ST_PYW) +DIRLIST += $(ST_SDK) +DIRLIST += $(ST_SWIG) +DIRLIST += $(ST_WRAP) +$(foreach d,$(sort $(DIRLIST)),$(if $(wildcard $(d)),,$(shell mkdir -p $(d)))) -# ------------------------------------------------------------------------- +#---------------------------------------------------------------------- # obj/.../idasdk/*.h[pp] -# ifeq ($(OUT_OF_TREE_BUILD),) -$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h | staging_dirs $(PRECOMPILED_COPY) - $(PYTHON) ../../bin/update_sdk.py $(FILTER_SDK_FLAGS) -filter-file -input $^ -output $@ -$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp | staging_dirs $(PRECOMPILED_COPY) - $(PYTHON) ../../bin/update_sdk.py $(FILTER_SDK_FLAGS) -filter-file -input $^ -output $@ +$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h + $(QUPATE_SDK)$(PYTHON) ../../bin/update_sdk.py $(FILTER_SDK_FLAGS) -filter-file -input $^ -output $@ +$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp + $(QUPATE_SDK)$(PYTHON) ../../bin/update_sdk.py $(FILTER_SDK_FLAGS) -filter-file -input $^ -output $@ endif -# ------------------------------------------------------------------------- +#---------------------------------------------------------------------- # obj/.../pywraps/* -# -$(ST_PYW)/%.hpp: pywraps/%.hpp | staging_dirs - @$(CP) $^ $@ && chmod +rw $@ -$(ST_PYW)/%.py: pywraps/%.py | staging_dirs - @$(CP) $^ $@ && chmod +rw $@ - +$(ST_PYW)/%.hpp: pywraps/%.hpp + $(Q)$(CP) $^ $@ && chmod +rw $@ +$(ST_PYW)/%.py: pywraps/%.py + $(Q)$(CP) $^ $@ && chmod +rw $@ # These require special care, as they will have to be injected w/ hooks -- this # only happens if we are sitting in the hexrays source tree; when published to # the outside world, the pywraps must already contain the injected code. $(ST_PYW)/py_idp.hpp: pywraps/py_idp.hpp \ - $(I)idp.hpp \ - $(GENHOOKS)genhooks.py \ - $(GENHOOKS)recipe_idphooks.py \ - $(PARSED_HEADERS_MARKER) | staging_dirs $(SDK_SOURCES) - @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ - -x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e event_t \ - -r int -n 0 -m hookgenIDP -q "processor_t::" \ - -R $(GENHOOKS)recipe_idphooks.py + $(I)idp.hpp \ + $(GENHOOKS)genhooks.py \ + $(GENHOOKS)recipe_idphooks.py \ + $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES) + $(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e event_t \ + -r int -n 0 -m hookgenIDP -q "processor_t::" \ + -R $(GENHOOKS)recipe_idphooks.py $(ST_PYW)/py_idp_idbhooks.hpp: pywraps/py_idp_idbhooks.hpp \ - $(I)idp.hpp \ - $(GENHOOKS)genhooks.py \ - $(GENHOOKS)recipe_idbhooks.py \ - $(PARSED_HEADERS_MARKER) | staging_dirs $(SDK_SOURCES) - @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ - -x $(ST_PARSED_HEADERS)/namespaceidb__event.xml -e event_code_t \ - -r int -n 0 -m hookgenIDB -q "idb_event::" \ - -R $(GENHOOKS)recipe_idbhooks.py + $(I)idp.hpp \ + $(GENHOOKS)recipe_idbhooks.py \ + $(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES) + $(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/namespaceidb__event.xml -e event_code_t \ + -r int -n 0 -m hookgenIDB -q "idb_event::" \ + -R $(GENHOOKS)recipe_idbhooks.py $(ST_PYW)/py_dbg.hpp: pywraps/py_dbg.hpp \ - $(I)dbg.hpp \ - $(GENHOOKS)genhooks.py \ - $(GENHOOKS)recipe_dbghooks.py \ - $(PARSED_HEADERS_MARKER) | staging_dirs $(SDK_SOURCES) - @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ - -x $(ST_PARSED_HEADERS)/dbg_8hpp.xml -e dbg_notification_t \ - -r void -n 0 -m hookgenDBG \ - -R $(GENHOOKS)recipe_dbghooks.py + $(I)dbg.hpp \ + $(GENHOOKS)recipe_dbghooks.py \ + $(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES) + $(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/dbg_8hpp.xml -e dbg_notification_t \ + -r void -n 0 -m hookgenDBG \ + -R $(GENHOOKS)recipe_dbghooks.py $(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \ - $(I)kernwin.hpp \ - $(GENHOOKS)genhooks.py \ - $(GENHOOKS)recipe_uihooks.py \ - $(PARSED_HEADERS_MARKER) | staging_dirs $(SDK_SOURCES) - @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ - -x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e ui_notification_t \ - -r void -n 0 -m hookgenUI \ - -R $(GENHOOKS)recipe_uihooks.py \ - -d "ui_dbg_,ui_obsolete" -D "ui:" -s "ui_" + $(I)kernwin.hpp \ + $(GENHOOKS)recipe_uihooks.py \ + $(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES) + $(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e ui_notification_t \ + -r void -n 0 -m hookgenUI \ + -R $(GENHOOKS)recipe_uihooks.py \ + -d "ui_dbg_,ui_obsolete" -D "ui:" -s "ui_" $(ST_PYW)/py_kernwin_viewhooks.hpp: pywraps/py_kernwin_viewhooks.hpp \ - $(I)kernwin.hpp \ - $(GENHOOKS)genhooks.py \ - $(GENHOOKS)recipe_viewhooks.py \ - $(PARSED_HEADERS_MARKER) | staging_dirs $(SDK_SOURCES) - @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ - -x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e view_notification_t \ - -r void -n 0 -m hookgenVIEW \ - -R $(GENHOOKS)recipe_viewhooks.py + $(I)kernwin.hpp \ + $(GENHOOKS)recipe_viewhooks.py \ + $(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES) + $(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e view_notification_t \ + -r void -n 0 -m hookgenVIEW \ + -R $(GENHOOKS)recipe_viewhooks.py +$(ST_PYW)/py_hexrays_hooks.hpp: pywraps/py_hexrays_hooks.hpp \ + $(I)hexrays.hpp \ + $(GENHOOKS)recipe_hexrays.py \ + $(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES) + $(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/hexrays_8hpp.xml -e hexrays_event_t \ + -r int -n 0 -m hookgenHEXRAYS \ + -R $(GENHOOKS)recipe_hexrays.py \ + -s "hxe_,lxe_" -CFLAGS= $(CCOPT) $(PLATFORM_CFLAGS) $(MSRUNTIME) -D__EXPR_SRC -I. -I$(ST_SWIG) -I$(ST_SDK) -I$(F) \ - -DVER_MAJOR="1" -DVER_MINOR="7" -DVER_PATCH="0" -D__IDP__ -D__PLUGIN__ \ - -DUSE_STANDARD_FILE_FUNCTIONS $(IDAPYTHON_CFLAGS) \ - $(SWITCH64) $(SWITCHX64) $(ARCH_CFLAGS) $(WITH_HEXRAYS) $(DEF_TYPE_TABLE) $(BC695_CFLAGS) +#---------------------------------------------------------------------- +CFLAGS += $(PYTHON_CFLAGS) +CC_DEFS += $(BC695_CC_DEF) +CC_DEFS += $(DEF_TYPE_TABLE) +CC_DEFS += $(WITH_HEXRAYS_DEF) +CC_DEFS += USE_STANDARD_FILE_FUNCTIONS +CC_DEFS += VER_MAJOR="1" +CC_DEFS += VER_MINOR="7" +CC_DEFS += VER_PATCH="0" +CC_DEFS += __EXPR_SRC +CC_INCP += $(F) +CC_INCP += $(IDA_INCLUDE) +CC_INCP += $(ST_SWIG) +CC_INCP += . + +# suppress warnings +WARNS = $(NOWARNS) + +# disable -pthread in CFLAGS +PTHR_SWITCH = + +# disable -DNO_OBSOLETE_FUNCS in CFLAGS +NO_OBSOLETE_FUNCS = + +#---------------------------------------------------------------------- ifdef TESTABLE_BUILD - CFLAGS+=-DTESTABLE_BUILD SWIGFLAGS+=-DTESTABLE_BUILD FILTER_SDK_FLAGS+=-testable-build endif -ST_SWIG_HEADER=$(ST_SWIG)/header.i -$(ST_SWIG)/header.i: tools/deploy/header.i.in tools/genswigheader.py $(ST_SDK_TARGETS) | staging_dirs - $(PYTHON) tools/genswigheader.py -i $< -o $@ -m $(subst $(_SPACE),$(_COMMA),$(MODULES_NAMES)) -s $(ST_SDK) - +ST_SWIG_HEADER = $(ST_SWIG)/header.i +$(ST_SWIG)/header.i: tools/deploy/header.i.in tools/genswigheader.py $(ST_SDK_TARGETS) + $(QGENSWIGHEADER)$(PYTHON) tools/genswigheader.py -i $< -o $@ -m $(subst $(space),$(comma),$(MODULES_NAMES)) -s $(ST_SDK) ifdef __NT__ -PATCH_DIRECTORS_SCRIPT:=tools/patch_directors_cc.py - -$(IDAPYTHON_IMPLIB_DEF): $(IDAPYTHON_IMPLIB_DEF_IN) - sed s/%LIBNAME%/$(notdir $(BINARY))/ < $? > $@ - sed -i s/%PLUGIN_DATA_EXP%// $@ + PATCH_DIRECTORS_SCRIPT = tools/patch_directors_cc.py endif -PATCH_CODEGEN_X64_OPTS=--apply-valist-patches +find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $(1)))*.hpp) $(wildcard pywraps/py_$(subst .i,,$(notdir $(1)))*.py) +find-pydoc-patches-deps = $(wildcard tools/inject_pydoc/$(1).py) -find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $1))*.*) -find-pydoc-patches-deps = $(wildcard tools/inject_pydoc/$1.py) + +ADDITIONAL_PYWRAP_DEP_idp=$(ST_PYW)/py_idp.py +$(ST_PYW)/py_idp.py: pywraps/py_idp.py.in tools/inject_plfm.py $(ST_SDK)/idp.hpp + $(QINJECT_PLFM)$(PYTHON) tools/inject_plfm.py -i $< -o $@ -d $(ST_SDK)/idp.hpp # Some .i files depend on some other .i files in order to be parseable by SWiG # (e.g., segregs.i imports range.i). Declare the list of such dependencies here @@ -407,6 +431,7 @@ SWIG_IFACE_frame=range SWIG_IFACE_funcs=range SWIG_IFACE_gdl=range SWIG_IFACE_hexrays=typeinf +SWIG_IFACE_idd=range SWIG_IFACE_segment=range SWIG_IFACE_segregs=range SWIG_IFACE_typeinf=idp @@ -421,116 +446,146 @@ define make-module-rules # http://stackoverflow.com/questions/19822435/multiple-targets-from-one-recipe-and-parallel-execution # Consequently, rules such as this: # - # $(ST_WRAP)/ida_$1.py: $(ST_WRAP)/$1.cpp + # $(ST_WRAP)/ida_$(1).py: $(ST_WRAP)/$(1).cpp # # i.e., that do nothing but rely on the generation of another file, # will not work in // execution. Thus, we will rely exclusively on # the presence of the generated .cpp file, and not other generated # files. - # ../../bin/x86_linux_gcc/python/ida_$1.py (note: dep. on .cpp. See note above.) - $(DEPLOY_PYDIR)/ida_$1.py: $(ST_WRAP)/$1.cpp $(PARSED_HEADERS_MARKER) $(call find-pydoc-patches-deps,$1) | $(DEPLOY_PYDIR) tools/inject_pydoc.py - $(PYTHON) tools/inject_pydoc.py \ + # ../../bin/x86_linux_gcc/python/ida_$(1).py (note: dep. on .cpp. See note above.) + $(DEPLOY_PYDIR)/ida_$(1).py: $(ST_WRAP)/$(1).cpp $(PARSED_HEADERS_MARKER) $(call find-pydoc-patches-deps,$(1)) | tools/inject_pydoc.py + $(QINJECT_PYDOC)$(PYTHON) tools/inject_pydoc.py \ -x $(ST_PARSED_HEADERS) \ - -m $1 \ - -i $(ST_WRAP)/ida_$1.py \ - -w $(ST_SWIG)/$1.i \ - -o $$@ \ - -e $(ST_WRAP)/ida_$1.epydoc_injection \ - -v > $(ST_WRAP)/ida_$1.pydoc_injection 2>&1 + -m $(1) \ + -i $(ST_WRAP)/ida_$(1).py \ + -w $(ST_SWIG)/$(1).i \ + -o $$@ \ + -e $(ST_WRAP)/ida_$(1).epydoc_injection \ + -v > $(ST_WRAP)/ida_$(1).pydoc_injection 2>&1 # obj/x86_linux_gcc/swig/X.i - $(ST_SWIG)/$1.i: $(addprefix $(F),$(call find-pywraps-deps,$1)) swig/$1.i $(ST_SWIG_HEADER) $(SWIG_IFACE_$1:%=$(ST_SWIG)/%.i) $(ST_SWIG_HEADER) tools/deploy.py - $(PYTHON) tools/deploy.py \ - --pywraps $(ST_PYW) \ - --template $$(subst $(F),,$$@) \ - --output $$@ \ - --module $$(subst .i,,$$(notdir $$@)) \ - $(MODULE_LIFECYCLE_$1) \ - $(BC695_DEPLOYFLAGS) \ - --interface-dependencies=$(subst $(_SPACE),$(_COMMA),$(SWIG_IFACE_$1)) + $(ST_SWIG)/$(1).i: $(addprefix $(F),$(call find-pywraps-deps,$(1))) $(ADDITIONAL_PYWRAP_DEP_$(1)) swig/$(1).i $(ST_SWIG_HEADER) $(SWIG_IFACE_$(1):%=$(ST_SWIG)/%.i) $(ST_SWIG_HEADER) tools/deploy.py $(PARSED_HEADERS_MARKER) + $(QDEPLOY)$(PYTHON) tools/deploy.py \ + --pywraps $(ST_PYW) \ + --template $$(subst $(F),,$$@) \ + --output $$@ \ + --module $$(subst .i,,$$(notdir $$@)) \ + $(MODULE_LIFECYCLE_$(1)) \ + $(BC695_DEPLOYFLAGS) \ + --interface-dependencies=$(subst $(space),$(comma),$(SWIG_IFACE_$(1))) \ + --xml-doc-directory $(ST_PARSED_HEADERS) # obj/x86_linux_gcc/wrappers/X.cpp - $(ST_WRAP)/$1.cpp: $(ST_SWIG)/$1.i tools/patch_codegen.py makefile $(PATCH_DIRECTORS_SCRIPT) tools/chkapi.py - $(SWIG) -modern $(WITH_HEXRAYS) -python -threads -c++ -shadow \ - $(MACDEFINES) -D__GNUC__ $(SWIGFLAGS) $(SWITCH64) $(SWITCHX64) -I$(ST_SWIG) \ - -outdir $(ST_WRAP) -o $$@ -I$(ST_SDK) $$< - @$(PYTHON) tools/patch_constants.py --file $(ST_WRAP)/$1.cpp - $(PYTHON) tools/patch_codegen.py $(PATCH_CODEGEN_X64_OPTS) --file $(ST_WRAP)/$1.cpp --patches tools/patch_codegen/$1.py + $(ST_WRAP)/$(1).cpp: $(ST_SWIG)/$(1).i tools/patch_codegen.py $(PATCH_DIRECTORS_SCRIPT) $(PARSED_HEADERS_MARKER) tools/chkapi.py + $(QSWIG)$(SWIG) -modern $(addprefix -D,$(WITH_HEXRAYS_DEF)) -python -threads -c++ -shadow \ + -D__GNUC__ $(SWIGFLAGS) $(addprefix -D,$(DEF64)) -I$(ST_SWIG) \ + -outdir $(ST_WRAP) -o $$@ -I$(ST_SDK) $$< + $(Q)$(PYTHON) tools/patch_constants.py --file $(ST_WRAP)/$(1).cpp + $(QPATCH_CODEGEN)$(PYTHON) tools/patch_codegen.py \ + --apply-valist-patches \ + --file $(ST_WRAP)/$(1).cpp \ + --module $(1) \ + --xml-doc-directory $(ST_PARSED_HEADERS) \ + --patches tools/patch_codegen/$(1).py ifdef __NT__ - $(PYTHON) $(PATCH_DIRECTORS_SCRIPT) --file $(ST_WRAP)/$1.h + $(PYTHON) $(PATCH_DIRECTORS_SCRIPT) --file $(ST_WRAP)/$(1).h endif # The copying of the .py will preserve attributes (including timestamps). - # And, since we have patched $1.cpp, it'll be more recent than ida_$1.py, + # And, since we have patched $(1).cpp, it'll be more recent than ida_$(1).py, # and make would keep copying the .py file at each invocation. # To prevent that, let's make the source .py file more recent than .cpp. - @touch $(ST_WRAP)/ida_$1.py - - # obj/x86_linux_gcc/X.o32 - $(F)$1$(O): $(ST_WRAP)/$1.cpp - ifdef __CODE_CHECKER__ - touch $$@ - else - $(CXX) $(CFLAGS) $(MSRUNTIME) $(MSCLOPTS) $(NORTTI) -DPLUGIN_SUBMODULE -DSWIG_DIRECTOR_NORTTI -c $(OBJSW)$$@ $(ST_WRAP)/$1.cpp - ifndef __NT__ - ifeq ($(OUT_OF_TREE_BUILD),) - @$(STRIPSYM_TOOL) $$@ $(STRIPSYMS) > /dev/null || ($(RM) $$@; false) - endif - endif - endif - - # obj/x86_linux_gcc/_ida_X.so - $(F)_ida_$1$(MODULE_SFX): $(F)$1$(O) $(BINARY) $(IDAPYTHON_IMPLIB_DEF) - ifdef __NT__ # we repeat /map switch with the explicit file name because @F does not work inside macro - $(LINKER) $(LINKOPTS) /map:$(F)_ida_$1$(MODULE_SFX).map $(MSLDOPTS) /OPT:ICF /OPT:REF /INCREMENTAL:NO /STUB:../../plugins/stub /OUT:$$@ $$< $(IDALIB) user32.lib $(ADDITIONAL_LIBS_MODULE) $(IDAPYTHON_IMPLIB_PATH) - else - $(CCL) $(OUTDLL) $(OUTSW)$$@ $$< $(MODULE_LINKIDA) $(PLUGIN_SCRIPT) $(ADDITIONAL_LIBS_MODULE) $(STDLIBS) - endif - - # ../../bin/x86_linux_gcc/python/lib/lib-dynload/ida_32/_ida_X.so - $(DEPLOY_LIBDIR)/_ida_$1$(MODULE_SFX): $(F)_ida_$1$(MODULE_SFX) | $(DEPLOY_LIBDIR) - @$(CP) $$< $$@ + $(Q)touch $(ST_WRAP)/ida_$(1).py endef $(foreach mod,$(MODULES_NAMES),$(eval $(call make-module-rules,$(mod)))) +# obj/x86_linux_gcc/X.o +X_O = $(call objs,$(MODULES_NAMES)) +vpath %.cpp $(ST_WRAP) +ifdef __NT__ + # remove warnings from generated code: + # error C4296: '<': expression is always false + # warning C4700: uninitialized local variable 'c_result' used + # warning C4706: assignment within conditional expression + $(X_O): CFLAGS += /wd4296 /wd4700 /wd4706 +endif +# disable -fno-rtti +$(X_O): NORTTI = +$(X_O): CC_DEFS += PLUGIN_SUBMODULE +$(X_O): CC_DEFS += SWIG_DIRECTOR_NORTTI +ifdef __CODE_CHECKER__ +$(X_O): + $(Q)touch $@ +endif + +# obj/x86_linux_gcc/_ida_X.so +_IDA_X_SO = $(addprefix $(F)_ida_,$(addsuffix $(MODULE_SFX),$(MODULES_NAMES))) +ifdef __NT__ + $(_IDA_X_SO): STDLIBS += user32.lib +endif +# Note: On Windows, IDAPython's python.lib must come *after* python27.lib +# in the linking command line, otherwise Python will misdetect +# IDAPython's python.dll as the main "python" DLL, and IDAPython +# will fail to load with the following error: +# "Module use of python.dll conflicts with this version of Python." +# To achieve this, we add IDAPython's python.lib to STDLIBS, which +# is at the end of the link command. +# See Python's dynload_win.c:GetPythonImport() for more details. +$(_IDA_X_SO): STDLIBS += $(LINKIDAPYTHON) +$(_IDA_X_SO): LDFLAGS += $(PYTHON_LDFLAGS_RPATH_MODULE) $(OUTMAP)$(F)$(@F).map +$(F)_ida_%$(MODULE_SFX): $(F)%$(O) $(MODULE) $(IDAPYTHON_IMPLIB_DEF) + $(call link_dll, $<, $(LINKIDA)) +ifdef __NT__ + $(Q)$(RM) $(@:$(MODULE_SFX)=.exp) $(@:$(MODULE_SFX)=.lib) +endif + +# ../../bin/x86_linux_gcc/python/lib/lib-dynload/ida_32/_ida_X.so +$(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX): $(F)_ida_%$(MODULE_SFX) + $(Q)$(CP) $< $@ + +#---------------------------------------------------------------------- +API_CONTENTS = api_contents.txt +ST_API_CONTENTS = $(F)$(API_CONTENTS) +.PRECIOUS: $(ST_API_CONTENTS) + +api_contents: $(ST_API_CONTENTS) $(ST_API_CONTENTS): $(ALL_ST_WRAP_CPP) - $(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(_SPACE),$(_COMMA),$(ALL_ST_WRAP_CPP)) -p $(subst $(_SPACE),$(_COMMA),$(ALL_ST_WRAP_PY)) -r $(ST_API_CONTENTS) + $(QCHKAPI)$(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(space),$(comma),$(ALL_ST_WRAP_CPP)) -p $(subst $(space),$(comma),$(ALL_ST_WRAP_PY)) -r $(ST_API_CONTENTS) ifeq ($(OUT_OF_TREE_BUILD),) ifdef BC695 # turn off comparison when bw-compat is off, or api_contents will differ - @(diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null || \ - (echo "API CONTENTS CHANGED! update api_contents.txt or fix the API" && \ - echo "(New API: $(ST_API_CONTENTS)) ***" && \ - (diff -U 1 -w $(API_CONTENTS) $(ST_API_CONTENTS) && false)) + $(Q)(diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null || \ + (echo "API CONTENTS CHANGED! update $(API_CONTENTS) or fix the API" && \ + echo "(New API: $(ST_API_CONTENTS)) ***" && \ + (diff -U 1 -w $(API_CONTENTS) $(ST_API_CONTENTS) && false)) endif endif +#---------------------------------------------------------------------- # Check that doc injection is stable -PYDOC_INJECTIONS_RESULTS=$(MODULES_NAMES:%=$(ST_WRAP)/ida_%.pydoc_injection) -$(ST_PYDOC_INJECTIONS): tools/dumpdoc.py $(PYTHON_MODULES) $(PYTHON_BINARY_MODULES) +PYDOC_INJECTIONS = pydoc_injections.txt +ST_PYDOC_INJECTIONS = $(F)$(PYDOC_INJECTIONS) +.PRECIOUS: $(ST_PYDOC_INJECTIONS) + +pydoc_injections: $(ST_PYDOC_INJECTIONS) +$(ST_PYDOC_INJECTIONS): tools/dumpdoc.py $(IDAPYTHON_MODULES) $(PYTHON_BINARY_MODULES) ifdef __CODE_CHECKER__ - @touch $@ + $(Q)touch $@ else ifeq ($(OUT_OF_TREE_BUILD),) - @$(IDA_CMD) $(BATCH_SWITCH) -OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO -S"$< $@ $(ST_WRAP)" -t -L$(F)dumpdoc.log >/dev/null - @(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \ - (echo "PYDOC INJECTION CHANGED! update $(PYDOC_INJECTIONS) or fix .. what needs fixing" && \ - echo "(New API: $(ST_PYDOC_INJECTIONS)) ***" && \ - (diff -U 1 -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS) && false)) + $(Q)$(IDA_CMD) $(BATCH_SWITCH) -OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO -S"$< $@ $(ST_WRAP)" -t -L$(F)dumpdoc.log >/dev/null + $(Q)(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \ + (echo "PYDOC INJECTION CHANGED! update $(PYDOC_INJECTIONS) or fix .. what needs fixing" && \ + echo "(New API: $(ST_PYDOC_INJECTIONS)) ***" && \ + (diff -U 1 -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS) && false)) else - @touch $@ + $(Q)touch $@ endif endif -# Require a strict SWiG version (other versions might generate different code.) -SWIG_VERSION_ACTUAL=$(shell $(SWIG) -version | awk "/SWIG Version [0-9.]+/ { if (match(\$$0, /([0-9.]+)/)) { print substr(\$$0, RSTART, RLENGTH); } }") - -# ST_WRAP_FILES=$(MODULES_NAMES:%=$(ST_WRAP)/%.cpp) $(MODULES_NAMES:%=$(ST_WRAP)/%.h) $(MODULES_NAMES:%=$(ST_WRAP)/ida_%.py) -# .PRECIOUS: $(ST_WRAP_FILES) $(MODULES_OBJECTS) -.PRECIOUS: $(ST_API_CONTENTS) $(ST_PYDOC_INJECTIONS) - -DOCS_MODULES=$(MODULES_NAMES:%=ida_%) +#---------------------------------------------------------------------- +DOCS_MODULES=$(foreach mod,$(MODULES_NAMES),ida_$(mod)) tools/docs/hrdoc.cfg: tools/docs/hrdoc.cfg.in - sed s/%IDA_MODULES%/"$(DOCS_MODULES)"/ < $? > $@ + sed s/%IDA_MODULES%/"$(DOCS_MODULES)"/ < $^ > $@ # the html files are produced in docs\hr-html directory docs: tools/docs/hrdoc.py tools/docs/hrdoc.cfg tools/docs/hrdoc.css @@ -548,50 +603,52 @@ ifeq ($(OUT_OF_TREE_BUILD),) endif endif +#---------------------------------------------------------------------- # Test that all functions that are present in ftable.cpp # are present in idc.py (and therefore made available by # the idapython). +test_idc: $(TEST_IDC) $(TEST_IDC): $(F)idctest.log -$(F)idctest.log: $(RS)idc/idc.idc | $(BINARY) pyfiles $(PRECOMPILED_COPY) +$(F)idctest.log: $(RS)idc/idc.idc | $(MODULE) pyfiles ifneq ($(wildcard ../../tests),) - @$(RM) $(F)idctest.log - @$(IDA_CMD) $(BATCH_SWITCH) -S"test_idc.py $^" -t -L$(F)idctest.log >/dev/null || \ - (echo "ERROR: The IDAPython IDC interface is incomplete. IDA log:" && cat $(F)idctest.log && false) -endif - -package: -ifeq ($(OUT_OF_TREE_BUILD),) - -@if [ ! -d "$(DIST)" ] ; then mkdir -p 2>/dev/null $(DIST) ; fi - $(PYTHON) $(PKGBIN_SCRIPT) \ - --input-binary-tree $(R) \ - --output-dir $(DIST) \ - --confirmed \ - --component plugins/idapython - (cd $(DIST) && $(PYTHON) $(DBLZIP_SCRIPT) --once --output ../../../obj/$(PACKAGE_NAME)) + $(Q)$(RM) $(F)idctest.log + $(Q)$(IDA_CMD) $(BATCH_SWITCH) -S"test_idc.py $^" -t -L$(F)idctest.log >/dev/null || \ + (echo "ERROR: The IDAPython IDC interface is incomplete. IDA log:" && cat $(F)idctest.log && false) endif +#---------------------------------------------------------------------- +PUBTREE_DIR=$(F)/public_tree public_tree: all ifeq ($(OUT_OF_TREE_BUILD),) - -@if [ ! -d "$(PUBTREE_DIR)/out_of_tree" ] ; then mkdir -p 2>/dev/null $(PUBTREE_DIR)/out_of_tree ; fi + -$(Q)if [ ! -d "$(PUBTREE_DIR)/out_of_tree" ] ; then mkdir -p 2>/dev/null $(PUBTREE_DIR)/out_of_tree ; fi rsync -a --exclude=obj/ \ - --exclude=precompiled/ \ - --exclude=repl.py \ - --exclude=test_idc.py \ - --exclude=RELEASE.md \ - --exclude=docs/hr-html/ \ - --exclude=**/*~ \ - . $(PUBTREE_DIR) + --exclude=precompiled/ \ + --exclude=repl.py \ + --exclude=test_idc.py \ + --exclude=RELEASE.md \ + --exclude=docs/hr-html/ \ + --exclude=**/*~ \ + . $(PUBTREE_DIR) (cd $(F) && zip -r ../../$(PUBTREE_DIR)/out_of_tree/parsed_notifications.zip parsed_notifications) endif +#---------------------------------------------------------------------- +# the 'echo_modules' target must be called explicitly +# Note: used by ida/build/pkgbin.py echo_modules: @echo $(MODULES_NAMES) +#---------------------------------------------------------------------- +clean:: + rm -rf obj/ + # MAKEDEP dependency list ------------------ -$(F)python$(O) : $(I)range.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)diskio.hpp $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)config.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)segment.hpp $(I)ua.hpp \ - $(I)gdl.hpp $(I)graph.hpp \ - $(I)xref.hpp python.cpp pywraps.hpp pywraps.cpp | $(ST_SDK_TARGETS) +$(F)python$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)diskio.hpp $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ + $(I)ida_highlighter.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)typeinf.hpp \ + $(I)ua.hpp $(I)xref.hpp python.cpp pywraps.cpp \ + pywraps.hpp diff --git a/out_of_tree/parsed_notifications.zip b/out_of_tree/parsed_notifications.zip index 9abb721..1203d94 100644 Binary files a/out_of_tree/parsed_notifications.zip and b/out_of_tree/parsed_notifications.zip differ diff --git a/pydoc_injections.txt b/pydoc_injections.txt index 367443b..06d1e06 100644 --- a/pydoc_injections.txt +++ b/pydoc_injections.txt @@ -390,7 +390,8 @@ ida_bytes.add_mapping(): set flag PR2_MAPPING in ph.flag2 to use memory mapping Add memory mapping range. - @param _from (C++: ea_t) + @param _from: start of the mapped range (nonexistent address) (C++: + ea_t) @param to: start of the mapping range (existent address) (C++: ea_t) @param size: size of the range (C++: asize_t) @return: success @@ -903,6 +904,11 @@ ida_bytes.data_format_t.id: __get_id(self) -> int +ida_bytes.data_format_t.is_present_in_menus(): + + is_present_in_menus(self) -> bool + + ida_bytes.data_format_t.menu_name: data_format_t_menu_name_get(self) -> char const * @@ -934,6 +940,11 @@ ida_bytes.data_type_t.id: __get_id(self) -> int +ida_bytes.data_type_t.is_present_in_menus(): + + is_present_in_menus(self) -> bool + + ida_bytes.data_type_t.menu_name: data_type_t_menu_name_get(self) -> char const * @@ -1092,6 +1103,11 @@ ida_bytes.equal_bytes(): @param sense_case: case-sensitive comparison? (C++: bool) +ida_bytes.f_has_cmt(): + + f_has_cmt(f, arg2) -> bool + + ida_bytes.f_has_dummy_name(): f_has_dummy_name(f, arg2) -> bool @@ -1104,6 +1120,11 @@ ida_bytes.f_has_dummy_name(): @param f (C++: flags_t) +ida_bytes.f_has_extra_cmts(): + + f_has_extra_cmts(f, arg2) -> bool + + ida_bytes.f_has_name(): f_has_name(f, arg2) -> bool @@ -1779,7 +1800,8 @@ ida_bytes.get_item_flag(): or structure. This function is used to get flags of structure members or array elements. - @param _from (C++: ea_t) + @param _from: linear address of the instruction which refers to 'ea' + (C++: ea_t) @param n: number of operand which refers to 'ea' (C++: int) @param ea: the referenced address (C++: ea_t) @param appzero: append a struct field name if the field offset is @@ -1864,8 +1886,7 @@ ida_bytes.get_max_strlit_length(): @param strtype: string type. one of String type codes (C++: int32) @param options: combination of string literal length options (C++: int) - @return: length of the string in bytes, including the terminating - character(s), if any + @return: length of the string in octets (octet==8bit) ida_bytes.get_next_hidden_range(): @@ -4630,7 +4651,7 @@ ida_dbg.DBG_Hooks.unhook(): ida_dbg.add_bpt(): - add_bpt(ea, size, type) -> bool + add_bpt(ea, size=0, type=BPT_DEFAULT) -> bool add_bpt(bpt) -> bool @@ -4666,7 +4687,7 @@ ida_dbg.add_virt_module(): ida_dbg.attach_process(): - attach_process(pid, event_id) -> int + attach_process(pid=pid_t(-1), event_id=-1) -> int Attach the debugger to a running process. {Type, Asynchronous function @@ -5144,7 +5165,7 @@ ida_dbg.dbg_add_debug_event(): ida_dbg.dbg_add_insn_tev(): - dbg_add_insn_tev(tid, ea, save) -> bool + dbg_add_insn_tev(tid, ea, save=SAVE_DIFF) -> bool Add a new instruction trace element to the current trace. {Type, @@ -5300,6 +5321,32 @@ ida_dbg.diff_trace_file(): Show difference between the current trace and the one from 'filename'. +ida_dbg.disable_bblk_trace(): + + disable_bblk_trace() -> bool + + +ida_dbg.disable_bpt(): + + disable_bpt(ea) -> bool + disable_bpt(bptloc) -> bool + + +ida_dbg.disable_func_trace(): + + disable_func_trace() -> bool + + +ida_dbg.disable_insn_trace(): + + disable_insn_trace() -> bool + + +ida_dbg.disable_step_trace(): + + disable_step_trace() -> bool + + ida_dbg.edit_manual_regions(): edit_manual_regions() @@ -5307,23 +5354,23 @@ ida_dbg.edit_manual_regions(): ida_dbg.enable_bblk_trace(): - enable_bblk_trace(enable) -> bool + enable_bblk_trace(enable=True) -> bool ida_dbg.enable_bpt(): - enable_bpt(ea, enable) -> bool - enable_bpt(bptloc, enable) -> bool + enable_bpt(ea, enable=True) -> bool + enable_bpt(bptloc, enable=True) -> bool ida_dbg.enable_func_trace(): - enable_func_trace(enable) -> bool + enable_func_trace(enable=True) -> bool ida_dbg.enable_insn_trace(): - enable_insn_trace(enable) -> bool + enable_insn_trace(enable=True) -> bool ida_dbg.enable_manual_regions(): @@ -5333,7 +5380,7 @@ ida_dbg.enable_manual_regions(): ida_dbg.enable_step_trace(): - enable_step_trace(enable) -> bool + enable_step_trace(enable=True) -> bool class ida_dbg.eval_ctx_t(): @@ -5344,6 +5391,17 @@ class ida_dbg.eval_ctx_t(): ida_dbg.eval_ctx_t.ea: eval_ctx_t_ea_get(self) -> ea_t +ida_dbg.exist_bpt(): + + exist_bpt(ea) -> bool + + + Does a breakpoint exist at the given location? + + + @param ea (C++: ea_t) + + ida_dbg.exit_process(): exit_process() -> bool @@ -5481,6 +5539,18 @@ ida_dbg.get_dbg_memory_info(): get_dbg_memory_info(ranges) -> int +ida_dbg.get_dbg_reg_info(): + + get_dbg_reg_info(regname, ri) -> bool + + + Get register information {Type, Synchronous function, Notification, + none (synchronous function)} + + @param regname (C++: const char *) + @param ri (C++: register_info_t *) + + ida_dbg.get_debug_event(): get_debug_event() -> debug_event_t @@ -5497,12 +5567,6 @@ ida_dbg.get_debugger_event_cond(): ida_dbg.get_first_module(): get_first_module(modinfo) -> bool - - - See 'Modules' . - - - @param modinfo (C++: modinfo_t *) ida_dbg.get_func_trace_options(): @@ -5603,12 +5667,13 @@ ida_dbg.get_local_vars(): ida_dbg.get_manual_regions(): - get_manual_regions() -> PyObject * + get_manual_regions(ranges) + get_manual_regions() -> PyObject * Returns the manual memory regions @return: list(start_ea, end_ea, name, sclass, sbase, bitness, perm) - + ida_dbg.get_module_info(): @@ -5618,12 +5683,6 @@ ida_dbg.get_module_info(): ida_dbg.get_next_module(): get_next_module(modinfo) -> bool - - - See 'Modules' . - - - @param modinfo (C++: modinfo_t *) ida_dbg.get_process_options(): @@ -5666,7 +5725,8 @@ ida_dbg.get_processes(): ida_dbg.get_reg_val(): - get_reg_val(regname, regval) -> bool + get_reg_val(regname, regval) -> bool + get_reg_val(regname, ival) -> bool Read a register value from the current thread. {Type, Synchronous @@ -5674,7 +5734,7 @@ ida_dbg.get_reg_val(): @param regname (C++: const char *) @param regval (C++: regval_t *) - + ida_dbg.get_reg_vals(): @@ -5903,17 +5963,6 @@ ida_dbg.handle_debug_event(): handle_debug_event(ev, rqflags) -> int -ida_dbg.have_set_options(): - - have_set_options(_dbg) -> bool - - - Is 'set_dbg_options()' present in 'debugger_t' ? - - - @param _dbg (C++: const debugger_t *) - - ida_dbg.hide_all_bpts(): hide_all_bpts() -> int @@ -5934,6 +5983,18 @@ ida_dbg.internal_ioctl(): internal_ioctl(fn, buf, poutbuf, poutsize) -> int +ida_dbg.invalidate_dbg_state(): + + invalidate_dbg_state(dbginv) -> int + + + Invalidate cached debugger information. {Type, Synchronous function, + Notification, none (synchronous function)} + + @param dbginv: Debugged process invalidation options (C++: int) + @return: current debugger state (one of Debugged process states ) + + ida_dbg.invalidate_dbgmem_config(): invalidate_dbgmem_config() @@ -6045,6 +6106,14 @@ ida_dbg.is_reg_integer(): @param regname (C++: const char *) +ida_dbg.is_request_running(): + + is_request_running() -> bool + + + Is a request currently running? + + ida_dbg.is_step_trace_enabled(): is_step_trace_enabled() -> bool @@ -6073,7 +6142,7 @@ ida_dbg.list_bptgrps(): ida_dbg.load_debugger(): - load_debugger(nonnul_dbgname, use_remote) -> bool + load_debugger(dbgname, use_remote) -> bool ida_dbg.load_trace_file(): @@ -6252,7 +6321,7 @@ ida_dbg.rename_bptgrp(): ida_dbg.request_add_bpt(): - request_add_bpt(ea, size, type) -> bool + request_add_bpt(ea, size=0, type=BPT_DEFAULT) -> bool request_add_bpt(bpt) -> bool @@ -6313,30 +6382,56 @@ ida_dbg.request_detach_process(): Post a 'detach_process()' request. +ida_dbg.request_disable_bblk_trace(): + + request_disable_bblk_trace() -> bool + + +ida_dbg.request_disable_bpt(): + + request_disable_bpt(ea) -> bool + request_disable_bpt(bptloc) -> bool + + +ida_dbg.request_disable_func_trace(): + + request_disable_func_trace() -> bool + + +ida_dbg.request_disable_insn_trace(): + + request_disable_insn_trace() -> bool + + +ida_dbg.request_disable_step_trace(): + + request_disable_step_trace() -> bool + + ida_dbg.request_enable_bblk_trace(): - request_enable_bblk_trace(enable) -> bool + request_enable_bblk_trace(enable=True) -> bool ida_dbg.request_enable_bpt(): - request_enable_bpt(ea, enable) -> bool - request_enable_bpt(bptloc, enable) -> bool + request_enable_bpt(ea, enable=True) -> bool + request_enable_bpt(bptloc, enable=True) -> bool ida_dbg.request_enable_func_trace(): - request_enable_func_trace(enable) -> bool + request_enable_func_trace(enable=True) -> bool ida_dbg.request_enable_insn_trace(): - request_enable_insn_trace(enable) -> bool + request_enable_insn_trace(enable=True) -> bool ida_dbg.request_enable_step_trace(): - request_enable_step_trace(enable) -> bool + request_enable_step_trace(enable=True) -> bool ida_dbg.request_exit_process(): @@ -6452,7 +6547,7 @@ ida_dbg.request_set_step_trace_options(): ida_dbg.request_start_process(): - request_start_process(path, args, sdir) -> int + request_start_process(path=None, args=None, sdir=None) -> int Post a 'start_process()' request. @@ -6631,35 +6726,6 @@ ida_dbg.set_bptloc_string(): @param s (C++: const char *) -ida_dbg.set_dbg_default_options(): - - set_dbg_default_options(keyword, value_type, value) -> char const * - - - Set 'dbg' options with 'IDPOPT_PRI_DEFAULT' . - - - @param keyword (C++: const char *) - @param value_type (C++: int) - @param value (C++: const void *) - - -ida_dbg.set_dbg_options(): - - set_dbg_options(_dbg, keyword, pri, value_type, value) -> char const - set_dbg_options(keyword, pri, value_type, value) -> char const * - - - Convenience function to set debugger specific options. It checks if - the debugger is present and the function is present and calls it. - - @param _dbg (C++: debugger_t *) - @param keyword (C++: const char *) - @param pri (C++: int) - @param value_type (C++: int) - @param value (C++: const void *) - - ida_dbg.set_debugger_event_cond(): set_debugger_event_cond(nonnul_cond) @@ -6696,6 +6762,7 @@ ida_dbg.set_highlight_trace_options(): Set highlight trace parameters. + @param hilight (C++: bool) @param color (C++: bgcolor_t) @param diff (C++: bgcolor_t) @@ -6711,16 +6778,9 @@ ida_dbg.set_insn_trace_options(): @param options (C++: int) -ida_dbg.set_int_dbg_options(): +ida_dbg.set_manual_regions(): - set_int_dbg_options(keyword, value) -> char const * - - - Set an integer value option for 'dbg' . - - - @param keyword (C++: const char *) - @param value (C++: int32) + set_manual_regions(ranges) ida_dbg.set_process_options(): @@ -6766,6 +6826,7 @@ ida_dbg.set_process_state(): ida_dbg.set_reg_val(): set_reg_val(regname, regval) -> bool + set_reg_val(regname, ival) -> bool set_reg_val(tid, regidx, value) -> int @@ -6894,7 +6955,7 @@ ida_dbg.srcdbg_step_until_ret(): ida_dbg.start_process(): - start_process(path, args, sdir) -> int + start_process(path=None, args=None, sdir=None) -> int Start a process in the debugger. {Type, Asynchronous function - @@ -6977,6 +7038,17 @@ ida_dbg.suspend_thread(): @param tid: thread id (C++: thid_t) +class ida_dbg.tev_info_reg_t(): + + Proxy of C++ tev_info_reg_t class + + +ida_dbg.tev_info_reg_t.info: + tev_info_reg_t_info_get(self) -> tev_info_t + +ida_dbg.tev_info_reg_t.registers: + tev_info_reg_t_registers_get(self) -> tev_reg_values_t + class ida_dbg.tev_info_t(): Proxy of C++ tev_info_t class @@ -6991,6 +7063,227 @@ ida_dbg.tev_info_t.tid: ida_dbg.tev_info_t.type: tev_info_t_type_get(self) -> tev_type_t +class ida_dbg.tev_reg_value_t(): + + Proxy of C++ tev_reg_value_t class + + +ida_dbg.tev_reg_value_t.reg_idx: + tev_reg_value_t_reg_idx_get(self) -> int + +ida_dbg.tev_reg_value_t.value: + tev_reg_value_t_value_get(self) -> regval_t + +class ida_dbg.tev_reg_values_t(): + + Proxy of C++ qvector<(tev_reg_value_t)> class + + +ida_dbg.tev_reg_values_t.at(): + + at(self, _idx) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.begin(): + + begin(self) -> tev_reg_value_t + begin(self) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.capacity(): + + capacity(self) -> size_t + + +ida_dbg.tev_reg_values_t.clear(): + + clear(self) + + +ida_dbg.tev_reg_values_t.empty(): + + empty(self) -> bool + + +ida_dbg.tev_reg_values_t.end(): + + end(self) -> tev_reg_value_t + end(self) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.erase(): + + erase(self, it) -> tev_reg_value_t + erase(self, first, last) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.extract(): + + extract(self) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.grow(): + + grow(self, x=tev_reg_value_t()) + + +ida_dbg.tev_reg_values_t.inject(): + + inject(self, s, len) + + +ida_dbg.tev_reg_values_t.insert(): + + insert(self, it, x) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.pop_back(): + + pop_back(self) + + +ida_dbg.tev_reg_values_t.push_back(): + + push_back(self, x) + push_back(self) -> tev_reg_value_t + + +ida_dbg.tev_reg_values_t.qclear(): + + qclear(self) + + +ida_dbg.tev_reg_values_t.reserve(): + + reserve(self, cnt) + + +ida_dbg.tev_reg_values_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_dbg.tev_reg_values_t.size(): + + size(self) -> size_t + + +ida_dbg.tev_reg_values_t.swap(): + + swap(self, r) + + +ida_dbg.tev_reg_values_t.truncate(): + + truncate(self) + + +class ida_dbg.tevinforeg_vec_t(): + + Proxy of C++ qvector<(tev_info_reg_t)> class + + +ida_dbg.tevinforeg_vec_t.at(): + + at(self, _idx) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.begin(): + + begin(self) -> tev_info_reg_t + begin(self) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.capacity(): + + capacity(self) -> size_t + + +ida_dbg.tevinforeg_vec_t.clear(): + + clear(self) + + +ida_dbg.tevinforeg_vec_t.empty(): + + empty(self) -> bool + + +ida_dbg.tevinforeg_vec_t.end(): + + end(self) -> tev_info_reg_t + end(self) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.erase(): + + erase(self, it) -> tev_info_reg_t + erase(self, first, last) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.extract(): + + extract(self) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.grow(): + + grow(self, x=tev_info_reg_t()) + + +ida_dbg.tevinforeg_vec_t.inject(): + + inject(self, s, len) + + +ida_dbg.tevinforeg_vec_t.insert(): + + insert(self, it, x) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.pop_back(): + + pop_back(self) + + +ida_dbg.tevinforeg_vec_t.push_back(): + + push_back(self, x) + push_back(self) -> tev_info_reg_t + + +ida_dbg.tevinforeg_vec_t.qclear(): + + qclear(self) + + +ida_dbg.tevinforeg_vec_t.reserve(): + + reserve(self, cnt) + + +ida_dbg.tevinforeg_vec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_dbg.tevinforeg_vec_t.size(): + + size(self) -> size_t + + +ida_dbg.tevinforeg_vec_t.swap(): + + swap(self, r) + + +ida_dbg.tevinforeg_vec_t.truncate(): + + truncate(self) + + ida_dbg.update_bpt(): update_bpt(bpt) -> bool @@ -7015,7 +7308,7 @@ ida_dbg.update_bpt(): ida_dbg.wait_for_next_event(): - wait_for_next_event(wfne, timeout_in_secs) -> dbg_event_code_t + wait_for_next_event(wfne, timeout) -> dbg_event_code_t Wait for the next event.This function (optionally) resumes the process @@ -7024,7 +7317,7 @@ ida_dbg.wait_for_next_event(): @param wfne: combination of Wait for debugger event flags constants (C++: int) - @param timeout_in_secs (C++: int) + @param timeout: number of seconds to wait, -1-infinity (C++: int) @return: either an event_id_t (if > 0), or a dbg_event_code_t (if <= 0) @@ -7080,6 +7373,41 @@ ida_dbg.BKPT_TRACE trace bpt; should not be deleted when the process gets suspended """ +ida_dbg.BPTCK_ACT +""" +breakpoint is active (written to the process) +""" + +ida_dbg.BPTCK_NO +""" +breakpoint is disabled +""" + +ida_dbg.BPTCK_NONE +""" +breakpoint does not exist +""" + +ida_dbg.BPTCK_YES +""" +breakpoint is enabled +""" + +ida_dbg.BPTEV_ADDED +""" +Breakpoint has been added. +""" + +ida_dbg.BPTEV_CHANGED +""" +Breakpoint has been modified. +""" + +ida_dbg.BPTEV_REMOVED +""" +Breakpoint has been removed. +""" + ida_dbg.BPT_BRK """ suspend execution upon hit @@ -7137,6 +7465,41 @@ ida_dbg.BPT_UPDMEM refresh the memory layout and contents before evaluating bpt condition """ +ida_dbg.BT_LOG_INSTS +""" +log all instructions in the current basic block +""" + +ida_dbg.DBGINV_ALL +""" +invalidate everything +""" + +ida_dbg.DBGINV_MEMCFG +""" +invalidate cached process segmentation +""" + +ida_dbg.DBGINV_MEMORY +""" +invalidate cached memory contents +""" + +ida_dbg.DBGINV_NONE +""" +invalidate nothing +""" + +ida_dbg.DBGINV_REDRAW +""" +refresh the screen +""" + +ida_dbg.DBGINV_REGS +""" +invalidate cached register values +""" + ida_dbg.DOPT_BPT_MSGS """ log breakpoints @@ -7217,6 +7580,21 @@ ida_dbg.DOPT_THREAD_MSGS log thread starts/exits """ +ida_dbg.DSTATE_NOTASK +""" +no process is currently debugged +""" + +ida_dbg.DSTATE_RUN +""" +process is running +""" + +ida_dbg.DSTATE_SUSP +""" +process is suspended and will not continue +""" + ida_dbg.EXCDLG_ALWAYS """ always display @@ -7232,6 +7610,47 @@ ida_dbg.EXCDLG_UNKNOWN display for unknown exceptions """ +ida_dbg.FT_LOG_RET +""" +function tracing will log returning instructions +""" + +ida_dbg.IT_LOG_SAME_IP +""" +instruction tracing will log instructions whose IP doesn't change +""" + +ida_dbg.ST_ALREADY_LOGGED +""" +step tracing will be disabled when IP is already logged +""" + +ida_dbg.ST_DIFFERENTIAL +""" +tracing: log only new instructions +""" + +ida_dbg.ST_OPTIONS_MASK +""" +mask of available options, to ensure compatibility with newer IDA +versions +""" + +ida_dbg.ST_OVER_DEBUG_SEG +""" +step tracing will be disabled when IP is in a debugger segment +""" + +ida_dbg.ST_OVER_LIB_FUNC +""" +step tracing will be disabled when IP is in a library function +""" + +ida_dbg.ST_SKIP_LOOPS +""" +step tracing will try to skip loops already recorded +""" + ida_dbg.WFNE_ANY """ return the first event (even if it doesn't suspend the process) @@ -9301,6 +9720,11 @@ ida_fixup.fixup_data_t.set_unused(): set_unused(self) +ida_fixup.fixup_data_t.was_created(): + + was_created(self) -> bool + + class ida_fixup.fixup_info_t(): Proxy of C++ fixup_info_t class @@ -9953,7 +10377,9 @@ ida_frame.get_frame_size(): Get full size of a function frame. This function takes into account size of local variables + size of saved registers + size of return - address + size of function arguments. + address + number of purged bytes. The purged bytes correspond to the + arguments of the functions with __stdcall and __fastcall calling + conventions. @param pfn: pointer to function structure, may be NULL (C++: const func_t *) @@ -10153,12 +10579,16 @@ ida_frame.set_frame_size(): set_frame_size(pfn, frsize, frregs, argsize) -> bool - Set size of function frame. + Set size of function frame. Note: The returned size may not include + all stack arguments. It does so only for __stdcall and __fastcall + calling conventions. To get the entire frame size for all cases use + get_struc_size(get_frame(pfn)). @param pfn: pointer to function structure (C++: func_t *) @param frsize: size of function local variables (C++: asize_t) @param frregs: size of saved registers (C++: ushort) - @param argsize: size of function arguments (C++: asize_t) + @param argsize: size of function arguments that will be purged from + the stack upon return (C++: asize_t) @return: success @@ -10192,6 +10622,22 @@ ida_frame.set_regvar_cmt(): @return: Register variable error codes +class ida_frame.stkpnt_t(): + + Proxy of C++ stkpnt_t class + + +ida_frame.stkpnt_t.ea: + stkpnt_t_ea_get(self) -> ea_t + +ida_frame.stkpnt_t.spd: + stkpnt_t_spd_get(self) -> sval_t + +class ida_frame.stkpnts_t(): + + Proxy of C++ stkpnts_t class + + ida_frame.update_fpd(): update_fpd(pfn, fpd) -> bool @@ -10450,6 +10896,17 @@ ida_funcs.apply_startup_sig(): @return: true if successfully applied the signature +ida_funcs.calc_func_size(): + + calc_func_size(pfn) -> asize_t + + + Calculate function size. This function takes into account all + fragments of the function. + + @param pfn: ptr to function structure (C++: func_t *) + + ida_funcs.calc_idasgn_state(): calc_idasgn_state(n) -> int @@ -10464,14 +10921,12 @@ ida_funcs.calc_idasgn_state(): ida_funcs.calc_thunk_func_target(): - calc_thunk_func_target(pfn, fptr) -> ea_t + calc_thunk_func_target(pfn) -> ea_t Calculate target of a thunk function. @param pfn: pointer to function (may not be NULL) (C++: func_t *) - @param fptr: out: will hold address of a function pointer (if indirect - jump) (C++: ea_t *) @return: the target function or BADADDR @@ -10774,7 +11229,7 @@ ida_funcs.func_t.extend(): ida_funcs.func_t.flags: - func_t_flags_get(self) -> ushort + func_t_flags_get(self) -> uint64 ida_funcs.func_t.fpd: func_t_fpd_get(self) -> asize_t @@ -10821,7 +11276,9 @@ ida_funcs.func_t.pntqty: func_t_pntqty_get(self) -> uint32 ida_funcs.func_t.points: - func_t_points_get(self) -> stkpnt_t * + + __get_points__(self) -> stkpnt_array + ida_funcs.func_t.referers: func_t_referers_get(self) -> ea_t * @@ -10839,7 +11296,9 @@ ida_funcs.func_t.regvarqty: func_t_regvarqty_get(self) -> int ida_funcs.func_t.regvars: - func_t_regvars_get(self) -> regvar_t * + + __get_regvars__(self) -> regvar_array + ida_funcs.func_t.size(): @@ -10853,7 +11312,9 @@ ida_funcs.func_t.tailqty: func_t_tailqty_get(self) -> int ida_funcs.func_t.tails: - func_t_tails_get(self) -> range_t + + __get_tails__(self) -> range_array + ida_funcs.func_t__from_ptrval__(): @@ -11308,6 +11769,17 @@ ida_funcs.plan_to_apply_idasgn(): signatures +class ida_funcs.range_array(): + + Proxy of C++ dynamic_wrapped_array_t<(range_t)> class + + +ida_funcs.range_array.count: + range_array_count_get(self) -> size_t + +ida_funcs.range_array.data: + range_array_data_get(self) -> range_t + ida_funcs.read_regargs(): read_regargs(pfn) @@ -11356,6 +11828,17 @@ ida_funcs.regarg_t.reg: ida_funcs.regarg_t.type: regarg_t_type_get(self) -> type_t * +class ida_funcs.regvar_array(): + + Proxy of C++ dynamic_wrapped_array_t<(regvar_t)> class + + +ida_funcs.regvar_array.count: + regvar_array_count_get(self) -> size_t + +ida_funcs.regvar_array.data: + regvar_array_data_get(self) -> regvar_t * + ida_funcs.remove_func_tail(): remove_func_tail(pfn, tail_ea) -> bool @@ -11462,6 +11945,17 @@ ida_funcs.set_visible_func(): @param visible (C++: bool) +class ida_funcs.stkpnt_array(): + + Proxy of C++ dynamic_wrapped_array_t<(stkpnt_t)> class + + +ida_funcs.stkpnt_array.count: + stkpnt_array_count_get(self) -> size_t + +ida_funcs.stkpnt_array.data: + stkpnt_array_data_get(self) -> stkpnt_t * + ida_funcs.try_to_add_libfunc(): try_to_add_libfunc(ea) -> int @@ -11565,6 +12059,11 @@ ida_funcs.FUNC_LIB Library function. """ +ida_funcs.FUNC_LUMINA +""" +Function info is provided by Lumina. +""" + ida_funcs.FUNC_NORET """ Function doesn't return. @@ -12212,6 +12711,11 @@ ida_graph.GraphViewer.Show(): @return: Boolean +ida_graph.GraphViewer.UI_Hooks_Trampoline.create_desktop_widget(): + + create_desktop_widget(self, title, cfg) -> PyObject * + + ida_graph.GraphViewer.UI_Hooks_Trampoline.current_widget_changed(): current_widget_changed(self, widget, prev_widget) @@ -12229,7 +12733,7 @@ ida_graph.GraphViewer.UI_Hooks_Trampoline.debugger_menu_change(): ida_graph.GraphViewer.UI_Hooks_Trampoline.finish_populating_widget_popup(): - finish_populating_widget_popup(self, widget, popup_handle) + finish_populating_widget_popup(self, widget, popup_handle, ctx=None) The UI is about to be done populating the TWidget's popup menu. @@ -12901,6 +13405,11 @@ ida_graph.mutable_graph_t.get_custom_layout(): get_custom_layout(self) -> bool +ida_graph.mutable_graph_t.get_edge(): + + get_edge(self, e) -> edge_info_t + + ida_graph.mutable_graph_t.get_first_subgraph_node(): get_first_subgraph_node(self, group) -> int @@ -13305,6 +13814,243 @@ class ida_graph.pointseq_t(): Proxy of C++ pointseq_t class +ida_graph.pointseq_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_graph.pointseq_t.at(): + + at(self, _idx) -> point_t + + +ida_graph.pointseq_t.begin(): + + begin(self) -> point_t + begin(self) -> point_t + + +ida_graph.pointseq_t.capacity(): + + capacity(self) -> size_t + + +ida_graph.pointseq_t.clear(): + + clear(self) + + +ida_graph.pointseq_t.empty(): + + empty(self) -> bool + + +ida_graph.pointseq_t.end(): + + end(self) -> point_t + end(self) -> point_t + + +ida_graph.pointseq_t.erase(): + + erase(self, it) -> point_t + erase(self, first, last) -> point_t + + +ida_graph.pointseq_t.extract(): + + extract(self) -> point_t + + +ida_graph.pointseq_t.find(): + + find(self, x) -> point_t + find(self, x) -> point_t + + +ida_graph.pointseq_t.grow(): + + grow(self, x=point_t()) + + +ida_graph.pointseq_t.has(): + + has(self, x) -> bool + + +ida_graph.pointseq_t.inject(): + + inject(self, s, len) + + +ida_graph.pointseq_t.insert(): + + insert(self, it, x) -> point_t + + +ida_graph.pointseq_t.pop_back(): + + pop_back(self) + + +ida_graph.pointseq_t.push_back(): + + push_back(self, x) + push_back(self) -> point_t + + +ida_graph.pointseq_t.qclear(): + + qclear(self) + + +ida_graph.pointseq_t.reserve(): + + reserve(self, cnt) + + +ida_graph.pointseq_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_graph.pointseq_t.size(): + + size(self) -> size_t + + +ida_graph.pointseq_t.swap(): + + swap(self, r) + + +ida_graph.pointseq_t.truncate(): + + truncate(self) + + +class ida_graph.pointvec_t(): + + Proxy of C++ qvector<(point_t)> class + + +ida_graph.pointvec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_graph.pointvec_t.at(): + + at(self, _idx) -> point_t + + +ida_graph.pointvec_t.begin(): + + begin(self) -> point_t + begin(self) -> point_t + + +ida_graph.pointvec_t.capacity(): + + capacity(self) -> size_t + + +ida_graph.pointvec_t.clear(): + + clear(self) + + +ida_graph.pointvec_t.empty(): + + empty(self) -> bool + + +ida_graph.pointvec_t.end(): + + end(self) -> point_t + end(self) -> point_t + + +ida_graph.pointvec_t.erase(): + + erase(self, it) -> point_t + erase(self, first, last) -> point_t + + +ida_graph.pointvec_t.extract(): + + extract(self) -> point_t + + +ida_graph.pointvec_t.find(): + + find(self, x) -> point_t + find(self, x) -> point_t + + +ida_graph.pointvec_t.grow(): + + grow(self, x=point_t()) + + +ida_graph.pointvec_t.has(): + + has(self, x) -> bool + + +ida_graph.pointvec_t.inject(): + + inject(self, s, len) + + +ida_graph.pointvec_t.insert(): + + insert(self, it, x) -> point_t + + +ida_graph.pointvec_t.pop_back(): + + pop_back(self) + + +ida_graph.pointvec_t.push_back(): + + push_back(self, x) + push_back(self) -> point_t + + +ida_graph.pointvec_t.qclear(): + + qclear(self) + + +ida_graph.pointvec_t.reserve(): + + reserve(self, cnt) + + +ida_graph.pointvec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_graph.pointvec_t.size(): + + size(self) -> size_t + + +ida_graph.pointvec_t.swap(): + + swap(self, r) + + +ida_graph.pointvec_t.truncate(): + + truncate(self) + + ida_graph.pyg_close(): pyg_close(self) @@ -13788,6 +14534,176 @@ class ida_hexrays.DecompilationFailure(): 'info' member of this exception. +class ida_hexrays.Hexrays_Hooks(): + + Proxy of C++ Hexrays_Hooks class + + +ida_hexrays.Hexrays_Hooks.close_pseudocode(): + + close_pseudocode(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.cmt_changed(): + + cmt_changed(self, cfunc, loc, cmt) -> int + + +ida_hexrays.Hexrays_Hooks.combine(): + + combine(self, blk, insn) -> int + + +ida_hexrays.Hexrays_Hooks.create_hint(): + + create_hint(self, vu) -> PyObject * + + +ida_hexrays.Hexrays_Hooks.curpos(): + + curpos(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.double_click(): + + double_click(self, vu, shift_state) -> int + + +ida_hexrays.Hexrays_Hooks.flowchart(): + + flowchart(self, fc) -> int + + +ida_hexrays.Hexrays_Hooks.func_printed(): + + func_printed(self, cfunc) -> int + + +ida_hexrays.Hexrays_Hooks.glbopt(): + + glbopt(self, mba) -> int + + +ida_hexrays.Hexrays_Hooks.hook(): + + hook(self) -> bool + + +ida_hexrays.Hexrays_Hooks.interr(): + + interr(self, errcode) -> int + + +ida_hexrays.Hexrays_Hooks.keyboard(): + + keyboard(self, vu, key_code, shift_state) -> int + + +ida_hexrays.Hexrays_Hooks.locopt(): + + locopt(self, mba) -> int + + +ida_hexrays.Hexrays_Hooks.lvar_cmt_changed(): + + lvar_cmt_changed(self, vu, v, cmt) -> int + + +ida_hexrays.Hexrays_Hooks.lvar_mapping_changed(): + + lvar_mapping_changed(self, vu, _from, to) -> int + + +ida_hexrays.Hexrays_Hooks.lvar_name_changed(): + + lvar_name_changed(self, vu, v, name, is_user_name) -> int + + +ida_hexrays.Hexrays_Hooks.lvar_type_changed(): + + lvar_type_changed(self, vu, v, tinfo) -> int + + +ida_hexrays.Hexrays_Hooks.maturity(): + + maturity(self, cfunc, new_maturity) -> int + + +ida_hexrays.Hexrays_Hooks.microcode(): + + microcode(self, mba) -> int + + +ida_hexrays.Hexrays_Hooks.open_pseudocode(): + + open_pseudocode(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.populating_popup(): + + populating_popup(self, widget, popup_handle, vu) -> int + + +ida_hexrays.Hexrays_Hooks.prealloc(): + + prealloc(self, mba) -> int + + +ida_hexrays.Hexrays_Hooks.preoptimized(): + + preoptimized(self, mba) -> int + + +ida_hexrays.Hexrays_Hooks.print_func(): + + print_func(self, cfunc, vp) -> int + + +ida_hexrays.Hexrays_Hooks.prolog(): + + prolog(self, mba, fc, reachable_blocks) -> int + + +ida_hexrays.Hexrays_Hooks.refresh_pseudocode(): + + refresh_pseudocode(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.resolve_stkaddrs(): + + resolve_stkaddrs(self, mba) -> int + + +ida_hexrays.Hexrays_Hooks.right_click(): + + right_click(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.stkpnts(): + + stkpnts(self, mba, stkpnts) -> int + + +ida_hexrays.Hexrays_Hooks.structural(): + + structural(self, ct) -> int + + +ida_hexrays.Hexrays_Hooks.switch_pseudocode(): + + switch_pseudocode(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.text_ready(): + + text_ready(self, vu) -> int + + +ida_hexrays.Hexrays_Hooks.unhook(): + + unhook(self) -> bool + + ida_hexrays.accepts_udts(): accepts_udts(op) -> bool @@ -13832,6 +14748,17 @@ ida_hexrays.asgop_revert(): operator. +class ida_hexrays.bit_bound_t(): + + Proxy of C++ bit_bound_t class + + +ida_hexrays.bit_bound_t.nbits: + bit_bound_t_nbits_get(self) -> int16 + +ida_hexrays.bit_bound_t.sbits: + bit_bound_t_sbits_get(self) -> int16 + ida_hexrays.boundaries_begin(): boundaries_begin(map) -> boundaries_iterator_t @@ -14032,6 +14959,11 @@ ida_hexrays.boundaries_t.keytype.compare(): compare(self, r) -> int +ida_hexrays.boundaries_t.keytype.contains_expr(): + + contains_expr(self, e) -> bool + + ida_hexrays.boundaries_t.keytype.contains_free_break(): contains_free_break(self) -> bool @@ -14134,18 +15066,18 @@ ida_hexrays.boundaries_t.keytype.zero(): ida_hexrays.boundaries_t.pop(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.boundaries_t.popitem(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.boundaries_t.setdefault(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + class ida_hexrays.boundaries_t.valuetype(): @@ -14321,6 +15253,11 @@ ida_hexrays.carg_t.contains_comma_or_insn_or_label(): contains_comma_or_insn_or_label(self, maxcommas=1) -> bool +ida_hexrays.carg_t.contains_expr(): + + contains_expr(self, e) -> bool + + ida_hexrays.carg_t.contains_insn(): contains_insn(self, times=1) -> bool @@ -14355,7 +15292,7 @@ ida_hexrays.carg_t.equal_effect(): ida_hexrays.carg_t.exflags: - cexpr_t_exflags_get(self) -> int + cexpr_t_exflags_get(self) -> uint32 ida_hexrays.carg_t.find_closest_addr(): @@ -14395,12 +15332,12 @@ ida_hexrays.carg_t.get_const_value(): ida_hexrays.carg_t.get_high_nbit_bound(): - get_high_nbit_bound(self, pbits, psign, p_maybe_negative=None) -> int + get_high_nbit_bound(self) -> bit_bound_t ida_hexrays.carg_t.get_low_nbit_bound(): - get_low_nbit_bound(self, psign, p_maybe_negative=None) -> int + get_low_nbit_bound(self) -> int ida_hexrays.carg_t.get_ptr_or_array(): @@ -14461,6 +15398,11 @@ ida_hexrays.carg_t.is_fpop(): is_fpop(self) -> bool +ida_hexrays.carg_t.is_jumpout(): + + is_jumpout(self) -> bool + + ida_hexrays.carg_t.is_negative_const(): is_negative_const(self) -> bool @@ -14476,6 +15418,11 @@ ida_hexrays.carg_t.is_nice_expr(): is_nice_expr(self) -> bool +ida_hexrays.carg_t.is_non_negative_const(): + + is_non_negative_const(self) -> bool + + ida_hexrays.carg_t.is_non_zero_const(): is_non_zero_const(self) -> bool @@ -14496,9 +15443,19 @@ ida_hexrays.carg_t.is_type_unsigned(): is_type_unsigned(self) -> bool +ida_hexrays.carg_t.is_undef_val(): + + is_undef_val(self) -> bool + + ida_hexrays.carg_t.is_vararg: carg_t_is_vararg_get(self) -> bool +ida_hexrays.carg_t.is_vftable(): + + is_vftable(self) -> bool + + ida_hexrays.carg_t.is_zero_const(): is_zero_const(self) -> bool @@ -14557,6 +15514,11 @@ ida_hexrays.carg_t.set_v(): set_v(self, v) +ida_hexrays.carg_t.set_vftable(): + + set_vftable(self) + + ida_hexrays.carg_t.swap(): swap(self, r) @@ -14761,7 +15723,7 @@ ida_hexrays.cblock_t.end(): ida_hexrays.cblock_t.erase(): - erase(self, p) + erase(self, p) -> qlist< cinsn_t >::iterator erase(self, p1, p2) erase(self, p) @@ -14853,6 +15815,11 @@ ida_hexrays.ccase_t.compare(): compare(self, r) -> int +ida_hexrays.ccase_t.contains_expr(): + + contains_expr(self, e) -> bool + + ida_hexrays.ccase_t.contains_free_break(): contains_free_break(self) -> bool @@ -14959,7 +15926,7 @@ ida_hexrays.ccase_t.value(): ida_hexrays.ccase_t.values: - ccase_t_values_get(self) -> qvector< uint64 > * + ccase_t_values_get(self) -> uint64vec_t * ida_hexrays.ccase_t.zero(): @@ -15172,6 +16139,11 @@ ida_hexrays.cexpr_t.contains_comma_or_insn_or_label(): contains_comma_or_insn_or_label(self, maxcommas=1) -> bool +ida_hexrays.cexpr_t.contains_expr(): + + contains_expr(self, e) -> bool + + ida_hexrays.cexpr_t.contains_insn(): contains_insn(self, times=1) -> bool @@ -15206,7 +16178,7 @@ ida_hexrays.cexpr_t.equal_effect(): ida_hexrays.cexpr_t.exflags: - cexpr_t_exflags_get(self) -> int + cexpr_t_exflags_get(self) -> uint32 ida_hexrays.cexpr_t.find_closest_addr(): @@ -15243,12 +16215,12 @@ ida_hexrays.cexpr_t.get_const_value(): ida_hexrays.cexpr_t.get_high_nbit_bound(): - get_high_nbit_bound(self, pbits, psign, p_maybe_negative=None) -> int + get_high_nbit_bound(self) -> bit_bound_t ida_hexrays.cexpr_t.get_low_nbit_bound(): - get_low_nbit_bound(self, psign, p_maybe_negative=None) -> int + get_low_nbit_bound(self) -> int ida_hexrays.cexpr_t.get_ptr_or_array(): @@ -15309,6 +16281,11 @@ ida_hexrays.cexpr_t.is_fpop(): is_fpop(self) -> bool +ida_hexrays.cexpr_t.is_jumpout(): + + is_jumpout(self) -> bool + + ida_hexrays.cexpr_t.is_negative_const(): is_negative_const(self) -> bool @@ -15324,6 +16301,11 @@ ida_hexrays.cexpr_t.is_nice_expr(): is_nice_expr(self) -> bool +ida_hexrays.cexpr_t.is_non_negative_const(): + + is_non_negative_const(self) -> bool + + ida_hexrays.cexpr_t.is_non_zero_const(): is_non_zero_const(self) -> bool @@ -15344,6 +16326,16 @@ ida_hexrays.cexpr_t.is_type_unsigned(): is_type_unsigned(self) -> bool +ida_hexrays.cexpr_t.is_undef_val(): + + is_undef_val(self) -> bool + + +ida_hexrays.cexpr_t.is_vftable(): + + is_vftable(self) -> bool + + ida_hexrays.cexpr_t.is_zero_const(): is_zero_const(self) -> bool @@ -15402,6 +16394,11 @@ ida_hexrays.cexpr_t.set_v(): set_v(self, v) +ida_hexrays.cexpr_t.set_vftable(): + + set_vftable(self) + + ida_hexrays.cexpr_t.swap(): swap(self, r) @@ -15599,6 +16596,7 @@ ida_hexrays.cfunc_t.entry_ea: ida_hexrays.cfunc_t.find_item_coords(): find_item_coords(self, item, px, py) -> bool + find_item_coords(self, item) -> PyObject * ida_hexrays.cfunc_t.find_label(): @@ -15821,6 +16819,7 @@ ida_hexrays.cfuncptr_t.entry_ea: ida_hexrays.cfuncptr_t.find_item_coords(): find_item_coords(self, item, px, py) -> bool + find_item_coords(self, item) -> PyObject * ida_hexrays.cfuncptr_t.find_label(): @@ -16081,6 +17080,11 @@ ida_hexrays.cinsn_t.compare(): compare(self, r) -> int +ida_hexrays.cinsn_t.contains_expr(): + + contains_expr(self, e) -> bool + + ida_hexrays.cinsn_t.contains_free_break(): contains_free_break(self) -> bool @@ -16342,6 +17346,11 @@ ida_hexrays.citem_t.cexpr: ida_hexrays.citem_t.cinsn: citem_t_cinsn_get(self) -> cinsn_t +ida_hexrays.citem_t.contains_expr(): + + contains_expr(self, e) -> bool + + ida_hexrays.citem_t.contains_label(): contains_label(self) -> bool @@ -16480,6 +17489,17 @@ ida_hexrays.codegen_t.analyze_prolog(): analyze_prolog(self, fc, reachable) -> merror_t +ida_hexrays.codegen_t.emit(): + + emit(self, code, width, l, r, d, offsize) -> minsn_t + emit(self, code, l, r, d) -> minsn_t * + + +ida_hexrays.codegen_t.emit_micro_mvm(): + + emit_micro_mvm(self, code, dtype, l, r, d, offsize) -> minsn_t * + + ida_hexrays.codegen_t.gen_micro(): gen_micro(self) -> merror_t @@ -16539,13 +17559,12 @@ ida_hexrays.compare(): compare(a, b) -> int compare(a, b) -> int compare(a, b) -> int + compare(a, b) -> int + compare(a, b) -> int + compare(a, b) -> int + compare(a, b) -> int -ida_hexrays.compare_typsrc(): - - compare_typsrc(s1, s2) -> int - - ida_hexrays.convert_to_user_call(): convert_to_user_call(udc, cdg) -> merror_t @@ -17271,18 +18290,18 @@ ida_hexrays.eamap_t.keytype.real: ida_hexrays.eamap_t.pop(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.eamap_t.popitem(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.eamap_t.setdefault(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + class ida_hexrays.eamap_t.valuetype(): @@ -17565,6 +18584,11 @@ ida_hexrays.has_cached_cfunc(): @param ea (C++: ea_t) +ida_hexrays.hexrays_alloc(): + + hexrays_alloc(size) -> void * + + class ida_hexrays.hexrays_failure_t(): Proxy of C++ hexrays_failure_t class @@ -17584,6 +18608,11 @@ ida_hexrays.hexrays_failure_t.errea: ida_hexrays.hexrays_failure_t.str: hexrays_failure_t_str_get(self) -> qstring * +ida_hexrays.hexrays_free(): + + hexrays_free(ptr) + + class ida_hexrays.hexwarn_t(): Proxy of C++ hexwarn_t class @@ -17906,14 +18935,7 @@ ida_hexrays.init_hexrays_plugin(): ida_hexrays.install_hexrays_callback(): - - install_hexrays_callback(hx_cblist_callback) -> bool - - - Install handler for decompiler events. - - @return: false if failed - + Deprecated. Please use Hexrays_Hooks instead ida_hexrays.install_microcode_filter(): @@ -18184,17 +19206,17 @@ ida_hexrays.lvar_locator_t.get_reg2(): get_reg2(self) -> mreg_t -ida_hexrays.lvar_locator_t.get_regnum(): - - get_regnum(self) -> sval_t - - ida_hexrays.lvar_locator_t.get_scattered(): get_scattered(self) -> scattered_aloc_t get_scattered(self) -> scattered_aloc_t +ida_hexrays.lvar_locator_t.get_stkoff(): + + get_stkoff(self) -> sval_t + + ida_hexrays.lvar_locator_t.is_reg1(): is_reg1(self) -> bool @@ -18401,6 +19423,16 @@ ida_hexrays.lvar_saved_info_t.clear_keep(): clear_keep(self) +ida_hexrays.lvar_saved_info_t.clr_forced_lvar(): + + clr_forced_lvar(self) + + +ida_hexrays.lvar_saved_info_t.clr_noptr_lvar(): + + clr_noptr_lvar(self) + + ida_hexrays.lvar_saved_info_t.cmt: lvar_saved_info_t_cmt_get(self) -> qstring * @@ -18412,22 +19444,42 @@ ida_hexrays.lvar_saved_info_t.has_info(): has_info(self) -> bool +ida_hexrays.lvar_saved_info_t.is_forced_lvar(): + + is_forced_lvar(self) -> bool + + ida_hexrays.lvar_saved_info_t.is_kept(): is_kept(self) -> bool +ida_hexrays.lvar_saved_info_t.is_noptr_lvar(): + + is_noptr_lvar(self) -> bool + + ida_hexrays.lvar_saved_info_t.ll: lvar_saved_info_t_ll_get(self) -> lvar_locator_t ida_hexrays.lvar_saved_info_t.name: lvar_saved_info_t_name_get(self) -> qstring * +ida_hexrays.lvar_saved_info_t.set_forced_lvar(): + + set_forced_lvar(self) + + ida_hexrays.lvar_saved_info_t.set_keep(): set_keep(self) +ida_hexrays.lvar_saved_info_t.set_noptr_lvar(): + + set_noptr_lvar(self) + + ida_hexrays.lvar_saved_info_t.size: lvar_saved_info_t_size_get(self) -> ssize_t @@ -18562,7 +19614,12 @@ class ida_hexrays.lvar_t(): ida_hexrays.lvar_t.accepts_type(): - accepts_type(self, t) -> bool + accepts_type(self, t, may_change_thisarg=False) -> bool + + +ida_hexrays.lvar_t.append_list(): + + append_list(self, lst, pad_if_scattered=False) ida_hexrays.lvar_t.clear_used(): @@ -18585,6 +19642,11 @@ ida_hexrays.lvar_t.clr_floating_var(): clr_floating_var(self) +ida_hexrays.lvar_t.clr_forced_var(): + + clr_forced_var(self) + + ida_hexrays.lvar_t.clr_mapdst_var(): clr_mapdst_var(self) @@ -18595,6 +19657,11 @@ ida_hexrays.lvar_t.clr_mreg_done(): clr_mreg_done(self) +ida_hexrays.lvar_t.clr_noptr_var(): + + clr_noptr_var(self) + + ida_hexrays.lvar_t.clr_overlapped_var(): clr_overlapped_var(self) @@ -18605,6 +19672,11 @@ ida_hexrays.lvar_t.clr_spoiled_var(): clr_spoiled_var(self) +ida_hexrays.lvar_t.clr_thisarg(): + + clr_thisarg(self) + + ida_hexrays.lvar_t.clr_unknown_width(): clr_unknown_width(self) @@ -18652,17 +19724,17 @@ ida_hexrays.lvar_t.get_reg2(): get_reg2(self) -> mreg_t -ida_hexrays.lvar_t.get_regnum(): - - get_regnum(self) -> sval_t - - ida_hexrays.lvar_t.get_scattered(): get_scattered(self) -> scattered_aloc_t get_scattered(self) -> scattered_aloc_t +ida_hexrays.lvar_t.get_stkoff(): + + get_stkoff(self) -> sval_t + + ida_hexrays.lvar_t.has_common(): has_common(self, v) -> bool @@ -18678,6 +19750,11 @@ ida_hexrays.lvar_t.has_nice_name: has_nice_name(self) -> bool +ida_hexrays.lvar_t.has_regname(): + + has_regname(self) -> bool + + ida_hexrays.lvar_t.has_user_info: has_user_info(self) -> bool @@ -18693,6 +19770,11 @@ ida_hexrays.lvar_t.has_user_type: has_user_type(self) -> bool +ida_hexrays.lvar_t.is_aliasable(): + + is_aliasable(self, mba) -> bool + + ida_hexrays.lvar_t.is_arg_var: is_arg_var(self) -> bool @@ -18708,11 +19790,21 @@ ida_hexrays.lvar_t.is_floating_var: is_floating_var(self) -> bool +ida_hexrays.lvar_t.is_forced_var(): + + is_forced_var(self) -> bool + + ida_hexrays.lvar_t.is_mapdst_var: is_mapdst_var(self) -> bool +ida_hexrays.lvar_t.is_noptr_var(): + + is_noptr_var(self) -> bool + + ida_hexrays.lvar_t.is_overlapped_var: is_overlapped_var(self) -> bool @@ -18753,6 +19845,11 @@ ida_hexrays.lvar_t.is_stk_var(): is_stk_var(self) -> bool +ida_hexrays.lvar_t.is_thisarg(): + + is_thisarg(self) -> bool + + ida_hexrays.lvar_t.is_unknown_width: is_unknown_width(self) -> bool @@ -18789,6 +19886,11 @@ ida_hexrays.lvar_t.set_floating_var(): set_floating_var(self) +ida_hexrays.lvar_t.set_forced_var(): + + set_forced_var(self) + + ida_hexrays.lvar_t.set_lvar_type(): set_lvar_type(self, t, may_fail=False) -> bool @@ -18809,21 +19911,26 @@ ida_hexrays.lvar_t.set_non_typed(): set_non_typed(self) +ida_hexrays.lvar_t.set_noptr_var(): + + set_noptr_var(self) + + ida_hexrays.lvar_t.set_overlapped_var(): set_overlapped_var(self) -ida_hexrays.lvar_t.set_reg_name(): - - set_reg_name(self, n) - - ida_hexrays.lvar_t.set_spoiled_var(): set_spoiled_var(self) +ida_hexrays.lvar_t.set_thisarg(): + + set_thisarg(self) + + ida_hexrays.lvar_t.set_typed(): set_typed(self) @@ -19292,7 +20399,14 @@ ida_hexrays.partial_type_num(): ida_hexrays.print_vdloc(): - print_vdloc(loc, w) + print_vdloc(loc, nbytes) + + + Print vdloc. Since vdloc does not always carry the size info, we pass + it as NBYTES.. + + @param loc (C++: const vdloc_t &) + @param nbytes (C++: int) class ida_hexrays.qlist_cinsn_t(): @@ -19328,7 +20442,7 @@ ida_hexrays.qlist_cinsn_t.end(): ida_hexrays.qlist_cinsn_t.erase(): - erase(self, p) + erase(self, p) -> qlist< cinsn_t >::iterator erase(self, p1, p2) erase(self, p) @@ -19399,7 +20513,7 @@ ida_hexrays.qlist_cinsn_t_iterator.cur: ida_hexrays.qlist_cinsn_t_iterator.next(): - next(self) -> qlist_cinsn_t_iterator + next(self) class ida_hexrays.qstring_printer_t(): @@ -19929,14 +21043,7 @@ ida_hexrays.remitem(): ida_hexrays.remove_hexrays_callback(): - - remove_hexrays_callback(hx_cblist_callback) -> int - - - Uninstall handler for decompiler events. - - @return: number of uninstalled handlers. - + Deprecated. Please use Hexrays_Hooks instead ida_hexrays.restore_user_cmts(): @@ -20113,7 +21220,7 @@ ida_hexrays.send_database(): Send the database to Hex-Rays. This function sends the current - database to the hex-rays server. The database is sent in the + database to the Hex-Rays server. The database is sent in the compressed form over an encrypted (SSL) connection. @param err: failure description object. Empty hexrays_failure_t @@ -20139,6 +21246,17 @@ ida_hexrays.set_type(): @return: success +ida_hexrays.swapped_relation(): + + swapped_relation(op) -> ctype_t + + + Swap a comparison operator. For example, cot_sge becomes cot_sle. + + + @param op (C++: ctype_t) + + ida_hexrays.term_hexrays_plugin(): term_hexrays_plugin() @@ -20516,18 +21634,18 @@ ida_hexrays.user_cmts_t.keytype.itp: ida_hexrays.user_cmts_t.pop(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_cmts_t.popitem(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_cmts_t.setdefault(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + class ida_hexrays.user_cmts_t.valuetype(): @@ -20674,7 +21792,7 @@ ida_hexrays.user_iflags_prev(): ida_hexrays.user_iflags_second(): - user_iflags_second(p) -> int32 & + user_iflags_second(p) -> int32 const & Get reference to the current map value. @@ -20722,18 +21840,42 @@ ida_hexrays.user_iflags_t.keytype.op: ida_hexrays.user_iflags_t.pop(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_iflags_t.popitem(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_iflags_t.setdefault(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + + +ida_hexrays.user_iflags_t.valuetype.bit_length(): + int.bit_length() -> int + + Number of bits necessary to represent self in binary. + >>> bin(37) + '0b100101' + >>> (37).bit_length() + 6 + +ida_hexrays.user_iflags_t.valuetype.conjugate(): + Returns self, the complex conjugate of any int. + +ida_hexrays.user_iflags_t.valuetype.denominator: + the denominator of a rational number in lowest terms + +ida_hexrays.user_iflags_t.valuetype.imag: + the imaginary part of a complex number + +ida_hexrays.user_iflags_t.valuetype.numerator: + the numerator of a rational number in lowest terms + +ida_hexrays.user_iflags_t.valuetype.real: + the real part of a complex number ida_hexrays.user_labels_begin(): @@ -21093,18 +22235,18 @@ ida_hexrays.user_numforms_t.keytype.opnum: ida_hexrays.user_numforms_t.pop(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_numforms_t.popitem(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_numforms_t.setdefault(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + class ida_hexrays.user_numforms_t.valuetype(): @@ -21343,18 +22485,18 @@ ida_hexrays.user_unions_t.at(): ida_hexrays.user_unions_t.pop(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_unions_t.popitem(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + ida_hexrays.user_unions_t.setdefault(): - Sets the value associated with the provided key. - + Sets the value associated with the provided key. + class ida_hexrays.user_unions_t.valuetype(): @@ -21415,11 +22557,6 @@ ida_hexrays.user_unions_t.valuetype.find(): find(self, x) -> qvector< int >::const_iterator -ida_hexrays.user_unions_t.valuetype.grow(): - - grow(self, x=int()) - - ida_hexrays.user_unions_t.valuetype.has(): has(self, x) -> bool @@ -21617,6 +22754,11 @@ ida_hexrays.vdloc_t.get_rrel(): get_rrel(self) -> rrel_t +ida_hexrays.vdloc_t.is_aliasable(): + + is_aliasable(self, mb, size) -> bool + + ida_hexrays.vdloc_t.is_badloc(): is_badloc(self) -> bool @@ -21897,6 +23039,11 @@ ida_hexrays.vdui_t.set_lvar_type(): set_lvar_type(self, v, type) -> bool +ida_hexrays.vdui_t.set_noptr_lvar(): + + set_noptr_lvar(self, v) -> bool + + ida_hexrays.vdui_t.set_num_enum(): set_num_enum(self) -> bool @@ -22086,6 +23233,11 @@ ida_hexrays.DECOMP_NO_WAIT do not display waitbox """ +ida_hexrays.DECOMP_WARNINGS +""" +display warnings in the output window +""" + ida_hexrays.EXFL_ALL """ all currently defined bits @@ -22111,6 +23263,11 @@ ida_hexrays.EXFL_FPOP floating point operation """ +ida_hexrays.EXFL_JUMPOUT +""" +jump out-of-function +""" + ida_hexrays.EXFL_LVALUE """ expression is lvalue even if it doesn't look like it @@ -22121,6 +23278,16 @@ ida_hexrays.EXFL_PARTIAL type of the expression is considered partial """ +ida_hexrays.EXFL_UNDEF +""" +expression uses undefined value +""" + +ida_hexrays.EXFL_VFTABLE +""" +is ptr to vftable (used for cot_memptr, cot_memref) +""" + ida_hexrays.GLN_ALL """ get both @@ -22136,9 +23303,23 @@ ida_hexrays.GLN_GOTO_TARGET get goto target """ +ida_hexrays.LVINF_FORCE +""" +force allocation of a new variable. forces the decompiler to create a +new variable at ll.defea +""" + ida_hexrays.LVINF_KEEP """ -keep saved user settings regardless of vars +preserve saved user settings regardless of vars for example, if a var +loses all its user-defined attributes or even gets destroyed, keep its +'lvar_saved_info_t' . this is used for ephemeral variables that get +destroyed by macro recognition. +""" + +ida_hexrays.LVINF_NOPTR +""" +variable type should not be a pointer """ ida_hexrays.NF_BINVDONE @@ -22171,6 +23352,26 @@ ida_hexrays.NF_STROFF internal bit: used as stroff, valid iff 'is_stroff()' """ +ida_hexrays.SHINS_LDXEA +""" +display address of ldx expressions (not used) +""" + +ida_hexrays.SHINS_NUMADDR +""" +display definition addresses for numbers +""" + +ida_hexrays.SHINS_SHORT +""" +do not display use-def chains and other attrs +""" + +ida_hexrays.SHINS_VALNUM +""" +display value numbers +""" + ida_hexrays.ULV_PRECISE_DEFEA """ Use precise defea's for lvar locations. @@ -22186,6 +23387,11 @@ ida_hexrays.VDRUN_CMDLINE called from ida's command line """ +ida_hexrays.VDRUN_LUMINA +""" +use lumina server +""" + ida_hexrays.VDRUN_MAYSTOP """ the user can cancel decompilation @@ -22236,7 +23442,7 @@ ida_ida.calc_default_idaplace_flags(): calc_default_idaplace_flags() -> int - Get default disassembly line options (see 'Disassembly line options' ) + Get default disassembly line options. class ida_ida.compiler_info_t(): @@ -22298,11 +23504,6 @@ ida_ida.idainfo.af: ida_ida.idainfo.af2: idainfo_af2_get(self) -> uint32 -ida_ida.idainfo.allow_nonmatched_ops(): - - allow_nonmatched_ops(self) -> bool - - ida_ida.idainfo.appcall_options: idainfo_appcall_options_get(self) -> uint32 @@ -22326,11 +23527,6 @@ ida_ida.idainfo.bin_prefix_size: ida_ida.idainfo.cc: idainfo_cc_get(self) -> compiler_info_t -ida_ida.idainfo.check_manual_ops(): - - check_manual_ops(self) -> bool - - ida_ida.idainfo.comment: idainfo_comment_get(self) -> uchar @@ -22571,11 +23767,6 @@ ida_ida.idainfo.set_64bit(): set_64bit(self) -ida_ida.idainfo.set_allow_nonmatched_ops(): - - set_allow_nonmatched_ops(self, value) - - ida_ida.idainfo.set_auto_enabled(): set_auto_enabled(self, value) @@ -22586,11 +23777,6 @@ ida_ida.idainfo.set_be(): set_be(self, value) -> bool -ida_ida.idainfo.set_check_manual_ops(): - - set_check_manual_ops(self, value) - - ida_ida.idainfo.set_gen_lzero(): set_gen_lzero(self, value) @@ -23038,17 +24224,6 @@ ida_ida.DEMNAM_NONE don't display demangled names """ -ida_ida.IDAPLACE_SEGADDR -""" -display line prefixes with the segment part -""" - -ida_ida.IDAPLACE_STACK -""" -produce 2/4/8 bytes per undefined item. (used to display the stack -contents) the number of displayed bytes depends on the stack bitness -""" - ida_ida.IDB_COMPRESSED """ compress & pack database components @@ -24652,6 +25827,199 @@ ida_idd.get_event_module_size(): get_event_module_size(ev) -> asize_t +class ida_idd.meminfo_vec_t(): + + Proxy of C++ qvector<(memory_info_t)> class + + +ida_idd.meminfo_vec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_idd.meminfo_vec_t.at(): + + at(self, _idx) -> memory_info_t + + +ida_idd.meminfo_vec_t.begin(): + + begin(self) -> memory_info_t + begin(self) -> memory_info_t + + +ida_idd.meminfo_vec_t.capacity(): + + capacity(self) -> size_t + + +ida_idd.meminfo_vec_t.clear(): + + clear(self) + + +ida_idd.meminfo_vec_t.empty(): + + empty(self) -> bool + + +ida_idd.meminfo_vec_t.end(): + + end(self) -> memory_info_t + end(self) -> memory_info_t + + +ida_idd.meminfo_vec_t.erase(): + + erase(self, it) -> memory_info_t + erase(self, first, last) -> memory_info_t + + +ida_idd.meminfo_vec_t.extract(): + + extract(self) -> memory_info_t + + +ida_idd.meminfo_vec_t.find(): + + find(self, x) -> memory_info_t + find(self, x) -> memory_info_t + + +ida_idd.meminfo_vec_t.grow(): + + grow(self, x=memory_info_t()) + + +ida_idd.meminfo_vec_t.has(): + + has(self, x) -> bool + + +ida_idd.meminfo_vec_t.inject(): + + inject(self, s, len) + + +ida_idd.meminfo_vec_t.insert(): + + insert(self, it, x) -> memory_info_t + + +ida_idd.meminfo_vec_t.pop_back(): + + pop_back(self) + + +ida_idd.meminfo_vec_t.push_back(): + + push_back(self, x) + push_back(self) -> memory_info_t + + +ida_idd.meminfo_vec_t.qclear(): + + qclear(self) + + +ida_idd.meminfo_vec_t.reserve(): + + reserve(self, cnt) + + +ida_idd.meminfo_vec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_idd.meminfo_vec_t.size(): + + size(self) -> size_t + + +ida_idd.meminfo_vec_t.swap(): + + swap(self, r) + + +ida_idd.meminfo_vec_t.truncate(): + + truncate(self) + + +class ida_idd.memory_info_t(): + + Proxy of C++ memory_info_t class + + +ida_idd.memory_info_t._print(): + + _print(self) -> size_t + + +ida_idd.memory_info_t.bitness: + memory_info_t_bitness_get(self) -> uchar + +ida_idd.memory_info_t.clear(): + + clear(self) + + +ida_idd.memory_info_t.compare(): + + compare(self, r) -> int + + +ida_idd.memory_info_t.contains(): + + contains(self, ea) -> bool + contains(self, r) -> bool + + +ida_idd.memory_info_t.empty(): + + empty(self) -> bool + + +ida_idd.memory_info_t.end_ea: + range_t_end_ea_get(self) -> ea_t + +ida_idd.memory_info_t.extend(): + + extend(self, ea) + + +ida_idd.memory_info_t.intersect(): + + intersect(self, r) + + +ida_idd.memory_info_t.name: + memory_info_t_name_get(self) -> qstring * + +ida_idd.memory_info_t.overlaps(): + + overlaps(self, r) -> bool + + +ida_idd.memory_info_t.perm: + memory_info_t_perm_get(self) -> uchar + +ida_idd.memory_info_t.sbase: + memory_info_t_sbase_get(self) -> ea_t + +ida_idd.memory_info_t.sclass: + memory_info_t_sclass_get(self) -> qstring * + +ida_idd.memory_info_t.size(): + + size(self) -> asize_t + + +ida_idd.memory_info_t.start_ea: + range_t_start_ea_get(self) -> ea_t + class ida_idd.modinfo_t(): Proxy of C++ modinfo_t class @@ -24848,9 +26216,61 @@ class ida_idd.scattered_segm_t(): Proxy of C++ scattered_segm_t class +ida_idd.scattered_segm_t._print(): + + _print(self) -> size_t + + +ida_idd.scattered_segm_t.clear(): + + clear(self) + + +ida_idd.scattered_segm_t.compare(): + + compare(self, r) -> int + + +ida_idd.scattered_segm_t.contains(): + + contains(self, ea) -> bool + contains(self, r) -> bool + + +ida_idd.scattered_segm_t.empty(): + + empty(self) -> bool + + +ida_idd.scattered_segm_t.end_ea: + range_t_end_ea_get(self) -> ea_t + +ida_idd.scattered_segm_t.extend(): + + extend(self, ea) + + +ida_idd.scattered_segm_t.intersect(): + + intersect(self, r) + + ida_idd.scattered_segm_t.name: scattered_segm_t_name_get(self) -> qstring * +ida_idd.scattered_segm_t.overlaps(): + + overlaps(self, r) -> bool + + +ida_idd.scattered_segm_t.size(): + + size(self) -> asize_t + + +ida_idd.scattered_segm_t.start_ea: + range_t_start_ea_get(self) -> ea_t + ida_idd.set_debug_event_code(): set_debug_event_code(ev, id) @@ -24960,11 +26380,21 @@ ida_idp.IDB_Hooks.auto_empty_finally(): auto_empty_finally(self) -> int +ida_idp.IDB_Hooks.bookmark_changed(): + + bookmark_changed(self, index, pos, desc) -> int + + ida_idp.IDB_Hooks.byte_patched(): byte_patched(self, ea, old_value) -> int +ida_idp.IDB_Hooks.callee_addr_changed(): + + callee_addr_changed(self, ea, callee) -> int + + ida_idp.IDB_Hooks.changing_cmt(): changing_cmt(self, ea, repeatable_cmt, newcmt) -> int @@ -25195,6 +26625,11 @@ ida_idp.IDB_Hooks.idasgn_loaded(): idasgn_loaded(self, short_sig_name) -> int +ida_idp.IDB_Hooks.item_color_changed(): + + item_color_changed(self, ea, color) -> int + + ida_idp.IDB_Hooks.kernel_config_loaded(): kernel_config_loaded(self) -> int @@ -25315,6 +26750,11 @@ ida_idp.IDB_Hooks.sgr_changed(): sgr_changed(self, start_ea, end_ea, regnum, value, old_value, tag) -> int +ida_idp.IDB_Hooks.sgr_deleted(): + + sgr_deleted(self, start_ea, end_ea, regnum) -> int + + ida_idp.IDB_Hooks.stkpnts_changed(): stkpnts_changed(self, pfn) -> int @@ -25680,7 +27120,7 @@ ida_idp.IDP_Hooks.ev_get_autocmt(): ida_idp.IDP_Hooks.ev_get_bg_color(): - ev_get_bg_color(self, color, ea) -> int + ev_get_bg_color(self, ea) -> int or None ida_idp.IDP_Hooks.ev_get_cc_regs(): @@ -26307,6 +27747,17 @@ ida_idp.delay_slot_insn(): @param fexec (C++: bool *) +ida_idp.gen_idb_event(): + + gen_idb_event(code) + + + the kernel will use this function to generate idb_events + + + @param code (C++: idb_event::event_code_t) + + ida_idp.get_idp_name(): get_idp_name() -> char * @@ -27111,6 +28562,11 @@ ida_idp.PLFM_6502 6502 """ +ida_idp.PLFM_65C816 +""" +65802/65816 +""" + ida_idp.PLFM_6800 """ Motorola 68xx. @@ -27131,6 +28587,11 @@ ida_idp.PLFM_8051 8051 """ +ida_idp.PLFM_AD2106X +""" +Analog Devices ADSP 2106X. +""" + ida_idp.PLFM_AD218X """ Analog Devices ADSP 218X. @@ -27141,6 +28602,11 @@ ida_idp.PLFM_ALPHA DEC Alpha. """ +ida_idp.PLFM_ARC +""" +Argonaut RISC Core. +""" + ida_idp.PLFM_ARM """ Advanced RISC Machines. @@ -27166,11 +28632,21 @@ ida_idp.PLFM_CR16 NSC CR16. """ +ida_idp.PLFM_DALVIK +""" +Android Dalvik Virtual Machine. +""" + ida_idp.PLFM_DSP56K """ Motorola DSP5600x. """ +ida_idp.PLFM_DSP96K +""" +Motorola DSP96000. +""" + ida_idp.PLFM_EBC """ EFI Bytecode. @@ -27226,6 +28702,11 @@ ida_idp.PLFM_KR1878 Angstrem KR1878. """ +ida_idp.PLFM_M16C +""" +Renesas M16C. +""" + ida_idp.PLFM_M32R """ Mitsubishi 32bit RISC. @@ -27306,6 +28787,11 @@ ida_idp.PLFM_PIC Microchip's PIC. """ +ida_idp.PLFM_PIC16 +""" +Microchip's 16-bit PIC. +""" + ida_idp.PLFM_PPC """ PowerPC. @@ -27327,6 +28813,11 @@ ida_idp.PLFM_SPARC SPARC. """ +ida_idp.PLFM_SPC700 +""" +Sony SPC700. +""" + ida_idp.PLFM_SPU """ Cell Broadband Engine Synergistic Processor Unit. @@ -27362,6 +28853,11 @@ ida_idp.PLFM_TMS320C1X Texas Instruments TMS320C1x. """ +ida_idp.PLFM_TMS320C28 +""" +Texas Instruments TMS320C28x. +""" + ida_idp.PLFM_TMS320C3 """ Texas Instruments TMS320C3. @@ -27392,6 +28888,11 @@ ida_idp.PLFM_TRIMEDIA Trimedia. """ +ida_idp.PLFM_UNSP +""" +SunPlus unSP. +""" + ida_idp.PLFM_Z8 """ Z8. @@ -27596,11 +29097,8 @@ ida_kernwin.Choose.Embedded(): ida_kernwin.Choose.GetEmbSelection(): - Returns the selection associated with an embedded chooser - - @return: - - None if chooser is not embedded - - A list with selection indexes (0-based) + Deprecated. For embedded choosers, the selection is + available through 'Form.EmbeddedChooserControl.selection' ida_kernwin.Choose.GetWidget(): @@ -27629,6 +29127,11 @@ ida_kernwin.Choose.Show(): or ALREADY_EXISTS if the chooser was already open and is active now; +ida_kernwin.Choose.UI_Hooks_Trampoline.create_desktop_widget(): + + create_desktop_widget(self, title, cfg) -> PyObject * + + ida_kernwin.Choose.UI_Hooks_Trampoline.current_widget_changed(): current_widget_changed(self, widget, prev_widget) @@ -27646,7 +29149,7 @@ ida_kernwin.Choose.UI_Hooks_Trampoline.debugger_menu_change(): ida_kernwin.Choose.UI_Hooks_Trampoline.finish_populating_widget_popup(): - finish_populating_widget_popup(self, widget, popup_handle) + finish_populating_widget_popup(self, widget, popup_handle, ctx=None) The UI is about to be done populating the TWidget's popup menu. @@ -28729,16 +30232,23 @@ ida_kernwin.PluginForm.Close(): ida_kernwin.PluginForm.FormToPyQtWidget(): - Use this method to convert a TWidget* to a QWidget to be used by PyQt + Convert a TWidget* to a QWidget to be used by PyQt - @param ctx: Context. Reference to a module that already imported SIP and QtGui modules + @param ctx: Context. Reference to a module that already imported SIP and QtWidgets modules ida_kernwin.PluginForm.FormToPySideWidget(): Use this method to convert a TWidget* to a QWidget to be used by PySide - @param ctx: Context. Reference to a module that already imported QtGui module + @param ctx: Context. Reference to a module that already imported QtWidgets module + + +ida_kernwin.PluginForm.GetWidget(): + + Return the TWidget underlying this view. + + @return: The TWidget underlying this view, or None. ida_kernwin.PluginForm.OnClose(): @@ -28756,6 +30266,13 @@ ida_kernwin.PluginForm.OnCreate(): @return: None +ida_kernwin.PluginForm.QtWidgetToTWidget(): + + Convert a QWidget to a TWidget* to be used by IDA + + @param ctx: Context. Reference to a module that already imported SIP and QtWidgets modules + + ida_kernwin.PluginForm.Show(): Creates the form if not was not created or brings to front if it was already created @@ -28764,11 +30281,35 @@ ida_kernwin.PluginForm.Show(): @param options: One of PluginForm.WOPN_ constants +ida_kernwin.PluginForm.TWidgetToPyQtWidget(): + + Convert a TWidget* to a QWidget to be used by PyQt + + @param ctx: Context. Reference to a module that already imported SIP and QtWidgets modules + + +ida_kernwin.PluginForm.TWidgetToPySideWidget(): + + Use this method to convert a TWidget* to a QWidget to be used by PySide + + @param ctx: Context. Reference to a module that already imported QtWidgets module + + +ida_kernwin.TWidget__from_ptrval__(): + + TWidget__from_ptrval__(ptrval) -> TWidget * + + class ida_kernwin.UI_Hooks(): Proxy of C++ UI_Hooks class +ida_kernwin.UI_Hooks.create_desktop_widget(): + + create_desktop_widget(self, title, cfg) -> PyObject * + + ida_kernwin.UI_Hooks.current_widget_changed(): current_widget_changed(self, widget, prev_widget) @@ -28786,7 +30327,7 @@ ida_kernwin.UI_Hooks.debugger_menu_change(): ida_kernwin.UI_Hooks.finish_populating_widget_popup(): - finish_populating_widget_popup(self, widget, popup_handle) + finish_populating_widget_popup(self, widget, popup_handle, ctx=None) The UI is about to be done populating the TWidget's popup menu. @@ -28855,7 +30396,7 @@ ida_kernwin.UI_Hooks.plugin_unloading(): ida_kernwin.UI_Hooks.populating_widget_popup(): - populating_widget_popup(self, widget, popup_handle) + populating_widget_popup(self, widget, popup_handle, ctx=None) The UI is populating the TWidget's popup menu. @@ -29062,89 +30603,6 @@ ida_kernwin.View_Hooks.view_switched(): view_switched(self, view, rt) -class ida_kernwin.action_activation_ctx_t(): - - Proxy of C++ action_activation_ctx_t class - - -ida_kernwin.action_activation_ctx_t.action: - action_ctx_base_t_action_get(self) -> char const * - -ida_kernwin.action_activation_ctx_t.chooser_selection: - action_ctx_base_t_chooser_selection_get(self) -> sizevec_t * - -ida_kernwin.action_activation_ctx_t.cur_ea: - action_ctx_base_t_cur_ea_get(self) -> ea_t - -ida_kernwin.action_activation_ctx_t.cur_enum: - action_ctx_base_t_cur_enum_get(self) -> enum_t - -ida_kernwin.action_activation_ctx_t.cur_extracted_ea: - action_ctx_base_t_cur_extracted_ea_get(self) -> ea_t - -ida_kernwin.action_activation_ctx_t.cur_fchunk: - action_ctx_base_t_cur_fchunk_get(self) -> func_t * - -ida_kernwin.action_activation_ctx_t.cur_flags: - action_ctx_base_t_cur_flags_get(self) -> uint32 - -ida_kernwin.action_activation_ctx_t.cur_func: - action_ctx_base_t_cur_func_get(self) -> func_t * - -ida_kernwin.action_activation_ctx_t.cur_seg: - action_ctx_base_t_cur_seg_get(self) -> segment_t * - -ida_kernwin.action_activation_ctx_t.cur_strmem: - action_ctx_base_t_cur_strmem_get(self) -> member_t * - -ida_kernwin.action_activation_ctx_t.cur_struc: - action_ctx_base_t_cur_struc_get(self) -> struc_t * - -ida_kernwin.action_activation_ctx_t.focus: - action_ctx_base_t_focus_get(self) -> TWidget * - -ida_kernwin.action_activation_ctx_t.form: - - _get_form(self) -> TWidget * - - -ida_kernwin.action_activation_ctx_t.form_title: - - _get_form_title(self) -> qstring - - -ida_kernwin.action_activation_ctx_t.form_type: - - _get_form_type(self) -> twidget_type_t - - -ida_kernwin.action_activation_ctx_t.has_flag(): - - has_flag(self, flag) -> bool - - -ida_kernwin.action_activation_ctx_t.reg: - - _get_reg(self) -> int - - -ida_kernwin.action_activation_ctx_t.reserved: - action_ctx_base_t_reserved_get(self) -> void * - -ida_kernwin.action_activation_ctx_t.reset(): - - reset(self) - - -ida_kernwin.action_activation_ctx_t.widget: - action_ctx_base_t_widget_get(self) -> TWidget * - -ida_kernwin.action_activation_ctx_t.widget_title: - action_ctx_base_t_widget_title_get(self) -> qstring * - -ida_kernwin.action_activation_ctx_t.widget_type: - action_ctx_base_t_widget_type_get(self) -> twidget_type_t - class ida_kernwin.action_ctx_base_t(): Proxy of C++ action_ctx_base_t class @@ -29206,10 +30664,8 @@ ida_kernwin.action_ctx_base_t.has_flag(): has_flag(self, flag) -> bool -ida_kernwin.action_ctx_base_t.reg: - - _get_reg(self) -> int - +ida_kernwin.action_ctx_base_t.regname: + action_ctx_base_t_regname_get(self) -> char const * ida_kernwin.action_ctx_base_t.reserved: action_ctx_base_t_reserved_get(self) -> void * @@ -29257,89 +30713,6 @@ ida_kernwin.action_desc_t.shortcut: ida_kernwin.action_desc_t.tooltip: action_desc_t_tooltip_get(self) -> char const * -class ida_kernwin.action_update_ctx_t(): - - Proxy of C++ action_update_ctx_t class - - -ida_kernwin.action_update_ctx_t.action: - action_ctx_base_t_action_get(self) -> char const * - -ida_kernwin.action_update_ctx_t.chooser_selection: - action_ctx_base_t_chooser_selection_get(self) -> sizevec_t * - -ida_kernwin.action_update_ctx_t.cur_ea: - action_ctx_base_t_cur_ea_get(self) -> ea_t - -ida_kernwin.action_update_ctx_t.cur_enum: - action_ctx_base_t_cur_enum_get(self) -> enum_t - -ida_kernwin.action_update_ctx_t.cur_extracted_ea: - action_ctx_base_t_cur_extracted_ea_get(self) -> ea_t - -ida_kernwin.action_update_ctx_t.cur_fchunk: - action_ctx_base_t_cur_fchunk_get(self) -> func_t * - -ida_kernwin.action_update_ctx_t.cur_flags: - action_ctx_base_t_cur_flags_get(self) -> uint32 - -ida_kernwin.action_update_ctx_t.cur_func: - action_ctx_base_t_cur_func_get(self) -> func_t * - -ida_kernwin.action_update_ctx_t.cur_seg: - action_ctx_base_t_cur_seg_get(self) -> segment_t * - -ida_kernwin.action_update_ctx_t.cur_strmem: - action_ctx_base_t_cur_strmem_get(self) -> member_t * - -ida_kernwin.action_update_ctx_t.cur_struc: - action_ctx_base_t_cur_struc_get(self) -> struc_t * - -ida_kernwin.action_update_ctx_t.focus: - action_ctx_base_t_focus_get(self) -> TWidget * - -ida_kernwin.action_update_ctx_t.form: - - _get_form(self) -> TWidget * - - -ida_kernwin.action_update_ctx_t.form_title: - - _get_form_title(self) -> qstring - - -ida_kernwin.action_update_ctx_t.form_type: - - _get_form_type(self) -> twidget_type_t - - -ida_kernwin.action_update_ctx_t.has_flag(): - - has_flag(self, flag) -> bool - - -ida_kernwin.action_update_ctx_t.reg: - - _get_reg(self) -> int - - -ida_kernwin.action_update_ctx_t.reserved: - action_ctx_base_t_reserved_get(self) -> void * - -ida_kernwin.action_update_ctx_t.reset(): - - reset(self) - - -ida_kernwin.action_update_ctx_t.widget: - action_ctx_base_t_widget_get(self) -> TWidget * - -ida_kernwin.action_update_ctx_t.widget_title: - action_ctx_base_t_widget_title_get(self) -> qstring * - -ida_kernwin.action_update_ctx_t.widget_type: - action_ctx_base_t_widget_type_get(self) -> twidget_type_t - ida_kernwin.activate_widget(): activate_widget(widget, take_focus) @@ -29478,18 +30851,6 @@ ida_kernwin.ask_for_feedback(): *) -ida_kernwin.ask_form(): - - Calls ask_form() - @param: Compiled Arguments obtain through the Form.Compile() function - @return: 1 = ok, 0 = cancel - - - Display a dialog box and wait for the user. If the form contains the - "BUTTON NO " keyword, then the return values are the same as in - the 'ask_yn()' function ( 'Button IDs' ) - - ida_kernwin.ask_str(): ask_str(defval, hist, prompt) -> PyObject * @@ -29728,16 +31089,6 @@ ida_kernwin.choose_func(): @return: pointer to function that was selected, NULL if none selected -ida_kernwin.choose_get_embedded(): - - choose_get_embedded(self) -> PyObject * - - -ida_kernwin.choose_get_embedded_selection(): - - choose_get_embedded_selection(self) -> PyObject * - - ida_kernwin.choose_get_widget(): choose_get_widget(self) -> TWidget * @@ -30593,6 +31944,18 @@ ida_kernwin.get_action_visibility(): @return: success +ida_kernwin.get_active_modal_widget(): + + get_active_modal_widget() -> TWidget * + + + Get the current, active modal TWidget instance. Note that in this + context, the "wait dialog" is not considered: this function will + return NULL even if it is currently shown. + + @return: TWidget * the active modal widget, or NULL + + ida_kernwin.get_addon_info(): get_addon_info(id, info) -> bool @@ -30759,6 +32122,28 @@ ida_kernwin.get_key_code(): @param keyname (C++: const char *) +ida_kernwin.get_navband_ea(): + + get_navband_ea(pixel) -> ea_t + + + Translate the pixel position on the navigation band, into an address. + + + @param pixel (C++: int) + + +ida_kernwin.get_navband_pixel(): + + get_navband_pixel(ea) -> int + + + Maps an address, onto a pixel coordinate within the navband + + @param ea: The address to map + @return: a list [pixel, is_vertical] + + ida_kernwin.get_opnum(): get_opnum() -> int @@ -30927,6 +32312,17 @@ ida_kernwin.get_widget_type(): @param widget (C++: TWidget *) +ida_kernwin.get_window_id(): + + get_window_id(name=None) -> void * + + + Get the system-specific window ID (GUI version only) + + @param name (C++: const char *) + @return: the low-level window ID + + ida_kernwin.hide_wait_box(): hide_wait_box() @@ -31130,10 +32526,20 @@ ida_kernwin.is_refresh_requested(): Get a refresh request state - @param mask: Window refresh flags (C++: unsigned int) + @param mask: Window refresh flags (C++: uint64) @return: the state (set or cleared) +class ida_kernwin.jobj_wrapper_t(): + + Proxy of C++ jobj_wrapper_t class + + +ida_kernwin.jobj_wrapper_t.get_dict(): + + get_dict(self) -> PyObject * + + ida_kernwin.jumpto(): jumpto(ea, opnum=-1, uijmp_flags=0x0001) -> bool @@ -31321,18 +32727,6 @@ ida_kernwin.open_exports_window(): @return: pointer to resulting window -ida_kernwin.open_form(): - - Calls open_form() - @param: Compiled Arguments obtain through the Form.Compile() function - - - Display a dockable modeless dialog box and return a handle to it. - - @return: handle to the form or NULL. the handle can be used with - TWidget functions: close_widget() /activate_widget()/etc - - ida_kernwin.open_frame_window(): open_frame_window(pfn, offset) -> TWidget * @@ -31718,6 +33112,11 @@ ida_kernwin.plgform_close(): plgform_close(py_link, options) +ida_kernwin.plgform_get_widget(): + + plgform_get_widget(py_link) -> TWidget * + + ida_kernwin.plgform_new(): plgform_new() -> PyObject * @@ -31725,7 +33124,7 @@ ida_kernwin.plgform_new(): ida_kernwin.plgform_show(): - plgform_show(py_link, py_obj, caption, options=WOPN_TAB|WOPN_MENU|WOPN_RESTORE) -> bool + plgform_show(py_link, py_obj, caption, options=WOPN_TAB|WOPN_RESTORE) -> bool ida_kernwin.process_ui_action(): @@ -32116,7 +33515,7 @@ ida_kernwin.request_refresh(): Request a refresh of a builtin window. - @param mask: Window refresh flags (C++: unsigned int) + @param mask: Window refresh flags (C++: uint64) @param cnd: set if true or clear flag otherwise (C++: bool) @@ -32463,6 +33862,12 @@ ida_kernwin.simplecustviewer_t.IsFocused(): Returns True if the current view is the focused view +ida_kernwin.simplecustviewer_t.OnPopup(): + + Context menu popup is about to be shown. Create items dynamically if you wish + @return: Boolean. True if you handled the event + + ida_kernwin.simplecustviewer_t.PatchLine(): Patches an existing line character at the given offset. This is a low level function. You must know what you're doing @@ -32479,6 +33884,216 @@ ida_kernwin.simplecustviewer_t.Show(): @return: Boolean +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.create_desktop_widget(): + + create_desktop_widget(self, title, cfg) -> PyObject * + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.current_widget_changed(): + + current_widget_changed(self, widget, prev_widget) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.database_inited(): + + database_inited(self, is_new_database, idc_script) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.debugger_menu_change(): + + debugger_menu_change(self, enable) -> int + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.finish_populating_widget_popup(): + + finish_populating_widget_popup(self, widget, popup_handle, ctx=None) + + + The UI is about to be done populating the TWidget's popup menu. + Now is a good time to call idaapi.attach_action_to_popup() + + @param widget: The widget + @param popup: The popup menu. + @return: Ignored + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.get_chooser_item_attrs(): + + get_chooser_item_attrs(self, chooser, n, attrs) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.get_custom_viewer_hint(): + + get_custom_viewer_hint(self, viewer, place) -> PyObject * + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.get_ea_hint(): + + get_ea_hint(self, ea) -> PyObject * + + + The UI wants to display a simple hint for an address in the navigation band + + @param ea: The address + @return: String with the hint or None + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.get_item_hint(): + + get_item_hint(self, ea, max_lines) -> PyObject * + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.hook(): + + hook(self) -> bool + + + Creates an UI hook + + @return: Boolean true on success + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.idcstart(): + + idcstart(self) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.idcstop(): + + idcstop(self) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.plugin_loaded(): + + plugin_loaded(self, plugin_info) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.plugin_unloading(): + + plugin_unloading(self, plugin_info) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.postprocess_action(): + + postprocess_action(self) + + + An ida ui action has been handled + + @return: Ignored + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.preprocess_action(): + + preprocess_action(self, name) + + + IDA ui is about to handle a user action + + @param name: ui action name + (these names can be looked up in ida[tg]ui.cfg) + @return: 0-ok, nonzero - a plugin has handled the action + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.range(): + + range(self) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.ready_to_run(): + + ready_to_run(self) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.resume(): + + resume(self) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.saved(): + + saved(self) + + + The kernel has saved the database. + + @return: Ignored + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.saving(): + + saving(self) + + + The kernel is saving the database. + + @return: Ignored + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.screen_ea_changed(): + + screen_ea_changed(self, ea, prev_ea) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.suspend(): + + suspend(self) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.term(): + + term(self) + + + IDA is terminated and the database is already closed. + The UI may close its windows in this callback. + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.unhook(): + + unhook(self) -> bool + + + Removes the UI hook + @return: Boolean true on success + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.updated_actions(): + + updated_actions(self) + + + The UI is done updating actions. + + @return: Ignored + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.updating_actions(): + + updating_actions(self, ctx) + + + The UI is about to batch-update some actions. + + @param ctx: The action_update_ctx_t instance + @return: Ignored + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.widget_closing(): + + widget_closing(self, widget) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.widget_invisible(): + + widget_invisible(self, widget) + + +ida_kernwin.simplecustviewer_t.UI_Hooks_Trampoline.widget_visible(): + + widget_visible(self, widget) + + class ida_kernwin.simpleline_place_t(): Proxy of C++ simpleline_place_t class @@ -33200,6 +34815,16 @@ ida_kernwin.BWN_CALLS function calls """ +ida_kernwin.BWN_CALLS_CALLEES +""" +function calls, callees +""" + +ida_kernwin.BWN_CALLS_CALLERS +""" +function calls, callers +""" + ida_kernwin.BWN_CALL_STACK """ call stack @@ -33292,6 +34917,11 @@ ida_kernwin.BWN_LOCTYPS local types """ +ida_kernwin.BWN_MDVIEWCSR +""" +lumina metadata view chooser +""" + ida_kernwin.BWN_MODULES """ modules @@ -33616,6 +35246,11 @@ ida_kernwin.HIST_TYPE type declarations """ +ida_kernwin.IWID_ADDRWATCH +""" +address watches (47) +""" + ida_kernwin.IWID_ALL """ mask @@ -33631,6 +35266,46 @@ ida_kernwin.IWID_CALLS function calls (11) """ +ida_kernwin.IWID_CALLS_CALLEES +""" +funcalls, callees (50) +""" + +ida_kernwin.IWID_CALLS_CALLERS +""" +funcalls, callers (49) +""" + +ida_kernwin.IWID_CHOOSER +""" +chooser (37) +""" + +ida_kernwin.IWID_CLI +""" +input line (33) +""" + +ida_kernwin.IWID_CMDPALCSR +""" +command palette (43) +""" + +ida_kernwin.IWID_CMDPALWIN +""" +command palette (44) +""" + +ida_kernwin.IWID_CPUREGS +""" +registers (40) +""" + +ida_kernwin.IWID_CUSTVIEW +""" +custom viewers (46) +""" + ida_kernwin.IWID_DISASMS """ disassembly views (29) @@ -33671,11 +35346,21 @@ ida_kernwin.IWID_IMPORTS imports (1) """ +ida_kernwin.IWID_LOCALS +""" +locals (35) +""" + ida_kernwin.IWID_LOCTYPS """ local types (10) """ +ida_kernwin.IWID_MDVIEWCSR +""" +lumina md view (51) +""" + ida_kernwin.IWID_MODULES """ modules (15) @@ -33696,11 +35381,21 @@ ida_kernwin.IWID_NOTEPAD notepad (31) """ +ida_kernwin.IWID_OUTPUT +""" +output (32) +""" + ida_kernwin.IWID_PROBS """ problems (12) """ +ida_kernwin.IWID_PSEUDOCODE +""" +decompiler (48) +""" + ida_kernwin.IWID_SEARCHS """ search results (19) @@ -33721,16 +35416,46 @@ ida_kernwin.IWID_SELS selectors (7) """ +ida_kernwin.IWID_SHORTCUTCSR +""" +shortcuts chooser (38) +""" + +ida_kernwin.IWID_SHORTCUTWIN +""" +shortcuts window (39) +""" + ida_kernwin.IWID_SIGNS """ signatures (8) """ +ida_kernwin.IWID_SNIPPETS +""" +snippets (45) +""" + +ida_kernwin.IWID_SO_OFFSETS +""" +stroff (42) +""" + +ida_kernwin.IWID_SO_STRUCTS +""" +stroff (41) +""" + ida_kernwin.IWID_STACK """ call stack (17) """ +ida_kernwin.IWID_STKVIEW +""" +stack view (36) +""" + ida_kernwin.IWID_STRINGS """ strings (4) @@ -33756,6 +35481,11 @@ ida_kernwin.IWID_TRACE trace view (16) """ +ida_kernwin.IWID_WATCH +""" +watches (34) +""" + ida_kernwin.IWID_XREFS """ xrefs (18) @@ -33963,7 +35693,7 @@ ida_lines.del_sourcefile(): ida_lines.delete_extra_cmts(): - delete_extra_cmts(ea, cmtidx) + delete_extra_cmts(ea, what) ida_lines.generate_disasm_line(): @@ -34184,6 +35914,11 @@ ida_lines.COLOR_LIBFUNC Library function. """ +ida_lines.COLOR_LUMFUNC +""" +Lumina function. +""" + ida_lines.COLOR_OFF """ Followed by a color code ( 'color_t' ). @@ -34564,6 +36299,14 @@ ida_loader.get_basic_file_type(): @param li (C++: linput_t *) +ida_loader.get_elf_debug_file_directory(): + + get_elf_debug_file_directory() -> char const * + + + Get the value of the ELF_DEBUG_FILE_DIRECTORY configuration directive. + + ida_loader.get_file_type_name(): get_file_type_name() -> size_t @@ -35952,7 +37695,7 @@ ida_nalt.del_ind_purged(): ida_nalt.del_item_color(): - del_item_color(ea) + del_item_color(ea) -> bool ida_nalt.del_op_tinfo(): @@ -36055,11 +37798,6 @@ ida_nalt.find_custom_refinfo(): @param name (C++: const char *) -ida_nalt.get_abi_name(): - - get_abi_name() -> ssize_t - - ida_nalt.get_absbase(): get_absbase(ea) -> ea_t @@ -38133,6 +39871,111 @@ ida_name.ea_name_t.ea: ida_name.ea_name_t.name: ea_name_t_name_get(self) -> qstring * +class ida_name.ea_name_vec_t(): + + Proxy of C++ qvector<(ea_name_t)> class + + +ida_name.ea_name_vec_t.at(): + + at(self, _idx) -> ea_name_t + + +ida_name.ea_name_vec_t.begin(): + + begin(self) -> ea_name_t + begin(self) -> ea_name_t + + +ida_name.ea_name_vec_t.capacity(): + + capacity(self) -> size_t + + +ida_name.ea_name_vec_t.clear(): + + clear(self) + + +ida_name.ea_name_vec_t.empty(): + + empty(self) -> bool + + +ida_name.ea_name_vec_t.end(): + + end(self) -> ea_name_t + end(self) -> ea_name_t + + +ida_name.ea_name_vec_t.erase(): + + erase(self, it) -> ea_name_t + erase(self, first, last) -> ea_name_t + + +ida_name.ea_name_vec_t.extract(): + + extract(self) -> ea_name_t + + +ida_name.ea_name_vec_t.grow(): + + grow(self, x=ea_name_t()) + + +ida_name.ea_name_vec_t.inject(): + + inject(self, s, len) + + +ida_name.ea_name_vec_t.insert(): + + insert(self, it, x) -> ea_name_t + + +ida_name.ea_name_vec_t.pop_back(): + + pop_back(self) + + +ida_name.ea_name_vec_t.push_back(): + + push_back(self, x) + push_back(self) -> ea_name_t + + +ida_name.ea_name_vec_t.qclear(): + + qclear(self) + + +ida_name.ea_name_vec_t.reserve(): + + reserve(self, cnt) + + +ida_name.ea_name_vec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_name.ea_name_vec_t.size(): + + size(self) -> size_t + + +ida_name.ea_name_vec_t.swap(): + + swap(self, r) + + +ida_name.ea_name_vec_t.truncate(): + + truncate(self) + + ida_name.extract_name(): extract_name(line, x) -> ssize_t @@ -38182,8 +40025,9 @@ ida_name.get_debug_name_ea(): ida_name.get_debug_names(): - get_debug_names(ea1, ea2) -> PyObject * - + get_debug_names(names, ea1, ea2) + get_debug_names(ea1, ea2) -> PyObject * + ida_name.get_demangled_name(): @@ -38221,7 +40065,8 @@ ida_name.get_name_base_ea(): Get address of the name used in the expression for the address - @param _from (C++: ea_t) + @param _from: address of the operand which references to the address + (C++: ea_t) @param to: the referenced address (C++: ea_t) @return: address of the name used to represent the operand @@ -38235,7 +40080,11 @@ ida_name.get_name_color(): Get name color. - @param _from (C++: ea_t) + @param _from: linear address where the name is used. if not + applicable, then should be BADADDR . The kernel returns + a local name color if the reference is within a + function, i.e. 'from' and 'ea' belong to the same + function. (C++: ea_t) @param ea: linear address (C++: ea_t) @@ -38249,7 +40098,8 @@ ida_name.get_name_ea(): database is not consulted for them. This function works only with regular names. - @param _from (C++: ea_t) + @param _from: linear address where the name is used. if not + applicable, then should be BADADDR . (C++: ea_t) @param name: any name in the program or NULL (C++: const char *) @return: address of the name or BADADDR @@ -38265,7 +40115,10 @@ ida_name.get_name_expr(): structure members and arrays. If the specified address doesn't have a name, a dummy name is generated. - @param _from (C++: ea_t) + @param _from: linear address of instruction operand or data referring + to the name. This address will be used to get fixup + information, so it should point to exact position of the + operand in the instruction. (C++: ea_t) @param n: number of referencing operand. for data items specify 0 (C++: int) @param ea: address to convert to name expression (C++: ea_t) @@ -38286,7 +40139,8 @@ ida_name.get_name_value(): Get value of the name. This function knows about: regular names, enums, special segments, etc. - @param _from (C++: ea_t) + @param _from: linear address where the name is used if not applicable, + then should be BADADDR (C++: ea_t) @param name: any name in the program or NULL (C++: const char *) @return: Name value result codes @@ -38560,7 +40414,8 @@ ida_name.set_dummy_name(): Give an autogenerated (dummy) name. Autogenerated names have special prefixes (loc_...). - @param _from (C++: ea_t) + @param _from: linear address of the operand which references to the + address (C++: ea_t) @param ea: linear address (C++: ea_t) @@ -38711,6 +40566,11 @@ ida_name.GN_LONG use long form of demangled name """ +ida_name.GN_NOT_DUMMY +""" +do not return a dummy name +""" + ida_name.GN_NOT_ISRET """ for dummy names: do not use retloc @@ -39446,7 +41306,7 @@ ida_offset.add_refinfo_dref(): 'offset' operand. @param insn: the referencing instruction (C++: const insn_t &) - @param _from (C++: ea_t) + @param _from: the referencing instruction/data address (C++: ea_t) @param ri: reference info block from the database (C++: const refinfo_t &) @param opval: operand value (usually op_t::value or op_t::addr ) @@ -39511,7 +41371,7 @@ ida_offset.calc_reference_data(): @param target: output target address (C++: ea_t *) @param base: output base address (C++: ea_t *) - @param _from (C++: ea_t) + @param _from: the referencing instruction/data address (C++: ea_t) @param ri: reference info block from the database (C++: const refinfo_t &) @param opval: operand value (usually op_t::value or op_t::addr ) @@ -39521,17 +41381,17 @@ ida_offset.calc_reference_data(): ida_offset.calc_target(): - calc_target(_from, ea, n, opval) -> ea_t + calc_target(_from, opval, ri) -> ea_t + calc_target(_from, ea, n, opval) -> ea_t - Retrieves 'refinfo_t' structure and calculates the target. + Calculates the target, using the provided 'refinfo_t' . @param _from (C++: ea_t) - @param ea (C++: ea_t) - @param n (C++: int) @param opval (C++: adiff_t) - + @param ri (C++: const refinfo_t &) + ida_offset.can_be_off32(): @@ -39606,7 +41466,10 @@ ida_offset.get_offset_expression(): (C++: ea_t) @param n: number of operand (may be ORed with OPND_OUTER ) 0: first operand 1: second operand (C++: int) - @param _from (C++: ea_t) + @param _from: linear address of instruction operand or data referring + to the name. This address will be used to get fixup + information, so it should point to exact position of + operand in the instruction. (C++: ea_t) @param offset: value of operand or its part. The function will return text representation of this value as offset expression. (C++: adiff_t) @@ -40150,11 +42013,6 @@ ida_pro.intvec_t.find(): find(self, x) -> qvector< int >::const_iterator -ida_pro.intvec_t.grow(): - - grow(self, x=int()) - - ida_pro.intvec_t.has(): has(self, x) -> bool @@ -40247,6 +42105,122 @@ ida_pro.log2floor(): log2floor(d64) -> int +class ida_pro.longlongvec_t(): + + Proxy of C++ qvector<(long long)> class + + +ida_pro.longlongvec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_pro.longlongvec_t.at(): + + __getitem__(self, i) -> long long const & + + +ida_pro.longlongvec_t.begin(): + + begin(self) -> qvector< long long >::iterator + begin(self) -> qvector< long long >::const_iterator + + +ida_pro.longlongvec_t.capacity(): + + capacity(self) -> size_t + + +ida_pro.longlongvec_t.clear(): + + clear(self) + + +ida_pro.longlongvec_t.empty(): + + empty(self) -> bool + + +ida_pro.longlongvec_t.end(): + + end(self) -> qvector< long long >::iterator + end(self) -> qvector< long long >::const_iterator + + +ida_pro.longlongvec_t.erase(): + + erase(self, it) -> qvector< long long >::iterator + erase(self, first, last) -> qvector< long long >::iterator + + +ida_pro.longlongvec_t.extract(): + + extract(self) -> long long * + + +ida_pro.longlongvec_t.find(): + + find(self, x) -> qvector< long long >::iterator + find(self, x) -> qvector< long long >::const_iterator + + +ida_pro.longlongvec_t.has(): + + has(self, x) -> bool + + +ida_pro.longlongvec_t.inject(): + + inject(self, s, len) + + +ida_pro.longlongvec_t.insert(): + + insert(self, it, x) -> qvector< long long >::iterator + + +ida_pro.longlongvec_t.pop_back(): + + pop_back(self) + + +ida_pro.longlongvec_t.push_back(): + + push_back(self, x) + push_back(self) -> long long & + + +ida_pro.longlongvec_t.qclear(): + + qclear(self) + + +ida_pro.longlongvec_t.reserve(): + + reserve(self, cnt) + + +ida_pro.longlongvec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_pro.longlongvec_t.size(): + + size(self) -> size_t + + +ida_pro.longlongvec_t.swap(): + + swap(self, r) + + +ida_pro.longlongvec_t.truncate(): + + truncate(self) + + ida_pro.parse_dbgopts(): parse_dbgopts(ido, r_switch) -> bool @@ -40762,6 +42736,122 @@ ida_pro.sval_pointer_frompointer(): sval_pointer_frompointer(t) -> sval_pointer +class ida_pro.svalvec_t(): + + Proxy of C++ qvector<(signed-ea-like-numeric-type)> class + + +ida_pro.svalvec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_pro.svalvec_t.at(): + + __getitem__(self, i) -> signed-ea-like-numeric-type & + + +ida_pro.svalvec_t.begin(): + + begin(self) -> qvector< signed-ea-like-numeric-type >::iterator + begin(self) -> qvector< signed-ea-like-numeric-type >::const_iterator + + +ida_pro.svalvec_t.capacity(): + + capacity(self) -> size_t + + +ida_pro.svalvec_t.clear(): + + clear(self) + + +ida_pro.svalvec_t.empty(): + + empty(self) -> bool + + +ida_pro.svalvec_t.end(): + + end(self) -> qvector< signed-ea-like-numeric-type >::iterator + end(self) -> qvector< signed-ea-like-numeric-type >::const_iterator + + +ida_pro.svalvec_t.erase(): + + erase(self, it) -> qvector< signed-ea-like-numeric-type >::iterator + erase(self, first, last) -> qvector< signed-ea-like-numeric-type >::iterator + + +ida_pro.svalvec_t.extract(): + + extract(self) -> signed-ea-like-numeric-type * + + +ida_pro.svalvec_t.find(): + + find(self, x) -> qvector< signed-ea-like-numeric-type >::iterator + find(self, x) -> qvector< signed-ea-like-numeric-type >::const_iterator + + +ida_pro.svalvec_t.has(): + + has(self, x) -> bool + + +ida_pro.svalvec_t.inject(): + + inject(self, s, len) + + +ida_pro.svalvec_t.insert(): + + insert(self, it, x) -> qvector< signed-ea-like-numeric-type >::iterator + + +ida_pro.svalvec_t.pop_back(): + + pop_back(self) + + +ida_pro.svalvec_t.push_back(): + + push_back(self, x) + push_back(self) -> signed-ea-like-numeric-type & + + +ida_pro.svalvec_t.qclear(): + + qclear(self) + + +ida_pro.svalvec_t.reserve(): + + reserve(self, cnt) + + +ida_pro.svalvec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_pro.svalvec_t.size(): + + size(self) -> size_t + + +ida_pro.svalvec_t.swap(): + + swap(self, r) + + +ida_pro.svalvec_t.truncate(): + + truncate(self) + + class ida_pro.tid_array(): Proxy of C++ tid_array class @@ -40802,6 +42892,354 @@ ida_pro.uchar_array_frompointer(): uchar_array_frompointer(t) -> uchar_array +class ida_pro.uint64vec_t(): + + Proxy of C++ qvector<(unsigned long long)> class + + +ida_pro.uint64vec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_pro.uint64vec_t.at(): + + __getitem__(self, i) -> unsigned long long const & + + +ida_pro.uint64vec_t.begin(): + + begin(self) -> qvector< unsigned long long >::iterator + begin(self) -> qvector< unsigned long long >::const_iterator + + +ida_pro.uint64vec_t.capacity(): + + capacity(self) -> size_t + + +ida_pro.uint64vec_t.clear(): + + clear(self) + + +ida_pro.uint64vec_t.empty(): + + empty(self) -> bool + + +ida_pro.uint64vec_t.end(): + + end(self) -> qvector< unsigned long long >::iterator + end(self) -> qvector< unsigned long long >::const_iterator + + +ida_pro.uint64vec_t.erase(): + + erase(self, it) -> qvector< unsigned long long >::iterator + erase(self, first, last) -> qvector< unsigned long long >::iterator + + +ida_pro.uint64vec_t.extract(): + + extract(self) -> unsigned long long * + + +ida_pro.uint64vec_t.find(): + + find(self, x) -> qvector< unsigned long long >::iterator + find(self, x) -> qvector< unsigned long long >::const_iterator + + +ida_pro.uint64vec_t.has(): + + has(self, x) -> bool + + +ida_pro.uint64vec_t.inject(): + + inject(self, s, len) + + +ida_pro.uint64vec_t.insert(): + + insert(self, it, x) -> qvector< unsigned long long >::iterator + + +ida_pro.uint64vec_t.pop_back(): + + pop_back(self) + + +ida_pro.uint64vec_t.push_back(): + + push_back(self, x) + push_back(self) -> unsigned long long & + + +ida_pro.uint64vec_t.qclear(): + + qclear(self) + + +ida_pro.uint64vec_t.reserve(): + + reserve(self, cnt) + + +ida_pro.uint64vec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_pro.uint64vec_t.size(): + + size(self) -> size_t + + +ida_pro.uint64vec_t.swap(): + + swap(self, r) + + +ida_pro.uint64vec_t.truncate(): + + truncate(self) + + +class ida_pro.uintvec_t(): + + Proxy of C++ qvector<(unsigned int)> class + + +ida_pro.uintvec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_pro.uintvec_t.at(): + + __getitem__(self, i) -> unsigned int const & + + +ida_pro.uintvec_t.begin(): + + begin(self) -> qvector< unsigned int >::iterator + begin(self) -> qvector< unsigned int >::const_iterator + + +ida_pro.uintvec_t.capacity(): + + capacity(self) -> size_t + + +ida_pro.uintvec_t.clear(): + + clear(self) + + +ida_pro.uintvec_t.empty(): + + empty(self) -> bool + + +ida_pro.uintvec_t.end(): + + end(self) -> qvector< unsigned int >::iterator + end(self) -> qvector< unsigned int >::const_iterator + + +ida_pro.uintvec_t.erase(): + + erase(self, it) -> qvector< unsigned int >::iterator + erase(self, first, last) -> qvector< unsigned int >::iterator + + +ida_pro.uintvec_t.extract(): + + extract(self) -> unsigned int * + + +ida_pro.uintvec_t.find(): + + find(self, x) -> qvector< unsigned int >::iterator + find(self, x) -> qvector< unsigned int >::const_iterator + + +ida_pro.uintvec_t.has(): + + has(self, x) -> bool + + +ida_pro.uintvec_t.inject(): + + inject(self, s, len) + + +ida_pro.uintvec_t.insert(): + + insert(self, it, x) -> qvector< unsigned int >::iterator + + +ida_pro.uintvec_t.pop_back(): + + pop_back(self) + + +ida_pro.uintvec_t.push_back(): + + push_back(self, x) + push_back(self) -> unsigned int & + + +ida_pro.uintvec_t.qclear(): + + qclear(self) + + +ida_pro.uintvec_t.reserve(): + + reserve(self, cnt) + + +ida_pro.uintvec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_pro.uintvec_t.size(): + + size(self) -> size_t + + +ida_pro.uintvec_t.swap(): + + swap(self, r) + + +ida_pro.uintvec_t.truncate(): + + truncate(self) + + +class ida_pro.ulonglongvec_t(): + + Proxy of C++ qvector<(unsigned long long)> class + + +ida_pro.ulonglongvec_t.add_unique(): + + add_unique(self, x) -> bool + + +ida_pro.ulonglongvec_t.at(): + + __getitem__(self, i) -> unsigned long long const & + + +ida_pro.ulonglongvec_t.begin(): + + begin(self) -> qvector< unsigned long long >::iterator + begin(self) -> qvector< unsigned long long >::const_iterator + + +ida_pro.ulonglongvec_t.capacity(): + + capacity(self) -> size_t + + +ida_pro.ulonglongvec_t.clear(): + + clear(self) + + +ida_pro.ulonglongvec_t.empty(): + + empty(self) -> bool + + +ida_pro.ulonglongvec_t.end(): + + end(self) -> qvector< unsigned long long >::iterator + end(self) -> qvector< unsigned long long >::const_iterator + + +ida_pro.ulonglongvec_t.erase(): + + erase(self, it) -> qvector< unsigned long long >::iterator + erase(self, first, last) -> qvector< unsigned long long >::iterator + + +ida_pro.ulonglongvec_t.extract(): + + extract(self) -> unsigned long long * + + +ida_pro.ulonglongvec_t.find(): + + find(self, x) -> qvector< unsigned long long >::iterator + find(self, x) -> qvector< unsigned long long >::const_iterator + + +ida_pro.ulonglongvec_t.has(): + + has(self, x) -> bool + + +ida_pro.ulonglongvec_t.inject(): + + inject(self, s, len) + + +ida_pro.ulonglongvec_t.insert(): + + insert(self, it, x) -> qvector< unsigned long long >::iterator + + +ida_pro.ulonglongvec_t.pop_back(): + + pop_back(self) + + +ida_pro.ulonglongvec_t.push_back(): + + push_back(self, x) + push_back(self) -> unsigned long long & + + +ida_pro.ulonglongvec_t.qclear(): + + qclear(self) + + +ida_pro.ulonglongvec_t.reserve(): + + reserve(self, cnt) + + +ida_pro.ulonglongvec_t.resize(): + + resize(self, _newsize, x) + resize(self, _newsize) + + +ida_pro.ulonglongvec_t.size(): + + size(self) -> size_t + + +ida_pro.ulonglongvec_t.swap(): + + swap(self, r) + + +ida_pro.ulonglongvec_t.truncate(): + + truncate(self) + + class ida_pro.uval_array(): Proxy of C++ uval_array class @@ -40824,7 +43262,7 @@ ida_pro.uval_array_frompointer(): class ida_pro.uvalvec_t(): - Proxy of C++ qvector<(uval_t)> class + Proxy of C++ qvector<(unsigned-ea-like-numeric-type)> class ida_pro.uvalvec_t.add_unique(): @@ -40832,6 +43270,17 @@ ida_pro.uvalvec_t.add_unique(): add_unique(self, x) -> bool +ida_pro.uvalvec_t.at(): + + __getitem__(self, i) -> unsigned-ea-like-numeric-type & + + +ida_pro.uvalvec_t.begin(): + + begin(self) -> qvector< unsigned-ea-like-numeric-type >::iterator + begin(self) -> qvector< unsigned-ea-like-numeric-type >::const_iterator + + ida_pro.uvalvec_t.capacity(): capacity(self) -> size_t @@ -40847,6 +43296,29 @@ ida_pro.uvalvec_t.empty(): empty(self) -> bool +ida_pro.uvalvec_t.end(): + + end(self) -> qvector< unsigned-ea-like-numeric-type >::iterator + end(self) -> qvector< unsigned-ea-like-numeric-type >::const_iterator + + +ida_pro.uvalvec_t.erase(): + + erase(self, it) -> qvector< unsigned-ea-like-numeric-type >::iterator + erase(self, first, last) -> qvector< unsigned-ea-like-numeric-type >::iterator + + +ida_pro.uvalvec_t.extract(): + + extract(self) -> unsigned-ea-like-numeric-type * + + +ida_pro.uvalvec_t.find(): + + find(self, x) -> qvector< unsigned-ea-like-numeric-type >::iterator + find(self, x) -> qvector< unsigned-ea-like-numeric-type >::const_iterator + + ida_pro.uvalvec_t.has(): has(self, x) -> bool @@ -40857,11 +43329,22 @@ ida_pro.uvalvec_t.inject(): inject(self, s, len) +ida_pro.uvalvec_t.insert(): + + insert(self, it, x) -> qvector< unsigned-ea-like-numeric-type >::iterator + + ida_pro.uvalvec_t.pop_back(): pop_back(self) +ida_pro.uvalvec_t.push_back(): + + push_back(self, x) + push_back(self) -> unsigned-ea-like-numeric-type & + + ida_pro.uvalvec_t.qclear(): qclear(self) @@ -40916,7 +43399,7 @@ UTF-16 codepage. ida_pro.IDA_SDK_VERSION """ -IDA SDK v7.1. +IDA SDK v7.2. """ ida_pro.IDBDEC_ESCAPE @@ -44431,6 +46914,21 @@ ida_struct.member_t.has_union(): ida_struct.member_t.id: member_t_id_get(self) -> tid_t +ida_struct.member_t.is_baseclass(): + + is_baseclass(self) -> bool + + +ida_struct.member_t.is_destructor(): + + is_destructor(self) -> bool + + +ida_struct.member_t.is_dupname(): + + is_dupname(self) -> bool + + ida_struct.member_t.props: member_t_props_get(self) -> uint32 @@ -44718,11 +47216,26 @@ ida_struct.visit_stroff_fields(): === ida_struct EPYDOC INJECTIONS === +ida_struct.MF_BASECLASS +""" +a special member representing base class +""" + ida_struct.MF_BYTIL """ the member was created due to the type system """ +ida_struct.MF_DTOR +""" +a special member representing destructor +""" + +ida_struct.MF_DUPNAME +""" +duplicate name resolved with _N suffix (N==soff) +""" + ida_struct.MF_HASTI """ has type information? @@ -46485,6 +48998,22 @@ ida_typeinf.convert_pt_flags_to_hti(): @param pt_flags (C++: int) +ida_typeinf.copy_named_type(): + + copy_named_type(dsttil, srctil, name) -> uint32 + + + Copy a named type from one til to another. This function will copy the + specified type and all dependent types from the source type library to + the destination library. + + @param dsttil: Destination til. It must have orginal types enabled + (C++: til_t *) + @param srctil: Source til. (C++: const til_t *) + @param name: name of the type to copy (C++: const char *) + @return: ordinal number of the copied type. 0 means error + + ida_typeinf.copy_tinfo_t(): copy_tinfo_t(_this, r) @@ -47113,6 +49642,16 @@ ida_typeinf.gen_use_arg_tinfos(): @param has_delay_slot (C++: has_delay_slot_t *) +ida_typeinf.get_abi_name(): + + get_abi_name() -> ssize_t + + + Get ABI name. + + @return: length of the name (>=0) + + ida_typeinf.get_alias_target(): get_alias_target(ti, ordinal) -> uint32 @@ -47241,16 +49780,12 @@ ida_typeinf.get_full_type(): ida_typeinf.get_idainfo_by_type(): - get_idainfo_by_type(psize, pflags, mt, tif, alsize=None) -> bool + get_idainfo_by_type(tif) -> bool Extract information from a 'tinfo_t' . - @param psize: size of tif (C++: size_t *) - @param pflags: description of type using flags_t (C++: flags_t *) - @param mt: info for non-scalar types (C++: opinfo_t *) @param tif: the type to inspect (C++: const tinfo_t &) - @param alsize: alignment (C++: size_t *) ida_typeinf.get_idati(): @@ -47963,6 +50498,17 @@ ida_typeinf.is_type_sue(): @param t (C++: type_t) +ida_typeinf.is_type_tbyte(): + + is_type_tbyte(t) -> bool + + + See 'BTF_FLOAT' . + + + @param t (C++: type_t) + + ida_typeinf.is_type_typedef(): is_type_typedef(t) -> bool @@ -48292,13 +50838,13 @@ ida_typeinf.parse_decl(): Parse ONE declaration. If the input string contains more than one declaration, the first complete type declaration ( 'PT_TYP' ) or the - last variable declaration ( 'PT_VAR' ) will be used.name & type & - fields might be empty after the call! + last variable declaration ( 'PT_VAR' ) will be used.name & tif may be + empty after the call! @param tif: type info (C++: tinfo_t *) - @param til: type library to use (C++: til_t *) + @param til: type library to use. may be NULL (C++: til_t *) @param decl: C declaration to parse (C++: const char *) - @param flags: combination of Type parsing flags (C++: int) + @param flags: combination of Type parsing flags bits (C++: int) ida_typeinf.parse_decls(): @@ -48385,14 +50931,25 @@ ida_typeinf.ptr_type_data_t.based_ptr_size: ida_typeinf.ptr_type_data_t.closure: ptr_type_data_t_closure_get(self) -> tinfo_t +ida_typeinf.ptr_type_data_t.delta: + ptr_type_data_t_delta_get(self) -> int32 + ida_typeinf.ptr_type_data_t.is_code_ptr(): is_code_ptr(self) -> bool +ida_typeinf.ptr_type_data_t.is_shifted(): + + is_shifted(self) -> bool + + ida_typeinf.ptr_type_data_t.obj_type: ptr_type_data_t_obj_type_get(self) -> tinfo_t +ida_typeinf.ptr_type_data_t.parent: + ptr_type_data_t_parent_get(self) -> tinfo_t + ida_typeinf.ptr_type_data_t.swap(): swap(self, r) @@ -48581,6 +51138,19 @@ ida_typeinf.remove_tinfo_pointer(): @param til (C++: const til_t *) +ida_typeinf.replace_ordinal_typerefs(): + + replace_ordinal_typerefs(til, tif) -> int + + + Replace references to ordinal types by name references. This function + 'unties' the type from the current local type library and makes it + easier to export it. + + @param til: type library to use. may be NULL. (C++: til_t *) + @param tif: type to modify (in/out) (C++: tinfo_t *) + + ida_typeinf.resolve_typedef(): resolve_typedef(til, type) -> type_t const * @@ -48975,7 +51545,6 @@ ida_typeinf.tinfo_t.deserialize(): deserialize(self, til, ptype, pfields=None, pfldcmts=None) -> bool deserialize(self, til, ptype, pfields=None, pfldcmts=None) -> bool deserialize(self, til, type, fields, cmts=None) -> bool - deserialize(self, til, _type, _fields, _cmts=None) -> bool ida_typeinf.tinfo_t.dstr(): @@ -49178,6 +51747,16 @@ ida_typeinf.tinfo_t.has_details(): has_details(self) -> bool +ida_typeinf.tinfo_t.has_vftable(): + + has_vftable(self) -> bool + + +ida_typeinf.tinfo_t.is_anonymous_udt(): + + is_anonymous_udt(self) -> bool + + ida_typeinf.tinfo_t.is_arithmetic(): is_arithmetic(self) -> bool @@ -49338,6 +51917,11 @@ ida_typeinf.tinfo_t.is_decl_sue(): is_decl_sue(self) -> bool +ida_typeinf.tinfo_t.is_decl_tbyte(): + + is_decl_tbyte(self) -> bool + + ida_typeinf.tinfo_t.is_decl_typedef(): is_decl_typedef(self) -> bool @@ -49538,6 +52122,11 @@ ida_typeinf.tinfo_t.is_scalar(): is_scalar(self) -> bool +ida_typeinf.tinfo_t.is_shifted_ptr(): + + is_shifted_ptr(self) -> bool + + ida_typeinf.tinfo_t.is_signed(): is_signed(self) -> bool @@ -49563,6 +52152,11 @@ ida_typeinf.tinfo_t.is_sue(): is_sue(self) -> bool +ida_typeinf.tinfo_t.is_tbyte(): + + is_tbyte(self) -> bool + + ida_typeinf.tinfo_t.is_typeref(): is_typeref(self) -> bool @@ -49628,6 +52222,11 @@ ida_typeinf.tinfo_t.is_vararg_cc(): is_vararg_cc(self) -> bool +ida_typeinf.tinfo_t.is_vftable(): + + is_vftable(self) -> bool + + ida_typeinf.tinfo_t.is_void(): is_void(self) -> bool @@ -49658,6 +52257,11 @@ ida_typeinf.tinfo_t.remove_ptr_or_array(): remove_ptr_or_array(self) -> bool +ida_typeinf.tinfo_t.requires_qualifier(): + + requires_qualifier(self, name, offset) -> bool + + ida_typeinf.tinfo_t.serialize(): serialize(self, sudt_flags=SUDT_FAST|SUDT_TRUNC) -> PyObject * @@ -49958,6 +52562,11 @@ ida_typeinf.udt_member_t.clr_unaligned(): clr_unaligned(self) +ida_typeinf.udt_member_t.clr_vftable(): + + clr_vftable(self) + + ida_typeinf.udt_member_t.clr_virtbase(): clr_virtbase(self) @@ -49977,6 +52586,11 @@ ida_typeinf.udt_member_t.end(): ida_typeinf.udt_member_t.fda: udt_member_t_fda_get(self) -> uchar +ida_typeinf.udt_member_t.is_anonymous_udm(): + + is_anonymous_udm(self) -> bool + + ida_typeinf.udt_member_t.is_baseclass(): is_baseclass(self) -> bool @@ -49992,6 +52606,11 @@ ida_typeinf.udt_member_t.is_unaligned(): is_unaligned(self) -> bool +ida_typeinf.udt_member_t.is_vftable(): + + is_vftable(self) -> bool + + ida_typeinf.udt_member_t.is_virtbase(): is_virtbase(self) -> bool @@ -50018,6 +52637,11 @@ ida_typeinf.udt_member_t.set_unaligned(): set_unaligned(self) +ida_typeinf.udt_member_t.set_vftable(): + + set_vftable(self) + + ida_typeinf.udt_member_t.set_virtbase(): set_virtbase(self) @@ -50142,6 +52766,11 @@ ida_typeinf.udt_type_data_t.is_unaligned(): ida_typeinf.udt_type_data_t.is_union: udt_type_data_t_is_union_get(self) -> bool +ida_typeinf.udt_type_data_t.is_vftable(): + + is_vftable(self) -> bool + + ida_typeinf.udt_type_data_t.pack: udt_type_data_t_pack_get(self) -> uchar @@ -50734,6 +53363,13 @@ ida_typeinf.NTF_64BIT value is 64bit """ +ida_typeinf.NTF_CHKSYNC +""" +(set_numbered_type, set_named_type) + +check that synchronization to IDB passed OK +""" + ida_typeinf.NTF_FIXNAME """ (set_named_type, set_numbered_type only) @@ -51053,6 +53689,12 @@ get member by type. - in: udm->type - the desired member type. member types are compared with tinfo_t::equals_to() """ +ida_typeinf.STRMEM_VFTABLE +""" +can be combined with 'STRMEM_OFFSET' , 'STRMEM_AUTO' get vftable +instead of the base class +""" + ida_typeinf.SUDT_ALIGN """ to match the offsets and size info @@ -51113,6 +53755,11 @@ ida_typeinf.TAFLD_UNALIGNED field: unaligned field """ +ida_typeinf.TAFLD_VFTABLE +""" +field: ptr to virtual function table +""" + ida_typeinf.TAFLD_VIRTBASE """ field: virtual base (not supported yet) @@ -51148,6 +53795,11 @@ ida_typeinf.TAPTR_RESTRICT ptr: __restrict """ +ida_typeinf.TAPTR_SHIFTED +""" +ptr: __shifted(parent_struct, delta) +""" + ida_typeinf.TAUDT_CPPOBJ """ struct: a c++ object, not simple pod type @@ -51163,6 +53815,11 @@ ida_typeinf.TAUDT_UNALIGNED struct: unaligned struct """ +ida_typeinf.TAUDT_VFTABLE +""" +struct: is virtual function table +""" + ida_typeinf.TA_ORG_ARRDIM """ the original array dimension (append_dd) @@ -51173,6 +53830,11 @@ ida_typeinf.TA_ORG_TYPEDEF the original typedef name (simple string) """ +ida_typeinf.TCMP_ANYBASE +""" +accept any base class when casting +""" + ida_typeinf.TCMP_AUTOCAST """ can t1 be cast into t2 automatically? @@ -51208,6 +53870,11 @@ ida_typeinf.TCMP_MANCAST can t1 be cast into t2 manually? """ +ida_typeinf.TCMP_SKIPTHIS +""" +skip the first function argument in comparison +""" + ida_typeinf.TIL_ADD_ALREADY """ the base til was already added @@ -51454,16 +54121,20 @@ ida_ua.get_dtype_size(): ida_ua.get_immvals(): - get_immvals(ea, n) -> PyObject * + get_immvals(ea, n, F=0) -> PyObject * Get immediate values at the specified address. This function decodes instruction at the specified address or inspects the data item. It - finds immediate values and copies them to 'out'. + finds immediate values and copies them to 'out'. This function will + store the original value of the operands in 'out', unless the last + bits of 'F' are "...0 11111111", in which case the transformed values + (as needed for printing) will be stored instead. @param ea: address to analyze (C++: ea_t) @param n: number of operand (0.. UA_MAXOP -1), -1 means all operands (C++: int) + @param F: flags for the specified address (C++: flags_t) @return: number of immediate values (0..2* UA_MAXOP ) @@ -51477,6 +54148,20 @@ ida_ua.get_lookback(): IDP may use it as you like it. (TMS module uses it) +ida_ua.get_printable_immvals(): + + get_printable_immvals(ea, n, F=0) -> PyObject * + + + Get immediate ready-to-print values at the specified address + + @param ea: address to analyze (C++: ea_t) + @param n: number of operand (0.. UA_MAXOP -1), -1 means all operands + (C++: int) + @param F: flags for the specified address (C++: flags_t) + @return: number of immediate values (0..2* UA_MAXOP ) + + ida_ua.guess_table_address(): guess_table_address(insn) -> ea_t @@ -51606,6 +54291,11 @@ ida_ua.insn_t.insnpref: ida_ua.insn_t.ip: insn_t_ip_get(self) -> ea_t +ida_ua.insn_t.is_64bit(): + + is_64bit(self) -> bool + + ida_ua.insn_t.is_canon_insn(): is_canon_insn(self) -> bool @@ -51990,6 +54680,11 @@ ida_ua.outctx_base_t.set_comment_addr(): set_comment_addr(self, ea) +ida_ua.outctx_base_t.set_dlbind_opnd(): + + set_dlbind_opnd(self) + + ida_ua.outctx_base_t.set_gen_cmt(): set_gen_cmt(self, on=True) @@ -52317,6 +55012,11 @@ ida_ua.outctx_t.set_comment_addr(): set_comment_addr(self, ea) +ida_ua.outctx_t.set_dlbind_opnd(): + + set_dlbind_opnd(self) + + ida_ua.outctx_t.set_gen_cmt(): set_gen_cmt(self, on=True) @@ -52352,6 +55052,9 @@ ida_ua.outctx_t.term_outctx(): term_outctx(self, prefix=None) -> int +ida_ua.outctx_t.wif: + outctx_t_wif_get(self) -> printop_t + ida_ua.outctx_t__from_ptrval__(): outctx_t__from_ptrval__(ptrval) -> outctx_t @@ -52425,6 +55128,11 @@ Y WITH DIAERESIS) If both this, and FCBF_REPL are specified, this will take precedence """ +ida_ua.INSN_64BIT +""" +belongs to 64bit segment? +""" + ida_ua.INSN_MACRO """ macro instruction @@ -52719,6 +55427,17 @@ ida_xref.casevec_t.add_unique(): add_unique(self, x) -> bool +ida_xref.casevec_t.at(): + + __getitem__(self, i) -> qvector< signed-ea-like-numeric-type > const & + + +ida_xref.casevec_t.begin(): + + begin(self) -> qvector< qvector< signed-ea-like-numeric-type > >::iterator + begin(self) -> qvector< qvector< signed-ea-like-numeric-type > >::const_iterator + + ida_xref.casevec_t.capacity(): capacity(self) -> size_t @@ -52734,6 +55453,34 @@ ida_xref.casevec_t.empty(): empty(self) -> bool +ida_xref.casevec_t.end(): + + end(self) -> qvector< qvector< signed-ea-like-numeric-type > >::iterator + end(self) -> qvector< qvector< signed-ea-like-numeric-type > >::const_iterator + + +ida_xref.casevec_t.erase(): + + erase(self, it) -> qvector< qvector< signed-ea-like-numeric-type > >::iterator + erase(self, first, last) -> qvector< qvector< signed-ea-like-numeric-type > >::iterator + + +ida_xref.casevec_t.extract(): + + extract(self) -> qvector< signed-ea-like-numeric-type > * + + +ida_xref.casevec_t.find(): + + find(self, x) -> qvector< qvector< signed-ea-like-numeric-type > >::iterator + find(self, x) -> qvector< qvector< signed-ea-like-numeric-type > >::const_iterator + + +ida_xref.casevec_t.grow(): + + grow(self, x=qvector< signed-ea-like-numeric-type >()) + + ida_xref.casevec_t.has(): has(self, x) -> bool @@ -52744,11 +55491,22 @@ ida_xref.casevec_t.inject(): inject(self, s, len) +ida_xref.casevec_t.insert(): + + insert(self, it, x) -> qvector< qvector< signed-ea-like-numeric-type > >::iterator + + ida_xref.casevec_t.pop_back(): pop_back(self) +ida_xref.casevec_t.push_back(): + + push_back(self, x) + push_back(self) -> qvector< signed-ea-like-numeric-type > & + + ida_xref.casevec_t.qclear(): qclear(self) @@ -53533,7 +56291,7 @@ idc.atoa(): idc.attach_process(): - attach_process(pid, event_id) -> int + attach_process(pid=pid_t(-1), event_id=-1) -> int Attach the debugger to a running process. {Type, Asynchronous function @@ -54144,8 +56902,8 @@ idc.diff_trace_file(): idc.enable_bpt(): - enable_bpt(ea, enable) -> bool - enable_bpt(bptloc, enable) -> bool + enable_bpt(ea, enable=True) -> bool + enable_bpt(bptloc, enable=True) -> bool idc.enable_tracing(): @@ -55506,7 +58264,8 @@ idc.get_name_ea(): database is not consulted for them. This function works only with regular names. - @param _from (C++: ea_t) + @param _from: linear address where the name is used. if not + applicable, then should be BADADDR . (C++: ea_t) @param name: any name in the program or NULL (C++: const char *) @return: address of the name or BADADDR @@ -56431,7 +59190,7 @@ idc.load_and_run_plugin(): idc.load_debugger(): - load_debugger(nonnul_dbgname, use_remote) -> bool + load_debugger(dbgname, use_remote) -> bool idc.load_trace_file(): @@ -57225,7 +59984,7 @@ idc.select_thread(): idc.selector_by_name(): - Get segment by name + Get segment selector by name @param segname: name of segment @@ -57947,7 +60706,7 @@ idc.split_sreg_range(): idc.start_process(): - start_process(path, args, sdir) -> int + start_process(path=None, args=None, sdir=None) -> int Start a process in the debugger. {Type, Asynchronous function - @@ -58085,7 +60844,7 @@ idc.validate_idb_names(): idc.wait_for_next_event(): - wait_for_next_event(wfne, timeout_in_secs) -> dbg_event_code_t + wait_for_next_event(wfne, timeout) -> dbg_event_code_t Wait for the next event.This function (optionally) resumes the process @@ -58094,7 +60853,7 @@ idc.wait_for_next_event(): @param wfne: combination of Wait for debugger event flags constants (C++: int) - @param timeout_in_secs (C++: int) + @param timeout: number of seconds to wait, -1-infinity (C++: int) @return: either an event_id_t (if > 0), or a dbg_event_code_t (if <= 0) diff --git a/python.cpp b/python.cpp index 3d97cbf..458124a 100644 --- a/python.cpp +++ b/python.cpp @@ -70,6 +70,7 @@ static bool g_instance_initialized = false; // This instance of the plugin is th static int g_run_when = -1; static char g_run_script[QMAXPATH]; static char g_idapython_dir[QMAXPATH]; +static qstring requested_plugin_path; //------------------------------------------------------------------------- // Prototypes and forward declarations @@ -82,6 +83,8 @@ static char g_idapython_dir[QMAXPATH]; bool idaapi run(size_t); static PyObject *get_module_globals_from_path(const char *path); +//lint -e818 could be pointer to const + //------------------------------------------------------------------------- // This is a simple tracing code for debugging purposes. // It might evolve into a tracing facility for user scripts. @@ -90,23 +93,22 @@ static PyObject *get_module_globals_from_path(const char *path); #ifdef ENABLE_PYTHON_PROFILING #include "compile.h" #include "frameobject.h" - -int tracefunc(PyObject *obj, _frame *frame, int what, PyObject *arg) +static int tracefunc(PyObject *obj, _frame *frame, int what, PyObject *arg) { - PyObject *str; + PyObject *str; - /* Catch line change events. */ - /* Print the filename and line number */ - if ( what == PyTrace_LINE ) + /* Catch line change events. */ + /* Print the filename and line number */ + if ( what == PyTrace_LINE ) + { + str = PyObject_Str(frame->f_code->co_filename); + if ( str != NULL ) { - str = PyObject_Str(frame->f_code->co_filename); - if ( str ) - { - msg("PROFILING: %s:%d\n", PyString_AsString(str), frame->f_lineno); - Py_DECREF(str); - } + msg("PROFILING: %s:%d\n", PyString_AsString(str), frame->f_lineno); + Py_DECREF(str); } - return 0; + } + return 0; } #endif @@ -184,9 +186,9 @@ static execution_t execution; //#define LOG_EXEC 1 #ifdef LOG_EXEC -#define LEXEC(Format, ...) msg("IDAPython exec: " Format, __VA_ARGS__) +#define LEXEC(...) msg("IDAPython exec: " __VA_ARGS__) #else -#define LEXEC(Format, ...) +#define LEXEC(...) #endif //------------------------------------------------------------------------- @@ -267,11 +269,18 @@ bool execution_t::can_interrupt_current(time_t now) const int execution_t::on_trace(PyObject *obj, _frame *frame, int what, PyObject *arg) { LEXEC("on_trace() (steps=%d, nentries=%d)\n", - int(execution.steps_before_action), int(execution.entries.size())); + int(execution.steps_before_action), + int(execution.entries.size())); // we don't want to query for time at every trace event if ( execution.steps_before_action-- > 0 ) return 0; + if ( get_active_modal_widget() != NULL ) + { + LEXEC("on_trace()::a modal widget is active. Not showing the wait dialog.\n"); + return 0; + } + execution.reset_steps(); time_t now = time(NULL); LEXEC("on_trace()::now: %d\n", int(now)); @@ -338,6 +347,12 @@ void ida_export set_interruptible_state(bool interruptible) execution.set_interruptible(interruptible); } +//------------------------------------------------------------------------- +void ida_export prepare_programmatic_plugin_load(const char *path) +{ + requested_plugin_path = path; +} + //------------------------------------------------------------------------- //lint -esym(714,disable_script_timeout) Symbol not referenced idaman void ida_export disable_script_timeout() @@ -576,7 +591,7 @@ static int PyRunFile(const char *FileName) #endif PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *file_obj = PyFile_FromString((char*)FileName, "r"); //lint !e605 + PyObject *file_obj = PyFile_FromString((char*)FileName, "r"); //lint !e605 !e1776 PyObject *globals = get_module_globals(); if ( globals == NULL || file_obj == NULL ) { @@ -810,14 +825,13 @@ static bool idaapi IDAPython_extlang_call_func( if ( !ok ) break; - if ( imported_module ) + const char *final_modname = imported_module ? modname : S_MAIN; + module = PyImport_ImportModule(final_modname); + if ( module == NULL ) { - module = PyImport_ImportModule(modname); - } - else - { - module = PyImport_AddModule(S_MAIN); - QASSERT(30156, module != NULL); + errbuf->sprnt("couldn't import module %s", final_modname); + ok = false; + break; } PyObject *globals = PyModule_GetDict(module); @@ -1416,7 +1430,7 @@ static bool idaapi IDAPython_cli_find_completions( if ( py_fc == NULL ) return false; - newref_t py_res(PyObject_CallFunction(py_fc.o, "si", line, x)); //lint !e605 + newref_t py_res(PyObject_CallFunction(py_fc.o, "si", line, x)); //lint !e605 !e1776 if ( PyErr_Occurred() != NULL ) return false; return idapython_convert_cli_completions( @@ -1426,11 +1440,36 @@ static bool idaapi IDAPython_cli_find_completions( py_res); } +//------------------------------------------------------------------------- +static PyObject *get_module_globals_from_path_with_kind(const char *path, const char *kind) +{ + const char *fname = qbasename(path); + if ( fname != NULL ) + { + const char *ext = get_file_ext(fname); + if ( ext == NULL ) + ext = tail(fname); + else + --ext; + if ( ext > fname ) + { + int len = ext - fname; + qstring modname; + modname.sprnt("__%s__%*.*s", kind, len, len, fname); + return get_module_globals(modname.begin()); + } + } + return NULL; +} + //------------------------------------------------------------------------- static PyObject *get_module_globals_from_path(const char *path) { if ( (extlang_python.flags & EXTLANG_NS_AWARE) != 0 ) { + if ( requested_plugin_path == path ) + return get_module_globals_from_path_with_kind(path, PLG_SUBDIR); + char dirpath[QMAXPATH]; if ( qdirname(dirpath, sizeof(dirpath), path) ) { @@ -1439,22 +1478,7 @@ static PyObject *get_module_globals_from_path(const char *path) || streq(dirname, IDP_SUBDIR) || streq(dirname, LDR_SUBDIR) ) { - const char *fname = qbasename(path); - if ( fname != NULL ) - { - const char *ext = get_file_ext(fname); - if ( ext == NULL ) - ext = tail(fname); - else - --ext; - if ( ext > fname ) - { - int len = ext - fname; - qstring modname; - modname.sprnt("__%s__%*.*s", dirname, len, len, fname); - return get_module_globals(modname.begin()); - } - } + return get_module_globals_from_path_with_kind(path, dirname); } } } @@ -1464,15 +1488,15 @@ static PyObject *get_module_globals_from_path(const char *path) //------------------------------------------------------------------------- static const cli_t cli_python = { - sizeof(cli_t), - 0, - "Python", - "Python - IDAPython plugin", - "Enter any Python expression", - IDAPython_cli_execute_line, - NULL, - NULL, - IDAPython_cli_find_completions, + sizeof(cli_t), + 0, + "Python", + "Python - IDAPython plugin", + "Enter any Python expression", + IDAPython_cli_execute_line, + NULL, + NULL, + IDAPython_cli_find_completions, }; //------------------------------------------------------------------------- @@ -1480,9 +1504,9 @@ static const cli_t cli_python = idaman void ida_export enable_python_cli(bool enable) { if ( enable ) - install_command_interpreter(&cli_python); + install_command_interpreter(&cli_python); else - remove_command_interpreter(&cli_python); + remove_command_interpreter(&cli_python); } //------------------------------------------------------------------------ @@ -2018,21 +2042,21 @@ bool idaapi run(size_t arg) { switch ( arg ) { - case IDAPYTHON_RUNSTATEMENT: - IDAPython_RunStatement(); - break; - case IDAPYTHON_ENABLE_EXTLANG: - enable_extlang_python(true); - break; - case IDAPYTHON_DISABLE_EXTLANG: - enable_extlang_python(false); - break; - default: - warning("IDAPython: unknown plugin argument %d", int(arg)); - break; + case IDAPYTHON_RUNSTATEMENT: + IDAPython_RunStatement(); + break; + case IDAPYTHON_ENABLE_EXTLANG: + enable_extlang_python(true); + break; + case IDAPYTHON_DISABLE_EXTLANG: + enable_extlang_python(false); + break; + default: + warning("IDAPython: unknown plugin argument %d", int(arg)); + break; } } - catch(...) + catch(...) //lint !e1766 without preceding catch clause { warning("Exception in Python interpreter. Reloading..."); IDAPython_Term(); diff --git a/python/idaapi.py b/python/idaapi.py index 8e39a09..4ee2678 100644 --- a/python/idaapi.py +++ b/python/idaapi.py @@ -3,6 +3,11 @@ import sys ${IMPORTS} +# guerilla-patch a few unfortunate overrides +from ida_funcs import set_func_start +from ida_funcs import set_func_end +from ida_dbg import dbg_can_query + class idaapi_Cvar(object): def __init__(self): # prevent endless recursion diff --git a/python/idautils.py b/python/idautils.py index 6b25c94..0009519 100644 --- a/python/idautils.py +++ b/python/idautils.py @@ -118,29 +118,30 @@ def DataRefsFrom(ea): return refs(ea, ida_xref.get_first_dref_from, ida_xref.get_next_dref_from) +# Xref type names table +_ref_types = { + ida_xref.fl_U : 'Data_Unknown', + ida_xref.dr_O : 'Data_Offset', + ida_xref.dr_W : 'Data_Write', + ida_xref.dr_R : 'Data_Read', + ida_xref.dr_T : 'Data_Text', + ida_xref.dr_I : 'Data_Informational', + ida_xref.fl_CF : 'Code_Far_Call', + ida_xref.fl_CN : 'Code_Near_Call', + ida_xref.fl_JF : 'Code_Far_Jump', + ida_xref.fl_JN : 'Code_Near_Jump', + 20 : 'Code_User', + ida_xref.fl_F : 'Ordinary_Flow' +} + def XrefTypeName(typecode): """ Convert cross-reference type codes to readable names @param typecode: cross-reference type code """ - ref_types = { - 0 : 'Data_Unknown', - 1 : 'Data_Offset', - 2 : 'Data_Write', - 3 : 'Data_Read', - 4 : 'Data_Text', - 5 : 'Data_Informational', - 16 : 'Code_Far_Call', - 17 : 'Code_Near_Call', - 18 : 'Code_Far_Jump', - 19 : 'Code_Near_Jump', - 20 : 'Code_User', - 21 : 'Ordinary_Flow' - } - assert typecode in ref_types, "unknown reference type %d" % typecode - return ref_types[typecode] - + assert typecode in _ref_types, "unknown reference type %d" % typecode + return _ref_types[typecode] def _copy_xref(xref): """ Make a private copy of the xref class to preserve its contents """ diff --git a/python/idc.py b/python/idc.py index 771d770..7337eb5 100644 --- a/python/idc.py +++ b/python/idc.py @@ -68,7 +68,6 @@ import time import types import sys -__X64__ = sys.maxsize > 0xFFFFFFFF __EA64__ = ida_idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL WORDMASK = 0xFFFFFFFFFFFFFFFF if __EA64__ else 0xFFFFFFFF class DeprecatedIDCError(Exception): @@ -2358,8 +2357,6 @@ def get_next_seg(ea): else: return nextseg.start_ea - return BADADDR - def get_segm_start(ea): """ @@ -2604,7 +2601,7 @@ def set_segm_addressing(ea, bitness): def selector_by_name(segname): """ - Get segment by name + Get segment selector by name @param segname: name of segment @@ -3070,53 +3067,28 @@ def set_func_attr(ea, attr, value): FUNCATTR_START = 0 # readonly: function start address FUNCATTR_END = 4 # readonly: function end address FUNCATTR_FLAGS = 8 # function flags -FUNCATTR_FRAME = 12 # readonly: function frame id -FUNCATTR_FRSIZE = 16 # readonly: size of local variables -FUNCATTR_FRREGS = 20 # readonly: size of saved registers area -FUNCATTR_ARGSIZE = 24 # readonly: number of bytes purged from the stack -FUNCATTR_FPD = 28 # frame pointer delta -FUNCATTR_COLOR = 32 # function color code -FUNCATTR_OWNER = 12 # readonly: chunk owner (valid only for tail chunks) -FUNCATTR_REFQTY = 16 # readonly: number of chunk parents (valid only for tail chunks) +FUNCATTR_FRAME = 16 # readonly: function frame id +FUNCATTR_FRSIZE = 20 # readonly: size of local variables +FUNCATTR_FRREGS = 24 # readonly: size of saved registers area +FUNCATTR_ARGSIZE = 28 # readonly: number of bytes purged from the stack +FUNCATTR_FPD = 32 # frame pointer delta +FUNCATTR_COLOR = 36 # function color code +FUNCATTR_OWNER = 16 # readonly: chunk owner (valid only for tail chunks) +FUNCATTR_REFQTY = 20 # readonly: number of chunk parents (valid only for tail chunks) -if __X64__: - FUNCATTR_START = 0 - FUNCATTR_END = 4 - FUNCATTR_FLAGS = 8 - FUNCATTR_FRAME = 16 - FUNCATTR_FRSIZE = 20 - FUNCATTR_FRREGS = 24 - FUNCATTR_ARGSIZE = 28 - FUNCATTR_FPD = 32 - FUNCATTR_COLOR = 36 - FUNCATTR_OWNER = 16 - FUNCATTR_REFQTY = 20 - -# Redefining the constants for 64-bit +# Redefining the constants for ea64 if __EA64__: FUNCATTR_START = 0 FUNCATTR_END = 8 FUNCATTR_FLAGS = 16 - FUNCATTR_FRAME = 20 - FUNCATTR_FRSIZE = 28 - FUNCATTR_FRREGS = 36 - FUNCATTR_ARGSIZE = 40 - FUNCATTR_FPD = 48 - FUNCATTR_COLOR = 56 - FUNCATTR_OWNER = 20 - FUNCATTR_REFQTY = 28 - if __X64__: - FUNCATTR_START = 0 - FUNCATTR_END = 8 - FUNCATTR_FLAGS = 16 - FUNCATTR_FRAME = 24 - FUNCATTR_FRSIZE = 32 - FUNCATTR_FRREGS = 40 - FUNCATTR_ARGSIZE = 48 - FUNCATTR_FPD = 56 - FUNCATTR_COLOR = 64 - FUNCATTR_OWNER = 24 - FUNCATTR_REFQTY = 32 + FUNCATTR_FRAME = 24 + FUNCATTR_FRSIZE = 32 + FUNCATTR_FRREGS = 40 + FUNCATTR_ARGSIZE = 48 + FUNCATTR_FPD = 56 + FUNCATTR_COLOR = 64 + FUNCATTR_OWNER = 24 + FUNCATTR_REFQTY = 32 _FUNCATTRMAP = { FUNCATTR_START : (True, 'start_ea'), diff --git a/python/init.py b/python/init.py index 8f818e9..197adb0 100644 --- a/python/init.py +++ b/python/init.py @@ -47,8 +47,6 @@ except ImportError as e: print "\t%s" % p raise -# __EA64__ is set if IDA is running in 64-bit mode -__EA64__ = ida_idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL # ----------------------------------------------------------------------- # Take over the standard text outputs @@ -86,7 +84,7 @@ def runscript(script): def print_banner(): banner = [ "Python %s " % sys.version, - "IDAPython" + (" 64-bit" if __EA64__ else "") + " v%d.%d.%d %s (serial %d) (c) The IDAPython Team <idapython@googlegroups.com>" % IDAPYTHON_VERSION + "IDAPython" + (" 64-bit" if ida_idaapi.__EA64__ else "") + " v%d.%d.%d %s (serial %d) (c) The IDAPython Team <idapython@googlegroups.com>" % IDAPYTHON_VERSION ] sepline = '-' * (max([len(s) for s in banner])+1) diff --git a/pywraps.cpp b/pywraps.cpp index 4a99665..343e12d 100644 --- a/pywraps.cpp +++ b/pywraps.cpp @@ -86,6 +86,17 @@ ref_t ida_export PyW_SizeVecToPyList(const sizevec_t &vec) return ref_t(py_list); } +//--------------------------------------------------------------------------- +ref_t ida_export PyW_UvalVecToPyList(const uvalvec_t &vec) +{ + size_t n = vec.size(); + PYW_GIL_CHECK_LOCKED_SCOPE(); + newref_t py_list(PyList_New(n)); + for ( size_t i = 0; i < n; ++i ) + PyList_SetItem(py_list.o, i, Py_BuildValue(PY_BV_UVAL, bvuval_t(vec[i]))); + return ref_t(py_list); +} + //------------------------------------------------------------------------- static Py_ssize_t pyvar_walk_list( const ref_t &py_list, @@ -495,93 +506,92 @@ int ida_export pyvar_to_idcvar( // // INT64 // - case PY_ICID_INT64: - { - // Get the value attribute - ref_t attr(PyW_TryGetAttrString(py_var.o, S_PY_IDCCVT_VALUE_ATTR)); - if ( attr == NULL ) - return false; - idc_var->set_int64(PyLong_AsLongLong(attr.o)); - return CIP_OK; - } + case PY_ICID_INT64: + { + // Get the value attribute + ref_t attr(PyW_TryGetAttrString(py_var.o, S_PY_IDCCVT_VALUE_ATTR)); + if ( attr == NULL ) + return false; + idc_var->set_int64(PyLong_AsLongLong(attr.o)); + return CIP_OK; + } // // BYREF // - case PY_ICID_BYREF: - { - // BYREF always require this parameter - if ( gvar_sn == NULL ) - return CIP_FAILED; - - // Get the value attribute - ref_t attr(PyW_TryGetAttrString(py_var.o, S_PY_IDCCVT_VALUE_ATTR)); - if ( attr == NULL ) - return CIP_FAILED; - - // Create a global variable - char buf[MAXSTR]; - qsnprintf(buf, sizeof(buf), S_PY_IDC_GLOBAL_VAR_FMT, *gvar_sn); - idc_value_t *gvar = add_idc_gvar(buf); - // Convert the python value into the IDC global variable - bool ok = pyvar_to_idcvar(attr, gvar, gvar_sn) >= CIP_OK; - if ( ok ) + case PY_ICID_BYREF: { - (*gvar_sn)++; - // Create a reference to this global variable - create_idcv_ref(idc_var, gvar); + // BYREF always require this parameter + if ( gvar_sn == NULL ) + return CIP_FAILED; + + // Get the value attribute + ref_t attr(PyW_TryGetAttrString(py_var.o, S_PY_IDCCVT_VALUE_ATTR)); + if ( attr == NULL ) + return CIP_FAILED; + + // Create a global variable + char buf[MAXSTR]; + qsnprintf(buf, sizeof(buf), S_PY_IDC_GLOBAL_VAR_FMT, *gvar_sn); + idc_value_t *gvar = add_idc_gvar(buf); + // Convert the python value into the IDC global variable + bool ok = pyvar_to_idcvar(attr, gvar, gvar_sn) >= CIP_OK; + if ( ok ) + { + (*gvar_sn)++; + // Create a reference to this global variable + create_idcv_ref(idc_var, gvar); + } + return ok ? CIP_OK : CIP_FAILED; } - return ok ? CIP_OK : CIP_FAILED; - } // // OPAQUE // - case PY_ICID_OPAQUE: - { + case PY_ICID_OPAQUE: if ( !wrap_PyObject_ptr(py_var, idc_var) ) return CIP_FAILED; return CIP_OK_OPAQUE; - } // // Other objects // - default: - // A normal object? - newref_t py_dir(PyObject_Dir(py_var.o)); - Py_ssize_t size = PyList_Size(py_dir.o); - if ( py_dir == NULL || !PyList_Check(py_dir.o) || size == 0 ) - return CIP_FAILED; - // Create the IDC object - idcv_object(idc_var); - for ( Py_ssize_t i=0; i < size; i++ ) - { - borref_t item(PyList_GetItem(py_dir.o, i)); - const char *field_name = PyString_AsString(item.o); - if ( field_name == NULL ) - continue; - - size_t len = strlen(field_name); - - // Skip private attributes - if ( (len > 2 ) - && (strncmp(field_name, "__", 2) == 0 ) - && (strncmp(field_name+len-2, "__", 2) == 0) ) - { - continue; - } - - idc_value_t v; - // Get the non-private attribute from the object - newref_t attr(PyObject_GetAttrString(py_var.o, field_name)); - if ( attr == NULL - // Convert the attribute into an IDC value - || pyvar_to_idcvar(attr, &v, gvar_sn) < CIP_OK ) - { + default: + // A normal object? + newref_t py_dir(PyObject_Dir(py_var.o)); + Py_ssize_t size = PyList_Size(py_dir.o); + if ( py_dir == NULL || !PyList_Check(py_dir.o) || size == 0 ) return CIP_FAILED; - } + // Create the IDC object + idcv_object(idc_var); + for ( Py_ssize_t i=0; i < size; i++ ) + { + borref_t item(PyList_GetItem(py_dir.o, i)); + const char *field_name = PyString_AsString(item.o); + if ( field_name == NULL ) + continue; - // Store the attribute - set_idcv_attr(idc_var, field_name, v); - } + size_t len = strlen(field_name); + + // Skip private attributes + if ( (len > 2 ) + && (strncmp(field_name, "__", 2) == 0 ) + && (strncmp(field_name+len-2, "__", 2) == 0) ) + { + continue; + } + + idc_value_t v; + // Get the non-private attribute from the object + newref_t attr(PyObject_GetAttrString(py_var.o, field_name)); + if ( attr == NULL + // Convert the attribute into an IDC value + || pyvar_to_idcvar(attr, &v, gvar_sn) < CIP_OK ) + { + return CIP_FAILED; + } + + // Store the attribute + set_idcv_attr(idc_var, field_name, v); + } + break; } } return CIP_OK; @@ -611,187 +621,187 @@ int ida_export idcvar_to_pyvar( PYW_GIL_CHECK_LOCKED_SCOPE(); switch ( idc_var.vtype ) { - case VT_PVOID: - if ( *py_var == NULL ) - { - newref_t nr(PyCObject_FromVoidPtr(idc_var.pvoid, NULL)); - *py_var = nr; - } - else - { - return CIP_IMMUTABLE; - } - break; - - case VT_INT64: - { - bool as_pylong = (flags & PYWCVTF_INT64_AS_UNSIGNED_PYLONG) != 0; - if ( as_pylong ) + case VT_PVOID: + if ( *py_var == NULL ) { - QASSERT(30513, *py_var == NULL); // recycling not supported in this case - *py_var = newref_t(PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) idc_var.i64)); - return CIP_OK; + newref_t nr(PyCObject_FromVoidPtr(idc_var.pvoid, NULL)); + *py_var = nr; } else { - // Recycle? - if ( *py_var != NULL ) + return CIP_IMMUTABLE; + } + break; + + case VT_INT64: + { + bool as_pylong = (flags & PYWCVTF_INT64_AS_UNSIGNED_PYLONG) != 0; + if ( as_pylong ) { - // Recycling an int64 object? - int t = get_pyidc_cvt_type(py_var->o); - if ( t != PY_ICID_INT64 ) - return CIP_IMMUTABLE; // Cannot recycle immutable object - // Update the attribute - PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64)); + QASSERT(30513, *py_var == NULL); // recycling not supported in this case + *py_var = newref_t(PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) idc_var.i64)); return CIP_OK; } - ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_INT64)); - if ( py_cls == NULL ) - return CIP_FAILED; - *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, PyLong_FromLongLong(idc_var.i64), NULL)); - if ( PyW_GetError() || *py_var == NULL ) - return CIP_FAILED; + else + { + // Recycle? + if ( *py_var != NULL ) + { + // Recycling an int64 object? + int t = get_pyidc_cvt_type(py_var->o); + if ( t != PY_ICID_INT64 ) + return CIP_IMMUTABLE; // Cannot recycle immutable object + // Update the attribute + PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64)); + return CIP_OK; + } + ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_INT64)); + if ( py_cls == NULL ) + return CIP_FAILED; + *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, PyLong_FromLongLong(idc_var.i64), NULL)); + if ( PyW_GetError() || *py_var == NULL ) + return CIP_FAILED; + } + break; } - break; - } - case VT_STR: - if ( *py_var == NULL ) - { - const qstring &s = idc_var.qstr(); - *py_var = newref_t(PyString_FromStringAndSize(s.begin(), s.length())); - break; - } - else - return CIP_IMMUTABLE; // Cannot recycle immutable object - case VT_LONG: - // Cannot recycle immutable objects - if ( *py_var != NULL ) - return CIP_IMMUTABLE; - *py_var = newref_t(cvt_to_pylong(idc_var.num)); - break; - case VT_FLOAT: - if ( *py_var == NULL ) - { - double x; - if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 1 ) - INTERR(30160); - - *py_var = newref_t(PyFloat_FromDouble(x)); - break; - } - else - return CIP_IMMUTABLE; - - case VT_REF: - { + case VT_STR: if ( *py_var == NULL ) { - ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_BYREF)); - if ( py_cls == NULL ) - return CIP_FAILED; - - // Create a byref object with None value. We populate it later - *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, Py_None, NULL)); - if ( PyW_GetError() || *py_var == NULL ) - return CIP_FAILED; - } - int t = get_pyidc_cvt_type(py_var->o); - if ( t != PY_ICID_BYREF ) - return CIP_FAILED; - - // Dereference - // (Since we are not using VREF_COPY flag, we can safely const_cast) - idc_value_t *dref_v = deref_idcv(const_cast<idc_value_t *>(&idc_var), VREF_LOOP); - if ( dref_v == NULL ) - return CIP_FAILED; - - // Can we recycle the object? - ref_t new_py_val(PyW_TryGetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR)); - if ( new_py_val != NULL ) - { - // Recycle - t = idcvar_to_pyvar(*dref_v, &new_py_val); - - // Success? Nothing more to be done - if ( t == CIP_OK ) - return CIP_OK; - - // Clear it so we don't recycle it - new_py_val = ref_t(); - } - // Try to convert (not recycle) - if ( idcvar_to_pyvar(*dref_v, &new_py_val) != CIP_OK ) - return CIP_FAILED; - - // Update the attribute - PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, new_py_val.o); - break; - } - - // Can convert back into a Python object or Python dictionary - // (Depending if py_var will be recycled and it was a dictionary) - case VT_OBJ: - { - // Check if this IDC object has __cvt_id__ and the __idc_cvt_value__ fields - idc_value_t idc_val; - if ( get_idcv_attr(&idc_val, &idc_var, S_PY_IDCCVT_ID_ATTR) == eOk - && get_idcv_attr(&idc_val, &idc_var, S_PY_IDCCVT_VALUE_ATTR) == eOk ) - { - // Extract the object - *py_var = borref_t((PyObject *) idc_val.pvoid); - return CIP_OK_OPAQUE; - } - ref_t obj; - bool is_dict = false; - - // Need to create a new object? - if ( *py_var == NULL ) - { - // Get skeleton class reference - ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_APPCALL_SKEL_OBJ)); - if ( py_cls == NULL ) - return CIP_FAILED; - - // Call constructor - obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL)); - if ( PyW_GetError() || obj == NULL ) - return CIP_FAILED; + const qstring &s = idc_var.qstr(); + *py_var = newref_t(PyString_FromStringAndSize(s.begin(), s.length())); + break; } else - { - // Recycle existing variable - obj = *py_var; - if ( PyDict_Check(obj.o) ) - is_dict = true; - } - - // Walk the IDC attributes and store into python - for ( const char *attr_name = first_idcv_attr(&idc_var); - attr_name != NULL; - attr_name = next_idcv_attr(&idc_var, attr_name) ) - { - // Get the attribute - idc_value_t v; - get_idcv_attr(&v, &idc_var, attr_name, true); - - // Convert attribute to a python value (recursively) - ref_t py_attr; - int cvt = idcvar_to_pyvar(v, &py_attr); - if ( cvt <= CIP_IMMUTABLE ) - return CIP_FAILED; - if ( is_dict ) - PyDict_SetItemString(obj.o, attr_name, py_attr.o); - else - PyObject_SetAttrString(obj.o, attr_name, py_attr.o); - } - *py_var = obj; + return CIP_IMMUTABLE; // Cannot recycle immutable object + case VT_LONG: + // Cannot recycle immutable objects + if ( *py_var != NULL ) + return CIP_IMMUTABLE; + *py_var = newref_t(cvt_to_pylong(idc_var.num)); break; - } - // Unhandled type - default: - *py_var = ref_t(); - return CIP_FAILED; + case VT_FLOAT: + if ( *py_var == NULL ) + { + double x; + if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 1 ) + INTERR(30160); + + *py_var = newref_t(PyFloat_FromDouble(x)); + break; + } + else + return CIP_IMMUTABLE; + + case VT_REF: + { + if ( *py_var == NULL ) + { + ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_BYREF)); + if ( py_cls == NULL ) + return CIP_FAILED; + + // Create a byref object with None value. We populate it later + *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, Py_None, NULL)); + if ( PyW_GetError() || *py_var == NULL ) + return CIP_FAILED; + } + int t = get_pyidc_cvt_type(py_var->o); + if ( t != PY_ICID_BYREF ) + return CIP_FAILED; + + // Dereference + // (Since we are not using VREF_COPY flag, we can safely const_cast) + idc_value_t *dref_v = deref_idcv(const_cast<idc_value_t *>(&idc_var), VREF_LOOP); + if ( dref_v == NULL ) + return CIP_FAILED; + + // Can we recycle the object? + ref_t new_py_val(PyW_TryGetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR)); + if ( new_py_val != NULL ) + { + // Recycle + t = idcvar_to_pyvar(*dref_v, &new_py_val); + + // Success? Nothing more to be done + if ( t == CIP_OK ) + return CIP_OK; + + // Clear it so we don't recycle it + new_py_val = ref_t(); + } + // Try to convert (not recycle) + if ( idcvar_to_pyvar(*dref_v, &new_py_val) != CIP_OK ) + return CIP_FAILED; + + // Update the attribute + PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, new_py_val.o); + break; + } + + // Can convert back into a Python object or Python dictionary + // (Depending if py_var will be recycled and it was a dictionary) + case VT_OBJ: + { + // Check if this IDC object has __cvt_id__ and the __idc_cvt_value__ fields + idc_value_t idc_val; + if ( get_idcv_attr(&idc_val, &idc_var, S_PY_IDCCVT_ID_ATTR) == eOk + && get_idcv_attr(&idc_val, &idc_var, S_PY_IDCCVT_VALUE_ATTR) == eOk ) + { + // Extract the object + *py_var = borref_t((PyObject *) idc_val.pvoid); + return CIP_OK_OPAQUE; + } + ref_t obj; + bool is_dict = false; + + // Need to create a new object? + if ( *py_var == NULL ) + { + // Get skeleton class reference + ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_APPCALL_SKEL_OBJ)); + if ( py_cls == NULL ) + return CIP_FAILED; + + // Call constructor + obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL)); + if ( PyW_GetError() || obj == NULL ) + return CIP_FAILED; + } + else + { + // Recycle existing variable + obj = *py_var; + if ( PyDict_Check(obj.o) ) + is_dict = true; + } + + // Walk the IDC attributes and store into python + for ( const char *attr_name = first_idcv_attr(&idc_var); + attr_name != NULL; + attr_name = next_idcv_attr(&idc_var, attr_name) ) + { + // Get the attribute + idc_value_t v; + get_idcv_attr(&v, &idc_var, attr_name, true); + + // Convert attribute to a python value (recursively) + ref_t py_attr; + int cvt = idcvar_to_pyvar(v, &py_attr); + if ( cvt <= CIP_IMMUTABLE ) + return CIP_FAILED; + if ( is_dict ) + PyDict_SetItemString(obj.o, attr_name, py_attr.o); + else + PyObject_SetAttrString(obj.o, attr_name, py_attr.o); + } + *py_var = obj; + break; + } + // Unhandled type + default: + *py_var = ref_t(); + return CIP_FAILED; } return CIP_OK; } @@ -1034,7 +1044,7 @@ static ref_t get_idaapi_attr_by_id(const int class_id) return ref_t(); // Some class names. The array is parallel with the PY_CLSID_xxx consts - static const char *class_names[]= + static const char *class_names[] = { "PyIdc_cvt_int64__", "object_t", @@ -1092,7 +1102,7 @@ ref_t ida_export PyW_TryImportModule(const char *name) PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t result(PyImport_ImportModule(name)); if ( result == NULL && PyErr_Occurred() ) - PyErr_Clear(); + PyErr_Clear(); return result; } @@ -2119,6 +2129,29 @@ ref_t ida_export try_create_swig_wrapper(ref_t mod, const char *clsname, void *c return res; } +//------------------------------------------------------------------------- +ssize_t ida_export get_callable_arg_count(ref_t callable) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + newref_t py_module(PyImport_ImportModule("inspect")); + ssize_t cnt = -1; + if ( py_module != NULL ) + { + ref_t py_fun = PyW_TryGetAttrString(py_module.o, "getargspec"); + if ( py_fun != NULL ) + { + newref_t py_tuple(PyObject_CallFunctionObjArgs(py_fun.o, callable.o, NULL)); + if ( PyTuple_Check(py_tuple.o) ) + { + borref_t py_args(PyTuple_GetItem(py_tuple.o, 0)); + if ( py_args != NULL && PySequence_Check(py_args.o) ) + cnt = PySequence_Length(py_args.o); + } + } + } + return cnt; +} + //------------------------------------------------------------------------- typedef qvector<module_callbacks_t> modules_callbacks_t; static modules_callbacks_t modules_callbacks; diff --git a/pywraps.hpp b/pywraps.hpp index b2caade..bcf9d76 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -42,17 +42,7 @@ struct switch_info_t; // mov %edx,0x4(%esp) // call 2d <_Z3barPv+0x16> -#ifdef __X64__ #define PTR2U64(Binding) (uint64(Binding)) -#else -#define PTR2U64(Binding) (uint64(uint32(Binding))) -#endif - -#if defined(__LINUX__) || defined(__MAC__) -#define exported __attribute__((visibility("default"))) -#else -#define exported -#endif //------------------------------------------------------------------------ #define S_IDA_IDAAPI_MODNAME "ida_idaapi" @@ -101,6 +91,7 @@ static const char S_ON_FIND_COMPLETIONS[] = "OnFindCompletions"; static const char S_ON_CREATE[] = "OnCreate"; static const char S_ON_POPUP[] = "OnPopup"; static const char S_ON_HINT[] = "OnHint"; +static const char S_ON_EDGE_HINT[] = "OnEdgeHint"; static const char S_ON_POPUP_MENU[] = "OnPopupMenu"; static const char S_ON_EDIT_LINE[] = "OnEditLine"; static const char S_ON_INSERT_LINE[] = "OnInsertLine"; @@ -358,45 +349,45 @@ struct ref_vec_t : public qvector<ref_t> // Tries to import a module and swallows the exception if it fails and returns NULL // Return value: New reference. -exported ref_t ida_export PyW_TryImportModule(const char *name); +idaman ref_t ida_export PyW_TryImportModule(const char *name); // Tries to get an attribute and swallows the exception if it fails and returns NULL -exported ref_t ida_export PyW_TryGetAttrString(PyObject *py_var, const char *attr); +idaman ref_t ida_export PyW_TryGetAttrString(PyObject *py_var, const char *attr); // Converts a Python number (LONGLONG or normal integer) to an IDC variable (VT_LONG or VT_INT64) -exported bool ida_export PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var); +idaman bool ida_export PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var); // Returns a qstring from a Python attribute string -exported bool ida_export PyW_GetStringAttr( +idaman bool ida_export PyW_GetStringAttr( PyObject *py_obj, const char *attr_name, qstring *str); // Converts a Python number to an uint64 and indicates whether the number was a long number -exported bool ida_export PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL); +idaman bool ida_export PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL); // Checks if an Python object can be treated like a sequence -exported bool ida_export PyW_IsSequenceType(PyObject *obj); +idaman bool ida_export PyW_IsSequenceType(PyObject *obj); // Returns an error string from the last exception (and clears it) -exported bool ida_export PyW_GetError(qstring *out = NULL, bool clear_err = true); +idaman bool ida_export PyW_GetError(qstring *out = NULL, bool clear_err = true); // If an error occurred (it calls PyGetError) it displays it and return TRUE // This function is used when calling callbacks -exported bool ida_export PyW_ShowCbErr(const char *cb_name); +idaman bool ida_export PyW_ShowCbErr(const char *cb_name); // Utility function to create linked class instances -exported ref_t ida_export create_linked_class_instance(const char *modname, const char *clsname, void *lnk); +idaman ref_t ida_export create_linked_class_instance(const char *modname, const char *clsname, void *lnk); // Returns the string representation of a PyObject -exported bool ida_export PyW_ObjectToString(PyObject *obj, qstring *out); +idaman bool ida_export PyW_ObjectToString(PyObject *obj, qstring *out); // Utility function to convert a python object to an IDC object // and sets a python exception on failure. -exported bool ida_export pyvar_to_idcvar_or_error(const ref_t &py_obj, idc_value_t *idc_obj); +idaman bool ida_export pyvar_to_idcvar_or_error(const ref_t &py_obj, idc_value_t *idc_obj); // Creates and initializes an IDC exception -exported error_t ida_export PyW_CreateIdcException(idc_value_t *res, const char *msg); +idaman error_t ida_export PyW_CreateIdcException(idc_value_t *res, const char *msg); // // Conversion functions @@ -405,7 +396,7 @@ exported error_t ida_export PyW_CreateIdcException(idc_value_t *res, const char #define PYWCVTF_INT64_AS_UNSIGNED_PYLONG 0x2 // don't wrap int64 into 'PyIdc_cvt_int64__' objects, but make them 'long' instead // Converts from IDC to Python -exported bool ida_export pyw_convert_idc_args( +idaman bool ida_export pyw_convert_idc_args( const idc_value_t args[], int nargs, ref_vec_t &pargs, @@ -414,7 +405,7 @@ exported bool ida_export pyw_convert_idc_args( // Converts from IDC to Python // We support converting VT_REF IDC variable types -exported int ida_export idcvar_to_pyvar( +idaman int ida_export idcvar_to_pyvar( const idc_value_t &idc_var, ref_t *py_var, uint32 flags=0); @@ -422,41 +413,42 @@ exported int ida_export idcvar_to_pyvar( //------------------------------------------------------------------------- // Converts Python variable to IDC variable // gvar_sn is used in case the Python object was a created from a call to idcvar_to_pyvar and the IDC object was a VT_REF -exported int ida_export pyvar_to_idcvar( +idaman int ida_export pyvar_to_idcvar( const ref_t &py_var, idc_value_t *idc_var, int *gvar_sn = NULL); //------------------------------------------------------------------------- // Walks a Python list or Sequence and calls the callback -exported Py_ssize_t ida_export pyvar_walk_list( +idaman Py_ssize_t ida_export pyvar_walk_list( PyObject *py_list, int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud)=NULL, void *ud = NULL); -// Converts a sizevec_t to a Python list object -exported ref_t ida_export PyW_SizeVecToPyList(const sizevec_t &vec); +// Converts a vector to a Python list object +idaman ref_t ida_export PyW_SizeVecToPyList(const sizevec_t &vec); +idaman ref_t ida_export PyW_UvalVecToPyList(const uvalvec_t &vec); // Converts a Python list, to a vector of the given type. // An exception will be raised in case: // - py_list is not a sequence // - a member of py_list cannot be converted to the numeric target type -exported Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_list); -exported Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list); -exported Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list); +idaman Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_list); +idaman Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list); +idaman Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list); //------------------------------------------------------------------------- -exported bool ida_export PyWStringOrNone_Check(PyObject *tp); +idaman bool ida_export PyWStringOrNone_Check(PyObject *tp); //------------------------------------------------------------------------- #include <idd.hpp> -exported PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &ranges); +idaman PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &ranges); //------------------------------------------------------------------------- -exported void ida_export PyW_register_compiled_form(PyObject *py_form); +idaman void ida_export PyW_register_compiled_form(PyObject *py_form); //------------------------------------------------------------------------- -exported void ida_export PyW_unregister_compiled_form(PyObject *py_form); +idaman void ida_export PyW_unregister_compiled_form(PyObject *py_form); //--------------------------------------------------------------------------- // notify_when() @@ -487,7 +479,7 @@ public: bool notify_va(int slot, va_list va); pywraps_notify_when_t() : in_notify(false) {} }; -exported bool ida_export add_notify_when(int when, PyObject *py_callable); +idaman bool ida_export add_notify_when(int when, PyObject *py_callable); // void hexrays_clear_python_cfuncptr_t_references(void); @@ -594,7 +586,17 @@ private: lookup_entries_t entries; }; -extern exported lookup_info_t ida_export_data pycim_lookup_info; +#ifdef __NT__ + #ifdef PLUGIN_SUBMODULE + #define plugin_export_data __declspec(dllimport) + #else + #define plugin_export_data __declspec(dllexport) + #endif +#else // unix + #define plugin_export_data __attribute__((visibility("default"))) +#endif + +extern lookup_info_t plugin_export_data pycim_lookup_info; //------------------------------------------------------------------------- struct pycim_callback_id_t @@ -710,7 +712,6 @@ class py_customidamemo_t // View events void on_view_mouse_moved(const view_mouse_event_t *event); - int get_py_method_arg_count(char *method_name); // View events that are bound with 'set_custom_viewer_handler()'. static void idaapi s_on_view_mouse_moved( @@ -786,8 +787,8 @@ T *view_extract_this(PyObject *self) //------------------------------------------------------------------------- #include <typeinf.hpp> #define DECL_REG_UNREG_REFCOUNTED(Type) \ - exported void ida_export til_register_python_##Type##_instance(Type *inst); \ - exported void ida_export til_deregister_python_##Type##_instance(Type *inst); + idaman void ida_export til_register_python_##Type##_instance(Type *inst); \ + idaman void ida_export til_deregister_python_##Type##_instance(Type *inst); DECL_REG_UNREG_REFCOUNTED(tinfo_t); DECL_REG_UNREG_REFCOUNTED(ptr_type_data_t); DECL_REG_UNREG_REFCOUNTED(array_type_data_t); @@ -803,17 +804,20 @@ struct py_timer_ctx_t qtimer_t timer_id; PyObject *pycallback; }; -exported py_timer_ctx_t *ida_export python_timer_new(PyObject *py_callback); -exported void ida_export python_timer_del(py_timer_ctx_t *t); +idaman py_timer_ctx_t *ida_export python_timer_new(PyObject *py_callback); +idaman void ida_export python_timer_del(py_timer_ctx_t *t); //------------------------------------------------------------------------- -exported ref_t ida_export try_create_swig_wrapper(ref_t mod, const char *clsname, void *cobj); +idaman ref_t ida_export try_create_swig_wrapper(ref_t mod, const char *clsname, void *cobj); + +//------------------------------------------------------------------------- +idaman ssize_t ida_export get_callable_arg_count(ref_t callable); //------------------------------------------------------------------------- // Useful for small operations that must not be interrupted: e.g., when // wrapping an insn_t into a SWiG proxy object, or when destroying // such an instance from the kernel. Use 'uninterruptible_op_t' if you can. -exported void ida_export set_interruptible_state(bool interruptible); +idaman void ida_export set_interruptible_state(bool interruptible); struct uninterruptible_op_t { uninterruptible_op_t() { set_interruptible_state(false); } @@ -821,25 +825,11 @@ struct uninterruptible_op_t }; // //------------------------------------------------------------------------- -// class py_custom_data_type_t; -// class py_custom_data_format_t; -// typedef void py_custom_data_type_t_unregisterer_t(py_custom_data_type_t *inst); -// typedef void py_custom_data_format_t_unregisterer_t(py_custom_data_format_t *inst); -// exported void ida_export register_py_custom_data_type_and_format_unregisterer( -// py_custom_data_type_t_unregisterer_t cdt_unregisterer, -// py_custom_data_format_t_unregisterer_t cdf_unregisterer); -// exported void ida_export register_py_custom_data_type_instance(py_custom_data_type_t *inst); -// exported void ida_export register_py_custom_data_format_instance(py_custom_data_format_t *inst); -// exported void ida_export unregister_py_custom_data_type_instance(py_custom_data_type_t *inst); -// exported void ida_export unregister_py_custom_data_format_instance(py_custom_data_format_t *inst); -// exported py_custom_data_type_t *py_custom_data_type_cast(data_type_t *inst); -// exported py_custom_data_format_t *py_custom_data_format_cast(data_format_t *inst); - -exported bool ida_export idapython_hook_to_notification_point( +idaman bool ida_export idapython_hook_to_notification_point( hook_type_t hook_type, hook_cb_t *cb, void *user_data); -exported bool ida_export idapython_unhook_from_notification_point( +idaman bool ida_export idapython_unhook_from_notification_point( hook_type_t hook_type, hook_cb_t *cb, void *user_data); @@ -847,7 +837,7 @@ exported bool ida_export idapython_unhook_from_notification_point( #define unhook_from_notification_point USE_IDAPYTHON_UNHOOK_FROM_NOTIFICATION_POINT //------------------------------------------------------------------------- -exported bool ida_export idapython_convert_cli_completions( +idaman bool ida_export idapython_convert_cli_completions( qstrvec_t *out_completions, int *out_match_start, int *out_match_end, @@ -861,7 +851,9 @@ struct module_callbacks_t void (*term) (void); }; DECLARE_TYPE_AS_MOVABLE(module_callbacks_t); -exported void register_module_lifecycle_callbacks( +idaman void register_module_lifecycle_callbacks( const module_callbacks_t &cbs); +idaman void ida_export prepare_programmatic_plugin_load(const char *path); + #endif // __PYWRAPS_HPP__ diff --git a/pywraps/py_bytes.py b/pywraps/py_bytes.py index 8331425..5344a06 100644 --- a/pywraps/py_bytes.py +++ b/pywraps/py_bytes.py @@ -47,7 +47,6 @@ doYwrd=create_yword doZwrd=create_zword do_data_ex=create_data do_unknown=del_items -@bc695redef def do_unknown_range(ea, size, flags): return del_items(ea, flags, size) # swap 2 last args dwrdflag=dword_flag @@ -88,10 +87,8 @@ get_flags_novalue=get_flags get_hidden_area=get_hidden_range get_hidden_area_num=get_hidden_range_num get_hidden_area_qty=get_hidden_range_qty -@bc695redef def get_many_bytes(ea, size): return get_bytes(ea, size) -@bc695redef def get_many_bytes_ex(ea, size): return get_bytes_and_mask(ea, size) get_max_ascii_length=get_max_strlit_length @@ -180,7 +177,6 @@ def get_opinfo(*args): else: # 7.00: buf, ea, n, flags buf, ea, n, flags = args return _ida_bytes.get_opinfo(buf, ea, n, flags) -@bc695redef def doASCI(ea, length): import ida_netnode return create_data(ea, FF_STRLIT, length, ida_netnode.BADNODE) @@ -222,7 +218,7 @@ stroffflag=stroff_flag struflag=stru_flag wordflag=word_flag invalidate_visea_cache=ida_idaapi._BC695.false_p -@bc695redef_with_pydoc(op_stroff.__doc__) +@bc695redef def op_stroff(*args): insn, n, path, path_len, delta = args import ida_ua diff --git a/pywraps/py_dbg.hpp b/pywraps/py_dbg.hpp index d47c060..3ca665e 100644 --- a/pywraps/py_dbg.hpp +++ b/pywraps/py_dbg.hpp @@ -76,13 +76,13 @@ public: bool hook() { return idapython_hook_to_notification_point(HT_DBG, DBG_Callback, this); } bool unhook() { return idapython_unhook_from_notification_point(HT_DBG, DBG_Callback, this); } - static int store_int(int rc, const debug_event_t *, int *warn) + static ssize_t store_int(int rc, const debug_event_t *, int *warn) { *warn = rc; return 0; } - static int store_int(int rc, thid_t, ea_t, int *warn) + static ssize_t store_int(int rc, thid_t, ea_t, int *warn) { *warn = rc; return 0; @@ -98,7 +98,7 @@ ssize_t idaapi DBG_Callback(void *ud, int notification_code, va_list va) class DBG_Hooks *proxy = (class DBG_Hooks *)ud; debug_event_t *event; - int ret = 0; + ssize_t ret = 0; try { diff --git a/pywraps/py_dbg.py b/pywraps/py_dbg.py index 04b8909..f6373dd 100644 --- a/pywraps/py_dbg.py +++ b/pywraps/py_dbg.py @@ -59,7 +59,6 @@ def send_dbg_command(command): #<pycode_BC695(py_dbg)> import ida_idd -@bc695redef def get_process_info(n, pi): pis = ida_idd.procinfo_vec_t() cnt = get_processes(pis) @@ -68,8 +67,6 @@ def get_process_info(n, pi): pi.name = pis[n].name pi.pid = pis[n].pid return pi.pid - -@bc695redef def get_process_qty(): pis = ida_idd.procinfo_vec_t() return get_processes(pis) diff --git a/pywraps/py_expr.hpp b/pywraps/py_expr.hpp index c313ab6..b1ee6a2 100644 --- a/pywraps/py_expr.hpp +++ b/pywraps/py_expr.hpp @@ -127,7 +127,7 @@ static bool py_add_idc_func( const idc_values_t &defvals, int flags) { - ext_idcfunc_t desc = { name, (idc_func_t *)fp_ptr, args, defvals.begin(), defvals.size(), flags }; + ext_idcfunc_t desc = { name, (idc_func_t *)fp_ptr, args, defvals.begin(), (int)defvals.size(), flags }; return add_idc_func(desc); } diff --git a/pywraps/py_expr.py b/pywraps/py_expr.py index f59f78e..a8b382c 100644 --- a/pywraps/py_expr.py +++ b/pywraps/py_expr.py @@ -138,7 +138,6 @@ VarCopy=copy_idcv VarDelAttr=del_idcv_attr VarDeref=deref_idcv VarFirstAttr=first_idcv_attr -@bc695redef def VarGetAttr(obj, attr, res, may_use_getattr=False): return get_idcv_attr(res, obj, attr, may_use_getattr) VarGetClassName=get_idcv_class_name @@ -155,20 +154,15 @@ VarSetAttr=set_idcv_attr VarSetSlice=set_idcv_slice VarString2=idcv_string VarSwap=swap_idcvs -@bc695redef def calc_idc_expr(where, expr, res): return eval_idc_expr(res, where, expr) -@bc695redef def calcexpr(where, expr, res): return eval_expr(res, where, expr) -@bc695redef def dosysfile(complain_if_no_file, fname): return exec_system_script(fname, complain_if_no_file) -@bc695redef def execute(line): return eval_idc_snippet(None, line) py_set_idc_func_ex=py_add_idc_func -@bc695redef def set_idc_func_ex(name, fp=None, args=(), flags=0): return add_idc_func(name, fp, args, (), flags) #</pycode_BC695(py_expr)> diff --git a/pywraps/py_frame.py b/pywraps/py_frame.py index 5081506..8b4f240 100644 --- a/pywraps/py_frame.py +++ b/pywraps/py_frame.py @@ -4,6 +4,7 @@ add_auto_stkpnt2=add_auto_stkpnt # in fact, we cannot simulate add_stkvar[23] here, because we simply # don't have the insn_t object -- and no way of retrieving it, either, # since cmd is gone +@bc695redef def get_stkvar(*args): if len(args) == 2: import ida_ua @@ -11,6 +12,8 @@ def get_stkvar(*args): else: insn, op, v = args return _ida_frame.get_stkvar(insn, op, v) + +@bc695redef def get_frame_part(*args): import ida_funcs if isinstance(args[0], ida_funcs.func_t): # 6.95: pfn, part, range diff --git a/pywraps/py_funcs.hpp b/pywraps/py_funcs.hpp index e918c64..ccde749 100644 --- a/pywraps/py_funcs.hpp +++ b/pywraps/py_funcs.hpp @@ -14,14 +14,14 @@ def get_fchunk_referer(ea, idx): */ static ea_t get_fchunk_referer(ea_t ea, size_t idx) { - func_t *pfn = get_fchunk(ea); - if ( pfn == NULL ) - return BADADDR; - func_parent_iterator_t dummy(pfn); // read referer info - if ( idx >= pfn->refqty || pfn->referers == NULL ) - return BADADDR; - else - return pfn->referers[idx]; + func_t *pfn = get_fchunk(ea); + if ( pfn == NULL ) + return BADADDR; + func_parent_iterator_t dummy(pfn); // read referer info + if ( idx >= pfn->refqty || pfn->referers == NULL ) + return BADADDR; + else + return pfn->referers[idx]; } //----------------------------------------------------------------------- diff --git a/pywraps/py_funcs.py b/pywraps/py_funcs.py index 8dbc3d7..4c029ad 100644 --- a/pywraps/py_funcs.py +++ b/pywraps/py_funcs.py @@ -1,18 +1,27 @@ #<pycode(py_funcs)> +import ida_idaapi +@ida_idaapi.replfun +def calc_thunk_func_target(*args): + if len(args) == 2: + pfn, rawptr = args + target, fptr = calc_thunk_func_target.func_dict["orig"](pfn) + import ida_pro + ida_pro.ea_pointer.frompointer(rawptr).assign(fptr) + return target + else: + return calc_thunk_func_target.func_dict["orig"](*args) #</pycode(py_funcs)> #<pycode_BC695(py_funcs)> FUNC_STATIC=FUNC_STATICDEF add_regarg2=add_regarg clear_func_struct=lambda *args: True -@bc695redef def del_func_cmt(pfn, rpt): set_func_cmt(pfn, "", rpt) func_parent_iterator_set2=func_parent_iterator_set func_setend=set_func_end func_setstart=set_func_start func_tail_iterator_set2=func_tail_iterator_set -@bc695redef def get_func_limits(pfn, limits): import ida_range rs = ida_range.rangeset_t() diff --git a/pywraps/py_graph.hpp b/pywraps/py_graph.hpp index b2583af..aaa4ef0 100644 --- a/pywraps/py_graph.hpp +++ b/pywraps/py_graph.hpp @@ -12,15 +12,16 @@ protected: private: enum { - GRCODE_HAVE_USER_HINT = 0x00010000, - GRCODE_HAVE_CLICKED = 0x00020000, - GRCODE_HAVE_DBL_CLICKED = 0x00040000, - GRCODE_HAVE_GOTFOCUS = 0x00080000, - GRCODE_HAVE_LOSTFOCUS = 0x00100000, - GRCODE_HAVE_CHANGED_CURRENT = 0x00200000, - GRCODE_HAVE_CREATING_GROUP = 0x00400000, - GRCODE_HAVE_DELETING_GROUP = 0x00800000, - GRCODE_HAVE_GROUP_VISIBILITY = 0x01000000, + GRCODE_HAVE_HINT = 0x00010000, + GRCODE_HAVE_EDGE_HINT = 0x00020000, + GRCODE_HAVE_CLICKED = 0x00040000, + GRCODE_HAVE_DBL_CLICKED = 0x00080000, + GRCODE_HAVE_GOTFOCUS = 0x00100000, + GRCODE_HAVE_LOSTFOCUS = 0x00200000, + GRCODE_HAVE_CHANGED_CURRENT = 0x00400000, + GRCODE_HAVE_CREATING_GROUP = 0x00800000, + GRCODE_HAVE_DELETING_GROUP = 0x01000000, + GRCODE_HAVE_GROUP_VISIBILITY = 0x02000000, }; struct nodetext_cache_t { @@ -55,7 +56,7 @@ private: // static callback static ssize_t idaapi s_callback(void *obj, int code, va_list va) -{ + { // don't perform sanity check for 'grcode_destroyed', since if we called // Close() on this object, it'll have been marked for later deletion in the // UI, and thus when we end up here, the view has already been destroyed. @@ -83,7 +84,9 @@ private: // Retrieves the hint for the user-defined graph // Calls Python and expects a string or None - int on_user_hint(mutable_graph_t *, int mousenode, int /*mouseedge_src*/, int /*mouseedge_dst*/, char **hint); + int on_hint(char **hint, int node); + int on_edge_hint(char **hint, int src, int dest); + int _on_hint_epilog(char **hint, ref_t result); // graph is being destroyed void on_graph_destroyed(mutable_graph_t * /*g*/ = NULL) @@ -233,7 +236,7 @@ private: { TWidget *view; if ( pycim_lookup_info.find_by_py_view(&view, this) ) - display_widget(view, WOPN_TAB|WOPN_MENU); + display_widget(view, WOPN_TAB); } void jump_to_node(int nid) @@ -282,7 +285,7 @@ private: this->self = borref_t(self); graph_viewer_t *pview = create_graph_viewer(title, id, s_callback, this, 0); this->self = ref_t(); - display_widget(pview, WOPN_TAB | WOPN_MENU); + display_widget(pview, WOPN_TAB); newref_t ret(PyObject_CallMethod(self, "hook", NULL)); if ( pview != NULL ) viewer_fit_window(pview); @@ -379,7 +382,8 @@ void py_graph_t::collect_class_callbacks_ids(pycim_callbacks_ids_t *out) out->add(S_ON_GETTEXT, 0); out->add(S_M_EDGES, -1); out->add(S_M_NODES, -1); - out->add(S_ON_HINT, GRCODE_HAVE_USER_HINT); + out->add(S_ON_HINT, GRCODE_HAVE_HINT); + out->add(S_ON_EDGE_HINT, GRCODE_HAVE_EDGE_HINT); out->add(S_ON_CLICK, GRCODE_HAVE_CLICKED); out->add(S_ON_DBL_CLICK, GRCODE_HAVE_DBL_CLICKED); out->add(S_ON_SELECT, GRCODE_HAVE_CHANGED_CURRENT); @@ -508,25 +512,34 @@ bool py_graph_t::on_user_text(mutable_graph_t * /*g*/, int node, const char **st } //------------------------------------------------------------------------- -int py_graph_t::on_user_hint(mutable_graph_t *, int mousenode, int /*mouseedge_src*/, int /*mouseedge_dst*/, char **hint) +int py_graph_t::on_hint(char **hint, int node) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_HINT, "i", node)); + PyW_ShowCbErr(S_ON_HINT); + return _on_hint_epilog(hint, result); +} + +//------------------------------------------------------------------------- +int py_graph_t::on_edge_hint(char **hint, int src, int dest) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_EDGE_HINT, "ii", src, dest)); + PyW_ShowCbErr(S_ON_EDGE_HINT); + return _on_hint_epilog(hint, result); +} + +//------------------------------------------------------------------------- +int py_graph_t::_on_hint_epilog(char **hint, ref_t result) { // 'hint' must be allocated by qalloc() or qstrdup() // out: 0-use default hint, 1-use proposed hint - - // We dispatch hints over nodes only - if ( mousenode == -1 ) - return 0; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_HINT, "i", mousenode)); - PyW_ShowCbErr(S_ON_HINT); bool ok = result != NULL && PyString_Check(result.o); if ( ok ) *hint = qstrdup(PyString_AsString(result.o)); - return ok; // use our hint + return ok; } - //------------------------------------------------------------------------- ssize_t py_graph_t::gr_callback(int code, va_list va) { @@ -600,18 +613,18 @@ ssize_t py_graph_t::gr_callback(int code, va_list va) break; // case grcode_user_hint: - if ( has_callback(GRCODE_HAVE_USER_HINT) ) { mutable_graph_t *g = va_arg(va, mutable_graph_t *); - int mousenode = va_arg(va, int); - int mouseedge_src = va_arg(va, int); - int mouseedge_dest = va_arg(va, int); - char **hint = va_arg(va, char **); - ret = on_user_hint(g, mousenode, mouseedge_src, mouseedge_dest, hint); - } - else - { - ret = 0; + int node = va_arg(va, int); + int src = va_arg(va, int); + int dest = va_arg(va, int); + char **hint = va_arg(va, char **); + if ( node == -1 && has_callback(GRCODE_HAVE_EDGE_HINT) ) + ret = on_edge_hint(hint, src, dest); + else if ( node >= 0 && has_callback(GRCODE_HAVE_HINT) ) + ret = on_hint(hint, node); + else + ret = 0; } break; // diff --git a/pywraps/py_graph.py b/pywraps/py_graph.py index add5856..d2dad98 100644 --- a/pywraps/py_graph.py +++ b/pywraps/py_graph.py @@ -44,6 +44,8 @@ class GraphViewer(ida_kernwin.CustomIDAMemo): def AddEdge(self, src_node, dest_node): """Creates an edge between two given node ids""" + assert src_node < len(self._nodes), "Source node %d is out of bounds" % src_node + assert dest_node < len(self._nodes), "Destination node %d is out of bounds" % dest_node self._edges.append( (src_node, dest_node) ) def Clear(self): @@ -166,6 +168,14 @@ class GraphViewer(ida_kernwin.CustomIDAMemo): # """ # return "hint for " + str(node_id) # +# def OnEdgeHint(self, src, dst): +# """ +# Triggered when the graph viewer wants to retrieve hint text associated with a edge +# +# @return: None if no hint is avail or a string designating the hint +# """ +# return "hint for edge %d -> %d" % (src, dst) +# # def OnClose(self): # """Triggered when the graph viewer window is being closed # @return: None diff --git a/pywraps/py_hexrays.hpp b/pywraps/py_hexrays.hpp index ca5da06..aeff661 100644 --- a/pywraps/py_hexrays.hpp +++ b/pywraps/py_hexrays.hpp @@ -26,7 +26,7 @@ static void debug_hexrays_ctree(const char *format, ...) // The hexrays+IDAPython term sequence goes as follows: // - hexrays is unloaded before IDAPython // - we receive the notification about hexrays going away and: -// + call hexrays_clear_python_clearable_references(); +// + call hexrays_unloading__clear_python_clearable_references(); // + set 'hexdsp = exit_time_dummy_hexdsp' (an NOP hexdsp) // - we receive 'ui_term', and // + set 'hexdsp = init_time_dummy_hexdsp' @@ -113,241 +113,14 @@ static int hexrays_python_intcall(ref_t fct, ref_t args) //--------------------------------------------------------------------- static bool idaapi __python_custom_viewer_popup_item_callback(void *ud) -{ - PYW_GIL_GET; - - int ret; - borref_t fct((PyObject *)ud); - newref_t nil(NULL); - ret = hexrays_python_intcall(fct, nil); - return ret ? true : false; -} - -//--------------------------------------------------------------------- -static ssize_t idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_list va) { PYW_GIL_GET; - ssize_t ret; + int ret; borref_t fct((PyObject *)ud); - switch ( event ) - { - case hxe_maturity: - ///< Ctree maturity level is being changed. - ///< cfunc_t *cfunc - ///< ctree_maturity_t new_maturity - { - cfunc_t *arg0 = va_arg(va, cfunc_t *); - ctree_maturity_t arg1 = va_argi(va, ctree_maturity_t); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 )); - newref_t args(Py_BuildValue("(iOi)", event, arg0obj.o, arg1)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_interr: - ///< Internal error has occurred. - ///< int errcode - { - int arg0 = va_argi(va, int); - newref_t args(Py_BuildValue("(ii)", event, arg0)); - ret = hexrays_python_intcall(fct, args); - } - break; - - case hxe_print_func: - ///< Printing ctree and generating text. - ///< cfunc_t *cfunc - ///< vc_printer_t *vp - ///< Returns: 1 if text has been generated by the plugin - { - cfunc_t *arg0 = va_arg(va, cfunc_t *); - vc_printer_t *arg1 = va_arg(va, vc_printer_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 )); - newref_t arg1obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg1), SWIGTYPE_p_vc_printer_t, 0 )); - newref_t args(Py_BuildValue("(iOO)", event, arg0obj.o, arg1obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - - case hxe_func_printed: - ///< Function text has been generated. Plugins may - ///< modify the text in \ref sv. - ///< cfunc_t *cfunc - { - cfunc_t *arg0 = va_arg(va, cfunc_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - - // User interface related events: - case hxe_open_pseudocode: - ///< New pseudocode view has been opened. - ///< vdui_t *vu - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_switch_pseudocode: - ///< Existing pseudocode view has been reloaded - ///< with a new function. Its text has not been - ///< refreshed yet, only cfunc and mba pointers are ready. - ///< vdui_t *vu - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_refresh_pseudocode: - ///< Existing pseudocode text has been refreshed. - ///< vdui_t *vu - ///< See also hxe_text_ready, which happens earlier - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_close_pseudocode: - ///< Pseudocode view is being closed. - ///< vdui_t *vu - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_keyboard: - ///< Keyboard has been hit. - ///< vdui_t *vu - ///< int key_code (VK_...) - ///< int shift_state - ///< Should return: 1 if the event has been handled - { - vdui_t *arg0 = va_arg(va, vdui_t *); - int arg1 = va_argi(va, int); - int arg2 = va_argi(va, int); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iOii)", event, arg0obj.o, arg1, arg2)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_right_click: - ///< Mouse right click. We can add menu items now. - ///< vdui_t *vu - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_double_click: - ///< Mouse double click. - ///< vdui_t *vu - ///< int shift_state - ///< Should return: 1 if the event has been handled - { - vdui_t *arg0 = va_arg(va, vdui_t *); - int arg1 = va_argi(va, int); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iOi)", event, arg0obj.o, arg1)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_curpos: - ///< Current cursor position has been changed. - ///< (for example, by left-clicking or using keyboard) - ///< vdui_t *vu - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_create_hint: - ///< Create a hint for the current item. - ///< vdui_t *vu - ///< qstring *result_hint - ///< int *implines - ///< Possible return values: - ///< 0: the event has not been handled - ///< 1: hint has been created (should set *implines to nonzero as well) - ///< 2: hint has been created but the standard hints must be - ///< appended by the decompiler - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = 0; - ref_t resultobj = hexrays_python_call(fct, args); - if ( PyTuple_Check(resultobj.o) && PyTuple_Size(resultobj.o) == 3 ) - { - borref_t i0 = PyTuple_GetItem(resultobj.o, 0); - borref_t i1 = PyTuple_GetItem(resultobj.o, 1); - borref_t i2 = PyTuple_GetItem(resultobj.o, 2); - if ( PyInt_Check(i0.o) && PyString_Check(i1.o) && PyInt_Check(i2.o) ) - { - qstring *result_hint = va_arg(va, qstring *); - char *buf; - Py_ssize_t bufsize; - if ( PyString_AsStringAndSize(i1.o, &buf, &bufsize) > -1 ) - { - ret = PyInt_AsLong(i0.o); - qstring tmp(buf, bufsize); - result_hint->swap(tmp); - int *implines = va_arg(va, int *); - *implines = PyInt_AsLong(i2.o); - } - } - } - } - break; - case hxe_text_ready: - ///< Decompiled text is ready. - ///< vdui_t *vu - ///< This event can be used to modify the output text (sv). - ///< The text uses regular color codes (see lines.hpp) - ///< COLOR_ADDR is used to store pointers to ctree elements - { - vdui_t *arg0 = va_arg(va, vdui_t *); - newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); - newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_intcall(fct, args); - } - break; - case hxe_populating_popup: - ///< Populating popup menu. We can add menu items now. - ///< TWidget *widget - ///< TPopupMenu *popup_handle - ///< vdui_t *vu - { - TWidget *widget = va_arg(va, TWidget *); - TPopupMenu *pp = va_arg(va, TPopupMenu*); - vdui_t *vdui = va_arg(va, vdui_t *); - newref_t py_widget(SWIG_NewPointerObj(SWIG_as_voidptr(widget), SWIGTYPE_p_TWidget, 0)); - newref_t py_popup(SWIG_NewPointerObj(SWIG_as_voidptr(pp), SWIGTYPE_p_TPopupMenu, 0)); - newref_t py_vdui(SWIG_NewPointerObj(SWIG_as_voidptr(vdui), SWIGTYPE_p_vdui_t, 0 )); - newref_t py_args(Py_BuildValue("(iOOO)", event, py_widget.o, py_popup.o, py_vdui.o)); - ret = hexrays_python_intcall(fct, py_args); - } - break; - default: - //~ msg("IDAPython: Unknown event `%u' occurred\n", event); - ret = 0; - break; - } - - return ret; + newref_t nil(NULL); + ret = hexrays_python_intcall(fct, nil); + return ret ? true : false; } //------------------------------------------------------------------------- @@ -374,9 +147,9 @@ DECLARE_TYPE_AS_MOVABLE(hx_clearable_t); typedef qvector<hx_clearable_t> hx_clearables_t; static hx_clearables_t python_clearables; -void hexrays_clear_python_clearable_references(void) +void hexrays_unloading__clear_python_clearable_references(void) { - debug_hexrays_ctree("hexrays_clear_python_clearable_references()\n"); + debug_hexrays_ctree("hexrays_unloading__clear_python_clearable_references()\n"); for ( size_t i = 0, n = python_clearables.size(); i < n; ++i ) { const hx_clearable_t &hxc = python_clearables[i]; @@ -449,16 +222,16 @@ hx_clearable_type_t hexrays_is_registered_python_clearable_instance( //------------------------------------------------------------------------- cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf) { - try - { - cfuncptr_t cfunc = decompile(pfn, hf); - return cfunc; - } - catch(...) - { - error("Hex-Rays Python: decompiler threw an exception.\n"); - } - return cfuncptr_t(0); + try + { + cfuncptr_t cfunc = decompile(pfn, hf); + return cfunc; + } + catch(...) + { + error("Hex-Rays Python: decompiler threw an exception.\n"); + } + return cfuncptr_t(0); } //------------------------------------------------------------------------- @@ -505,6 +278,7 @@ inline bool hexdsp_inited() } //------------------------------------------------------------------------- +static void hexrays_unloading__unhook_hooks(void); static ssize_t idaapi ida_hexrays_ui_notification(void *, int code, va_list va) { switch ( code ) @@ -521,12 +295,17 @@ static ssize_t idaapi ida_hexrays_ui_notification(void *, int code, va_list va) case ui_plugin_unloading: if ( hexdsp != NULL && hexdsp != init_time_dummy_hexdsp ) { - // Make sure all the refcounted objects are cleared right away. const plugin_info_t *pi = va_arg(va, plugin_info_t *); if ( is_hexrays_plugin(pi) ) { QASSERT(30500, hexdsp != exit_time_dummy_hexdsp); - hexrays_clear_python_clearable_references(); + + // Make sure all the refcounted objects are cleared right away. + hexrays_unloading__clear_python_clearable_references(); + + // Make sure all hooks are unhooked + hexrays_unloading__unhook_hooks(); + hexdsp = exit_time_dummy_hexdsp; } } @@ -564,30 +343,6 @@ bool py_init_hexrays_plugin(int flags=0) return hexdsp_inited() || init_hexrays_plugin(flags); } -//--------------------------------------------------------------------- -bool py_install_hexrays_callback(PyObject *hx_cblist_callback) -{ - PYW_GIL_GET; - if ( install_hexrays_callback(__hexrays_python_callback, hx_cblist_callback) ) - { - Py_INCREF(hx_cblist_callback); - return true; - } - return false; -} - -//--------------------------------------------------------------------- -int py_remove_hexrays_callback(PyObject *hx_cblist_callback) -{ - PYW_GIL_GET; - int result, i; - result = remove_hexrays_callback(__hexrays_python_callback, hx_cblist_callback); - for ( i = 0; i < result; i++ ) - Py_DECREF(hx_cblist_callback); - - return result; -} - cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf); //------------------------------------------------------------------------- diff --git a/pywraps/py_hexrays.py b/pywraps/py_hexrays.py index e73f314..fe2183b 100644 --- a/pywraps/py_hexrays.py +++ b/pywraps/py_hexrays.py @@ -257,119 +257,6 @@ lvar_t.is_spoiled_var = property(lvar_t.is_spoiled_var) lvar_t.is_mapdst_var = property(lvar_t.is_mapdst_var) # dictify all dict-like types - -def _map___iter__(self): - """ Iterate over dictionary keys. """ - return self.iterkeys() - -def _map___getitem__(self, key): - """ Returns the value associated with the provided key. """ - if not isinstance(key, self.keytype): - raise KeyError('type of key should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) - if key not in self: - raise KeyError('key not found') - return self.second(self.find(key)) - -def _map___setitem__(self, key, value): - """ Returns the value associated with the provided key. """ - if not isinstance(key, self.keytype): - raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) - if not isinstance(value, self.valuetype): - raise KeyError('type of `value` should be ' + repr(self.valuetype) + ' but got ' + type(value)) - self.insert(key, value) - return - -def _map___delitem__(self, key): - """ Removes the value associated with the provided key. """ - if not isinstance(key, self.keytype): - raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) - if key not in self: - raise KeyError('key not found') - self.erase(self.find(key)) - return - -def _map___contains__(self, key): - """ Returns true if the specified key exists in the . """ - if not isinstance(key, self.keytype): - raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) - if self.find(key) != self.end(): - return True - return False - -def _map_clear(self): - self.clear() - return - -def _map_copy(self): - ret = {} - for k in self.iterkeys(): - ret[k] = self[k] - return ret - -def _map_get(self, key, default=None): - if key in self: - return self[key] - return default - -def _map_iterkeys(self): - iter = self.begin() - while iter != self.end(): - yield self.first(iter) - iter = self.next(iter) - return - -def _map_itervalues(self): - iter = self.begin() - while iter != self.end(): - yield self.second(iter) - iter = self.next(iter) - return - -def _map_iteritems(self): - iter = self.begin() - while iter != self.end(): - yield (self.first(iter), self.second(iter)) - iter = self.next(iter) - return - -def _map_keys(self): - return list(self.iterkeys()) - -def _map_values(self): - return list(self.itervalues()) - -def _map_items(self): - return list(self.iteritems()) - -def _map_has_key(self, key): - return key in self - -def _map_pop(self, key): - """ Sets the value associated with the provided key. """ - if not isinstance(key, self.keytype): - raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) - if key not in self: - raise KeyError('key not found') - ret = self[key] - del self[key] - return ret - -def _map_popitem(self): - """ Sets the value associated with the provided key. """ - if len(self) == 0: - raise KeyError('key not found') - key = self.keys()[0] - return (key, self.pop(key)) - -def _map_setdefault(self, key, default=None): - """ Sets the value associated with the provided key. """ - if not isinstance(key, self.keytype): - raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) - if key in self: - return self[key] - self[key] = default - return default - def _map_as_dict(maptype, name, keytype, valuetype): maptype.keytype = keytype @@ -393,29 +280,141 @@ def _map_as_dict(maptype, name, keytype, valuetype): maptype.erase = lambda self, *args: self.__erase(self, *args) maptype.clear = lambda self, *args: self.__clear(self, *args) maptype.size = lambda self, *args: self.__size(self, *args) + + def _map___iter__(self): + """ Iterate over dictionary keys. """ + return self.iterkeys() maptype.__iter__ = _map___iter__ + + def _map___getitem__(self, key): + """ Returns the value associated with the provided key. """ + if not isinstance(key, self.keytype): + raise KeyError('type of key should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) + if key not in self: + raise KeyError('key not found') + return self.second(self.find(key)) maptype.__getitem__ = _map___getitem__ + + def _map___setitem__(self, key, value): + """ Returns the value associated with the provided key. """ + if not isinstance(key, self.keytype): + raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) + if not isinstance(value, self.valuetype): + raise KeyError('type of `value` should be ' + repr(self.valuetype) + ' but got ' + type(value)) + self.insert(key, value) + return maptype.__setitem__ = _map___setitem__ + + def _map___delitem__(self, key): + """ Removes the value associated with the provided key. """ + if not isinstance(key, self.keytype): + raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) + if key not in self: + raise KeyError('key not found') + self.erase(self.find(key)) + return maptype.__delitem__ = _map___delitem__ + + def _map___contains__(self, key): + """ Returns true if the specified key exists in the . """ + if not isinstance(key, self.keytype): + raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) + if self.find(key) != self.end(): + return True + return False maptype.__contains__ = _map___contains__ + + def _map_clear(self): + self.clear() + return maptype.clear = _map_clear + + def _map_copy(self): + ret = {} + for k in self.iterkeys(): + ret[k] = self[k] + return ret maptype.copy = _map_copy + + def _map_get(self, key, default=None): + if key in self: + return self[key] + return default maptype.get = _map_get + + def _map_iterkeys(self): + iter = self.begin() + while iter != self.end(): + yield self.first(iter) + iter = self.next(iter) + return maptype.iterkeys = _map_iterkeys + + def _map_itervalues(self): + iter = self.begin() + while iter != self.end(): + yield self.second(iter) + iter = self.next(iter) + return maptype.itervalues = _map_itervalues + + def _map_iteritems(self): + iter = self.begin() + while iter != self.end(): + yield (self.first(iter), self.second(iter)) + iter = self.next(iter) + return maptype.iteritems = _map_iteritems + + def _map_keys(self): + return list(self.iterkeys()) maptype.keys = _map_keys + + def _map_values(self): + return list(self.itervalues()) maptype.values = _map_values + + def _map_items(self): + return list(self.iteritems()) maptype.items = _map_items + + def _map_has_key(self, key): + return key in self maptype.has_key = _map_has_key + + def _map_pop(self, key): + """ Sets the value associated with the provided key. """ + if not isinstance(key, self.keytype): + raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) + if key not in self: + raise KeyError('key not found') + ret = self[key] + del self[key] + return ret maptype.pop = _map_pop + + def _map_popitem(self): + """ Sets the value associated with the provided key. """ + if len(self) == 0: + raise KeyError('key not found') + key = self.keys()[0] + return (key, self.pop(key)) maptype.popitem = _map_popitem + + def _map_setdefault(self, key, default=None): + """ Sets the value associated with the provided key. """ + if not isinstance(key, self.keytype): + raise KeyError('type of `key` should be ' + repr(self.keytype) + ' but got ' + repr(type(key))) + if key in self: + return self[key] + self[key] = default + return default maptype.setdefault = _map_setdefault #_map_as_dict(user_labels_t, 'user_labels', (int, long), qstring) _map_as_dict(user_cmts_t, 'user_cmts', treeloc_t, citem_cmt_t) _map_as_dict(user_numforms_t, 'user_numforms', operand_locator_t, number_format_t) -_map_as_dict(user_iflags_t, 'user_iflags', citem_locator_t, (int, long)) +_map_as_dict(user_iflags_t, 'user_iflags', citem_locator_t, int) import ida_pro _map_as_dict(user_unions_t, 'user_unions', (int, long), ida_pro.intvec_t) _map_as_dict(eamap_t, 'eamap', long, cinsnptrvec_t) @@ -477,6 +476,49 @@ def create_helper(*args): res._own_and_register() return res +# ---------------- + +class __cbhooks_t(Hexrays_Hooks): + + instances = [] + + def __init__(self, callback): + self.callback = callback + self.instances.append(self) + Hexrays_Hooks.__init__(self) + + def maturity(self, *args): return self.callback(hxe_maturity, *args) + def interr(self, *args): return self.callback(hxe_interr, **args) + def print_func(self, *args): return self.callback(hxe_print_func, *args) + def func_printed(self, *args): return self.callback(hxe_func_printed, *args) + def open_pseudocode(self, *args): return self.callback(hxe_open_pseudocode, *args) + def switch_pseudocode(self, *args): return self.callback(hxe_switch_pseudocode, *args) + def refresh_pseudocode(self, *args): return self.callback(hxe_refresh_pseudocode, *args) + def close_pseudocode(self, *args): return self.callback(hxe_close_pseudocode, *args) + def keyboard(self, *args): return self.callback(hxe_keyboard, *args) + def right_click(self, *args): return self.callback(hxe_right_click, *args) + def double_click(self, *args): return self.callback(hxe_double_click, *args) + def curpos(self, *args): return self.callback(hxe_curpos, *args) + def create_hint(self, *args): return self.callback(hxe_create_hint, *args) + def text_ready(self, *args): return self.callback(hxe_text_ready, *args) + def populating_popup(self, *args): return self.callback(hxe_populating_popup, *args) + + +def install_hexrays_callback(callback): + "Deprecated. Please use Hexrays_Hooks instead" + h = __cbhooks_t(callback) + h.hook() + return True + +def remove_hexrays_callback(callback): + "Deprecated. Please use Hexrays_Hooks instead" + for inst in __cbhooks_t.instances: + if inst.callback == callback: + inst.unhook() + __cbhooks_t.instances.remove(inst) + return 1 + return 0 + #</pycode(py_hexrays)> #<pycode_BC695(py_hexrays)> diff --git a/pywraps/py_hexrays_hooks.hpp b/pywraps/py_hexrays_hooks.hpp new file mode 100644 index 0000000..79e67e6 --- /dev/null +++ b/pywraps/py_hexrays_hooks.hpp @@ -0,0 +1,107 @@ + +//<code(py_hexrays_hooks)> +//--------------------------------------------------------------------------- +ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t event, va_list va) +{ + // This hook gets called from the kernel. Ensure we hold the GIL. + PYW_GIL_GET; + class Hexrays_Hooks *proxy = (class Hexrays_Hooks *)ud; + ssize_t ret = 0; + try + { + switch ( event ) + { + // hookgenHEXRAYS:notifications + } + } + catch (Swig::DirectorException &e) + { + msg("Exception in Hexrays Hook function: %s\n", e.getMessage()); + PYW_GIL_CHECK_LOCKED_SCOPE(); + if ( PyErr_Occurred() ) + PyErr_Print(); + } + return ret; +} + +//------------------------------------------------------------------------- +static qvector<Hexrays_Hooks*> hexrays_hooks_instances; + +//------------------------------------------------------------------------- +static void hexrays_unloading__unhook_hooks(void) +{ + for ( size_t i = 0, n = hexrays_hooks_instances.size(); i < n; ++i ) + hexrays_hooks_instances[i]->unhook(); +} + +//------------------------------------------------------------------------- +Hexrays_Hooks::Hexrays_Hooks() + : hooked(false) +{ + hexrays_hooks_instances.push_back(this); +} + +//------------------------------------------------------------------------- +Hexrays_Hooks::~Hexrays_Hooks() +{ + hexrays_hooks_instances.del(this); + unhook(); +} +//</code(py_hexrays_hooks)> + +//<inline(py_hexrays_hooks)> +//------------------------------------------------------------------------- +// Hexrays hooks +//--------------------------------------------------------------------------- +ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t event, va_list va); +class control_graph_t; + +class Hexrays_Hooks +{ + friend ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t event, va_list va); + static ssize_t handle_create_hint_output(PyObject *o, vdui_t *, qstring *out_hint, int *out_implines) + { + ssize_t rc = 0; + if ( o != NULL && PySequence_Check(o) && PySequence_Size(o) == 3 ) + { + newref_t py_rc(PySequence_GetItem(o, 0)); + newref_t py_hint(PySequence_GetItem(o, 1)); + newref_t py_implines(PySequence_GetItem(o, 2)); + if ( PyInt_Check(py_rc.o) && PyString_Check(py_hint.o) && PyInt_Check(py_implines.o) ) + { + char *buf; + Py_ssize_t bufsize; + if ( PyString_AsStringAndSize(py_hint.o, &buf, &bufsize) > -1 ) + { + rc = PyInt_AsLong(py_rc.o); + qstring tmp(buf, bufsize); + out_hint->swap(tmp); + *out_implines = PyInt_AsLong(py_implines.o); + } + } + } + return rc; + } + + bool hooked; + +public: + Hexrays_Hooks(); + virtual ~Hexrays_Hooks(); + + bool hook() + { + if ( !hooked ) + hooked = install_hexrays_callback(Hexrays_Callback, this); + return hooked; + } + bool unhook() + { + if ( hooked ) + hooked = !remove_hexrays_callback(Hexrays_Callback, this); + return !hooked; + } + + // hookgenHEXRAYS:methods +}; +//</inline(py_hexrays_hooks)> diff --git a/pywraps/py_ida.py b/pywraps/py_ida.py index 8c4277c..f15d2dc 100644 --- a/pywraps/py_ida.py +++ b/pywraps/py_ida.py @@ -88,4 +88,12 @@ def make_lflags_accessors(bit): self.lflags &= ~bit return getter, setter idainfo.wide_high_byte_first = property(*make_lflags_accessors(LFLG_WIDE_HBF)) +def make_obsolete_accessors(): + def getter(self): + return False + def setter(self, value): + pass + return getter, setter +idainfo.allow_nonmatched_ops = property(*make_obsolete_accessors()) +idainfo.check_manual_ops = property(*make_obsolete_accessors()) #</pycode_BC695(py_ida)> diff --git a/pywraps/py_idaapi.py b/pywraps/py_idaapi.py index ef03f73..4dc3868 100644 --- a/pywraps/py_idaapi.py +++ b/pywraps/py_idaapi.py @@ -12,6 +12,8 @@ import datetime #<pycode(py_idaapi)> +__EA64__ = BADADDR == 0xFFFFFFFFFFFFFFFFL + import struct import traceback import os @@ -56,6 +58,22 @@ def require(modulename, package=None): sys.modules[modulename] = m setattr(importer_module, modulename, m) +def _replace_module_function(replacement): + name = replacement.__name__ + modname = replacement.__module__ + assert(name) + assert(modname) + mod = sys.modules[modname] + orig = getattr(mod, name) + replacement.__doc__ = orig.__doc__ + replacement.__name__ = name + replacement.func_dict["orig"] = orig + setattr(mod, name, replacement) + +def replfun(func): + _replace_module_function(func) + return func + # ----------------------------------------------------------------------- @@ -629,6 +647,10 @@ class __BC695: def dummy(self, *args): pass + def replace_fun(self, new): + new.func_dict["bc695redef"] = True + _replace_module_function(new) + _BC695 = __BC695() #</pycode(py_idaapi)> diff --git a/pywraps/py_idd.hpp b/pywraps/py_idd.hpp index 20d4f43..d35f823 100644 --- a/pywraps/py_idd.hpp +++ b/pywraps/py_idd.hpp @@ -370,50 +370,50 @@ PyObject *py_appcall( char get_event_module_name(const debug_event_t *ev, char *buf, size_t bufsize) { - qstrncpy(buf, ev->modinfo().name.c_str(), bufsize); - return true; + qstrncpy(buf, ev->modinfo().name.c_str(), bufsize); + return true; } ea_t get_event_module_base(const debug_event_t *ev) { - return ev->modinfo().base; + return ev->modinfo().base; } asize_t get_event_module_size(const debug_event_t *ev) { - return ev->modinfo().size; + return ev->modinfo().size; } char get_event_exc_info(const debug_event_t *ev, char *buf, size_t bufsize) { - qstrncpy(buf, ev->exc().info.c_str(), bufsize); - return true; + qstrncpy(buf, ev->exc().info.c_str(), bufsize); + return true; } char get_event_info(const debug_event_t *ev, char *buf, size_t bufsize) { - qstrncpy(buf, ev->info().c_str(), bufsize); - return true; + qstrncpy(buf, ev->info().c_str(), bufsize); + return true; } ea_t get_event_bpt_hea(const debug_event_t *ev) { - return ev->bpt().hea; + return ev->bpt().hea; } uint get_event_exc_code(const debug_event_t *ev) { - return ev->exc().code; + return ev->exc().code; } ea_t get_event_exc_ea(const debug_event_t *ev) { - return ev->exc().ea; + return ev->exc().ea; } bool can_exc_continue(const debug_event_t *ev) { - return ev->exc().can_cont; + return ev->exc().can_cont; } //</inline(py_idd)> diff --git a/pywraps/py_idp.hpp b/pywraps/py_idp.hpp index 8d46051..0359b23 100644 --- a/pywraps/py_idp.hpp +++ b/pywraps/py_idp.hpp @@ -600,9 +600,9 @@ ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va); class IDP_Hooks { friend ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va); - static int bool_to_insn_t_size(bool in, const insn_t *insn) { return in ? insn->size : 0; } - static int bool_to_1or0(bool in) { return in ? 1 : 0; } - static int cm_t_to_int(cm_t cm) { return int(cm); } + static ssize_t bool_to_insn_t_size(bool in, const insn_t *insn) { return in ? insn->size : 0; } + static ssize_t bool_to_1or0(bool in) { return in ? 1 : 0; } + static ssize_t cm_t_to_ssize_t(cm_t cm) { return ssize_t(cm); } static bool _handle_qstring_output(PyObject *o, qstring *buf) { bool is_str = o != NULL && PyString_Check(o); @@ -611,13 +611,13 @@ class IDP_Hooks Py_XDECREF(o); return is_str; } - static int handle_custom_mnem_output(PyObject *o, qstring *out, const insn_t *) + static ssize_t handle_custom_mnem_output(PyObject *o, qstring *out, const insn_t *) { return _handle_qstring_output(o, out) && !out->empty() ? 1 : 0; } - static int handle_assemble_output(PyObject *o, uchar *bin, ea_t /*ea*/, ea_t /*cs*/, ea_t /*ip*/, bool /*use32*/, const char */*line*/) + static ssize_t handle_assemble_output(PyObject *o, uchar *bin, ea_t /*ea*/, ea_t /*cs*/, ea_t /*ip*/, bool /*use32*/, const char */*line*/) { - int rc = 0; + ssize_t rc = 0; if ( o != NULL && PyString_Check(o) ) { char *s; @@ -628,20 +628,20 @@ class IDP_Hooks len = MAXSTR; memcpy(bin, s, len); } - rc = int(len); + rc = ssize_t(len); } Py_XDECREF(o); return rc; } - static int handle_get_reg_name_output(PyObject *o, qstring *buf, int /*reg*/, size_t /*width*/, int /*reghi*/) + static ssize_t handle_get_reg_name_output(PyObject *o, qstring *buf, int /*reg*/, size_t /*width*/, int /*reghi*/) { return _handle_qstring_output(o, buf) ? buf->length() : 0; } - static int handle_decorate_name3_output(PyObject *o, qstring *outbuf, const char * /*name*/, bool /*mangle*/, int /*cc*/, const tinfo_t * /*type*/) + static ssize_t handle_decorate_name3_output(PyObject *o, qstring *outbuf, const char * /*name*/, bool /*mangle*/, int /*cc*/, const tinfo_t * /*type*/) { return _handle_qstring_output(o, outbuf) ? 1 : 0; } - static int handle_delay_slot_insn_output(PyObject *o, ea_t *pea, bool *pbexec, bool *pfexec) + static ssize_t handle_delay_slot_insn_output(PyObject *o, ea_t *pea, bool *pbexec, bool *pfexec) { if ( PySequence_Check(o) && PySequence_Size(o) == 3 ) { @@ -664,9 +664,9 @@ class IDP_Hooks } return -1; } - static int handle_use_regarg_type_output(PyObject *o, int *idx, ea_t, const funcargvec_t *) + static ssize_t handle_use_regarg_type_output(PyObject *o, int *idx, ea_t, const funcargvec_t *) { - int rc = 0; + ssize_t rc = 0; if ( PySequence_Check(o) && PySequence_Size(o) == 2 ) { newref_t py_rc(PySequence_GetItem(o, 0)); @@ -679,7 +679,7 @@ class IDP_Hooks } return rc; } - static int handle_demangle_name_output( + static ssize_t handle_demangle_name_output( PyObject *o, int32 *out_res, qstring *out, @@ -687,7 +687,7 @@ class IDP_Hooks uint32 disable_mask, demreq_type_t demreq) { - int rc = 0; + ssize_t rc = 0; if ( PySequence_Check(o) && PySequence_Size(o) == 3 ) { newref_t py_rc(PySequence_GetItem(o, 0)); @@ -711,14 +711,14 @@ class IDP_Hooks } return rc; } - static int handle_find_value_output( + static ssize_t handle_find_value_output( PyObject *o, uval_t *out, const insn_t *pinsn, int reg) { uint64 num; - int rc = PyW_GetNumber(o, &num); + ssize_t rc = PyW_GetNumber(o, &num); if ( rc ) *out = num; return rc; @@ -751,7 +751,7 @@ ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va) // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; IDP_Hooks *proxy = (IDP_Hooks *)ud; - int ret = 0; + ssize_t ret = 0; try { switch ( notification_code ) diff --git a/pywraps/py_idp.py b/pywraps/py_idp.py.in similarity index 78% rename from pywraps/py_idp.py rename to pywraps/py_idp.py.in index a473ccd..cd05906 100644 --- a/pywraps/py_idp.py +++ b/pywraps/py_idp.py.in @@ -28,66 +28,7 @@ OP_SP_ADD = 0x00000000 # operand value is added to the pointer OP_SP_SUB = 0x00000002 # operand value is substracted from the pointer # processor_t.id -PLFM_386 = 0 # Intel 80x86 -PLFM_Z80 = 1 # 8085, Z80 -PLFM_I860 = 2 # Intel 860 -PLFM_8051 = 3 # 8051 -PLFM_TMS = 4 # Texas Instruments TMS320C5x -PLFM_6502 = 5 # 6502 -PLFM_PDP = 6 # PDP11 -PLFM_68K = 7 # Motoroal 680x0 -PLFM_JAVA = 8 # Java -PLFM_6800 = 9 # Motorola 68xx -PLFM_ST7 = 10 # SGS-Thomson ST7 -PLFM_MC6812 = 11 # Motorola 68HC12 -PLFM_MIPS = 12 # MIPS -PLFM_ARM = 13 # Advanced RISC Machines -PLFM_TMSC6 = 14 # Texas Instruments TMS320C6x -PLFM_PPC = 15 # PowerPC -PLFM_80196 = 16 # Intel 80196 -PLFM_Z8 = 17 # Z8 -PLFM_SH = 18 # Renesas (formerly Hitachi) SuperH -PLFM_NET = 19 # Microsoft Visual Studio.Net -PLFM_AVR = 20 # Atmel 8-bit RISC processor(s) -PLFM_H8 = 21 # Hitachi H8/300, H8/2000 -PLFM_PIC = 22 # Microchip's PIC -PLFM_SPARC = 23 # SPARC -PLFM_ALPHA = 24 # DEC Alpha -PLFM_HPPA = 25 # Hewlett-Packard PA-RISC -PLFM_H8500 = 26 # Hitachi H8/500 -PLFM_TRICORE = 27 # Tasking Tricore -PLFM_DSP56K = 28 # Motorola DSP5600x -PLFM_C166 = 29 # Siemens C166 family -PLFM_ST20 = 30 # SGS-Thomson ST20 -PLFM_IA64 = 31 # Intel Itanium IA64 -PLFM_I960 = 32 # Intel 960 -PLFM_F2MC = 33 # Fujistu F2MC-16 -PLFM_TMS320C54 = 34 # Texas Instruments TMS320C54xx -PLFM_TMS320C55 = 35 # Texas Instruments TMS320C55xx -PLFM_TRIMEDIA = 36 # Trimedia -PLFM_M32R = 37 # Mitsubishi 32bit RISC -PLFM_NEC_78K0 = 38 # NEC 78K0 -PLFM_NEC_78K0S = 39 # NEC 78K0S -PLFM_M740 = 40 # Mitsubishi 8bit -PLFM_M7700 = 41 # Mitsubishi 16bit -PLFM_ST9 = 42 # ST9+ -PLFM_FR = 43 # Fujitsu FR Family -PLFM_MC6816 = 44 # Motorola 68HC16 -PLFM_M7900 = 45 # Mitsubishi 7900 -PLFM_TMS320C3 = 46 # Texas Instruments TMS320C3 -PLFM_KR1878 = 47 # Angstrem KR1878 -PLFM_AD218X = 48 # Analog Devices ADSP 218X -PLFM_OAKDSP = 49 # Atmel OAK DSP -PLFM_TLCS900 = 50 # Toshiba TLCS-900 -PLFM_C39 = 51 # Rockwell C39 -PLFM_CR16 = 52 # NSC CR16 -PLFM_MN102L00 = 53 # Panasonic MN10200 -PLFM_TMS320C1X = 54 # Texas Instruments TMS320C1x -PLFM_NEC_V850X = 55 # NEC V850 and V850ES/E1/E2 -PLFM_SCR_ADPT = 56 # Processor module adapter for processor modules written in scripting languages -PLFM_EBC = 57 # EFI Bytecode -PLFM_MSP430 = 58 # Texas Instruments MSP430 -PLFM_SPU = 59 # Cell Broadband Engine Synergistic Processor Unit +${PLFM_DECLS} # # processor_t.flag diff --git a/pywraps/py_idp_idbhooks.hpp b/pywraps/py_idp_idbhooks.hpp index 8ef143b..de2754d 100644 --- a/pywraps/py_idp_idbhooks.hpp +++ b/pywraps/py_idp_idbhooks.hpp @@ -31,7 +31,7 @@ ssize_t idaapi IDB_Callback(void *ud, int notification_code, va_list va) // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; class IDB_Hooks *proxy = (class IDB_Hooks *)ud; - int ret = 0; + ssize_t ret = 0; try { switch ( notification_code ) diff --git a/pywraps/py_kernwin.hpp b/pywraps/py_kernwin.hpp index d81f76a..52101cd 100644 --- a/pywraps/py_kernwin.hpp +++ b/pywraps/py_kernwin.hpp @@ -55,7 +55,16 @@ static PyObject *py_register_timer(int interval, PyObject *py_callback) PYW_GIL_GET; py_timer_ctx_t *ctx = (py_timer_ctx_t *)ud; newref_t py_result(PyObject_CallFunctionObjArgs(ctx->pycallback, NULL)); - int ret = py_result == NULL ? -1 : PyLong_AsLong(py_result.o); + int ret = -1; + if ( PyErr_Occurred() ) + { + msg("Exception in timer callback. This timer will be unregistered.\n"); + PyErr_Print(); + } + else if ( py_result != NULL ) + { + ret = PyLong_AsLong(py_result.o); + } // Timer has been unregistered? if ( ret == -1 ) @@ -768,6 +777,43 @@ def is_idaq(): #</pydoc> */ + +struct jobj_wrapper_t +{ +private: + const jobj_t *o; + +public: + jobj_wrapper_t(const jobj_t *_o) : o(_o) {} + + PyObject *get_dict() + { + newref_t json_module(PyImport_ImportModule("json")); + if ( json_module != NULL ) + { + borref_t json_globals(PyModule_GetDict(json_module.o)); + if ( json_globals != NULL ) + { + borref_t json_loads(PyDict_GetItemString(json_globals.o, "loads")); + if ( json_loads != NULL ) + { + qstring clob; + if ( serialize_json(&clob, o) ) + { + newref_t dict(PyObject_CallFunction(json_loads.o, "s", clob.c_str())); + if ( dict != NULL ) + { + dict.incref(); + return dict.o; + } + } + } + } + } + Py_RETURN_NONE; + } +}; + //--------------------------------------------------------------------------- // UI hooks //--------------------------------------------------------------------------- @@ -903,9 +949,9 @@ public: return idapython_unhook_from_notification_point(HT_UI, UI_Callback, this); } - static int handle_get_ea_hint_output(PyObject *o, qstring *buf, ea_t) + static ssize_t handle_get_ea_hint_output(PyObject *o, qstring *buf, ea_t) { - int rc = 0; + ssize_t rc = 0; char *_buf; Py_ssize_t _len; if ( o != NULL && PyString_Check(o) && PyString_AsStringAndSize(o, &_buf, &_len) != -1 ) @@ -917,9 +963,9 @@ public: return rc; } - static int handle_hint_output(PyObject *o, qstring *hint, int *important_lines) + static ssize_t handle_hint_output(PyObject *o, qstring *hint, int *important_lines) { - int rc = 0; + ssize_t rc = 0; if ( o != NULL && PyTuple_Check(o) && PyTuple_Size(o) == 2 ) { borref_t el0(PyTuple_GetItem(o, 0)); @@ -946,16 +992,32 @@ public: return rc; } - static int handle_hint_output(PyObject *o, qstring *hint, ea_t, int, int *important_lines) + static ssize_t handle_hint_output(PyObject *o, qstring *hint, ea_t, int, int *important_lines) { return handle_hint_output(o, hint, important_lines); } - static int handle_hint_output(PyObject *o, qstring *hint, TWidget *, place_t *, int *important_lines) + static ssize_t handle_hint_output(PyObject *o, qstring *hint, TWidget *, place_t *, int *important_lines) { return handle_hint_output(o, hint, important_lines); } + static jobj_wrapper_t wrap_widget_cfg(const jobj_t *jobj) + { + return jobj_wrapper_t(jobj); + } + + static ssize_t handle_create_desktop_widget_output(PyObject *o) + { + if ( o == Py_None ) + return 0; + TWidget *widget = NULL; + int cvt = SWIG_ConvertPtr(o, (void **) &widget, SWIGTYPE_p_TWidget, 0); + if ( !SWIG_IsOK(cvt) || widget == NULL ) + return 0; + return ssize_t(widget); + } + // hookgenUI:methods }; @@ -1206,6 +1268,11 @@ def error(format): #</pydoc> */ +static TWidget *TWidget__from_ptrval__(size_t ptrval) +{ + return (TWidget *) ptrval; +} + //</inline(py_kernwin)> //--------------------------------------------------------------------------- @@ -1216,7 +1283,7 @@ ssize_t idaapi UI_Callback(void *ud, int notification_code, va_list va) // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; UI_Hooks *proxy = (UI_Hooks *)ud; - int ret = 0; + ssize_t ret = 0; try { switch ( notification_code ) @@ -1256,6 +1323,20 @@ bool idaapi py_menu_item_callback(void *userdata) return PyObject_IsTrue(result.o) != 0; } + +/* +#<pydoc> +def get_navband_pixel(ea): + """ + Maps an address, onto a pixel coordinate within the navband + + @param ea: The address to map + @return: a list [pixel, is_vertical] + """ + pass +#</pydoc> +*/ + //</code(py_kernwin)> #endif diff --git a/pywraps/py_kernwin.py b/pywraps/py_kernwin.py index a4939a1..b02e271 100644 --- a/pywraps/py_kernwin.py +++ b/pywraps/py_kernwin.py @@ -92,7 +92,7 @@ close_tform=close_widget find_tform=find_widget get_current_tform=get_current_widget def get_highlighted_identifier(): - thing = get_highlight(get_current_widget()) + thing = get_highlight(get_current_viewer()) if thing and thing[1]: return thing[0] get_tform_title=get_widget_title @@ -130,30 +130,27 @@ __wrap_uihooks_callback("populating_widget_popup", lambda cb, *args: cb(*args)) __wrap_uihooks_callback("finish_populating_widget_popup", lambda cb, *args: cb(*args)) __wrap_uihooks_callback("current_widget_changed", lambda cb, *args: cb(*args)) -AskUsingForm=ask_form +AskUsingForm=_call_ask_form HIST_ADDR=0 HIST_NUM=0 KERNEL_VERSION_MAGIC1=0 KERNEL_VERSION_MAGIC2=0 -OpenForm=open_form +OpenForm=_call_open_form _askaddr=_ida_kernwin._ask_addr _asklong=_ida_kernwin._ask_long _askseg=_ida_kernwin._ask_seg askaddr=ask_addr askbuttons_c=ask_buttons askfile_c=ask_file -@bc695redef def askfile2_c(forsave, defdir, filters, fmt): if filters: fmt = "FILTER %s\n%s" % (filters, fmt) return ask_file(forsave, defdir, fmt) askident=ask_ident asklong=ask_long -@bc695redef def askqstr(defval, fmt): return ask_str(defval, 0, fmt) askseg=ask_seg -@bc695redef def askstr(hist, defval, fmt): return ask_str(defval, hist, fmt) asktext=ask_text @@ -162,8 +159,8 @@ choose2_activate=choose_activate choose2_close=choose_close choose2_create=choose_create choose2_find=choose_find -choose2_get_embedded=choose_get_embedded -choose2_get_embedded_selection=choose_get_embedded_selection +choose2_get_embedded=_choose_get_embedded_chobj_pointer +choose2_get_embedded_selection=lambda *args: None choose2_refresh=choose_refresh clearBreak=clr_cancelled py_get_AskUsingForm=py_get_ask_form diff --git a/pywraps/py_kernwin_askform.hpp b/pywraps/py_kernwin_askform.hpp index 6119faa..7404270 100644 --- a/pywraps/py_kernwin_askform.hpp +++ b/pywraps/py_kernwin_askform.hpp @@ -145,7 +145,6 @@ static PyObject *formchgcbfa_get_field_value( { // dropdown list case 8: - { // Readonly? Then return the selected index if ( sz == 1 ) { @@ -161,111 +160,101 @@ static PyObject *formchgcbfa_get_field_value( return PyString_FromString(val.c_str()); } break; - } + // multilinetext - tuple representing textctrl_info_t case 7: - { - textctrl_info_t ti; - if ( fa->get_text_value(fid, &ti) ) - return Py_BuildValue("(sII)", ti.text.c_str(), ti.flags, ti.tabsize); - break; - } + { + textctrl_info_t ti; + if ( fa->get_text_value(fid, &ti) ) + return Py_BuildValue("(sII)", ti.text.c_str(), ti.flags, ti.tabsize); + break; + } // button - uint32 case 4: - { - uval_t val; - if ( fa->get_unsigned_value(fid, &val) ) - return PyLong_FromUnsignedLong(val); - break; - } + { + uval_t val; + if ( fa->get_unsigned_value(fid, &val) ) + return PyLong_FromUnsignedLong(val); + break; + } // ushort case 2: - { - ushort val; - if ( fa->_get_field_value(fid, &val) ) - return PyLong_FromUnsignedLong(val); - break; - } + { + ushort val; + if ( fa->_get_field_value(fid, &val) ) + return PyLong_FromUnsignedLong(val); + break; + } // string label case 1: - { - char val[MAXSTR]; - if ( fa->get_string_value(fid, val, sizeof(val)) ) - return PyString_FromString(val); - break; - } + { + char val[MAXSTR]; + if ( fa->get_string_value(fid, val, sizeof(val)) ) + return PyString_FromString(val); + break; + } // string input case 3: - { - qstring val; - val.resize(sz + 1); - if ( fa->get_string_value(fid, val.begin(), val.size()) ) - return PyString_FromString(val.begin()); - break; - } - case 5: - { - sizevec_t selection; - if ( fa->get_chooser_value(fid, &selection) ) { - ref_t l(PyW_SizeVecToPyList(selection)); - l.incref(); - return l.o; + qstring val; + val.resize(sz + 1); + if ( fa->get_string_value(fid, val.begin(), val.size()) ) + return PyString_FromString(val.begin()); + break; + } + case 5: + { + sizevec_t selection; + if ( fa->get_chooser_value(fid, &selection) ) + { + ref_t l(PyW_SizeVecToPyList(selection)); + l.incref(); + return l.o; + } + break; } - break; - } // Numeric control case 6: - { - union { - sel_t sel; - sval_t sval; - uval_t uval; - ulonglong ull; - } u; - switch ( sz ) - { - case 'S': // sel_t + union { - if ( fa->get_segment_value(fid, &u.sel) ) - return Py_BuildValue(PY_BV_SEL, bvsel_t(u.sel)); - break; - } - // sval_t - case 'n': - case 'D': - case 'O': - case 'Y': - case 'H': + sel_t sel; + sval_t sval; + uval_t uval; + ulonglong ull; + } u; + switch ( sz ) { - if ( fa->get_signed_value(fid, &u.sval) ) - return Py_BuildValue(PY_BV_SVAL, bvsval_t(u.sval)); - break; - } - case 'L': // uint64 - case 'l': // int64 - { - if ( fa->_get_field_value(fid, &u.ull) ) - return Py_BuildValue("K", u.ull); - break; - } - case 'N': - case 'M': // uval_t - { - if ( fa->get_unsigned_value(fid, &u.uval) ) - return Py_BuildValue(PY_BV_UVAL, bvuval_t(u.uval)); - break; - } - case '$': // ea_t - { - if ( fa->get_ea_value(fid, &u.uval) ) - return Py_BuildValue(PY_BV_UVAL, bvuval_t(u.uval)); - break; + case 'S': // sel_t + if ( fa->get_segment_value(fid, &u.sel) ) + return Py_BuildValue(PY_BV_SEL, bvsel_t(u.sel)); + break; + // sval_t + case 'n': + case 'D': + case 'O': + case 'Y': + case 'H': + if ( fa->get_signed_value(fid, &u.sval) ) + return Py_BuildValue(PY_BV_SVAL, bvsval_t(u.sval)); + break; + case 'L': // uint64 + case 'l': // int64 + if ( fa->_get_field_value(fid, &u.ull) ) + return Py_BuildValue("K", u.ull); + break; + case 'N': + case 'M': // uval_t + if ( fa->get_unsigned_value(fid, &u.uval) ) + return Py_BuildValue(PY_BV_UVAL, bvuval_t(u.uval)); + break; + case '$': // ea_t + if ( fa->get_ea_value(fid, &u.uval) ) + return Py_BuildValue(PY_BV_UVAL, bvuval_t(u.uval)); + break; } + break; } - break; - } } Py_RETURN_NONE; } @@ -284,7 +273,6 @@ static bool formchgcbfa_set_field_value( { // dropdown list case 8: - { // Editable dropdown list if ( PyString_Check(py_val) ) { @@ -298,47 +286,47 @@ static bool formchgcbfa_set_field_value( return fa->set_combobox_value(fid, &sel_idx); } break; - } + // multilinetext - textctrl_info_t case 7: - { - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(py_val); - return ti == NULL ? false : fa->set_text_value(fid, ti); - } + { + textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(py_val); + return ti == NULL ? false : fa->set_text_value(fid, ti); + } // button - uint32 case 4: - { - uval_t val = PyLong_AsUnsignedLong(py_val); - return fa->set_unsigned_value(fid, &val); - } + { + uval_t val = PyLong_AsUnsignedLong(py_val); + return fa->set_unsigned_value(fid, &val); + } // ushort case 2: - { - ushort val = PyLong_AsUnsignedLong(py_val) & 0xffff; - return fa->_set_field_value(fid, &val); - } + { + ushort val = PyLong_AsUnsignedLong(py_val) & 0xffff; + return fa->_set_field_value(fid, &val); + } // strings case 3: case 1: return fa->set_string_value(fid, PyString_AsString(py_val)); // intvec_t case 5: - { - sizevec_t selection; - if ( !PySequence_Check(py_val) - || PyW_PyListToSizeVec(&selection, py_val) < 0 ) { - break; + sizevec_t selection; + if ( !PySequence_Check(py_val) + || PyW_PyListToSizeVec(&selection, py_val) < 0 ) + { + break; + } + return fa->set_chooser_value(fid, &selection); } - return fa->set_chooser_value(fid, &selection); - } // Numeric case 6: - { - uint64 num; - if ( PyW_GetNumber(py_val, &num) ) - return fa->_set_field_value(fid, &num); - } + { + uint64 num; + if ( PyW_GetNumber(py_val, &num) ) + return fa->_set_field_value(fid, &num); + } } return false; } diff --git a/pywraps/py_kernwin_askform.py b/pywraps/py_kernwin_askform.py index 3f1eb89..1a1bd5a 100644 --- a/pywraps/py_kernwin_askform.py +++ b/pywraps/py_kernwin_askform.py @@ -687,9 +687,12 @@ class Form(object): # Construct input control Form.InputControl.__init__(self, Form.FT_ECHOOSER, "", swidth) + self.selobj = ida_pro.sizevec_t() + # Get a pointer to the chooser_info_t and the selection vector # (These two parameters are the needed arguments for the ask_form()) - emb, sel = _ida_kernwin.choose_get_embedded(chooser) + emb = _ida_kernwin._choose_get_embedded_chobj_pointer(chooser) + sel = self.selobj.this.__long__() # Get a pointer to a c_void_p constructed from an address p_embedded = ctypes.pointer(ctypes.c_void_p.from_address(emb)) @@ -711,6 +714,14 @@ class Form(object): value = property(lambda self: self.chooser) """Returns the embedded chooser instance""" + def __get_selection__(self): + if len(self.selobj): + out = [] + for item in self.selobj: + out.append(int(item)) + return out + selection = property(__get_selection__) + """Returns the selection""" def free(self): """ @@ -1179,7 +1190,7 @@ class Form(object): if not self.modal: raise SyntaxError("Form is not modal. Open() should be instead") - return ask_form(*self.__args) + return _call_ask_form(*self.__args) def Open(self): @@ -1190,7 +1201,7 @@ class Form(object): if self.modal: raise SyntaxError("Form is modal. Execute() should be instead") - open_form(*self.__args) + _call_open_form(*self.__args) def EnableField(self, ctrl, enable): @@ -1334,33 +1345,24 @@ try: import ctypes # Setup the numeric argument size Form.NumericArgument.DefI64 = _ida_idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL - ask_form__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_ask_form()) - open_form__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_open_form()) + __ask_form_callable = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_ask_form()) + __open_form_callable = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_open_form()) except: - def ask_form__(*args): + def __ask_form_callable(*args): warning("ask_form() needs ctypes library in order to work") return 0 - def open_form__(*args): + def __open_form_callable(*args): warning("open_form() needs ctypes library in order to work") -def ask_form(*args): - """ - Calls ask_form() - @param: Compiled Arguments obtain through the Form.Compile() function - @return: 1 = ok, 0 = cancel - """ +def _call_ask_form(*args): old = _ida_idaapi.set_script_timeout(0) - r = ask_form__(*args) + r = __ask_form_callable(*args) _ida_idaapi.set_script_timeout(old) return r -def open_form(*args): - """ - Calls open_form() - @param: Compiled Arguments obtain through the Form.Compile() function - """ +def _call_open_form(*args): old = _ida_idaapi.set_script_timeout(0) - r = open_form__(*args) + r = __open_form_callable(*args) _ida_idaapi.set_script_timeout(old) #</pycode(py_kernwin_askform)> diff --git a/pywraps/py_kernwin_choose.hpp b/pywraps/py_kernwin_choose.hpp index e4d88e9..ed0cad5 100644 --- a/pywraps/py_kernwin_choose.hpp +++ b/pywraps/py_kernwin_choose.hpp @@ -28,7 +28,7 @@ void choose_del_instance(PyObject *self) } // set `prm` to the integer value of the `name` attribute -template<class T> +template <class T> static void py_get_int(PyObject *self, T *prm, const char *name) { ref_t attr(PyW_TryGetAttrString(self, name)); @@ -66,8 +66,6 @@ public: // One of CHOOSE_xxxx uint32 cb_flags; - sizevec_t embedded_sel; - // Chooser title qstring title; @@ -243,11 +241,6 @@ public: return chobj; } - const sizevec_t *get_sel_vec() const - { - return &embedded_sel; - } - bool is_valid() const { return chobj != NULL; @@ -781,33 +774,15 @@ void choose_activate(PyObject *self) } //------------------------------------------------------------------------ -PyObject *choose_get_embedded_selection(PyObject *self) +// Return the C instance as 64bit number +uint64 _choose_get_embedded_chobj_pointer(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); - + uint64 ptr = 0; py_choose_t *pych = choose_find_instance(self); - if ( pych == NULL || !pych->is_valid() || !pych->is_embedded() ) - Py_RETURN_NONE; - - ref_t ret(PyW_SizeVecToPyList(*pych->get_sel_vec())); - ret.incref(); - return ret.o; -} - -//------------------------------------------------------------------------ -// Return the C instances as 64bit numbers -PyObject *choose_get_embedded(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - py_choose_t *pych = choose_find_instance(self); - if ( pych == NULL || !pych->is_valid() || !pych->is_embedded() ) - Py_RETURN_NONE; - - return Py_BuildValue( - "(KK)", - PTR2U64(pych->get_chobj()), - PTR2U64(pych->get_sel_vec())); + if ( pych != NULL && pych->is_valid() && pych->is_embedded() ) + ptr = uint64(pych->get_chobj()); + return ptr; } //------------------------------------------------------------------------ @@ -829,8 +804,7 @@ void choose_refresh(PyObject *self); void choose_close(PyObject *self); int choose_create(PyObject *self); void choose_activate(PyObject *self); -PyObject *choose_get_embedded(PyObject *self); -PyObject *choose_get_embedded_selection(PyObject *self); +uint64 _choose_get_embedded_chobj_pointer(PyObject *self); PyObject *py_get_chooser_data(const char *chooser_caption, int n) { diff --git a/pywraps/py_kernwin_choose.py b/pywraps/py_kernwin_choose.py index 2c0d969..76860e3 100644 --- a/pywraps/py_kernwin_choose.py +++ b/pywraps/py_kernwin_choose.py @@ -32,6 +32,18 @@ class Choose(object): default one """ + CH_CAN_INS = 0x000100 + """allow to insert new items""" + + CH_CAN_DEL = 0x000200 + """allow to delete existing item(s)""" + + CH_CAN_EDIT = 0x000400 + """allow to edit existing item(s)""" + + CH_CAN_REFRESH = 0x000800 + """allow to refresh chooser""" + CH_QFLT = 0x1000 """open with quick filter enabled and focused""" @@ -43,14 +55,10 @@ class Choose(object): CH_QFTYP_FUZZY = 4 << CH_QFTYP_SHIFT CH_QFTYP_MASK = 0x7 << CH_QFTYP_SHIFT - CH_CAN_INS = 0x000100 - """allow to insert new items""" - CH_CAN_DEL = 0x000200 - """allow to delete existing item(s)""" - CH_CAN_EDIT = 0x000400 - """allow to edit existing item(s)""" - CH_CAN_REFRESH = 0x000800 - """allow to refresh chooser""" + CH_NO_STATUS_BAR = 0x00010000 + """don't show a status bar""" + CH_RESTORE = 0x00020000 + """restore floating position if present (equivalent of WOPN_RESTORE) (GUI version only)""" CH_BUILTIN_SHIFT = 19 CH_BUILTIN_MASK = 0x1F << CH_BUILTIN_SHIFT @@ -159,13 +167,10 @@ class Choose(object): def GetEmbSelection(self): """ - Returns the selection associated with an embedded chooser - - @return: - - None if chooser is not embedded - - A list with selection indexes (0-based) + Deprecated. For embedded choosers, the selection is + available through 'Form.EmbeddedChooserControl.selection' """ - return _ida_kernwin.choose_get_embedded_selection(self) + return None def Show(self, modal=False): diff --git a/pywraps/py_kernwin_custview.hpp b/pywraps/py_kernwin_custview.hpp index 5170a23..94af14f 100644 --- a/pywraps/py_kernwin_custview.hpp +++ b/pywraps/py_kernwin_custview.hpp @@ -150,11 +150,10 @@ protected: { HAVE_HINT = 0x0001, HAVE_KEYDOWN = 0x0002, - HAVE_POPUP = 0x0004, - HAVE_DBLCLICK = 0x0008, - HAVE_CURPOS = 0x0010, - HAVE_CLICK = 0x0020, - HAVE_CLOSE = 0x0040 + HAVE_DBLCLICK = 0x0004, + HAVE_CURPOS = 0x0008, + HAVE_CLICK = 0x0010, + HAVE_CLOSE = 0x0020 }; private: struct cvw_popupctx_t @@ -179,14 +178,6 @@ private: return _this->on_keydown(vk_key, shift); } - // The popup menu is being constructed - static void idaapi s_cv_popup(TWidget * /*cv*/, void *ud) - { - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - _this->on_popup(); - } - // The user clicked static bool idaapi s_cv_click(TWidget * /*cv*/, int shift, void *ud) { @@ -219,30 +210,33 @@ private: customviewer_t *_this = (customviewer_t *)ud; switch ( code ) { - case ui_get_custom_viewer_hint: - { - qstring &hint = *va_arg(va, qstring *); - TWidget *viewer = va_arg(va, TWidget *); - place_t *place = va_arg(va, place_t *); - int *important_lines = va_arg(va, int *); - if ( (_this->_features & HAVE_HINT) == 0 || place == NULL || _this->_cv != viewer ) - return 0; - else + case ui_get_custom_viewer_hint: + { + qstring &hint = *va_arg(va, qstring *); + TWidget *viewer = va_arg(va, TWidget *); + place_t *place = va_arg(va, place_t *); + int *important_lines = va_arg(va, int *); + if ( (_this->_features & HAVE_HINT) == 0 + || place == NULL + || _this->_cv != viewer ) + { + return 0; + } return _this->on_hint(place, important_lines, hint) ? 1 : 0; - } + } - case ui_widget_invisible: - { - TWidget *widget = va_arg(va, TWidget *); - if ( _this->_cv != widget ) - break; - } - // fallthrough... - case ui_term: - idapython_unhook_from_notification_point(HT_UI, s_ui_cb, _this); - _this->on_close(); - _this->on_post_close(); - break; + case ui_widget_invisible: + { + TWidget *widget = va_arg(va, TWidget *); + if ( _this->_cv != widget ) + break; + } + // fallthrough... + case ui_term: + idapython_unhook_from_notification_point(HT_UI, s_ui_cb, _this); + _this->on_close(); + _this->on_post_close(); + break; } return 0; @@ -276,9 +270,6 @@ public: // OnKeyDown virtual bool on_keydown(int /*vk_key*/, int /*shift*/) { return false; } - // OnPopupShow - virtual bool on_popup() { return false; } - // OnHint virtual bool on_hint(place_t * /*place*/, int * /*important_lines*/, qstring &/*hint*/) { return false; } @@ -425,9 +416,6 @@ public: if ( (features & HAVE_KEYDOWN) != 0 ) handlers.keyboard = s_cv_keydown; - if ( (features & HAVE_POPUP) != 0 ) - handlers.popup = s_cv_popup; - if ( (features & HAVE_CLICK) != 0 ) handlers.click = s_cv_click; @@ -461,7 +449,7 @@ public: if ( _cv == NULL ) return false; - display_widget(_cv, WOPN_TAB|WOPN_MENU|WOPN_RESTORE); + display_widget(_cv, WOPN_TAB|WOPN_RESTORE); return true; } }; @@ -554,12 +542,15 @@ private: // OnHostFormClose virtual void on_close() { - // Call the close method if it is there and the object is still bound - if ( (features & HAVE_CLOSE) != 0 && py_self != NULL ) + if ( py_self != NULL ) { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, NULL)); - PyW_ShowCbErr(S_ON_CLOSE); + // Call the close method if it is there and the object is still bound + if ( (features & HAVE_CLOSE) != 0 ) + { + PYW_GIL_CHECK_LOCKED_SCOPE(); + newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, NULL)); + PyW_ShowCbErr(S_ON_CLOSE); + } // Cleanup Py_DECREF(py_self); @@ -584,20 +575,6 @@ private: return py_result != NULL && PyObject_IsTrue(py_result.o); } - //-------------------------------------------------------------------------- -// OnPopupShow - virtual bool on_popup() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result( - PyObject_CallMethod( - py_self, - (char *)S_ON_POPUP, - NULL)); - PyW_ShowCbErr(S_ON_POPUP); - return py_result != NULL && PyObject_IsTrue(py_result.o); - } - //-------------------------------------------------------------------------- // OnHint virtual bool on_hint(place_t *place, int *important_lines, qstring &hint) @@ -763,7 +740,6 @@ public: { S_ON_CLOSE, HAVE_CLOSE }, { S_ON_HINT, HAVE_HINT }, { S_ON_KEYDOWN, HAVE_KEYDOWN }, - { S_ON_POPUP, HAVE_POPUP }, { S_ON_DBL_CLICK, HAVE_DBLCLICK }, { S_ON_CURSOR_POS_CHANGED, HAVE_CURPOS } }; diff --git a/pywraps/py_kernwin_custview.py b/pywraps/py_kernwin_custview.py index e738a0b..4ecca71 100644 --- a/pywraps/py_kernwin_custview.py +++ b/pywraps/py_kernwin_custview.py @@ -2,8 +2,27 @@ #<pycode(py_kernwin_custview)> class simplecustviewer_t(object): """The base class for implementing simple custom viewers""" + + class UI_Hooks_Trampoline(UI_Hooks): + def __init__(self, v): + UI_Hooks.__init__(self) + self.hook() + import weakref + self.v = weakref.ref(v) + + def populating_widget_popup(self, form, popup_handle): + my_form = self.v().GetWidget() + if form == my_form: + cb = self.v().OnPopup + from inspect import getargspec + if len(getargspec(cb).args) == 3: + cb(my_form, popup_handle) + else: + cb() # bw-compat + def __init__(self): self.__this = None + self.ui_hooks_trampoline = self.UI_Hooks_Trampoline(self) def __del__(self): """Destructor. It also frees the associated C++ object""" @@ -16,6 +35,13 @@ class simplecustviewer_t(object): def __make_sl_arg(line, fgcolor=None, bgcolor=None): return line if (fgcolor is None and bgcolor is None) else (line, fgcolor, bgcolor) + def OnPopup(self, form, popup_handle): + """ + Context menu popup is about to be shown. Create items dynamically if you wish + @return: Boolean. True if you handled the event + """ + pass + def Create(self, title): """ Creates the custom view. This should be the first method called after instantiation @@ -200,13 +226,6 @@ class simplecustviewer_t(object): # print "OnKeydown, vk=%d shift=%d" % (vkey, shift) # return False # -# def OnPopup(self): -# """ -# Context menu popup is about to be shown. Create items dynamically if you wish -# @return: Boolean. True if you handled the event -# """ -# print "OnPopup" -# # def OnHint(self, lineno): # """ # Hint requested for the given line number. diff --git a/pywraps/py_kernwin_plgform.hpp b/pywraps/py_kernwin_plgform.hpp index 58621a3..ad9ad05 100644 --- a/pywraps/py_kernwin_plgform.hpp +++ b/pywraps/py_kernwin_plgform.hpp @@ -5,7 +5,6 @@ //--------------------------------------------------------------------------- class plgform_t { -private: ref_t py_obj; TWidget *widget; @@ -15,24 +14,7 @@ private: PYW_GIL_GET; plgform_t *_this = (plgform_t *)ud; - if ( notification_code == ui_widget_visible ) - { - TWidget *widget = va_arg(va, TWidget *); - if ( widget == _this->widget ) - { - // Qt: QWidget* - // G: HWND - // We wrap and pass as a CObject in the hope that a Python UI framework - // can unwrap a CObject and get the hwnd/widget back - newref_t py_result( - PyObject_CallMethod( - _this->py_obj.o, - (char *)S_ON_CREATE, "O", - PyCObject_FromVoidPtr(widget, NULL))); - PyW_ShowCbErr(S_ON_CREATE); - } - } - else if ( notification_code == ui_widget_invisible ) + if ( notification_code == ui_widget_invisible ) { TWidget *widget = va_arg(va, TWidget *); if ( widget == _this->widget ) @@ -62,15 +44,15 @@ private: } public: - plgform_t(): widget(NULL) - { - } + plgform_t() : widget(NULL) {} bool show( PyObject *obj, const char *caption, int options) { + const bool create_only = options == -1; + // Already displayed? TWidget *f = find_widget(caption); if ( f != NULL ) @@ -79,7 +61,8 @@ public: if ( f == widget ) { // Switch to it - activate_widget(widget, true); + if ( !create_only ) + activate_widget(widget, true); return true; } // Fail to create @@ -100,7 +83,20 @@ public: py_obj = borref_t(obj); this->widget = widget; - display_widget(widget, options); + + // Qt: QWidget* + // G: HWND + // We wrap and pass as a CObject in the hope that a Python UI framework + // can unwrap a CObject and get the hwnd/widget back + newref_t py_result( + PyObject_CallMethod( + py_obj.o, + (char *)S_ON_CREATE, "O", + PyCObject_FromVoidPtr(widget, NULL))); + PyW_ShowCbErr(S_ON_CREATE); + + if ( !create_only ) + display_widget(widget, options); return true; } @@ -110,6 +106,8 @@ public: close_widget(widget, options); } + TWidget *get_widget() { return widget; } + static PyObject *create() { PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -135,7 +133,7 @@ static bool plgform_show( PyObject *py_link, PyObject *py_obj, const char *caption, - int options = WOPN_TAB|WOPN_MENU|WOPN_RESTORE) + int options = WOPN_TAB|WOPN_RESTORE) { DECL_PLGFORM; return plgform->show(py_obj, caption, options); @@ -148,6 +146,14 @@ static void plgform_close( DECL_PLGFORM; plgform->close(options); } + +static TWidget *plgform_get_widget( + PyObject *py_link) +{ + DECL_PLGFORM; + return plgform->get_widget(); +} + #undef DECL_PLGFORM //</inline(py_kernwin_plgform)> diff --git a/pywraps/py_kernwin_plgform.py b/pywraps/py_kernwin_plgform.py index 8237655..de7fc5c 100644 --- a/pywraps/py_kernwin_plgform.py +++ b/pywraps/py_kernwin_plgform.py @@ -7,66 +7,90 @@ class PluginForm(object): This form can be used to host additional controls. Please check the PyQt example. """ - WOPN_MDI = 0x01 - """start by default as MDI (obsolete)""" + WOPN_MDI = 0x01 # no-op WOPN_TAB = 0x02 """attached by default to a tab""" WOPN_RESTORE = 0x04 - """restore state from desktop config""" - WOPN_ONTOP = 0x08 - """form should be "ontop""" - WOPN_MENU = 0x10 - """form must be listed in the windows menu (automatically set for all plugins)""" - WOPN_CENTERED = 0x20 - """form will be centered on the screen""" + """ + if the widget is the only widget in a floating area when + it is closed, remember that area's geometry. The next + time that widget is created as floating (i.e., no WOPN_TAB) + its geometry will be restored (e.g., "Execute script" + """ + WOPN_ONTOP = 0x08 # no-op + WOPN_MENU = 0x10 # no-op + WOPN_CENTERED = 0x20 # no-op WOPN_PERSIST = 0x40 """form will persist until explicitly closed with Close()""" + WOPN_CREATE_ONLY = {} + + def __init__(self): """ """ self.__clink__ = _ida_kernwin.plgform_new() - - def Show(self, caption, options = 0): + def Show(self, caption, options=0): """ Creates the form if not was not created or brings to front if it was already created @param caption: The form caption @param options: One of PluginForm.WOPN_ constants """ - options |= PluginForm.WOPN_TAB|PluginForm.WOPN_MENU|PluginForm.WOPN_RESTORE + if options == self.WOPN_CREATE_ONLY: + options = -1 + else: + options |= PluginForm.WOPN_TAB|PluginForm.WOPN_RESTORE return _ida_kernwin.plgform_show(self.__clink__, self, caption, options) @staticmethod - def FormToPyQtWidget(form, ctx = sys.modules['__main__']): - """ - Use this method to convert a TWidget* to a QWidget to be used by PyQt + def _ensure_widget_deps(ctx): + for key, modname in [("sip", "sip"), ("QtWidgets", "PyQt5.QtWidgets")]: + if not hasattr(ctx, key): + print "Note: importing '%s' module into %s" % (key, ctx) + import importlib + setattr(ctx, key, importlib.import_module(modname)) - @param ctx: Context. Reference to a module that already imported SIP and QtGui modules + + @staticmethod + def TWidgetToPyQtWidget(form, ctx = sys.modules['__main__']): + """ + Convert a TWidget* to a QWidget to be used by PyQt + + @param ctx: Context. Reference to a module that already imported SIP and QtWidgets modules """ if type(form).__name__ == "SwigPyObject": ptr_l = long(form) else: ptr_l = form - for key, modname in [("sip", "sip"), ("QtWidgets", "PyQt5.QtWidgets")]: - if not hasattr(ctx, key): - print "Note: FormToPyQtWidget: importing '%s' module into %s" % (key, ctx) - import importlib - setattr(ctx, key, importlib.import_module(modname)) + PluginForm._ensure_widget_deps(ctx) vptr = ctx.sip.voidptr(ptr_l) return ctx.sip.wrapinstance(vptr.__int__(), ctx.QtWidgets.QWidget) + FormToPyQtWidget = TWidgetToPyQtWidget @staticmethod - def FormToPySideWidget(form, ctx = sys.modules['__main__']): + def QtWidgetToTWidget(w, ctx = sys.modules['__main__']): + """ + Convert a QWidget to a TWidget* to be used by IDA + + @param ctx: Context. Reference to a module that already imported SIP and QtWidgets modules + """ + PluginForm._ensure_widget_deps(ctx) + as_long = long(ctx.sip.unwrapinstance(w)) + return TWidget__from_ptrval__(as_long) + + + @staticmethod + def TWidgetToPySideWidget(form, ctx = sys.modules['__main__']): """ Use this method to convert a TWidget* to a QWidget to be used by PySide - @param ctx: Context. Reference to a module that already imported QtGui module + @param ctx: Context. Reference to a module that already imported QtWidgets module """ if form is None: return None @@ -82,7 +106,7 @@ class PluginForm(object): pythonapi.PyCObject_AsVoidPtr.argtypes = [c_void_p, c_void_p] form = pythonapi.PyCObject_FromVoidPtr(ptr_l, 0) return ctx.QtGui.QWidget.FromCObject(form) - + FormToPySideWidget = TWidgetToPySideWidget def OnCreate(self, form): """ @@ -113,6 +137,16 @@ class PluginForm(object): """ return _ida_kernwin.plgform_close(self.__clink__, options) + + def GetWidget(self): + """ + Return the TWidget underlying this view. + + @return: The TWidget underlying this view, or None. + """ + return _ida_kernwin.plgform_get_widget(self.__clink__) + + WCLS_SAVE = 0x1 """Save state in desktop config""" diff --git a/pywraps/py_kernwin_viewhooks.hpp b/pywraps/py_kernwin_viewhooks.hpp index a2df757..e8c8265 100644 --- a/pywraps/py_kernwin_viewhooks.hpp +++ b/pywraps/py_kernwin_viewhooks.hpp @@ -31,7 +31,7 @@ ssize_t idaapi View_Callback(void *ud, int notification_code, va_list va) // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; class View_Hooks *proxy = (class View_Hooks *)ud; - int ret = 0; + ssize_t ret = 0; try { switch ( notification_code ) diff --git a/pywraps/py_loader.hpp b/pywraps/py_loader.hpp index cc970ea..dcd7df5 100644 --- a/pywraps/py_loader.hpp +++ b/pywraps/py_loader.hpp @@ -49,8 +49,11 @@ def load_plugin(name): */ static PyObject *py_load_plugin(const char *name) { + if ( qfileexist(name) ) + prepare_programmatic_plugin_load(name); plugin_t *r = load_plugin(name); PYW_GIL_CHECK_LOCKED_SCOPE(); + prepare_programmatic_plugin_load(NULL); if ( r == NULL ) Py_RETURN_NONE; else @@ -87,6 +90,16 @@ static bool py_run_plugin(PyObject *plg, int arg) } } +//------------------------------------------------------------------------ +static bool py_load_and_run_plugin(const char *name, size_t arg) +{ + if ( qfileexist(name) ) + prepare_programmatic_plugin_load(name); + bool rc = load_and_run_plugin(name, arg); + prepare_programmatic_plugin_load(NULL); + return rc; +} + //</inline(py_loader)> #endif diff --git a/pywraps/py_nalt.py b/pywraps/py_nalt.py index dfefe60..f81e18d 100644 --- a/pywraps/py_nalt.py +++ b/pywraps/py_nalt.py @@ -6,6 +6,9 @@ def get_switch_info(*args): else: si, ea = args return None if _real_get_switch_info(si, ea) <= 0 else si +def get_abi_name(*args): + import ida_typeinf + return ida_typeinf.get_abi_name(args) #</pycode(py_nalt)> #<pycode_BC695(py_nalt)> @@ -28,7 +31,6 @@ SWI2_SUBTRACT=SWI_SUBTRACT >> 16 import ida_netnode RIDX_AUTO_PLUGINS=ida_netnode.BADNODE change_encoding_name=rename_encoding -@bc695redef def del_tinfo2(ea, n=None): if n is not None: return del_op_tinfo(ea, n) @@ -43,7 +45,6 @@ def get_op_tinfo(*args): tif, ea, n = args return _ida_nalt.get_op_tinfo(tif, ea, n) get_op_tinfo2=get_op_tinfo -@bc695redef def is_unicode(strtype): return (strtype & STRWIDTH_MASK) > 0 set_op_tinfo2=set_op_tinfo diff --git a/pywraps/py_name.hpp b/pywraps/py_name.hpp index f30469d..5d41302 100644 --- a/pywraps/py_name.hpp +++ b/pywraps/py_name.hpp @@ -5,7 +5,7 @@ //------------------------------------------------------------------------ //<inline(py_name)> //------------------------------------------------------------------------ -PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) +PyObject *get_debug_names(ea_t ea1, ea_t ea2) { // Get debug names ea_name_vec_t names; diff --git a/pywraps/py_name.py b/pywraps/py_name.py index cc544db..8b34ffa 100644 --- a/pywraps/py_name.py +++ b/pywraps/py_name.py @@ -76,12 +76,10 @@ GN_INSNLOC=0 def demangle_name(name, mask, demreq=DQT_FULL): # make flag optional, so demangle_name & demangle_name2 can use it return _ida_name.demangle_name(name, mask, demreq) demangle_name2=demangle_name -@bc695redef def do_name_anyway(ea, name, maxlen=0): return force_name(ea, name) extract_name2=extract_name get_debug_name2=get_debug_name -@bc695redef def get_true_name(ea0, ea1=None): if ea1 is None: ea = ea0 @@ -90,21 +88,18 @@ def get_true_name(ea0, ea1=None): return get_name(ea) is_ident_char=is_ident_cp is_visible_char=is_visible_cp -@bc695redef def make_visible_name(name, sz=0): if sz > 0: name = name[0:sz] return _ida_name.validate_name(name, VNT_VISIBLE) -@bc695redef def validate_name2(name, sz=0): if sz > 0: name = name[0:sz] return _ida_name.validate_name(name, VNT_IDENT) -@bc695redef def validate_name3(name): return _ida_name.validate_name(name, VNT_IDENT) isident=is_ident -@bc695redef_with_pydoc(get_name.__doc__) +@bc695redef def get_name(*args): if len(args) == 2: if args[0] != _ida_idaapi.BADADDR: diff --git a/pywraps/py_offset.py b/pywraps/py_offset.py index 663064e..93a5903 100644 --- a/pywraps/py_offset.py +++ b/pywraps/py_offset.py @@ -2,7 +2,6 @@ #<pycode_BC695(py_offset)> calc_reference_basevalue=calc_basevalue calc_reference_target=calc_target -@bc695redef def set_offset(ea, n, base): import ida_idaapi otype = get_default_reftype(ea) diff --git a/pywraps/py_pro.py b/pywraps/py_pro.py index afc419b..b8dd3f4 100644 --- a/pywraps/py_pro.py +++ b/pywraps/py_pro.py @@ -1,10 +1,21 @@ #<pycode(py_pro)> import ida_idaapi + +int64vec_t = longlongvec_t +uint64vec_t = ulonglongvec_t +if ida_idaapi.__EA64__: + svalvec_t = longlongvec_t + uvalvec_t = ulonglongvec_t +else: + svalvec_t = intvec_t + uvalvec_t = uintvec_t + ida_idaapi._listify_types( - uvalvec_t, intvec_t, - int64vec_t, + uintvec_t, + longlongvec_t, + ulonglongvec_t, boolvec_t, strvec_t) @@ -87,10 +98,8 @@ class _qstrvec_t(ida_idaapi.py_clinked_object_t): #</pycode(py_pro)> #<pycode_BC695(py_pro)> -@bc695redef def strlwr(s): return str(s).lower() -@bc695redef def strupr(s): return str(s).upper() #</pycode_BC695(py_pro)> diff --git a/pywraps/py_problems.py b/pywraps/py_problems.py index 50bd3fa..2e3225c 100644 --- a/pywraps/py_problems.py +++ b/pywraps/py_problems.py @@ -23,10 +23,8 @@ QueueGetMessage=get_problem_desc QueueGetType=get_problem QueueIsPresent=is_problem_present QueueSet=remember_problem -@bc695redef def get_long_queue_name(t): return get_problem_name(t, True) -@bc695redef def get_short_queue_name(t): return get_problem_name(t, False) #</pycode_BC695(py_problems)> diff --git a/pywraps/py_segment.hpp b/pywraps/py_segment.hpp index bb47c54..2837693 100644 --- a/pywraps/py_segment.hpp +++ b/pywraps/py_segment.hpp @@ -38,11 +38,11 @@ ea_t segment_t_end_ea_get(segment_t *segm) //<inline(py_segment)> sel_t get_defsr(segment_t *s, int reg) { - return s->defsr[reg]; + return s->defsr[reg]; } void set_defsr(segment_t *s, int reg, sel_t value) { - s->defsr[reg] = value; + s->defsr[reg] = value; } int py_rebase_program(PyObject *delta, int flags) { diff --git a/pywraps/py_segment.py b/pywraps/py_segment.py index d72ccac..f0c5180 100644 --- a/pywraps/py_segment.py +++ b/pywraps/py_segment.py @@ -5,7 +5,6 @@ SEGDEL_KEEP=SEGMOD_KEEP SEGDEL_KEEP0=SEGMOD_KEEP0 SEGDEL_PERM=SEGMOD_KILL SEGDEL_SILENT=SEGMOD_SILENT -@bc695redef def del_segment_cmt(s, rpt): set_segment_cmt(s, "", rpt) ask_selector=sel2para diff --git a/pywraps/py_typeinf.hpp b/pywraps/py_typeinf.hpp index 4a43453..174500b 100644 --- a/pywraps/py_typeinf.hpp +++ b/pywraps/py_typeinf.hpp @@ -399,7 +399,7 @@ PyObject *py_pack_object_to_bv( NULL, pio_flags); if ( err == eOk && !bytes.relocate(base_ea, inf.is_be()) ) - err = -1; + err = -1; Py_END_ALLOW_THREADS; if ( err == eOk ) return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size()); @@ -481,7 +481,7 @@ int idc_set_local_type(int ordinal, const char *dcl, int flags) if ( dcl == NULL || dcl[0] == '\0' ) { if ( !del_numbered_type(NULL, ordinal) ) - return 0; + return 0; } else { diff --git a/pywraps/py_typeinf.py b/pywraps/py_typeinf.py index db9aa8a..40b5556 100644 --- a/pywraps/py_typeinf.py +++ b/pywraps/py_typeinf.py @@ -17,7 +17,6 @@ TERR_TOOLONGNAME=TERR_WRONGNAME def add_til(name, flags=0): return _ida_typeinf.add_til(name, flags) add_til2=add_til -@bc695redef def apply_decl(arg0, arg1, arg2=None, arg3=0): if type(arg0) in [int, long]: # old apply_cdecl() return _ida_typeinf.apply_cdecl(cvar.idati, arg0, arg1, 0) @@ -30,7 +29,6 @@ calc_c_cpp_name4=calc_c_cpp_name import ida_idaapi callregs_init_regs=ida_idaapi._BC695.dummy choose_local_type=choose_local_tinfo -@bc695redef def choose_named_type2(root_til, title, ntf_flags, func, out_sym): class func_pred_t(predicate_t): def __init__(self, func): @@ -45,15 +43,13 @@ extract_varloc=extract_argloc const_vloc_visitor_t=const_aloc_visitor_t for_all_const_varlocs=for_all_const_arglocs for_all_varlocs=for_all_arglocs -@bc695redef def gen_decorate_name3(name, mangle, cc): return gen_decorate_name(name, mangle, cc, None) # ATM gen_decorate_name doesn't use its tinfo_t get_enum_member_expr2=get_enum_member_expr get_idainfo_by_type3=get_idainfo_by_type -@bc695redef def guess_func_tinfo2(pfn, tif): return guess_tinfo(pfn.start_ea, tif) -@bc695redef_with_pydoc(load_til.__doc__) +@bc695redef def load_til(name, tildir=None, *args): # 6.95 C++ prototypes # idaman til_t *ida_export load_til(const char *tildir, const char *name, char *errbuf, size_t bufsize); @@ -76,7 +72,6 @@ def load_til(name, tildir=None, *args): load_til2=load_til lower_type2=lower_type optimize_varloc=optimize_argloc -@bc695redef def parse_decl2(til, decl, tif, flags): return _ida_typeinf.parse_decl(tif, til, decl, flags) @bc695redef @@ -84,12 +79,10 @@ def print_type(ea, flags): if isinstance(flags, bool): flags = PRTYPE_1LINE if flags else 0 return _ida_typeinf.print_type(ea, flags) -@bc695redef def print_type2(ea, flags): return _ida_typeinf.print_type(ea, flags) print_type3=_ida_typeinf.print_type print_varloc=print_argloc -@bc695redef def resolve_typedef2(til, p, *args): return _ida_typeinf.resolve_typedef(til, p) scattered_vloc_t=scattered_aloc_t diff --git a/pywraps/py_ua.hpp b/pywraps/py_ua.hpp index 169d0cf..16fb92f 100644 --- a/pywraps/py_ua.hpp +++ b/pywraps/py_ua.hpp @@ -83,16 +83,31 @@ static int py_get_dtype_by_size(asize_t size) } //------------------------------------------------------------------------- -PyObject *py_get_immvals(ea_t ea, int n) +PyObject *py_get_immvals(ea_t ea, int n, flags_t F=0) { uvalvec_t storage; storage.resize(2 * UA_MAXOP); - flags_t F = get_flags(ea); + if ( F == 0 ) + F = get_flags(ea); size_t cnt = get_immvals(storage.begin(), ea, n, F); - PyObject *result = PyList_New(cnt); - for ( size_t i = 0; i < cnt; ++i ) - PyList_SetItem(result, i, Py_BuildValue(PY_BV_UVAL, bvuval_t(storage[i]))); - return result; + storage.resize(cnt); + ref_t result(PyW_UvalVecToPyList(storage)); + result.incref(); + return result.o; +} + +//------------------------------------------------------------------------- +PyObject *py_get_printable_immvals(ea_t ea, int n, flags_t F=0) +{ + uvalvec_t storage; + storage.resize(2 * UA_MAXOP); + if ( F == 0 ) + F = get_flags(ea); + size_t cnt = get_printable_immvals(storage.begin(), ea, n, F); + storage.resize(cnt); + ref_t result(PyW_UvalVecToPyList(storage)); + result.incref(); + return result.o; } //------------------------------------------------------------------------- diff --git a/pywraps/py_ua.py b/pywraps/py_ua.py index b94ddcf..c02e8bd 100644 --- a/pywraps/py_ua.py +++ b/pywraps/py_ua.py @@ -4,7 +4,6 @@ ua_mnem = print_insn_mnem #<pycode_BC695(py_ua)> import ida_idaapi -@bc695redef def codeSeg(ea, opnum): insn = insn_t() if decode_insn(insn, ea): @@ -17,7 +16,7 @@ get_dtyp_size=get_dtype_size get_operand_immvals=get_immvals op_t.dtyp = op_t.dtype cmd = insn_t() -@bc695redef_with_pydoc(decode_insn.__doc__) +@bc695redef def decode_insn(*args): if len(args) == 1: tmp = insn_t() @@ -26,7 +25,7 @@ def decode_insn(*args): return rc else: return _ida_ua.decode_insn(*args) -@bc695redef_with_pydoc(create_insn.__doc__) +@bc695redef def create_insn(*args): if len(args) == 1: tmp = insn_t() @@ -35,7 +34,7 @@ def create_insn(*args): return rc else: return _ida_ua.create_insn(*args) -@bc695redef_with_pydoc(decode_prev_insn.__doc__) +@bc695redef def decode_prev_insn(*args): if len(args) == 1: tmp = insn_t() @@ -44,7 +43,7 @@ def decode_prev_insn(*args): return rc else: return _ida_ua.decode_prev_insn(*args) -@bc695redef_with_pydoc(decode_preceding_insn.__doc__) +@bc695redef def decode_preceding_insn(*args): if len(args) == 1: tmp = insn_t() @@ -62,25 +61,18 @@ tbo_213=0 tbo_231=0 tbo_312=0 tbo_321=0 -@bc695redef def ua_add_cref(opoff, to, rtype): return cmd.add_cref(to, opoff, rtype) -@bc695redef def ua_add_dref(opoff, to, rtype): return cmd.add_dref(to, opoff, rtype) -@bc695redef def ua_add_off_drefs(x, rtype): return cmd.add_off_drefs(x, rtype, 0) -@bc695redef def ua_add_off_drefs2(x, rtype, outf): return cmd.add_off_drefs(x, rtype, outf) -@bc695redef def ua_dodata(ea, dtype): return cmd.create_op_data(ea, 0, dtype) -@bc695redef def ua_dodata2(opoff, ea, dtype): return cmd.create_op_data(ea, opoff, dtype) -@bc695redef def ua_stkvar2(x, v, flags): return cmd.create_stkvar(x, v, flags) #</pycode_BC695(py_ua)> diff --git a/pywraps/py_xref.hpp b/pywraps/py_xref.hpp index d2205bb..cfbc175 100644 --- a/pywraps/py_xref.hpp +++ b/pywraps/py_xref.hpp @@ -3,7 +3,6 @@ //<inline(py_xref)> // important for SWiG to generate properly-wrapped vector classes -typedef qvector<sval_t> svalvec_t; typedef qvector<svalvec_t> casevec_t; typedef qvector<ea_t> eavec_t; // diff --git a/pywraps/pywraps.vcproj b/pywraps/pywraps.vcproj index 4bcd7ba..a8b52e8 100644 --- a/pywraps/pywraps.vcproj +++ b/pywraps/pywraps.vcproj @@ -50,7 +50,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\..\include;c:\python26\include" - PreprocessorDefinitions="_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;__PYWRAPS__;_PYWRAPS_DEBUG" + PreprocessorDefinitions="_DEBUG;__NT__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;__PYWRAPS__;_PYWRAPS_DEBUG" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -151,7 +151,7 @@ Optimization="0" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\..\include;c:\python26\include" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -250,7 +250,7 @@ Optimization="0" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\..\include;c:\Python26\include" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;_PYWRAPS_DEBUG" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;_PYWRAPS_DEBUG" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -350,7 +350,7 @@ Optimization="0" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\include;c:\python26\include" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;_PYWRAPS_DEBUG;__EA64__" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;_PYWRAPS_DEBUG;__EA64__" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -451,7 +451,7 @@ Optimization="0" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\..\include;c:\python26\include" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;__EA64__;_PYWRAPS_DEBUG;__PYWRAPS__" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;__EA64__;_PYWRAPS_DEBUG;__PYWRAPS__" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -550,7 +550,7 @@ Optimization="0" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\..\include;c:\python26\include" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/swig/bytes.i b/swig/bytes.i index 124b90c..5573ddf 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -181,6 +181,9 @@ } } +//<typemaps(bytes)> +//</typemaps(bytes)> + %include "bytes.hpp" %apply (char *STRING, int LENGTH) { (const uchar *image, size_t len) }; diff --git a/swig/dbg.i b/swig/dbg.i index a984292..13d5524 100644 --- a/swig/dbg.i +++ b/swig/dbg.i @@ -8,7 +8,6 @@ %ignore dbg; %ignore register_srcinfo_provider; %ignore unregister_srcinfo_provider; -%ignore get_manual_regions; %ignore internal_cleanup_appcall; %ignore change_bptlocs; %ignore movbpt_info_t; @@ -27,31 +26,30 @@ %ignore bpt_t::get_cnd_elang; %ignore bpt_t::set_cnd_elang; %rename (get_manual_regions) py_get_manual_regions; -%ignore set_manual_regions; // TODO: This could be fixed (if needed) %ignore set_dbgmem_source; +// unusable functions because 'dbg' is not available: +%ignore have_set_options; +%ignore set_dbg_options; +%ignore set_int_dbg_options; +%ignore set_dbg_default_options; + +/* %ignore invalidate_dbg_state; */ +/* %ignore is_request_running; */ + %rename (list_bptgrps) py_list_bptgrps; %apply qstring *result { qstring *grp_name }; -%ignore qvector<bpt_t>::operator==; -%ignore qvector<bpt_t>::operator!=; -%ignore qvector<bpt_t>::find; -%ignore qvector<bpt_t>::has; -%ignore qvector<bpt_t>::del; -%ignore qvector<bpt_t>::add_unique; -%template(bpt_vec_t) qvector<bpt_t>; +%uncomparable_elements_qvector(bpt_t, bpt_vec_t); + %ignore write_dbg_memory; %rename (write_dbg_memory) py_write_dbg_memory; -%ignore qvector<memreg_info_t>::operator==; -%ignore qvector<memreg_info_t>::operator!=; -%ignore qvector<memreg_info_t>::find; -%ignore qvector<memreg_info_t>::has; -%ignore qvector<memreg_info_t>::del; -%ignore qvector<memreg_info_t>::add_unique; +%uncomparable_elements_qvector(tev_reg_value_t, tev_reg_values_t); +%uncomparable_elements_qvector(tev_info_reg_t, tevinforeg_vec_t); %ignore memreg_info_t::bytes; %rename (bytes) memreg_info_t_py_bytes; -%template(memreg_infos_t) qvector<memreg_info_t>; +%uncomparable_elements_qvector(memreg_info_t, memreg_infos_t); %ignore internal_get_sreg_base; %rename (internal_get_sreg_base) py_internal_get_sreg_base; @@ -64,11 +62,11 @@ bool run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD); bool request_run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD); +%ignore get_insn_tev_reg_val(int, const char *, uint64 *); +%ignore get_insn_tev_reg_result(int, const char *, uint64 *); + %thread; -%nonnul_argument_prototype( - inline bool idaapi load_debugger(const char *nonnul_dbgname, bool use_remote), - const char *nonnul_dbgname); %nonnul_argument_prototype( inline void idaapi set_debugger_event_cond(const char *nonnul_cond), const char *nonnul_cond); diff --git a/swig/expr.i b/swig/expr.i index 02d2caa..84f5614 100644 --- a/swig/expr.i +++ b/swig/expr.i @@ -94,13 +94,7 @@ } } -%ignore qvector<idc_value_t>::operator==; -%ignore qvector<idc_value_t>::operator!=; -%ignore qvector<idc_value_t>::find; -%ignore qvector<idc_value_t>::has; -%ignore qvector<idc_value_t>::del; -%ignore qvector<idc_value_t>::add_unique; -%template(idc_values_t) qvector<idc_value_t>; +%uncomparable_elements_qvector(idc_value_t, idc_values_t); %pythoncode %{ #<pycode(py_expr)> diff --git a/swig/funcs.i b/swig/funcs.i index 73f44ac..be336e3 100644 --- a/swig/funcs.i +++ b/swig/funcs.i @@ -1,6 +1,10 @@ %import "range.i" +%{ +#include <frame.hpp> +%} + // FIXME: Are these really useful? %ignore iterate_func_chunks; %ignore get_idasgn_header_by_short_name; @@ -17,6 +21,42 @@ %ignore func_md_t::cbsize; %ignore func_pat_t::cbsize; +%template (stkpnt_array) dynamic_wrapped_array_t<stkpnt_t>; +%template (regvar_array) dynamic_wrapped_array_t<regvar_t>; +%template (range_array) dynamic_wrapped_array_t<range_t>; + +%extend func_t +{ + dynamic_wrapped_array_t<stkpnt_t> __get_points__() + { + return dynamic_wrapped_array_t<stkpnt_t>($self->points, $self->pntqty); + } + + dynamic_wrapped_array_t<regvar_t> __get_regvars__() + { + if ( $self->regvarqty < 0 ) // force load + find_regvar($self, $self->start_ea, NULL); + return dynamic_wrapped_array_t<regvar_t>($self->regvars, $self->regvarqty); + } + + dynamic_wrapped_array_t<range_t> __get_tails__() + { + return dynamic_wrapped_array_t<range_t>($self->tails, $self->tailqty); + } + + %pythoncode { + points = property(__get_points__) + regvars = property(__get_regvars__) + tails = property(__get_tails__) + } +} + +//<typemaps(funcs)> +//</typemaps(funcs)> + +%apply ea_t *result { ea_t *fptr }; // calc_thunk_func_target() +%apply ea_t *appended_ea { ea_t *fptr }; + %include "funcs.hpp" %clear(char *buf); diff --git a/swig/graph.i b/swig/graph.i index 3ce2d40..a9536bf 100644 --- a/swig/graph.i +++ b/swig/graph.i @@ -33,7 +33,8 @@ %ignore mutable_graph_t::del_edge; %ignore mutable_graph_t::del_node; %ignore mutable_graph_t::fix_collapsed_group_edges; -%ignore mutable_graph_t::get_edge; +%ignore mutable_graph_t::get_edge(edge_t); +%rename (get_edge) my_get_edge; %ignore mutable_graph_t::groups_are_present; %ignore mutable_graph_t::insert_simple_nodes; %ignore mutable_graph_t::insert_visible_nodes; @@ -55,18 +56,22 @@ %ignore selection_item_t::selection_item_t(class graph_item_t &); %feature("nodirector") user_graph_place_t; -// Those were deprecated before they were available -// to IDAPython, so let's keep it that way. -%ignore viewer_add_menu_item; -%ignore viewer_del_menu_item; - %extend graph_visitor_t { public: virtual int idaapi visit_node(int /*n*/, rect_t & /*r*/) { return 0; } virtual int idaapi visit_edge(edge_t /*e*/, edge_info_t * /*ei*/) { return 0; } } +%extend mutable_graph_t { +public: + virtual edge_info_t my_get_edge(edge_t e) + { + return *($self->get_edge(e)); + } +} + %template(node_layout_t) qvector<rect_t>; +%template(pointvec_t) qvector<point_t>; %include "graph.hpp" %ignore graph_visitor_t::visit_node; diff --git a/swig/hexrays.i b/swig/hexrays.i index 02ed54f..3c04408 100644 --- a/swig/hexrays.i +++ b/swig/hexrays.i @@ -69,6 +69,7 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %ignore casm_t::print; %ignore cgoto_t::print; %ignore cexpr_t::is_aliasable; +%ignore cexpr_t::like_boolean; %ignore cexpr_t::contains_expr; %ignore cexpr_t::contains_expr; %ignore cexpr_t::cexpr_t(mbl_array_t *mba, const lvar_t &v); @@ -96,19 +97,19 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); // ignore microcode related stuff for now %ignore bitset_t; -%ignore ivlset_t; -%ignore ivl_t; %ignore mlist_t; %ignore rlist_t; %ignore mbl_array_t; +%ignore mbl_graph_t; %ignore mblock_t; %ignore minsn_t; %ignore mop_t; +%ignore mcode_t; %ignore mop_addr_t; %ignore mop_pair_t; %ignore mcases_t; -%ignore mfuncarg_t; -%ignore mfuncinfo_t; +%ignore mcallarg_t; +%ignore mcallinfo_t; %ignore mnumber_t; %ignore lvar_ref_t; %ignore stkvar_ref_t; @@ -116,6 +117,7 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %ignore op_parent_info_t; %ignore scif_visitor_t; %ignore mop_visitor_t; +%ignore mlist_mop_visitor_t; %ignore minsn_visitor_t; %ignore srcop_visitor_t; %ignore chain_t; @@ -126,21 +128,20 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %ignore block_chains_end; %ignore block_chains_erase; %ignore block_chains_find; -%ignore block_chains_first; %ignore block_chains_free; +%ignore block_chains_get; %ignore block_chains_insert; %ignore block_chains_new; %ignore block_chains_next; %ignore block_chains_prev; -%ignore block_chains_second; %ignore block_chains_size; %ignore graph_chains_t; %ignore chain_visitor_t; +%ignore gctype_t; %ignore simple_graph_t; -%ignore mcode_t; %ignore get_signed_mcode; %ignore get_unsigned_mcode; -%ignore is_dest_target_mcode; +%ignore mcode_modifies_d; %ignore is_may_access; %ignore is_mcode_addsub; %ignore is_mcode_call; @@ -158,6 +159,8 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %ignore is_mcode_xdsu; %ignore is_signed_mcode; %ignore is_unsigned_mcode; +%ignore is_kreg; +%ignore get_first_stack_reg; %ignore jcnd2set; %ignore must_mcode_close_block; %ignore negate_mcode_relation; @@ -186,6 +189,24 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %ignore mba_range_iterator_t; %ignore mba_ranges_t; %ignore deserialize_mbl_array; +%ignore get_temp_regs; +%ignore ivl_t; +%ignore ivlset_t; +%ignore ivl_with_name_t; +%ignore vivl_t; +%ignore voff_t; +%ignore voff_set_t; +%ignore gco_info_t; +%ignore get_current_operand; +%ignore valrng_t; + +// "Warning 473: Returning a pointer or reference in a director method is not recommended." +// In this particular case, we are telling SWiG that the object is always a +// %newobject (thus: even for base classes), but it seems it's not enough to +// shut the warning up. +%warnfilter(473) codegen_t::emit_micro_mvm; +%newobject codegen_t::emit_micro_mvm; +%newobject codegen_t::emit; %apply uchar { char ignore_micro }; %feature("nodirector") udc_filter_t::apply; @@ -209,10 +230,19 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %rename (_ll_make_num) make_num; %rename (_ll_create_helper) create_helper; - %extend cfunc_t { %immutable argidx; + PyObject *find_item_coords(const citem_t *item) + { + int px = 0; + int py = 0; + if ( $self->find_item_coords(item, &px, &py) ) + return Py_BuildValue("(ii)", px, py); + else + return Py_BuildValue("(OO)", Py_None, Py_None); + } + qstring __str__() const { qstring qs; qstring_printer_t p($self, qs, 0); @@ -241,26 +271,13 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %rename(dereference_uint16) operator uint16*; %rename(dereference_const_uint16) operator const uint16*; -#if !defined(__MAC__) || (MACSDKVER >= 1006) -#define HAS_MAP_AT -#endif - // Provide trivial std::map facade so basic operations are available. template<class key_type, class mapped_type> class std::map { public: -#ifdef HAS_MAP_AT mapped_type& at(const key_type& _Keyval); -#endif size_t size() const; }; -#ifndef HAS_MAP_AT -#warning "std::map doesn't provide at(). Augmenting it." -%extend std::map { - mapped_type& at(const key_type& _Keyval) { return $self->operator[](_Keyval); } -} -#endif - //------------------------------------------------------------------------- %typemap(check) citem_t *self { @@ -307,6 +324,11 @@ public: _get_op, lambda self, v: self._ensure_no_op() and self._set_op(v)) + def _ensure_cond(self, ok, cond_str): + if not ok: + raise Exception("Condition \"%s\" not verified" % cond_str) + return True + def _ensure_no_op(self): if self.op not in [cot_empty, cit_empty]: raise Exception("%s has op %s; cannot be modified" % (self, self.op)) @@ -368,7 +390,8 @@ public: %pythoncode { \ PName = property( \ lambda self: self._get_##PName() if Cond else Defval, \ - lambda self, v: Cond \ + lambda self, v: \ + self._ensure_cond(Cond, #Cond) \ and self._ensure_no_obj(self._get_##PName(), #PName, Acquire) \ and self._acquire_ownership(v, Acquire) \ and self._set_##PName(v)) \ @@ -517,10 +540,10 @@ public: /* for qvector instanciations where the class is a pointer (cinsn_t, citem_t) we need to fix the at() return type, otherwise swig mistakenly thinks it is "cinsn_t *&" and nonsense ensues. */ %extend qvector< cinsn_t *> { - cinsn_t *at(size_t n) { return self->at(n); } + cinsn_t *at(size_t n) { return self->at(n); } }; %extend qvector< citem_t *> { - citem_t *at(size_t n) { return self->at(n); } + citem_t *at(size_t n) { return self->at(n); } }; // ignore future declarations of at() for these classes @@ -531,11 +554,6 @@ public: %ignore qvector< citem_t *>::grow; %ignore qvector< cinsn_t *>::grow; - -//~ %template(qwstrvec_t) qvector<qwstring>; // vector of unicode strings -typedef intvec_t svalvec_t; // vector of signed values -//typedef intvec_t eavec_t;// vector of addresses - // At this point, SWIG doesn't know about this // type yet (kernwin.i is included later). Therefore, // unless we do this, swig will consider 'strvec_t' to be @@ -560,6 +578,15 @@ typedef qvector<simpleline_t> strvec_t; %template(eamap_t) std::map<ea_t, cinsnptrvec_t>; %template(boundaries_t) std::map<cinsn_t *, rangeset_t>; +%define %constify_iterator_value(NameBase, ReturnType) +%ignore NameBase ## _second; +%rename (NameBase ## _second) py_ ## NameBase ## _second; +%inline %{ +inline const ReturnType &py_ ## NameBase ## _second(NameBase ## _iterator_t p) { return NameBase ## _second(p); } +%} +%enddef +%constify_iterator_value(user_iflags, int32); + %ignore boundaries_find; %rename (boundaries_find) py_boundaries_find; %ignore boundaries_insert; @@ -605,7 +632,9 @@ typedef qlist<cinsn_t>::iterator qlist_cinsn_t_iterator; class qlist_cinsn_t_iterator {}; %extend qlist_cinsn_t_iterator { const cinsn_t &cur { return *(*self); } - qlist_cinsn_t_iterator &next(void) { (*self)++; return *self; } + void next(void) { (*self)++; } + bool operator==(const qlist_cinsn_t_iterator *x) const { return &(self->operator*()) == &(x->operator*()); } + bool operator!=(const qlist_cinsn_t_iterator *x) const { return &(self->operator*()) != &(x->operator*()); } }; %extend qlist<cinsn_t> { @@ -673,10 +702,7 @@ void qswap(cinsn_t &a, cinsn_t &b); %rename(init_hexrays_plugin) py_init_hexrays_plugin; %ignore install_hexrays_callback; -%rename(install_hexrays_callback) py_install_hexrays_callback; - %ignore remove_hexrays_callback; -%rename(remove_hexrays_callback) py_remove_hexrays_callback; %ignore decompile_many; %rename (decompile_many) py_decompile_many; @@ -726,7 +752,7 @@ void qswap(cinsn_t &a, cinsn_t &b); } %enddef -%python_callback_in(PyObject *hx_cblist_callback); +%python_callback_in(PyObject *hx_callback); %python_callback_in(PyObject *custom_viewer_popup_item_callback); %ignore cexpr_t::get_1num_op(const cexpr_t **, const cexpr_t **) const; @@ -766,10 +792,27 @@ void qswap(cinsn_t &a, cinsn_t &b); //</inline(py_hexrays)> %} +%ignore Hexrays_Callback; + +%inline %{ +//<inline(py_hexrays_hooks)> +//</inline(py_hexrays_hooks)> +%} + +%{ +//<code(py_hexrays_hooks)> +//</code(py_hexrays_hooks)> +%} + %include "hexrays.hpp" %exception; // Delete & restore handlers %exception_set_default_handlers(); +// These are microcode-related. Let's not expose them right now. +/* %template(ivl_t) ivl_tpl<uval_t>; */ +/* %template(ivlset_t) ivlset_tpl<ivl_t, uval_t>; */ +/* %template(array_of_ivlsets) qvector<ivlset_t>; */ + %pythoncode %{ #<pycode(py_hexrays)> #</pycode(py_hexrays)> diff --git a/swig/idd.i b/swig/idd.i index 44161ad..3086530 100644 --- a/swig/idd.i +++ b/swig/idd.i @@ -5,10 +5,11 @@ #include <err.h> %} +%import "range.i" + %ignore free_debug_event; %ignore copy_debug_event; %ignore debugger_t; -%ignore memory_info_t; %ignore lowcnd_t; %ignore lowcnd_vec_t; %ignore update_bpt_info_t; @@ -20,23 +21,10 @@ %ignore debug_event_t::exit_code(); %apply unsigned char { op_dtype_t dtype }; -%ignore qvector<exception_info_t>::operator==; -%ignore qvector<exception_info_t>::operator!=; -%ignore qvector<exception_info_t>::find; -%ignore qvector<exception_info_t>::has; -%ignore qvector<exception_info_t>::del; -%ignore qvector<exception_info_t>::add_unique; -%template(excvec_t) qvector<exception_info_t>; - -%ignore qvector<process_info_t>::operator==; -%ignore qvector<process_info_t>::operator!=; -%ignore qvector<process_info_t>::find; -%ignore qvector<process_info_t>::has; -%ignore qvector<process_info_t>::del; -%ignore qvector<process_info_t>::add_unique; - -%template(procinfo_vec_t) qvector<process_info_t>; +%uncomparable_elements_qvector(exception_info_t, excvec_t); +%uncomparable_elements_qvector(process_info_t, procinfo_vec_t); %template(call_stack_t) qvector<call_stack_info_t>; +%template(meminfo_vec_t) qvector<memory_info_t>; %include "idd.hpp" diff --git a/swig/kernwin.i b/swig/kernwin.i index efef604..224abde 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -1,5 +1,6 @@ %{ #include <kernwin.hpp> +#include <parsejson.hpp> %} %{ @@ -10,6 +11,13 @@ extern plugin_t PLUGIN; #endif %} + +%typemap(out) void *get_window_id +{ + // %typemap(out) void *get_window_id + $result = PyLong_FromUnsignedLongLong((unsigned long long) $1); +} + // Ignore the va_list functions %ignore vask_form; %ignore ask_form; @@ -27,6 +35,18 @@ extern plugin_t PLUGIN; %ignore vask_text; %ignore ask_text; %ignore vwarning; +// Note: don't do that for ask_form(), since that calls back into Python. +%thread ask_addr; +%thread ask_seg; +%thread ask_long; +%thread ask_yn; +%thread ask_buttons; +%thread ask_file; + +%calls_execute_sync(clr_cancelled); +%calls_execute_sync(set_cancelled); +%calls_execute_sync(user_cancelled); +%calls_execute_sync(hide_wait_box); %ignore choose_idasgn; %rename (choose_idasgn) py_choose_idasgn; @@ -40,9 +60,6 @@ extern plugin_t PLUGIN; %ignore msg; %rename (msg) py_msg; -%ignore umsg; -%rename (umsg) py_umsg; - %ignore vinfo; %ignore UI_Callback; %ignore vnomem; @@ -110,18 +127,15 @@ extern plugin_t PLUGIN; %rename (_ask_addr) ask_addr; %rename (_ask_seg) ask_seg; -%ignore qvector<disasm_line_t>::operator==; -%ignore qvector<disasm_line_t>::operator!=; -%ignore qvector<disasm_line_t>::find; -%ignore qvector<disasm_line_t>::has; -%ignore qvector<disasm_line_t>::del; -%ignore qvector<disasm_line_t>::add_unique; - %ignore gen_disasm_text; %rename (gen_disasm_text) py_gen_disasm_text; %ignore UI_Hooks::handle_hint_output; %ignore UI_Hooks::handle_get_ea_hint_output; +%ignore UI_Hooks::wrap_widget_cfg; +%ignore UI_Hooks::handle_create_desktop_widget_output; +%ignore jobj_wrapper_t::jobj_wrapper_t; +%ignore jobj_wrapper_t::~jobj_wrapper_t; // We will %ignore those ATM, since they cannot be trivially // wrapped: bytevec_t is not exposed. @@ -176,7 +190,7 @@ struct py_action_handler_t : public action_handler_t if ( !has_activate ) return 0; PYW_GIL_GET_AND_REPORT_ERROR; - newref_t pyctx(SWIG_NewPointerObj(SWIG_as_voidptr(ctx), SWIGTYPE_p_action_activation_ctx_t, 0)); + newref_t pyctx(SWIG_NewPointerObj(SWIG_as_voidptr(ctx), SWIGTYPE_p_action_ctx_base_t, 0)); newref_t pyres(PyObject_CallMethod(pyah.o, (char *)"activate", (char *) "O", pyctx.o)); return PyErr_Occurred() ? 0 : ((pyres != NULL && PyInt_Check(pyres.o)) ? PyInt_AsLong(pyres.o) : 0); } @@ -185,7 +199,7 @@ struct py_action_handler_t : public action_handler_t if ( !has_update ) return AST_DISABLE; PYW_GIL_GET_AND_REPORT_ERROR; - newref_t pyctx(SWIG_NewPointerObj(SWIG_as_voidptr(ctx), SWIGTYPE_p_action_update_ctx_t, 0)); + newref_t pyctx(SWIG_NewPointerObj(SWIG_as_voidptr(ctx), SWIGTYPE_p_action_ctx_base_t, 0)); newref_t pyres(PyObject_CallMethod(pyah.o, (char *)"update", (char *) "O", pyctx.o)); return PyErr_Occurred() ? AST_DISABLE_ALWAYS : ((pyres != NULL && PyInt_Check(pyres.o)) ? action_state_t(PyInt_AsLong(pyres.o)) : AST_DISABLE); } @@ -207,9 +221,13 @@ void refresh_choosers(void) } %} -# This is for get_cursor() +// get_cursor() %apply int *OUTPUT {int *x, int *y}; +// get_navband_pixel() +%apply bool *OUTPUT {bool *out_is_vertical}; + + %ignore textctrl_info_t; SWIG_DECLARE_PY_CLINKED_OBJECT(textctrl_info_t) @@ -239,9 +257,12 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); %ignore remove_command_interpreter; %rename (remove_command_interpreter) py_remove_command_interpreter; +//<typemaps(kernwin)> +//</typemaps(kernwin)> + %include "kernwin.hpp" -%template(disasm_text_t) qvector<disasm_line_t>; +%uncomparable_elements_qvector(disasm_line_t, disasm_text_t); %extend action_desc_t { action_desc_t( @@ -283,8 +304,6 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); %extend action_ctx_base_t { - int _get_reg() const { return $self->reg; } - #ifdef BC695 TWidget *_get_form() const { return $self->widget; } twidget_type_t _get_form_type() const { return $self->widget_type; } @@ -292,7 +311,6 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); #endif %pythoncode { - reg = property(_get_reg) #ifdef BC695 form = property(_get_form) form_type = property(_get_form_type) diff --git a/swig/lines.i b/swig/lines.i index b231b5f..c297d64 100644 --- a/swig/lines.i +++ b/swig/lines.i @@ -34,6 +34,24 @@ %ignore tag_advance; %rename (tag_advance) py_tag_advance; +%typemap(argout) (qstring *buf, ea_t ea, int what) +{ + // typemap(argout) (qstring *buf, ea_t ea, int what) + Py_XDECREF(resultobj); + if (result >= 0) + { + resultobj = PyString_FromStringAndSize((const char *) $1->c_str(), $1->length()); + } + else + { + Py_INCREF(Py_None); + resultobj = Py_None; + } +} + +//<typemaps(lines)> +//</typemaps(lines)> + %include "lines.hpp" %{ diff --git a/swig/loader.i b/swig/loader.i index cdfe883..b679547 100644 --- a/swig/loader.i +++ b/swig/loader.i @@ -77,6 +77,8 @@ %rename (load_plugin) py_load_plugin; %ignore run_plugin; %rename (run_plugin) py_run_plugin; +%ignore load_and_run_plugin; +%rename (load_and_run_plugin) py_load_and_run_plugin; %extend qvector< snapshot_t *> { snapshot_t *at(size_t n) { return self->at(n); } diff --git a/swig/name.i b/swig/name.i index b9ed913..7b19091 100644 --- a/swig/name.i +++ b/swig/name.i @@ -28,6 +28,8 @@ %ignore get_demangled_name(qstring *, ea_t, int32, int, int); %ignore get_colored_demangled_name(qstring *, ea_t, int32, int, int); +%uncomparable_elements_qvector(ea_name_t, ea_name_vec_t); + // get_name & get_colored_name have prototypes such that, // once converted to IDAPython, would be problematic because it'd // be impossible for SWiG to tell apart the (ea_t, ea_t) version @@ -50,10 +52,6 @@ inline qstring py_## FNAME(ea_t ea) { return FNAME(ea); } %restrict_ambiguous_name_function(get_name); %restrict_ambiguous_name_function(get_colored_name); - -%ignore get_debug_names; -%rename (get_debug_names) py_get_debug_names; - %ignore validate_name; %rename (validate_name) py_validate_name; diff --git a/swig/pro.i b/swig/pro.i index 9114436..9668549 100644 --- a/swig/pro.i +++ b/swig/pro.i @@ -21,6 +21,7 @@ %ignore utf8_wchar16; %ignore utf8_wchar32; %ignore skip_utf8; +%ignore qustrncpy; %ignore expand_argv; %ignore free_argv; %ignore qwait; @@ -28,6 +29,12 @@ %ignore qwait_timed; %ignore ida_true_type; %ignore ida_false_type; +%ignore bitcount; +%ignore round_up_power2; +%ignore round_down_power2; + +//<typemaps(pro)> +//</typemaps(pro)> %include "pro.h" @@ -39,12 +46,27 @@ %import "netnode.hpp" // +void qvector<int>::grow(const int &x=0); +%ignore qvector<int>::grow; +void qvector<unsigned int>::grow(const unsigned int &x=0); +%ignore qvector<unsigned int>::grow; +void qvector<long long>::grow(const long long &x=0); +%ignore qvector<long long>::grow; +void qvector<unsigned long long>::grow(const unsigned long long &x=0); +%ignore qvector<unsigned long long>::grow; + //--------------------------------------------------------------------- -%template(uvalvec_t) qvector<uval_t>; // unsigned values -%template(intvec_t) qvector<int>; -%template(int64vec_t) qvector<long long>; // for EA64 svalvec_t objects -%template(boolvec_t) qvector<bool>; -%template(strvec_t) qvector<simpleline_t>; +%template(intvec_t) qvector<int>; +%template(uintvec_t) qvector<unsigned int>; +%template(longlongvec_t) qvector<long long>; +%template(ulonglongvec_t) qvector<unsigned long long>; +%template(boolvec_t) qvector<bool>; + +%pythoncode %{ +%} + + +%uncomparable_elements_qvector(simpleline_t, strvec_t); %template(sizevec_t) qvector<size_t>; typedef uvalvec_t eavec_t;// vector of addresses diff --git a/swig/registry.i b/swig/registry.i index 2afb0ec..bbfde92 100644 --- a/swig/registry.i +++ b/swig/registry.i @@ -46,4 +46,7 @@ //</inline(py_registry)> %} +//<typemaps(registry)> +//</typemaps(registry)> + %include "registry.hpp" diff --git a/swig/segment.i b/swig/segment.i index 69cbe1f..f42d26f 100644 --- a/swig/segment.i +++ b/swig/segment.i @@ -40,6 +40,9 @@ *($2) = BADADDR; } +//<typemaps(py_segment)> +//</typemaps(py_segment)> + %include "segment.hpp" %inline %{ diff --git a/swig/struct.i b/swig/struct.i index f75660d..899cd30 100644 --- a/swig/struct.i +++ b/swig/struct.i @@ -37,7 +37,7 @@ %typemap(argout) struc_t **sptr_place { if ( result ) { - %append_output(SWIG_NewPointerObj(SWIG_as_voidptr($1), SWIGTYPE_p_struc_t, 0 | 0 )); + %append_output(SWIG_NewPointerObj(SWIG_as_voidptr(*($1)), SWIGTYPE_p_struc_t, 0 | 0 )); } else { diff --git a/swig/typeinf.i b/swig/typeinf.i index 009fa6e..019fe95 100644 --- a/swig/typeinf.i +++ b/swig/typeinf.i @@ -32,7 +32,6 @@ %ignore til_next_macro; %ignore parse_subtype; -%ignore calc_type_size; %ignore descr_t; @@ -94,7 +93,6 @@ %ignore max_ptr_size; %ignore based_ptr_name_and_size; -%ignore apply_type; %ignore apply_callee_type; %ignore get_arg_addrs; %rename (get_arg_addrs) py_get_arg_addrs; @@ -103,7 +101,9 @@ %ignore idb_type_to_til; %ignore get_idb_type; +%ignore calc_type_size; %rename (calc_type_size) py_calc_type_size; +%ignore apply_type; %rename (apply_type) py_apply_type; %ignore use_regarg_type_cb; @@ -128,6 +128,8 @@ %ignore func_type_data_t::serialize; %ignore func_type_data_t::deserialize; %ignore tinfo_t::serialize(qtype *, qtype *, qtype *, int) const; +%ignore name_requires_qualifier; +%ignore tinfo_visitor_t::level; %ignore custloc_desc_t; %ignore install_custom_argloc; @@ -164,18 +166,6 @@ return $self->deserialize(til, &type, &fields, cmts == NULL ? NULL : &cmts); } - bool deserialize( - const til_t *til, - const char *_type, - const char *_fields, - const char *_cmts = NULL) - { - const type_t *type = (const type_t *) _type; - const p_list *fields = (const p_list *) _fields; - const p_list *cmts = (const p_list *) _cmts; - return $self->deserialize(til, &type, &fields, cmts == NULL ? NULL : &cmts); - } - // The typemap in typeconv.i will take care of registering newly-constructed // tinfo_t instances. However, there's no such thing as a destructor typemap. // Therefore, we need to do the grunt work of de-registering ourselves. @@ -215,7 +205,7 @@ } } %enddef -%simple_tinfo_t_container_lifecycle(ptr_type_data_t, (tinfo_t c=tinfo_t(), uchar bps=0), (c, bps)); +%simple_tinfo_t_container_lifecycle(ptr_type_data_t, (tinfo_t c=tinfo_t(), uchar bps=0, tinfo_t p=tinfo_t(), int32 d=0), (c, bps, p, d)); %simple_tinfo_t_container_lifecycle(array_type_data_t, (size_t b=0, size_t n=0), (b, n)); %simple_tinfo_t_container_lifecycle(func_type_data_t, (), ()); %simple_tinfo_t_container_lifecycle(udt_type_data_t, (), ()); @@ -223,13 +213,7 @@ %template(funcargvec_t) qvector<funcarg_t>; %template(udtmembervec_t) qvector<udt_member_t>; %template(reginfovec_t) qvector<reg_info_t>; -%ignore qvector<type_attr_t>::operator==; -%ignore qvector<type_attr_t>::operator!=; -%ignore qvector<type_attr_t>::find; -%ignore qvector<type_attr_t>::has; -%ignore qvector<type_attr_t>::del; -%ignore qvector<type_attr_t>::add_unique; -%template(type_attrs_t) qvector<type_attr_t>; +%uncomparable_elements_qvector(type_attr_t, type_attrs_t); %extend tinfo_t { PyObject *get_attr(const qstring &key, bool all_attrs=true) @@ -261,6 +245,23 @@ char *buf, size_t bufsize); // idc_guess_type, idc_get_type +// set_numbered_type() +%typemap(in) const sclass_t * { + // %typemap(in) const sclass_t * + if ( $input == Py_None ) + $1 = new sclass_t(sc_unk); + else if ( PyInt_Check($input) ) + $1 = new sclass_t(sclass_t(PyInt_AsLong($input))); + else + SWIG_exception_fail( + SWIG_ValueError, + "invalid argument " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'"); +} +%typemap(freearg) const sclass_t * { + // %typemap(freearg) const sclass_t * + delete $1; +} + %include "typeinf.hpp" // Custom wrappers diff --git a/swig/ua.i b/swig/ua.i index 3e8e5ec..21de246 100644 --- a/swig/ua.i +++ b/swig/ua.i @@ -10,6 +10,9 @@ %ignore decode_preceding_insn; %ignore get_operand_immvals; %ignore get_immvals; +%rename (get_immvals) py_get_immvals; +%ignore get_printable_immvals; +%rename (get_printable_immvals) py_get_printable_immvals; %ignore get_immval; %ignore insn_create_op_data; @@ -142,7 +145,6 @@ %include "ua.hpp" %rename (decode_preceding_insn) py_decode_preceding_insn; -%rename (get_immvals) py_get_immvals; %{ //<code(py_ua)> diff --git a/tools/bc695.org b/tools/bc695.org deleted file mode 100644 index 38eaf23..0000000 --- a/tools/bc695.org +++ /dev/null @@ -1,9 +0,0 @@ -* DONE need to support all modules -* DONE cleanup idc.idc; have a map of correspondances so that we don't need /*ida_...*/ in idc.idc. -* TODO need a chooser_t-backed Chooser2 impl. -* TODO need a graph_viewer_t(or something)-backed GraphViewer impl. -* TODO re-enalbe those: EMPTY_SEL=chooser_t.NO_SELECTION -* TODO kernwin.py: add tests about add_menu_item/del_menu_item; it should be trivial to simulate with actions -* DONE inf.minEA, inf.maxEA -- super frequent! -* DONE ida_typeinf.cvar.idati doesn't exist anymore. Make it re-appear -* DONE re-instate AddCommand on Choose2 & GraphViewer diff --git a/tools/call_dmpapis.sh b/tools/call_dmpapis.sh deleted file mode 100755 index 02087a0..0000000 --- a/tools/call_dmpapis.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -PWD=`pwd` -API695=${PWD}/api695.txt -API700=${PWD}/api700.txt -TVHEADLESS=1 $IDAXBIN/idat -t -A "-S${PWD}/dmpapi.py ${API700}" > /dev/null -LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$IDA695OPTBIN TVHEADLESS=1 $IDA695OPTBIN/idal -t -A "-S${PWD}/dmpapi.py ${API695}" > /dev/null - -python cmpapi.py --api-695 ${API695} --api-700 ${API700} diff --git a/tools/chkapi.py b/tools/chkapi.py index 051b239..48415ad 100644 --- a/tools/chkapi.py +++ b/tools/chkapi.py @@ -86,8 +86,15 @@ def check_cpp(opts): "mustcall" : "PyString_FromStringAndSize", }, "_wrap_get_ip_val" : { - "string" : "resultobj = PyLong_FromUnsigned", + "string" : "resultobj = PyLong_FromUnsigned", }, + "_wrap_calc_thunk_func_target" : { + "string" : ["SWIG_Python_AppendOutput", "PyLong_FromUnsigned"], + }, + "SwigDirector_UI_Hooks::populating_widget_popup" : { + "string" : "get_callable_arg_count", + }, + # "_wrap_get_array_parameters" : { # "string" : "resultobj = PyLong_FromLongLong(result)", # }, @@ -147,7 +154,6 @@ def check_cpp(opts): "nullptrcheck" : 1, }, "_wrap_load_debugger" : { - "nullptrcheck" : 1, "string" : ["SWIG_PYTHON_THREAD_BEGIN_ALLOW", "SWIG_PYTHON_THREAD_END_ALLOW"], }, "_wrap_AssembleLine" : { @@ -162,7 +168,7 @@ def check_cpp(opts): "nostring" : ["SWIGTYPE_p_qoff64_t", "qoff64_t *"], }, - } + } functions_coherence_hexrays = { "_wrap_cfuncptr_t___str__" : { @@ -403,14 +409,13 @@ def check_python(opts): "regvar_t" : { "mustinherit" : "ida_range.range_t" }, "segment_t" : { "mustinherit" : "ida_range.range_t" }, "sreg_range_t" : { "mustinherit" : "ida_range.range_t" }, + "memory_info_t" : { "mustinherit" : "ida_range.range_t" }, "GraphViewer" : { "mustinherit" : "ida_kernwin.CustomIDAMemo" }, "IDAViewWrapper" : { "mustinherit" : "CustomIDAMemo" }, "PyIdc_cvt_int64__" : { "mustinherit" : "pyidc_cvt_helper__" }, "PyIdc_cvt_refclass__" : { "mustinherit" : "pyidc_cvt_helper__" }, "_qstrvec_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, - "action_activation_ctx_t" : { "mustinherit" : "action_ctx_base_t" }, - "action_update_ctx_t" : { "mustinherit" : "action_ctx_base_t" }, "argpart_t" : { "mustinherit" : "argloc_t" }, "cli_t" : { "mustinherit" : "ida_idaapi.pyidc_opaque_object_t" }, "enumplace_t" : { "mustinherit" : "place_t" }, @@ -457,6 +462,7 @@ def check_python(opts): "qstring_printer_t" : { "mustinherit" : "vc_printer_t" }, "vc_printer_t" : { "mustinherit" : "vd_printer_t" }, "vd_interr_t" : { "mustinherit" : "vd_failure_t" }, + # "vivl_t" : { "mustinherit" : "ivl_t" }, } types_coherence = types_coherence_base.copy() diff --git a/tools/cmpapi.py b/tools/cmpapi.py deleted file mode 100644 index b3c5953..0000000 --- a/tools/cmpapi.py +++ /dev/null @@ -1,722 +0,0 @@ - -import argparse -p = argparse.ArgumentParser() -p.add_argument("--api-695", required=True, help="Path to the 6.95 API desc file") -p.add_argument("--api-700", required=True, help="Path to the 7.00 API desc file") - -args = p.parse_args() -with open(args.api_695, "r") as fin: - api_695 = eval(fin.read()) -with open(args.api_700, "r") as fin: - api_700 = eval(fin.read()) - -renamed_modules = { - "ida_area" : "ida_range", - "ida_queue" : "ida_problems", - "ida_srarea" : "ida_segregs", - "ida_queue" : "ida_problems", - "ida_ints" : "ida_bytes", -} - -renamed_symbols = { - "ida_area" : { - "AREACB_TYPE_FUNC" : "RANGE_KIND_FUNC", - "AREACB_TYPE_FUNC" : "RANGE_KIND_FUNC", - "AREACB_TYPE_HIDDEN_AREA" : "RANGE_KIND_HIDDEN_RANGE", - "AREACB_TYPE_SEGMENT" : "RANGE_KIND_SEGMENT", - "AREACB_TYPE_UNKNOWN" : "RANGE_KIND_UNKNOWN", - "area_t_print(*args)" : "range_t_print(*args)", - "areavec_t" : "rangevec_t", - }, - - "ida_auto" : { - "analyze_area" : "plan_and_wait", - "autoCancel" : "auto_cancel", - "autoIsOk" : "auto_is_ok", - "autoMark" : "auto_mark", - "autoUnmark" : "auto_unmark", - "autoWait" : "auto_wait", - }, - - "ida_bytes" : { - "doExtra(_)" : "doExtra(_, *args)", - "noExtra(_)" : "noExtra(_, *args)", - "do3byte(*args)" : "do3byte(_, *args)", - "f_is3byte(*args)" : "f_is3byte(_, *args)", - "get_3byte(*args)" : "get_3byte(_, *args)", - "is3byte(*args)" : "is3byte(_, *args)", - "invalidate_visea_cache(*args)" : "invalidate_visea_cache(_, *args)", - }, - - "ida_dbg" : { - "get_tev_reg_mem_ea(*args)" : "get_tev_reg_mem_ea(_, _)", - "get_tev_reg_mem_qty(*args)" : "get_tev_reg_mem_qty(_)", - "get_tev_reg_val(*args)" : "get_tev_reg_val(_, _)", - }, - - "ida_frame" : { - "ida_area" : "ida_range", - - }, - - "ida_funcs" : { - "ida_area" : "ida_range", - - }, - - "ida_gdl" : { - "ida_area" : "ida_range", - - }, - - "ida_hexrays" : { - "call_helper(*args)" : "call_helper(_, _, *rest)", - "dereference(*args)" : "dereference(_, _, =False)", - "lnot(*args)" : "lnot(_)", - "make_ref(*args)" : "make_ref(_)", - "new_block(*args)" : "new_block()", - }, - - "ida_ida" : { - "ansi2idb(*args)" : "ansi2idb(_, _)", - "idb2scr(*args)" : "idb2scr(_, _)", - "scr2idb(*args)" : "scr2idb(_, _)", - }, - - "ida_kernwin" : { - "TODO" : [ - "Choose", - "EMPTY_SEL", - "END_SEL", - "START_SEL", - ], - "askident(*args)" : "askident(_, _)", - }, - - "ida_nalt" : { - "switch_info_ex_t_assign" : "switch_info_t_assign", - "switch_info_ex_t_create" : "switch_info_t_create", - "switch_info_ex_t_destroy" : "switch_info_t_destroy", - "switch_info_ex_t_get_custom" : "switch_info_t_get_custom", - "switch_info_ex_t_get_defjump" : "switch_info_t_get_defjump", - "switch_info_ex_t_get_elbase" : "switch_info_t_get_elbase", - "switch_info_ex_t_get_flags" : "switch_info_t_get_flags", - "switch_info_ex_t_get_ind_lowcase" : "switch_info_t_get_ind_lowcase", - "switch_info_ex_t_get_jcases" : "switch_info_t_get_jcases", - "switch_info_ex_t_get_jumps" : "switch_info_t_get_jumps", - "switch_info_ex_t_get_ncases" : "switch_info_t_get_ncases", - "switch_info_ex_t_get_regdtyp" : "switch_info_t_get_regdtyp", - "switch_info_ex_t_get_regnum" : "switch_info_t_get_regnum", - "switch_info_ex_t_get_startea" : "switch_info_t_get_startea", - "switch_info_ex_t_get_values_lowcase" : "switch_info_t_get_values_lowcase", - "switch_info_ex_t_set_custom" : "switch_info_t_set_custom", - "switch_info_ex_t_set_defjump" : "switch_info_t_set_defjump", - "switch_info_ex_t_set_elbase" : "switch_info_t_set_elbase", - "switch_info_ex_t_set_flags" : "switch_info_t_set_flags", - "switch_info_ex_t_set_ind_lowcase" : "switch_info_t_set_ind_lowcase", - "switch_info_ex_t_set_jcases" : "switch_info_t_set_jcases", - "switch_info_ex_t_set_jumps" : "switch_info_t_set_jumps", - "switch_info_ex_t_set_ncases" : "switch_info_t_set_ncases", - "switch_info_ex_t_set_regdtyp" : "switch_info_t_set_regdtyp", - "switch_info_ex_t_set_regnum" : "switch_info_t_set_regnum", - "switch_info_ex_t_set_startea" : "switch_info_t_set_startea", - "switch_info_ex_t_set_values_lowcase" : "switch_info_t_set_values_lowcase", - }, - - "ida_segment" : { - "ida_area" : "ida_range", - }, - - "ida_srarea" : { - "ida_area" : "ida_range", - "is_segreg_locked(*args)" : "is_segreg_locked(_, *args)", - }, - - "ida_typeinf" : { - "callregs_init_regs(*args)" : "callregs_init_regs(_, *args)", - "print_type3(*args)" : "print_type", - }, - - "idc" : { - "Fatal(_)" : "Fatal(*args)", - "Warning(_)" : "Warning(*args)", - }, -} - -removed_symbols = { - - "ida_allins" : [ - "NN_vmovntsd", - "NN_vmovntss", - ], - - "ida_area" : [ - "AREACB_TYPE_SRAREA", - "area_visitor2_t", - "areacb_t", - "lock_area", - ], - - "ida_auto" : [ - "autoGetName", - "autoStep", - ], - - "ida_bytes" : [ - "cvar", - # the following have been removed - "doVar", - "f_isUnknown", - "getRadixEA", - "get_data_type_size", - "get_typeinfo", - "ida_area", - "isVar", - "lowbits", - "noImmd", - "power2", - "setFlags", - "set_typeinfo", - ], - - "ida_dbg" : [ - "SRCIT_REGVAR", - "SRCIT_RRLVAR", - "SRCIT_STKVAR", - ], - - "ida_diskio" : [ - "call_system", - "echsize", - "echsize64", - "ecreate", - "ecreateT", - "enumerate_system_files", - "eseek", - "eseek64", - "getdspace", - "openM", - "openR", - "openRT", - "qfsize", - "qfsize64", - "qlgetz64", - "qlseek64", - "qlsize64", - "qltell64", - ], - - "ida_enum" : [ - "const_visitor_t", - "for_all_consts", - "get_bmask_node", - "ENUM_FLAGS_FROMTIL", - "ENUM_FLAGS_GHOST", - "ENUM_FLAGS_WIDTH", - ], - - "ida_expr" : [ - "call_idc_method", - "call_script_method", - "compile_script_file", - "compile_script_func", - "extlang_call_method_exists", - "extlang_compile_file_exists", - "extlang_run_statements_exists", - "extlang_set_attr_exists", - "extlang_unload_procmod", - "get_extlang_fileext", - "get_idcpath", - "install_extlang", - "remove_extlang", - "run_statements", - "select_extlang", - "VarAssign", - "find_extlang_by_ext", - "find_extlang_by_name", - "_IDCFUNC_CB_T", - "call_idc_func__", - ], - - "ida_fixup" : [ - "FIXUP_MASK", - "FIXUP_SELFREL", - "FIXUP_UNUSED", - "FIXUP_VHIGH", - "FIXUP_VLOW", - "get_fixup_base", - "get_fixup_extdef_ea", - "get_fixup_segdef_sel", - "set_custom_fixup_ex", - "set_fixup_ex", - ], - - "ida_frame" : [ - "add_stkvar2", - "add_stkvar3", - ], - - "ida_funcs" : [ - "a2funcoff", - "get_sig_filename", - "std_gen_func_header", - "apply_idasgn", - ], - - "ida_gdl" : [ - "display_complex_call_chart", - "display_flow_graph", - "display_simple_call_chart", - "ida_area", - ], - - "ida_graph" : [ - "pyg_add_command", - ], - - "ida_hexrays" : [ - "add_custom_viewer_popup_item", - "vcall_helper", - "vcreate_helper", - ], - - "ida_ida" : [ - "IDAPLACE_HEXDUMP", - "LFLG_UNUSED", - "PREF_VARMARK", - "text_options_t", - "dto_copy_from_inf", - "dto_copy_to_inf", - "dto_init", - ], - - "ida_idd" : [ - "BPT_OLD_EXEC", - "idd_opinfo_old_t", - ], - - "ida_idp" : [ - "create_custom_fixup", - "deleting_enum_const", - "enum_const_created", - "enum_const_deleted", - "gen_abssym", - "gen_comvar", - "gen_extern", - "gen_spcdef", - "intel_data", - "ph_get_high_fixup_bits", - ], - - "ida_kernwin" : [ - "CHOOSER_HOTKEY", - "add_chooser_command", - "add_menu_item", - "add_output_popup", - "choose2_add_command", - "choose_choose", - "create_ea_viewer", - "create_tform", - "del_menu_item", - "enable_menu_item", - "get_tform_idaview", - "obsolete_msg_popup", - "obsolete_view_popup", - "py_menu_item_callback", - "pyscv_add_popup_menu", - "pyscv_clear_popup_menu", - "set_menu_item_icon", - "vumsg", - "choose_enter", - "choose_getl", - "choose_segreg", - "choose_sizer", - "askfile2_cv", - "vaskqstr", - - # ctypes vars - "DEFAULT_MODE", - "RTLD_GLOBAL", - "RTLD_LOCAL", - ], - - "ida_lines" : [ - "ExtraFree", - "MakeBorder", - "MakeLine", - "MakeNull", - "MakeSolidBorder", - "gen_cmt_line", - "gen_collapsed_line", - "generate_big_comment", - "generate_many_lines", - "printf_line", - ], - - "ida_loader" : [ - "load_loader_module", - ], - - "ida_moves" : [ - "CURLOC_SISTACK_ITEMS", - "UNHID_AREA", - "curloc", - "location_t", - ], - - "ida_nalt" : [ - "SWI_SHIFT1", - "del_jumptable_info", - "get_auto_plugins", - "get_jumptable_info", - "ids_array", - "jumptable_info_t", - "set_auto_plugins", - "set_jumptable_info", - "switch_info_t_get_regdtyp", - "switch_info_t_set_regdtyp", - "switch_info_ex_t_set_flags2", - "switch_info_ex_t_get_flags2", - ], - - "ida_name" : [ - "append_struct_fields2", - "gen_name_decl", - ], - - "ida_netnode" : [ - "NNBASE_IOERR", - "NNBASE_OK", - "NNBASE_PAGE16", - "NNBASE_REPAIR", - ], - - "ida_pro" : [ - "convert_encoding", # wasn't usable (bytevec_t not exposed) - "init_process", - "qsplitpath", # wasn't usable (char **) - "replace_tabs", # wasn't usable (wasn't returning the string) - "vinterr", # wasn't usable (va_list) - "expand_argv", - "free_argv", - "qwait", - "qwait_timed", - "ida_false_type", # traits - "ida_true_type", # traits - ], - - "ida_queue" : [ - "QueueMark", - ], - - "ida_segment" : [ - "std_gen_segm_footer", - ], - - "ida_srarea" : [ - "get_srarea", - "get_srareas_qty", - "getn_srarea", - "segreg_t", - ], - - "ida_strlist" : [ - "set_strlist_options", - ], - - "ida_struct" : [ - "get_member_ti", - "set_member_ti", - "get_or_guess_member_type", - ], - - "ida_typeinf" : [ - "ARGLOC_REG", - "ARGLOC_REG2", - "BAD_VARLOC", - "append_complex_n", - "append_da", - "append_de", - "append_dt", - "append_name", - "append_varloc", - "apply_once_type_and_name", - "apply_type2", - "apply_type_to_stkarg", - "build_array_type", - "build_func_type", - "build_func_type2", - "build_funcarg_info", - "calc_argloc_info", - "calc_func_nargs", - "calc_max_children_qty", - "calc_max_number_of_children", - "calc_varloc_info", - "check_skip_type", - "convert_argloc_to_varloc", - "convert_varloc_to_argloc", - "create_numbered_type_reference", - "extract_and_convert_old_argloc", - "extract_old_argloc", - "for_all_types", - "func_type_info_t", - "funcarg_info_t", - "get_argloc_r1", - "get_argloc_r2", - "get_complex_n", - "get_enum_base_type", - "get_func_cc", - "get_func_cvtarg_map", - "get_func_nargs", - "get_func_rettype", - "get_funcarg_size", - "get_idainfo_by_type2", - "get_name_of_named_type", - "get_ptr_object_size", - "get_referred_ordinal", - "get_scattered_varloc", - "get_spoil_cnt", - "get_stkarg_offset", - "get_strmem", - "get_strmem2", - "get_strmem_by_name", - "get_strmem_t", - "get_tilpath", - "get_type_sign", - "get_type_size0", - "guess_func_tinfo", - "is_castable2", - "is_reg2_argloc", - "is_reg_argloc", - "cleanup_varloc", - "copy_varloc", - "is_resolved_type_struni", - "is_restype_array", - "is_restype_bitfld", - "is_restype_complex", - "is_restype_const", - "is_restype_floating", - "is_restype_func", - "is_restype_ptr", - "is_restype_union", - "is_stack_argloc", - "is_type_only_size", - "is_type_resolvable", - "is_type_scalar2", - "is_type_unk", - "is_type_void_obsolete", - "is_type_voiddef", - "is_valid_full_type", - "make_array_type", - "make_old_argloc", - "parse_types2", - "print_type_to_qstring", - "remove_type_pointer", - "rename_named_type", - "replace_subtypes", - "replace_subtypes2", - "resolve_complex_type2", - "set_complex_n", - "set_named_type64", - "set_scattered_varloc", - "set_spoils", - "skip_spoiled_info", - "skip_varloc", - "split_old_argloc", - "til2idb", - "type_mapper_t", - "type_pair_t", - "type_pair_vec_t", - "type_visitor_t", - "valstrs_deprecated2_t", - "valstrs_deprecated_t", - ], - - "ida_ua" : [ - "OutBadInstruction", - "OutChar", - "OutImmChar", - "OutLine", - "OutLong", - "OutMnem", - "OutValue", - "cmd", - # can't simulate those; they rely on cmd - "dataSeg", - "dataSeg_op", - "dataSeg_opreg", - "init_output_buffer", - "out_addr_tag", - "out_colored_register_line", - "out_keyword", - "out_line", - "out_long", - "out_name_expr", - "out_one_operand", - "out_register", - "out_symbol", - "out_tagoff", - "out_tagon", - "py_get_global_cmd_link", - "term_output_buffer", - "ua_ana0", - "ua_code", - "ua_outop", - "ua_outop2", - "ua_next_byte", - "ua_next_word", - "ua_next_long", - "ua_next_qword", - - # these guys are now handled by SWiG (no more c-link stuff.) - "insn_t_assign", - "insn_t_create", - "insn_t_destroy", - "insn_t_get_auxpref", - "insn_t_get_canon_feature", - "insn_t_get_canon_mnem", - "insn_t_get_cs", - "insn_t_get_ea", - "insn_t_get_flags", - "insn_t_get_insnpref", - "insn_t_get_ip", - "insn_t_get_itype", - "insn_t_get_op_link", - "insn_t_get_segpref", - "insn_t_get_size", - "insn_t_is_canon_insn", - "insn_t_set_auxpref", - "insn_t_set_cs", - "insn_t_set_ea", - "insn_t_set_flags", - "insn_t_set_insnpref", - "insn_t_set_ip", - "insn_t_set_itype", - "insn_t_set_segpref", - "insn_t_set_size", - "op_t_assign", - "op_t_create", - "op_t_destroy", - "op_t_get_addr", - "op_t_get_dtyp", - "op_t_get_flags", - "op_t_get_n", - "op_t_get_offb", - "op_t_get_offo", - "op_t_get_reg_phrase", - "op_t_get_specflag1", - "op_t_get_specflag2", - "op_t_get_specflag3", - "op_t_get_specflag4", - "op_t_get_specval", - "op_t_get_type", - "op_t_get_value", - "op_t_set_addr", - "op_t_set_dtyp", - "op_t_set_flags", - "op_t_set_n", - "op_t_set_offb", - "op_t_set_offo", - "op_t_set_reg_phrase", - "op_t_set_specflag1", - "op_t_set_specflag2", - "op_t_set_specflag3", - "op_t_set_specflag4", - "op_t_set_specval", - "op_t_set_type", - "op_t_set_value", - ], - - "idc" : [ - "ida_srarea", - "ASCSTR_LAST", - "FIXUP_MASK", - "GetOpnd", - "MakeCustomDataEx", - "SW_MICRO", - "SetFlags", - "SetHiddenArea", - "FF_VAR", - "INFFL_LZERO", - "INF_WIDE_HIGH_BYTE_FIRST", - "INF_ABINAME", - "INF_ASCIIFLAGS", - "INF_ASCIIPREF", - "INF_ASCIISERNUM", - "INF_ASCIIZEROES", - "INF_ASCII_BREAK", - "INF_ASSUME", - "INF_AUTO", - "INF_BEGIN_EA", - "INF_CHECKARG", - "INF_CORESTART", - "INF_ENTAB", - "INF_FCORESIZ", - "INF_MF", - "INF_NAMELEN", - "INF_NULL", - "INF_ORG", - "INF_PACKBASE", - "INF_PREFSEG", - "INF_SHOWAUTO", - "INF_SHOWBADS", - "INF_SHOWPREF", - "INF_START_AF", - "INF_VOIDS", - "REF_VHIGH", - "REF_VLOW", - "_invoke_idc_setprm", - "byteValue", - "isFop0", - "isFop1", - "isVar", - "Tabs", - "o_fpreg_arm", - "INF_TRIBYTE_ORDER", - "TRIBYTE_123", - "TRIBYTE_132", - "TRIBYTE_213", - "TRIBYTE_231", - "TRIBYTE_312", - "TRIBYTE_321", - "INF_LPREFIX", - "INF_LPREFIXLEN", - ], -} - -for modname in sorted(api_695.keys()): - m6 = api_695[modname] - new_modname = modname - m7 = api_700[renamed_modules.get(modname, modname)] - for symbol in m6: - symbol_root = symbol - params = "" - paren_idx = symbol_root.find("(") - if paren_idx > -1: - symbol_root, params = symbol_root[0:paren_idx], symbol_root[paren_idx:] - removed_set = removed_symbols.get(modname, []) - if symbol_root in removed_set: - continue - renamed_set = renamed_symbols.get(modname, {}) - if symbol_root in renamed_set.get("TODO", []): - continue - target_symbol = renamed_set.get(symbol_root, symbol_root) - if target_symbol not in m7: - # try looking for a full prototype then - target_symbol = renamed_set.get(symbol, symbol) - if target_symbol not in m7: - add = "" - is_redef = False - if params: - # search for something that might correspond - x = "%s(" % symbol_root - for s in m7: - if s.startswith(x): - # print ("Candidate for '%s': '%s'" % (x, s)) - if s.endswith("bc695redef"): - is_redef = True # symbol was redefined, and marked as such. We assume we know what we're doing - break - else: - add = " => %s" % s - if not is_redef: - print("Missing: '%s.%s'%s" % (modname, symbol, add)) diff --git a/tools/deploy.py b/tools/deploy.py index 420f136..2a6474e 100644 --- a/tools/deploy.py +++ b/tools/deploy.py @@ -23,8 +23,52 @@ parser.add_argument("-d", "--interface-dependencies", type=str, required=True) parser.add_argument("-l", "--lifecycle-aware", default=False, action="store_true") parser.add_argument("-v", "--verbose", default=False, action="store_true") parser.add_argument("-b", "--bc695", default=False, action="store_true") +parser.add_argument("-x", "--xml-doc-directory", required=True) args = parser.parse_args() +this_dir, _ = os.path.split(__file__) +sys.path.append(this_dir) +import doxygen_utils + +typemaps = [] + +# generate typemaps that will have to be injected for additional checks +xml_tree = doxygen_utils.load_xml_for_module(args.xml_doc_directory, args.module, or_dummy=False) +if xml_tree is not None: + all_functions = doxygen_utils.get_toplevel_functions(xml_tree) + for fun_node in all_functions: + fun_name = doxygen_utils.get_single_child_element_text_contents(fun_node, "name") + params = [] + def reg_param(*args): + params.append(args) + doxygen_utils.for_each_param(fun_node, reg_param) + def relevant_and_non_null(ptyp, desc): + if ptyp.strip().startswith("qstring"): + return False + return (desc or "").lower().find("not be null") > -1 + + for name, ptyp, desc in params: + if relevant_and_non_null(ptyp, desc): + # generate 'check' typemap + signature = [] + body = [] + for idx, tpl in enumerate(params): + name, ptyp, desc = tpl + signature.append("%s %s" % (ptyp, name or "")) + if relevant_and_non_null(ptyp, desc): + body.append("if ( $%d == NULL )" % (idx+1)) + body.append(""" SWIG_exception_fail(SWIG_ValueError, "invalid null reference in method '$symname', argument $argnum of type '$%d_type'");""" % (idx+1)) + pass + typemaps.append("%%typemap(check) (%s)" % ", ".join(signature)) + typemaps.append("{") + typemaps.extend(body) + typemaps.append("}") + break +else: + if args.module not in ["idaapi", "idc"]: + raise Exception("Missing XML file for module '%s'" % args.module) + + # creates a regular expression def make_re(tag, module, prefix): s = '%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s</%(tag)s\(%(m)s\)>' % {'m': module, 'tag': tag, 'p': prefix} @@ -91,17 +135,30 @@ def deploy(module, template, output, pywraps, iface_deps, lifecycle_aware, verbo # create regular expressions tags = ( - ('pycode', make_re('pycode', tagname, '#')), - ('code', make_re('code', tagname, '//')), - ('inline', make_re('inline', tagname, '//')), - ('decls', make_re('decls', tagname, '//')), - ('init', make_re('init', tagname, '//')), + ('pycode', make_re('pycode', tagname, '#')), + ('code', make_re('code', tagname, '//')), + ('inline', make_re('inline', tagname, '//')), + ('decls', make_re('decls', tagname, '//')), + ('init', make_re('init', tagname, '//')), ('pycode_BC695', make_re('pycode_BC695', tagname, '#')), ) input_str = "".join(file(path, "r").readlines()) template_str = apply_tags(template_str, input_str, tags, verbose, path) + # synthetic tags + if typemaps: + typemaps_str = "\n".join([ + "//<typemaps(%s)>" % module, + "\n".join(typemaps), + "//</typemaps(%s)>" % module, + ]) + synth_tags = ( + ('typemaps', make_re('typemaps', module, '//')), + ) + template_str = apply_tags(template_str, typemaps_str, synth_tags, verbose, "[generated]") + + # write output file with open(output, 'w') as f: # f.write("""%module(docstring="IDA Plugin SDK API wrapper: {0}",directors="1",threads="1") {1}\n""".format( diff --git a/tools/deploy/header.i.in b/tools/deploy/header.i.in index 9ad67f8..4746641 100644 --- a/tools/deploy/header.i.in +++ b/tools/deploy/header.i.in @@ -45,23 +45,19 @@ // Do not create separate wrappers for default arguments %feature("compactdefaultargs"); -void qvector<uval_t>::grow(const unsigned int &x=0); -%ignore qvector<uval_t>::grow; - -void qvector<long long>::grow(const long long &x=0); -%ignore qvector<long long>::grow; - %ignore qvector::at(size_t); %ignore qvector::front; %ignore qvector::back; -// simpleline_t doesn't implement '=='. Therefore, all these cannot be present in the instantiated template. -%ignore qvector<simpleline_t>::operator==; -%ignore qvector<simpleline_t>::operator!=; -%ignore qvector<simpleline_t>::find; -%ignore qvector<simpleline_t>::has; -%ignore qvector<simpleline_t>::del; -%ignore qvector<simpleline_t>::add_unique; +%define %uncomparable_elements_qvector(ELEMENT_TYPE, VECTOR_TYPE) +%ignore qvector<ELEMENT_TYPE>::operator==; +%ignore qvector<ELEMENT_TYPE>::operator!=; +%ignore qvector<ELEMENT_TYPE>::find; +%ignore qvector<ELEMENT_TYPE>::has; +%ignore qvector<ELEMENT_TYPE>::del; +%ignore qvector<ELEMENT_TYPE>::add_unique; +%template(VECTOR_TYPE) qvector<ELEMENT_TYPE>; +%enddef %ignore wchar2char; %ignore hit_counter_t; @@ -177,27 +173,15 @@ import sys _BC695 = sys.modules["__main__"].IDAPYTHON_COMPAT_695_API if _BC695: - # This is a decorator for eliminating false-positives when automatically - # performing diffs of API7.0 vs API6.95 (typically, the prototypes for the - # functions using this decorator will have changed, and this is used to - # mark that that change is on-purpose, under control, and should in fact - # provide bw-compat. Usually those prototypes went from '(*args)', to a - # more specialized argument list.) + # This is a helper for replacing an existing function, with a wrapper + # providing backwards-compatibility for API 6.95 -- typically because + # the number/types of arguments changed, while the function name itself + # remained the same in 7.0. + # (Note that this shouldn't be used for functions that don't exist + # in the vanilla 7.0 API, such as 'choose_named_type2'.) def bc695redef(func): - func.func_dict["bc695redef"] = True + ida_idaapi._BC695.replace_fun(func) return func - - class bc695redef_with_pydoc(object): - def __init__(self, pydoc): - self.pydoc = pydoc - - def __call__(self, f): - f.func_dict["bc695redef"] = True - def bc695redef_wrapper(*args): - return f(*args) - bc695redef_wrapper.func_dict["bc695redef"] = True - bc695redef_wrapper.__doc__ = self.pydoc - return bc695redef_wrapper } #endif // BC695 @@ -240,13 +224,11 @@ if _BC695: %{ static void __raise_ba(const std::bad_alloc &ba) { - Py_INCREF(PyExc_MemoryError); PyErr_SetString(PyExc_MemoryError, "Out of memory (bad_alloc)"); } static void __raise_u() { - Py_INCREF(PyExc_RuntimeError); PyErr_SetString(PyExc_RuntimeError, "Unknown exception"); } @@ -259,14 +241,12 @@ static void __raise_e(const std::exception &e) } else { - Py_INCREF(PyExc_RuntimeError); PyErr_SetString(PyExc_RuntimeError, what); } } static void __raise_ie(const interr_exc_t &ie) { - Py_INCREF(PyExc_RuntimeError); qstring emsg; emsg.sprnt(INTERR_EXC_FMT, ie.code); PyErr_SetString(PyExc_RuntimeError, emsg.begin()); @@ -274,16 +254,22 @@ static void __raise_ie(const interr_exc_t &ie) static void __raise_de(const Swig::DirectorException &e) { - Py_INCREF(PyExc_RuntimeError); PyErr_SetString(PyExc_RuntimeError, e.getMessage()); } static void __raise_oor(const std::out_of_range &e) { - Py_INCREF(PyExc_RuntimeError); PyErr_SetString(PyExc_IndexError, e.what()); } +static bool __chkthr() +{ + bool ok = is_main_thread(); + if ( !ok ) + PyErr_SetString(PyExc_RuntimeError, "Function can be called from the main thread only"); + return ok; +} + %} %define %exception_set_default_handlers() @@ -356,6 +342,14 @@ static PyObject *type##_get_clink_ptr(PyObject *self) %typemap(directorin) PyObject * "/*%din%*/Py_XINCREF($1_name);$input = $1_name;" %typemap(directorout) PyObject * "/*%dout%*/$result = result;Py_XINCREF($result);" +//--------------------------------------------------------------------- +%define %treat_serialized_tinfo_raw_pointer_as_str(TYPE) +%apply char * { TYPE * } +%apply const char * { const TYPE * } +%enddef +%treat_serialized_tinfo_raw_pointer_as_str(type_t); +%treat_serialized_tinfo_raw_pointer_as_str(p_list); + //------------------------------------------------------------------------- // For some reason, SWIG converts char arrays by computing the size // from the end of the array, and stops when it encounters a '\0'. @@ -377,13 +371,8 @@ static PyObject *type##_get_clink_ptr(PyObject *self) %set_output(SWIG_FromCharPtrAndSize($1, strnlen($1, $1_dim0))); } -#ifdef __X64__ %apply unsigned long long { size_t } %apply long long { ssize_t } -#else -%apply unsigned long { size_t } -%apply long { ssize_t } -#endif //--------------------------------------------------------------------- // Convert an incoming Python list to a tid_t[] array @@ -599,15 +588,23 @@ static PyObject *type##_get_clink_ptr(PyObject *self) $1 = $input; } %typemap(in) ea_t -{ +{ // %typemap(in) ea_t uint64 $1_temp; if ( !PyW_GetNumber($input, &$1_temp) ) - { - PyErr_SetString(PyExc_TypeError, "Expected an ea_t type"); - return NULL; - } + SWIG_exception_fail( + SWIG_TypeError, + "in method '" "$symname" "', argument " "$argnum"" of type 'ea_t'"); $1 = ea_t($1_temp); } +%typemap(in) sval_t +{ // %typemap(in) sval_t + uint64 $1_temp; + if ( !PyW_GetNumber($input, &$1_temp) ) + SWIG_exception_fail( + SWIG_TypeError, + "in method '" "$symname" "', argument " "$argnum"" of type 'sval_t'"); + $1 = sval_t($1_temp); +} // Use PyLong_FromUnsignedLongLong, because 'long' is 4 bytes on // windows, and thus the ea_t would be truncated at the // PyLong_FromUnsignedLong(unsigned int) call time. @@ -619,7 +616,7 @@ static PyObject *type##_get_clink_ptr(PyObject *self) //--------------------------------------------------------------------- // IN/OUT qstring/bytevec_t //--------------------------------------------------------------------- -%define %bytes_container(REFTYPE, CONTAINER_TYPE, START_ACCESSOR, SIZE_ACCESSOR) +%define %bytes_container(REFTYPE, CONTAINER_TYPE, START_ACCESSOR, SIZE_ACCESSOR, INSTANCE_CAST) %typemap(in) REFTYPE { // bytes_container REFTYPE, CONTAINER_TYPE typemap(in) if ( PyString_Check($input) ) @@ -628,7 +625,7 @@ static PyObject *type##_get_clink_ptr(PyObject *self) char *buf = NULL; Py_ssize_t length = 0; /*int success =*/ PyString_AsStringAndSize($input, &buf, &length); - $1 = new CONTAINER_TYPE(buf, length); // build regardless of success + $1 = new CONTAINER_TYPE(INSTANCE_CAST buf, length); // build regardless of success } else { @@ -696,10 +693,12 @@ static PyObject *type##_get_clink_ptr(PyObject *self) } %enddef -%bytes_container(qstring *, qstring, c_str, length); -%bytes_container(qstring &, qstring, c_str, length); -%bytes_container(bytevec_t *, bytevec_t, begin, size); -%bytes_container(bytevec_t &, bytevec_t, begin, size); +%bytes_container(qstring *, qstring, c_str, length,); +%bytes_container(qstring &, qstring, c_str, length,); +%bytes_container(bytevec_t *, bytevec_t, begin, size,); +%bytes_container(bytevec_t &, bytevec_t, begin, size,); +%bytes_container(qtype *, qtype, begin, length, (const uchar *)); +%bytes_container(qtype &, qtype, begin, length, (const uchar *)); //--------------------------------------------------------------------- // varargs (mostly kernwin.hpp) @@ -771,6 +770,10 @@ typedef long long longlong; // (Very) heavily inspired by: // http://stackoverflow.com/questions/7713318/nested-structure-array-access-in-python-using-swig?rq=1 // +// NOTE: This should probably hold a (weak?) reference +// to the parent PyObject, because it is technically possible +// to end up with dangling pointers otherwise +// See also dynamic_wrapped_array_t %immutable; %inline %{ template <typename Type, size_t N> @@ -801,6 +804,40 @@ struct wrapped_array_t { } } +//------------------------------------------------------------------------- +// NOTE: see note for wrapped_array_t +%immutable; +%inline %{ +template <typename Type> +struct dynamic_wrapped_array_t { + Type *data; + size_t count; + dynamic_wrapped_array_t(Type *_data, size_t _count) + : data(_data), count(_count) { } +}; +%} +%mutable; + +%extend dynamic_wrapped_array_t { + inline size_t __len__() const { return $self->count; } + + inline const Type& __getitem__(size_t i) const throw(std::out_of_range) { + if (i >= $self->count || i < 0) + throw std::out_of_range("out of bounds access"); + return $self->data[i]; + } + + inline void __setitem__(size_t i, const Type& v) throw(std::out_of_range) { + if (i >= $self->count || i < 0) + throw std::out_of_range("out of bounds access"); + $self->data[i] = v; + } + + %pythoncode { + __iter__ = ida_idaapi._bounded_getitem_iterator + } +} + //------------------------------------------------------------------------- #if SWIG_VERSION == 0x20012 %typemap(out) tinfo_t {} @@ -901,18 +938,20 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec) $1 = $1_temp; } -%typemap(in,numinputs=0) uint64 *result (uint64 temp) +//------------------------------------------------------------------------- +%define %uint_result_as_output(TYPE, CONVFUNC) +%typemap(in,numinputs=0) TYPE *result (TYPE temp) { - // %typemap(in,numinputs=0) uint64 *result + // %typemap(in,numinputs=0) TYPE *result $1 = &temp; } -%typemap(argout) uint64 *result +%typemap(argout) TYPE *result { - // %typemap(argout) uint64 *result + // %typemap(argout) TYPE *result Py_XDECREF(resultobj); if (result > 0) { - resultobj = PyLong_FromUnsignedLongLong(*(uint64 *) $1); + resultobj = CONVFUNC(*(TYPE *) $1); } else { @@ -920,31 +959,28 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec) resultobj = Py_None; } } +%enddef +%uint_result_as_output(uint32, PyLong_FromUnsignedLong); +%uint_result_as_output(uint64, PyLong_FromUnsignedLongLong); +%apply uint32 *result { uint32 *out }; %apply uint64 *result { uint64 *out }; +#ifdef __EA64__ +%apply uint64 *result { ea_t *result }; +#else +%apply uint32 *result { ea_t *result }; +#endif +// helpers to turn result into multiple values (just %apply, renaming 'appended_ea') +%typemap(argout) ea_t *appended_ea +{ + // %typemap(argout) ea_t *appended_ea +#ifdef __EA64__ + $result = SWIG_Python_AppendOutput($result, PyLong_FromUnsignedLongLong(*($1))); +#else + $result = SWIG_Python_AppendOutput($result, PyLong_FromUnsignedLong(*($1))); +#endif +} //------------------------------------------------------------------------- -%typemap(in,numinputs=0) uint32 *result (uint32 temp) -{ - // %typemap(in,numinputs=0) uint32 *result - $1 = &temp; -} -%typemap(argout) uint32 *result -{ - // %typemap(argout) uint32 *result - Py_XDECREF(resultobj); - if (result > 0) - { - resultobj = PyLong_FromUnsignedLong(*(uint32 *) $1); - } - else - { - Py_INCREF(Py_None); - resultobj = Py_None; - } -} -%apply uint32 *result { uint32 *out }; - - // Make get_any_cmt() work %apply unsigned char *OUTPUT { color_t *cmttype }; @@ -974,10 +1010,11 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec) %} %enddef -%define %numbers_list_to_values_vec(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR) -%typemap(arginit) VECTYPE * "VECTYPE $1_local_storage; // %numbers_list_to_values_vec(VECTYPE) %typemap(arginit) VECTYPE *" // *MUST NOT* be within '{}'s -%typemap(in) VECTYPE * -{ // %numbers_list_to_values_vec(VECTYPE) %typemap(in) VECTYPE * + +%define %numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, REFTYPE) +%typemap(arginit) VECTYPE REFTYPE "VECTYPE $1_local_storage; // %numbers_list_to_values_vec(VECTYPE) %typemap(arginit) VECTYPE REFTYPE" // *MUST NOT* be within '{}'s +%typemap(in) VECTYPE REFTYPE +{ // %numbers_list_to_values_vec(VECTYPE) %typemap(in) VECTYPE REFTYPE if ( PySequence_Check($input) ) { if ( PYLIST_CONVERTOR(&$1_local_storage, $input) < 0 ) @@ -993,9 +1030,68 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec) $1 = reinterpret_cast<VECTYPE*>($1_vptr); } } +%typecheck(SWIG_TYPECHECK_POINTER) VECTYPE REFTYPE +{ + // %numbers_list_to_values_vec(VECTYPE) %typecheck(SWIG_TYPECHECK_POINTER) VECTYPE REFTYPE + if ( PySequence_Check($input) > 0 ) + { + $1 = 1; + } + else + { + int res = SWIG_ConvertPtr($input, 0, SWIGTYPE, 0); + $1 = SWIG_CheckState(res); + } +} +%enddef + +//------------------------------------------------------------------------- +// For e.g., get_idainfo_by_type() +%apply uint32 * OUTPUT { flags_t *out_flags }; +%apply size_t * OUTPUT { size_t *out_size }; +%apply size_t * OUTPUT { size_t *out_alsize }; +%typemap(check) size_t *out_size "*($1) = 0; // %typemap(check) size_t *out_size"; +%typemap(check) size_t *out_alsize "*($1) = 0; // %typemap(check) size_t *out_alsize"; +%typemap(check) flags_t *out_flags "*($1) = 0; // %typemap(check) flags_t *out_flags"; + +%typemap(in,numinputs=0) opinfo_t *out_mt (opinfo_t temp) { + // typemap(in,numinputs=0) opinfo_t *out_mt + $1 = &temp; +} +%typemap(argout) opinfo_t *out_mt +{ + // typemap(argout) opinfo_t *out_mt + if ( result ) + { + PyObject *py_opinfo = SWIG_NewPointerObj(SWIG_as_voidptr(new opinfo_t(*($1))), SWIGTYPE_p_opinfo_t, SWIG_POINTER_NEW ); + $result = SWIG_Python_AppendOutput($result, py_opinfo); + } + else + { + Py_INCREF(Py_None); + $result = SWIG_Python_AppendOutput($result, Py_None); + } +} +%typemap(freearg) opinfo_t *out_mt +{ + // typemap(freearg) opinfo_t *out_mt + // Nothing. We certainly don't want 'temp' to be deleted. +} + +//------------------------------------------------------------------------- +%define %numbers_list_to_values_vec(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR) +%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, *); +%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, &); %enddef %numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_int_t, PyW_PyListToEaVec); +//------------------------------------------------------------------------- +// Make sure the GIL is released, in case 'NAME' is calling execute_sync +// either directly, or indirectly +%define %calls_execute_sync(NAME) +%thread NAME; +%enddef + %{ #include <expr.hpp> #include <ieee.h> diff --git a/tools/dmpapi.py b/tools/dmpapi.py deleted file mode 100644 index c3da559..0000000 --- a/tools/dmpapi.py +++ /dev/null @@ -1,60 +0,0 @@ - -# helper script, used to dump the contents of the IDA -# APIs (used for 7.00 -> 6.95 compat support) - -import os - -import idc -import idaapi -import inspect -outfile = idc.ARGV[1] - -def formatargspec(argspec): - # only format the default args + values - parts = [] - dflts = argspec.defaults or [] - for i in xrange(len(argspec.args) - len(dflts)): - parts.append("_") - for i in xrange(len(dflts)): - parts.append("=%s" % str(dflts[i])) - if argspec.varargs: - parts.append("*%s" % argspec.varargs) - if argspec.keywords: - parts.append("**%s" % argspec.keywords) - return ", ".join(parts) - - -def dump_module(module, out): - mname = module.__name__ - outmod = [] - out[mname] = outmod - for symbol in sorted(dir(module)): - if symbol.endswith("_swigregister"): - continue - if symbol == "_%s" % mname: # _ida_area - continue - if symbol == "cvar": - continue - srcmod = inspect.getmodule(getattr(module, symbol)) - if srcmod and (srcmod.__name__.find("ctypes") > -1): - continue - thing = getattr(module, symbol) - if inspect.isfunction(thing) or inspect.ismethod(thing): - argspec = inspect.getargspec(thing) - symbol = "%s(%s)" % (symbol, formatargspec(argspec)) - if thing.func_dict.get("bc695redef", False): - symbol = "%s!bc695redef" % symbol - outmod.append(symbol) - -out = {} -for modname in sorted(sys.modules): - module = sys.modules[modname] - if modname.startswith("ida_") or modname in ["idc"]: - # if modname not in ignorable_modules: - dump_module(module, out) - -with open(outfile, "w") as fout: - import pprint - fout.write("%s" % pprint.pformat(out)) - -idc.Exit(0) diff --git a/tools/doxygen_utils.py b/tools/doxygen_utils.py new file mode 100644 index 0000000..403c089 --- /dev/null +++ b/tools/doxygen_utils.py @@ -0,0 +1,51 @@ + +import os +import xml.etree.ElementTree as ET + +def load_xml_for_module(xml_dir_path, module_name, or_dummy=True): + xml_tree = ET.Element("dummy") if or_dummy else None + for sfx in ["_8hpp", "_8h"]: + xml_path = os.path.join(xml_dir_path, "%s%s.xml" % (module_name, sfx)) + if os.path.isfile(xml_path): + with open(xml_path, "rb") as fin: + xml_tree = ET.fromstring(fin.read()) + return xml_tree + +def get_toplevel_functions(xml_tree, name=None): + path = "./compounddef/sectiondef[@kind='%s']/memberdef[@kind='function']" + if name: + path = "%s/[name='%s']" % (path, name) + all_nodes = [] + for section_kind in ["func", "user-defined"]: + nodes = xml_tree.findall(path % section_kind) + all_nodes.extend(map(lambda n: n, nodes)) + return all_nodes + +def get_single_child_element_text_contents(el, child_element_tag): + nodes = el.findall("./%s" % child_element_tag) + nnodes = len(nodes) + if nnodes == 0: + return None + text = nodes[0].text + if nnodes > 1: + print("Warning: more than 1 child element with tag '%s' found; picking first" % (child_element_tag,)) + return text + +def for_each_param(node, callback): + assert(node.tag == "memberdef" and node.attrib.get("kind") == "function") + plist = node.find("./detaileddescription/para/parameterlist[@kind='param']") + def get_direct_text(n, tag): + c = n.find("./%s" % tag) + if c is not None: + return " ".join(c.itertext()).strip() + for param in node.findall("./param"): + name, ptyp, desc = None, None, None + name = get_direct_text(param, "declname") + ptyp = get_direct_text(param, "type") + if name and plist is not None: + for plist_item in plist.findall("parameteritem"): + if plist_item.find("./parameternamelist/[parametername='%s']" % name) is not None: + pdesc_node = plist_item.find("./parameterdescription") + if pdesc_node is not None: + desc = " ".join(pdesc_node.itertext()).strip() + callback(name, ptyp, desc) diff --git a/tools/dumpdoc.py b/tools/dumpdoc.py index 3cb109f..df6eae8 100644 --- a/tools/dumpdoc.py +++ b/tools/dumpdoc.py @@ -1,4 +1,5 @@ +import re import sys import inspect @@ -15,12 +16,14 @@ ignore_python_builtin_docs = [ tuple.__doc__, ] -def dump_thing(f, label, thing): +def dump_thing(f, label, thing, vec_info=None): try: doc = thing.__doc__ if doc and not doc in ignore_python_builtin_docs: doc_lines = doc.split("\n") doc_lines = map(lambda l: "\t%s" % l, doc_lines) + if vec_info: + doc_lines = map(vec_info["process_line"], doc_lines) f.write("%s:\n%s\n\n" % (label, "\n".join(doc_lines))) except: pass @@ -37,27 +40,6 @@ ignore_names = [ "weakref_proxy", "thisown", ("ida_nalt", "strpath_ids_array", "data"), - ("ida_pro", "uvalvec_t", "at"), - ("ida_pro", "uvalvec_t", "begin"), - ("ida_pro", "uvalvec_t", "end"), - ("ida_pro", "uvalvec_t", "erase"), - ("ida_pro", "uvalvec_t", "extract"), - ("ida_pro", "uvalvec_t", "find"), - ("ida_pro", "uvalvec_t", "insert"), - ("ida_pro", "uvalvec_t", "push_back"), - ("ida_xref", "casevec_t", "at"), - ("ida_xref", "casevec_t", "begin"), - ("ida_xref", "casevec_t", "end"), - ("ida_xref", "casevec_t", "erase"), - ("ida_xref", "casevec_t", "extract"), - ("ida_xref", "casevec_t", "find"), - ("ida_xref", "casevec_t", "grow"), - ("ida_xref", "casevec_t", "insert"), - ("ida_xref", "casevec_t", "push_back"), - ("ida_funcs", "compute_func_sig"), - ("ida_funcs", "extract_func_md"), - ("ida_funcs", "func_md_t"), - ("ida_funcs", "func_pat_t"), ] def should_ignore_name(namespace_name, name): for ign in ignore_names: @@ -68,7 +50,42 @@ def should_ignore_name(namespace_name, name): return True return False -def dump_namespace(f, namespace, namespace_name, keys): +def make_eavec_lines_processor(directives): + def f(l): + for tokens, replacement in directives: + for token in tokens: + l = l.replace(token, replacement) + return l + return f + +eavec_classes = { + "svalvec_t" : + { + "process_line" : make_eavec_lines_processor( + [ + (("<(int)>", "<(long long)>"), "<(signed-ea-like-numeric-type)>"), + (("qvector< int >", "qvector< long long >"), "qvector< signed-ea-like-numeric-type >"), + (("-> int &", "-> long long &"), "-> signed-ea-like-numeric-type &"), + (("-> int *", "-> long long *"), "-> signed-ea-like-numeric-type *"), + (("-> int const &", "-> long long const &"), "-> signed-ea-like-numeric-type &"), + ]) + }, + "uvalvec_t" : + { + "process_line" : make_eavec_lines_processor( + [ + (("<(unsigned int)>", "<(unsigned long long)>"), "<(unsigned-ea-like-numeric-type)>"), + (("qvector< unsigned int >", "qvector< unsigned long long >"), "qvector< unsigned-ea-like-numeric-type >"), + (("-> unsigned int &", "-> unsigned long long &"), "-> unsigned-ea-like-numeric-type &"), + (("-> unsigned int *", "-> unsigned long long *"), "-> unsigned-ea-like-numeric-type *"), + (("-> unsigned int const &", "-> unsigned long long const &"), "-> unsigned-ea-like-numeric-type &"), + ]) + } +} +eavec_classes["casevec_t"] = eavec_classes["svalvec_t"] + + +def dump_namespace(f, namespace, namespace_name, keys, vec_info=None): for thing_name in keys: if thing_name.startswith("_") and not thing_name in ["_print", "_free"]: continue @@ -76,13 +93,14 @@ def dump_namespace(f, namespace, namespace_name, keys): continue thing = getattr(namespace, thing_name) if inspect.isclass(thing): - dump_thing(f, "class %s.%s()" % (namespace_name, thing_name), thing) + vec_info = eavec_classes.get(thing_name, None) + dump_thing(f, "class %s.%s()" % (namespace_name, thing_name), thing, vec_info) members = map(lambda t: t[0], inspect.getmembers(thing)) - dump_namespace(f, thing, "%s.%s" % (namespace_name, thing_name), members) + dump_namespace(f, thing, "%s.%s" % (namespace_name, thing_name), members, vec_info) elif callable(thing): - dump_thing(f, "%s.%s()" % (namespace_name, thing_name), thing) + dump_thing(f, "%s.%s()" % (namespace_name, thing_name), thing, vec_info) elif not inspect.ismodule(thing): - dump_thing(f, "%s.%s" % (namespace_name, thing_name), thing) + dump_thing(f, "%s.%s" % (namespace_name, thing_name), thing, vec_info) output = idc.ARGV[1] wrappers_dir = idc.ARGV[2] diff --git a/tools/genhooks/doxy_gen_notifs.cfg.in b/tools/genhooks/doxy_gen_notifs.cfg.in index 854a34a..9cfb06c 100644 --- a/tools/genhooks/doxy_gen_notifs.cfg.in +++ b/tools/genhooks/doxy_gen_notifs.cfg.in @@ -1987,7 +1987,6 @@ INCLUDE_FILE_PATTERNS = PREDEFINED = __cplusplus \ __X86__ \ __NT__ \ - __VC__ \ _MSC_VER \ UNICODE \ NO_OBSOLETE_FUNCS \ diff --git a/tools/genhooks/genhooks.py b/tools/genhooks/genhooks.py index d36ffea..74be420 100644 --- a/tools/genhooks/genhooks.py +++ b/tools/genhooks/genhooks.py @@ -149,8 +149,12 @@ for enumval_el in enum_el.findall("./enumvalue"): discarded = collect_all_text(enumval_el.find("./detaileddescription")).strip().startswith(args.discard_doc) or \ collect_all_text(enumval_el.find("./briefdescription")).strip().startswith(args.discard_doc) if not discarded: - if args.strip_prefix and name.startswith(args.strip_prefix): - name = name[len(args.strip_prefix):] + if args.strip_prefix: + pfxes = args.strip_prefix.split(",") + for pfx in pfxes: + if name.startswith(pfx): + name = name[len(pfx):] + break add_enum_value(enumval_el, name, enum_name) @@ -198,6 +202,7 @@ def gen_methods(out): ptype = p["type"] suppress_for_call = False final_name = pname + defstr = "" if "params" in recipe_data: all_pdata = recipe_data["params"] if pname in all_pdata: @@ -208,8 +213,10 @@ def gen_methods(out): suppress_for_call = pdata["suppress_for_call"] if "rename" in pdata: final_name = pdata["rename"] + if "default" in pdata: + defstr = "=%s" % pdata["default"] if not suppress_for_call: - arg_strs.append("%s %s" % (ptype, final_name)) + arg_strs.append("%s %s%s" % (ptype, final_name, defstr)) qnotused_decls += "qnotused(%s); " % final_name text = "virtual %s %s(%s) {%s%s}\n" % ( rdata["type"], @@ -239,7 +246,7 @@ def gen_notifications(out): pname = p["name"] ptype = p["type"] pick_type = ptype - if ptype in ["bool", "char", "uchar", "uint16", "cref_t", "dref_t", "cm_t", "ui_notification_t", "dbg_notification_t", "tcc_renderer_type_t", "range_kind_t", "demreq_type_t"]: + if ptype in ["bool", "char", "uchar", "uint16", "cref_t", "dref_t", "cm_t", "ui_notification_t", "dbg_notification_t", "tcc_renderer_type_t", "range_kind_t", "demreq_type_t", "ctree_maturity_t"]: cast = ptype pick_type = "int" else: diff --git a/tools/genhooks/recipe_hexrays.py b/tools/genhooks/recipe_hexrays.py new file mode 100644 index 0000000..55524b6 --- /dev/null +++ b/tools/genhooks/recipe_hexrays.py @@ -0,0 +1,15 @@ + +recipe = { + "create_hint" : { + "params" : { + "result_hint" : { "suppress_for_call" : True, }, + "implines" : { "suppress_for_call" : True, }, + }, + "return" : { + "type" : "PyObject *", + "retexpr" : "Py_RETURN_NONE", + "convertor" : "Hexrays_Hooks::handle_create_hint_output", + "convertor_pass_args" : True, + } + } +} diff --git a/tools/genhooks/recipe_idphooks.py b/tools/genhooks/recipe_idphooks.py index 0d6262d..8b0ce14 100644 --- a/tools/genhooks/recipe_idphooks.py +++ b/tools/genhooks/recipe_idphooks.py @@ -59,7 +59,7 @@ recipe = { "params" : { "cc" : { "type" : "int", - "convertor" : "IDP_Hooks::cm_t_to_int", + "convertor" : "IDP_Hooks::cm_t_to_ssize_t", }, "outbuf" : { "suppress_for_call" : True, }, "type" : { diff --git a/tools/genhooks/recipe_uihooks.py b/tools/genhooks/recipe_uihooks.py index 8fc2826..1f34056 100644 --- a/tools/genhooks/recipe_uihooks.py +++ b/tools/genhooks/recipe_uihooks.py @@ -50,4 +50,33 @@ recipe = { "idp_event" : {"ignore" : True}, "refresh_choosers" : {"ignore" : True}, "load_dbg_dbginfo" : {"ignore" : True}, + + "populating_widget_popup" : { + "params" : { + "ctx" : { + "default" : "NULL", + }, + }, + }, + "finish_populating_widget_popup" : { + "params" : { + "ctx" : { + "default" : "NULL", + }, + }, + }, + "create_desktop_widget" : { + "params" : { + "cfg" : { + "type" : "jobj_wrapper_t", + "convertor" : "UI_Hooks::wrap_widget_cfg", + "convertor_pass_args" : True, + }, + }, + "return" : { + "type" : "PyObject *", + "retexpr" : "Py_RETURN_NONE", + "convertor" : "UI_Hooks::handle_create_desktop_widget_output", + } + }, } diff --git a/tools/inject_plfm.py b/tools/inject_plfm.py new file mode 100644 index 0000000..322f615 --- /dev/null +++ b/tools/inject_plfm.py @@ -0,0 +1,41 @@ + +import re +import string + +try: + from argparse import ArgumentParser +except: + print "Failed to import module 'argparse'. Upgrade to Python 2.7, copy argparse.py to this directory or try 'apt-get install python-argparse'" + raise + +parser = ArgumentParser() +parser.add_argument("-i", "--input", required=True) +parser.add_argument("-o", "--output", required=True) +parser.add_argument("-d", "--decls", required=True) +args = parser.parse_args() + +with open(args.input) as fin: + template = string.Template(fin.read()) + +with open(args.decls) as fin: + raw = fin.read() +pat = re.compile(r"^#\s*define\s+(PLFM_[A-Za-z0-9_]*)\s+([0-9x]*)\s*(.*)$") +decls = [] +for line in raw.split("\n"): + m = pat.match(line) + if m: + proc = m.group(1) + value = m.group(2) + cmt = None + rest = m.group(3) + rest_cmt = rest.find("///<") + if rest_cmt > -1: + cmt = rest[rest_cmt+4:].strip() + decls.append("{:20s} = {:8s} # {:s}".format(proc, value, cmt or "?")) +kvps = { + "PLFM_DECLS" : "\n".join(decls) +} + +with open(args.output, "wt") as fout: + fout.write(template.substitute(kvps)) + diff --git a/tools/inject_pydoc.py b/tools/inject_pydoc.py index 94e075f..3e8caaf 100644 --- a/tools/inject_pydoc.py +++ b/tools/inject_pydoc.py @@ -32,6 +32,10 @@ parser.add_argument("-m", "--module", required=True) parser.add_argument("-v", "--verbose", default=False, action="store_true") args = parser.parse_args() +this_dir, _ = os.path.split(__file__) +sys.path.append(this_dir) +import doxygen_utils + DOCSTR_MARKER = '"""' def verb(msg): @@ -304,38 +308,18 @@ class fun_doc_t(base_doc_t): self.params = [] self.retval = None - def _get_direct_text(self, n, tag): - c = n.find("./%s" % tag) - if c is not None: - return " ".join(c.itertext()).strip() - - def _get_declname(self, n): - dn = self._get_direct_text(n, "declname") - if dn == "from": - dn = "_from" # SWiG will rename 'from' to '_from' automatically, and we want to match that - return dn - - def _get_type(self, n): - return self._get_direct_text(n, "type") - def traverse(self, node, swig_generated_param_names): self.brief = self.get_description(node, "briefdescription") self.detailed = self.get_description(node, "detaileddescription") + # collect params - plist = node.find("./detaileddescription/para/parameterlist[@kind='param']") - for param in node.findall("./param"): - name, ptyp, desc = None, None, None - name = self._get_declname(param) - if name not in swig_generated_param_names: - continue - ptyp = self._get_type(param) - if name and plist is not None: - for plist_item in plist.findall("parameteritem"): - if plist_item.find("./parameternamelist/[parametername='%s']" % name) is not None: - pdesc_node = plist_item.find("./parameterdescription") - if pdesc_node is not None: - desc = " ".join(pdesc_node.itertext()).strip() - self.params.append(ioarg_t(name, ptyp, desc)) + def add_param(name, ptyp, desc): + if name == "from": + name = "_from" # SWiG will rename 'from' to '_from' automatically, and we want to match that + if name in swig_generated_param_names: + self.params.append(ioarg_t(name, ptyp, desc)) + doxygen_utils.for_each_param(node, add_param) + # return value return_node = node.find(".//simplesect[@kind='return']") if return_node is not None: @@ -435,10 +419,8 @@ class idaapi_fixer_t(object): def get_fun_info(self, fun_name, swig_generated_param_names): fun_info = self.collected_info["funcs"].get(fun_name) if not fun_info: - fnodes = [] - for section_kind in ["func", "user-defined"]: - sect_fnodes = self.xml_tree.findall("./compounddef/sectiondef[@kind='%s']/memberdef[@kind='function']/[name='%s']" % (section_kind, fun_name)) - fnodes.extend(map(lambda sfn: sfn, sect_fnodes)) + # def get_all_functions(xml_tree, name=None): + fnodes = doxygen_utils.get_toplevel_functions(self.xml_tree, name=fun_name) nfnodes = len(fnodes) if nfnodes > 0: if nfnodes > 1: @@ -499,11 +481,12 @@ class idaapi_fixer_t(object): line = self.copy(out) doc_start_line_idx = len(out) if line.find(DOCSTR_MARKER) > -1: - # Determine indentation level + # Opening docstring line; determine indentation level indent = get_indent_string(line) while True: line = self.next() if line.find(DOCSTR_MARKER) > -1: + # Closing docstring line swig_generated_param_names = self.extract_swig_generated_param_names(fun_name, out[doc_start_line_idx:]) if class_info is None: found = self.get_fun_info(fun_name, swig_generated_param_names) @@ -515,13 +498,23 @@ class idaapi_fixer_t(object): out.append("\n") out.extend(map(lambda l: indent + l, found)) + + # # apply possible additional patches + # fun_patches = self.patches.get(fun_name, {}) + example = fun_patches.get("+example", None) if example: ex_lines = map(lambda l: "Python> %s" % l, example.split("\n")) out.extend(map(lambda l: indent + l, ["", "Example:"] + ex_lines)) + repl_text = fun_patches.get("repl_text", None) + if repl_text: + from_text, to_text = repl_text + for i in xrange(doc_start_line_idx, len(out)): + out[i] = out[i].replace(from_text, to_text) + out.append(line) break else: @@ -595,13 +588,7 @@ class idaapi_fixer_t(object): input_path, xml_dir_path, out_path = args.input, args.xml_doc_directory, args.output with open(input_path, "rt") as f: self.lines = split_oneliner_comments(f.readlines()) - self.xml_tree = ET.Element("dummy") - for sfx in ["_8hpp", "_8h"]: - xml_path = os.path.join(xml_dir_path, "%s%s.xml" % (args.module, sfx)) - if os.path.isfile(xml_path): - with open(xml_path, "rb") as f: - self.xml_tree = ET.fromstring(f.read()) - break + self.xml_tree = doxygen_utils.load_xml_for_module(xml_dir_path, args.module) out = [] while len(self.lines) > 0: line = self.next() diff --git a/tools/inject_pydoc/idp.py b/tools/inject_pydoc/idp.py new file mode 100644 index 0000000..a32d307 --- /dev/null +++ b/tools/inject_pydoc/idp.py @@ -0,0 +1,5 @@ +{ + "ev_get_bg_color" : { + "repl_text" : ("(self, color, ea) -> int", "(self, ea) -> int or None"), + } +} diff --git a/tools/patch_codegen.py b/tools/patch_codegen.py index 3b4db59..7469360 100644 --- a/tools/patch_codegen.py +++ b/tools/patch_codegen.py @@ -1,5 +1,8 @@ -import os, re +import os +import re +import sys +import xml.etree.ElementTree as ET try: from argparse import ArgumentParser @@ -11,63 +14,148 @@ parser = ArgumentParser(description='Patch some code generation, so it builds') parser.add_argument("-f", "--file", required=True) parser.add_argument("-p", "--patches", required=True) parser.add_argument("-v", "--verbose", default=False, action="store_true") +parser.add_argument("-x", "--xml-doc-directory", required=True) +parser.add_argument("-m", "--module", required=True) parser.add_argument("-V", "--apply-valist-patches", default=False, action="store_true") args = parser.parse_args() +this_dir, _ = os.path.split(__file__) +sys.path.append(this_dir) +import doxygen_utils + patched_cmt = "// patched by patch_codegen.py" +# Load specific patches +patches = {} if os.path.isfile(args.patches): with open(args.patches, "r") as fin: patches = eval(fin.read()) - wrap_regex = re.compile(r"SWIGINTERN PyObject \*_wrap_([a-zA-Z0-9_]*)\(.*") - director_method_regex = re.compile(r".*(SwigDirector_[a-zA-Z0-9_]*::[a-zA-Z0-9_]*)\(.*") - swig_clink_var_get_regex = re.compile(r"SWIGINTERN PyObject \*(Swig_var_[a-zA-Z0-9_]*_get).*") - swig_clink_var_set_regex = re.compile(r"SWIGINTERN int (Swig_var_[a-zA-Z0-9_]*_set).*") +def add_thread_unsafe(fun_name): + pset = patches.get(fun_name, None) + if pset is None: + pset = [] + patches[fun_name] = pset + # avoid duplicates + exists = False + for thing in pset: + if thing[0] == "thread_unsafe": + exists = True + break + if not exists: + pset.append(("thread_unsafe", True)) - lines = [] - with open(args.file, "rb") as f: - STAT_UNKNOWN = {} - STAT_IN_FUNCTION = {} - stat = STAT_UNKNOWN - func_patches = [] - entered_function = False - for line in f: - m = wrap_regex.match(line) - if not m: - m = director_method_regex.match(line) - if not m: - m = swig_clink_var_get_regex.match(line) - if not m: - m = swig_clink_var_set_regex.match(line) - if m: - stat = STAT_IN_FUNCTION - fname = m.group(1) - entered_function = True - func_patches = patches.get(fname, []) - else: - for patch_kind, patch_data in func_patches: - if patch_kind == "va_copy": - if args.apply_valist_patches: - dst_va, src_va = patch_data - target = "%s = *%s;" % (dst_va, src_va) - if line.strip() == target: - line = "set_vva(%s, *%s); %s\n" % (dst_va, src_va, patched_cmt) - elif patch_kind == "acquire_gil": - if entered_function: - line = " PYW_GIL_GET; %s\n%s" % (patched_cmt, line) - elif patch_kind == "repl_text": - idx = line.find(patch_data[0]) - if idx > -1: - line = line.rstrip().replace(patch_data[0], patch_data[1]) - line = "%s %s\n" % (line, patched_cmt) +# Generate thread unsafe patches +xml_tree = doxygen_utils.load_xml_for_module(args.xml_doc_directory, args.module, or_dummy=False) +if xml_tree is not None: + all_functions = doxygen_utils.get_toplevel_functions(xml_tree) + for fun_node in all_functions: + fun_name = doxygen_utils.get_single_child_element_text_contents(fun_node, "name") + fun_defn = doxygen_utils.get_single_child_element_text_contents(fun_node, "definition") + #print("##### %s | %s" % (fun_name, fun_defn)) + if fun_name and fun_defn and fun_defn.find("THREAD_SAFE") < 0: + add_thread_unsafe(fun_name) +else: + if args.module not in ["idaapi", "idc"]: + raise Exception("Missing XML file for module '%s'" % args.module) + +# Handle manually added thread unsafe patches +add_tu = patches.get("__additional_thread_unsafe__", None) +if add_tu is not None: + del patches["__additional_thread_unsafe__"] + for one_add_tu in add_tu: + add_thread_unsafe(one_add_tu) + +# Patch the code +wrap_regex = re.compile(r"SWIGINTERN PyObject \*_wrap_([a-zA-Z0-9_]*)\(.*") +director_method_regex = re.compile(r".*(SwigDirector_[a-zA-Z0-9_]*::[a-zA-Z0-9_]*)\(.*") +swig_clink_var_get_regex = re.compile(r"SWIGINTERN PyObject \*(Swig_var_[a-zA-Z0-9_]*_get).*") +swig_clink_var_set_regex = re.compile(r"SWIGINTERN int (Swig_var_[a-zA-Z0-9_]*_set).*") + +all_lines = [] +with open(args.file, "rb") as f: + STAT_UNKNOWN = {} + STAT_IN_FUNCTION = {} + stat = STAT_UNKNOWN + func_patches = [] + entered_function = False + for line in f: + subst = None + m = wrap_regex.match(line) + if not m: + m = director_method_regex.match(line) + if not m: + m = swig_clink_var_get_regex.match(line) + if not m: + m = swig_clink_var_set_regex.match(line) + if m: + stat = STAT_IN_FUNCTION + fname = m.group(1) + entered_function = True + func_patches = patches.get(fname, []) + else: + for patch_kind, patch_data in func_patches: + if patch_kind == "va_copy": + if args.apply_valist_patches: + dst_va, src_va = patch_data + target = "%s = *%s;" % (dst_va, src_va) + if line.strip() == target: + subst = "set_vva(%s, *%s); %s" % (dst_va, src_va, patched_cmt) + elif patch_kind == "acquire_gil": + if entered_function: + subst = [ + " PYW_GIL_GET; %s" % patched_cmt, + line, + ] + elif patch_kind == "repl_text": + idx = line.find(patch_data[0]) + if idx > -1: + subst = line.rstrip().replace(patch_data[0], patch_data[1]) + subst = "%s %s" % (subst, patched_cmt) + elif patch_kind == "insert_before_text": + idx = line.find(patch_data[0]) + if idx > -1: + subst = ["%s %s" % (patch_data[1], patched_cmt), line] + elif patch_kind == "thread_unsafe": + if entered_function: + subst = [ + " if ( !__chkthr() ) return NULL; %s" % patched_cmt, + line, + ] + elif patch_kind == "director_method_call_arity_cap": + method_name, args_cfoa, args_cmoa = patch_data + if entered_function: + subst = [ + " %s" % patched_cmt, + " newref_t __method(PyObject_GetAttrString(swig_get_self(), \"%s\"));" % method_name, + " ssize_t __argcnt = get_callable_arg_count(__method);", + " QASSERT(0, __argcnt >= 0);", + line, + ] else: - raise Exception("Unknown patch kind: %s" % patch_kind) - entered_function = False - lines.append(line) + add_error = False + call_args = None + if line.find("result = PyObject_CallFunctionObjArgs") > -1: + call_args = args_cfoa + add_error = True + elif line.find("result = PyObject_CallMethodObjArgs") > -1: + call_args = args_cmoa + if call_args: + subst = re.sub("\(.*\);", call_args + ";", line) + if add_error: + subst = ["#error CHECK_THAT_THIS_WORKS", subst] + else: + raise Exception("Unknown patch kind: %s" % patch_kind) + entered_function = False + if subst is not None: + if isinstance(subst, basestring): + subst = [subst] + all_lines.extend(map(lambda l: "%s\n" % l, subst)) + else: + all_lines.append(line) - tmp_file = "%s.tmp" % args.file - with open(tmp_file, "w") as f: - f.writelines(lines) - os.unlink(args.file) - os.rename(tmp_file, args.file) +tmp_file = "%s.tmp" % args.file +with open(tmp_file, "wb") as f: + f.writelines(all_lines) +os.unlink(args.file) +os.rename(tmp_file, args.file) diff --git a/tools/patch_codegen/hexrays.py b/tools/patch_codegen/hexrays.py index 647d5c9..b969ba4 100644 --- a/tools/patch_codegen/hexrays.py +++ b/tools/patch_codegen/hexrays.py @@ -5,6 +5,9 @@ "vcall_helper" : [ ("va_copy", ("arg4", "temp")), ], + "Hexrays_Callback" : [ + ("va_copy", ("arg3", "temp")), + ], "SwigDirector_microcode_filter_t::match" : [ ("acquire_gil", True) ], diff --git a/tools/patch_codegen/idp.py b/tools/patch_codegen/idp.py new file mode 100644 index 0000000..4632f56 --- /dev/null +++ b/tools/patch_codegen/idp.py @@ -0,0 +1,27 @@ +{ + "SwigDirector_IDP_Hooks::ev_get_bg_color" : [ + + ("director_method_call_arity_cap", ( + "ev_get_bg_color", + "(method , __argcnt == 2 ? (PyObject *) obj1 : (PyObject *) obj0, __argcnt == 2 ? (PyObject *) NULL : (PyObject *) obj1, NULL)", + "(swig_get_self(), (PyObject *) swig_method_name , __argcnt == 2 ? (PyObject *) obj1 : (PyObject *) obj0, __argcnt == 2 ? (PyObject *) NULL : (PyObject *) obj1, NULL)") + ), + + ("insert_before_text", ("int swig_val;", +""" +if ( __argcnt == 2 ) +{ + if ( result == Py_None ) + { + result = PyInt_FromLong(0); + } + else if ( PyInt_Check(result) ) + { + *color = bgcolor_t(PyInt_AsLong(result)); + result = PyInt_FromLong(1); + } +} +""")), + + ], +} diff --git a/tools/patch_codegen/kernwin.py b/tools/patch_codegen/kernwin.py index cd6b38f..4716586 100644 --- a/tools/patch_codegen/kernwin.py +++ b/tools/patch_codegen/kernwin.py @@ -2,4 +2,19 @@ "vask_file" : [ ("va_copy", ("arg4", "temp")), ], + "SwigDirector_UI_Hooks::populating_widget_popup" : [ + ("director_method_call_arity_cap", ( + "populating_widget_popup", + "(method ,(PyObject *)obj0,(PyObject *)obj1,(__argcnt < 3 ? NULL : (PyObject *)obj2), NULL)", + "(swig_get_self(), (PyObject *) swig_method_name ,(PyObject *)obj0,(PyObject *)obj1,(__argcnt < 4 ? NULL : (PyObject *)obj2), NULL)", + )), + ], + "SwigDirector_UI_Hooks::finish_populating_widget_popup" : [ + ("director_method_call_arity_cap", ( + "finish_populating_widget_popup", + "(method ,(PyObject *)obj0,(PyObject *)obj1,(__argcnt < 3 ? NULL : (PyObject *)obj2), NULL)", + "(swig_get_self(), (PyObject *) swig_method_name ,(PyObject *)obj0,(PyObject *)obj1,(__argcnt < 4 ? NULL : (PyObject *)obj2), NULL)", + )), + ], + "__additional_thread_unsafe__" : ["py_get_ask_form", "py_get_open_form"], } diff --git a/tools/patch_constants.py b/tools/patch_constants.py index 551a234..b6b5c65 100644 --- a/tools/patch_constants.py +++ b/tools/patch_constants.py @@ -14,9 +14,11 @@ args = parser.parse_args() outlines = [] STAT_SEEKING = 1 -STAT_COLLECTING = 2 +STAT_ALMOST_THERE = 2 +STAT_COLLECTING = 3 -start_collecting_re = re.compile(r"^SWIG_init\(void\)") +almost_there_re = re.compile(r"^\s+\*\s+Partial Init method.*") +start_collecting_re = re.compile(r"^#ifdef __cplusplus.*") end_collecting_re = re.compile(r"^\s*/\* Initialize threading \*/") # SWIG_Python_SetConstant(d, "BADADDR",SWIG_From_unsigned_SS_int(static_cast< unsigned int >(ea_t(-1)))); @@ -37,10 +39,11 @@ pyobj_expr_str = re.compile(r"SWIG_FromCharPtr\((.*)\)") status = STAT_SEEKING class Foldable(object): - def __init__(self, re, enum, initializer, replacement): + def __init__(self, re, enum, initializer, cast, replacement): self.re = re self.enum = enum self.initializer = initializer + self.cast = cast self.replacement = replacement self.found_any = False @@ -49,26 +52,31 @@ subexprs = { pyobj_expr_int, "cit_int", "i", + "int", "SWIG_From_int(static_cast< int >(ci.val.i))"), "u" : Foldable( pyobj_expr_uint, "cit_uint", "u", + "unsigned int", "SWIG_From_unsigned_SS_int(static_cast< unsigned int >(ci.val.u))"), "l" : Foldable( pyobj_expr_long, "cit_long", "l", + "long", "SWIG_From_long(static_cast< long >(ci.val.l))"), "ul" : Foldable( pyobj_expr_ulong, "cit_ulong", "ul", + "unsigned long", "SWIG_From_unsigned_SS_long(static_cast< unsigned long >(ci.val.ul))"), "s" : Foldable( pyobj_expr_str, "cit_charptr", "s", + "char *", "SWIG_FromCharPtr(ci.val.s)"), } @@ -108,6 +116,7 @@ static const ida_local struct ci_t name = c[0] expr = c[1] init = "o" + cast = "PyObject *" citype = "cit_obj" # Analyze expression. If it is one of the @@ -119,9 +128,10 @@ static const ida_local struct ci_t citype = subexpr.enum expr = sematch.group(1) init = subexpr.initializer + cast = subexpr.cast subexpr.found_any = True break - outlines.append("\t{%s, {%s: (%s)}, %s},\n" % (name, init, expr, citype)) + outlines.append("\t{%s, {%s: (%s) (%s)}, %s},\n" % (name, init, cast, expr, citype)) outlines.append(""" }; @@ -158,11 +168,20 @@ with open(args.file, "rb") as f: for line in f: if status == STAT_SEEKING: + if almost_there_re.match(line): + status = STAT_ALMOST_THERE + if args.verbose: + print "Almost there at line: '%s'" % line outlines.append(line) + elif status == STAT_ALMOST_THERE: if start_collecting_re.match(line): status = STAT_COLLECTING if args.verbose: print "Starting to collect at line: '%s'" % line + outlines.append("#ifdef __NT__\n") + outlines.append("#pragma warning(disable: 4883)\n") + outlines.append("#endif // __NT__\n") + outlines.append(line) elif status == STAT_COLLECTING: if end_collecting_re.match(line): outlines.append(line) diff --git a/tools/patch_directors_cc.py b/tools/patch_directors_cc.py index c1d1164..4e25675 100644 --- a/tools/patch_directors_cc.py +++ b/tools/patch_directors_cc.py @@ -96,6 +96,7 @@ patches = [ "virtual mreg_t idaapi load_operand", "virtual merror_t idaapi analyze_prolog", "virtual merror_t idaapi gen_micro", + "virtual minsn_t *idaapi emit_micro_mvm", ]