diff --git a/BUILDING.txt b/BUILDING.txt index dc2abea..999154a 100644 --- a/BUILDING.txt +++ b/BUILDING.txt @@ -32,26 +32,23 @@ REQUIREMENTS - Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition] http://msdn.microsoft.com/vstudio/express/visualc/ + - Cygwin (requires GNU make) BUILDING -------- Make sure all the needed tools (compiler, swig) are on the PATH. -1. Unpack the IDAPython source and IDA SDK into the following - directory structure: +1. Unpack the IDA SDK into: + '.../idasdk69' + and run 'make' to make sure it compiles - swigsdk-versions/x.y/ - A supported version of the IDA SDK - idapython/ - IDAPython source code +2. Place these IDAPython sources into the SDK directory, such that the file: + '.../idasdk69/plugins/idapython/BUILDING.txt' exists Note: To build with Hex-Rays decompiler support, please copy hexrays.hpp from the decompiler SDK folder into IDA's include folder (in the SDK). -2. On Mac OS X copy libida.dylib from the IDA install directory to - swigsdk-versions/x.y/lib/x86_mac_gcc_32/ - and libida64.dylib to - swigsdk-versions/x.y/lib/x86_mac_gcc_64/ - 3. Build the plugin python build.py diff --git a/api_contents.txt b/api_contents.txt new file mode 100644 index 0000000..677d85d --- /dev/null +++ b/api_contents.txt @@ -0,0 +1,7283 @@ +{'functions': ['AssembleLine', + 'Compile', + 'CompileEx', + 'CompileLine', + 'DBG_Hooks_dbg_bpt', + 'DBG_Hooks_dbg_bpt_changed', + 'DBG_Hooks_dbg_exception', + 'DBG_Hooks_dbg_information', + 'DBG_Hooks_dbg_library_load', + 'DBG_Hooks_dbg_library_unload', + 'DBG_Hooks_dbg_process_attach', + 'DBG_Hooks_dbg_process_detach', + 'DBG_Hooks_dbg_process_exit', + 'DBG_Hooks_dbg_process_start', + 'DBG_Hooks_dbg_request_error', + 'DBG_Hooks_dbg_run_to', + 'DBG_Hooks_dbg_step_into', + 'DBG_Hooks_dbg_step_over', + 'DBG_Hooks_dbg_step_until_ret', + 'DBG_Hooks_dbg_suspend_process', + 'DBG_Hooks_dbg_thread_exit', + 'DBG_Hooks_dbg_thread_start', + 'DBG_Hooks_dbg_trace', + 'DBG_Hooks_hook', + 'DBG_Hooks_unhook', + 'ExtraFree', + 'IDB_Hooks_allsegs_moved', + 'IDB_Hooks_area_cmt_changed', + 'IDB_Hooks_byte_patched', + 'IDB_Hooks_changed_stkpnts', + 'IDB_Hooks_changed_struc', + 'IDB_Hooks_changing_area_cmt', + 'IDB_Hooks_changing_cmt', + 'IDB_Hooks_changing_enum_bf', + 'IDB_Hooks_changing_enum_cmt', + 'IDB_Hooks_changing_op_ti', + 'IDB_Hooks_changing_op_type', + 'IDB_Hooks_changing_segm_class', + 'IDB_Hooks_changing_segm_end', + 'IDB_Hooks_changing_segm_name', + 'IDB_Hooks_changing_segm_start', + 'IDB_Hooks_changing_struc', + 'IDB_Hooks_changing_struc_cmt', + 'IDB_Hooks_changing_struc_member', + 'IDB_Hooks_changing_ti', + 'IDB_Hooks_cmt_changed', + 'IDB_Hooks_deleting_enum', + 'IDB_Hooks_deleting_enum_const', + 'IDB_Hooks_deleting_segm', + 'IDB_Hooks_deleting_struc', + 'IDB_Hooks_deleting_struc_member', + 'IDB_Hooks_destroyed_items', + 'IDB_Hooks_enum_bf_changed', + 'IDB_Hooks_enum_cmt_changed', + 'IDB_Hooks_enum_created', + 'IDB_Hooks_enum_deleted', + 'IDB_Hooks_enum_member_created', + 'IDB_Hooks_enum_member_deleted', + 'IDB_Hooks_enum_renamed', + 'IDB_Hooks_expanding_struc', + 'IDB_Hooks_extra_cmt_changed', + 'IDB_Hooks_func_noret_changed', + 'IDB_Hooks_func_tail_appended', + 'IDB_Hooks_func_tail_removed', + 'IDB_Hooks_hook', + 'IDB_Hooks_local_types_changed', + 'IDB_Hooks_op_ti_changed', + 'IDB_Hooks_op_type_changed', + 'IDB_Hooks_removing_func_tail', + 'IDB_Hooks_renaming_enum', + 'IDB_Hooks_renaming_struc', + 'IDB_Hooks_renaming_struc_member', + 'IDB_Hooks_segm_added', + 'IDB_Hooks_segm_attrs_changed', + 'IDB_Hooks_segm_class_changed', + 'IDB_Hooks_segm_deleted', + 'IDB_Hooks_segm_end_changed', + 'IDB_Hooks_segm_moved', + 'IDB_Hooks_segm_name_changed', + 'IDB_Hooks_segm_start_changed', + 'IDB_Hooks_struc_cmt_changed', + 'IDB_Hooks_struc_created', + 'IDB_Hooks_struc_deleted', + 'IDB_Hooks_struc_expanded', + 'IDB_Hooks_struc_member_changed', + 'IDB_Hooks_struc_member_created', + 'IDB_Hooks_struc_member_deleted', + 'IDB_Hooks_struc_member_renamed', + 'IDB_Hooks_struc_renamed', + 'IDB_Hooks_tail_owner_changed', + 'IDB_Hooks_thunk_func_created', + 'IDB_Hooks_ti_changed', + 'IDB_Hooks_unhook', + 'IDP_Hooks_add_cref', + 'IDP_Hooks_add_dref', + 'IDP_Hooks_add_func', + 'IDP_Hooks_adjust_libfunc_ea', + 'IDP_Hooks_assemble', + 'IDP_Hooks_auto_empty', + 'IDP_Hooks_auto_empty_finally', + 'IDP_Hooks_auto_queue_empty', + 'IDP_Hooks_based_ptr', + 'IDP_Hooks_calc_arglocs3', + 'IDP_Hooks_calc_cdecl_purged_bytes2', + 'IDP_Hooks_calc_next_eas', + 'IDP_Hooks_calc_purged_bytes3', + 'IDP_Hooks_calc_retloc3', + 'IDP_Hooks_calc_step_over', + 'IDP_Hooks_calc_switch_cases', + 'IDP_Hooks_calc_varglocs3', + 'IDP_Hooks_clean_tbit', + 'IDP_Hooks_closebase', + 'IDP_Hooks_coagulate', + 'IDP_Hooks_coagulate_dref', + 'IDP_Hooks_create_flat_group', + 'IDP_Hooks_create_switch_xrefs', + 'IDP_Hooks_custom_ana', + 'IDP_Hooks_custom_emu', + 'IDP_Hooks_custom_mnem', + 'IDP_Hooks_custom_out', + 'IDP_Hooks_custom_outop', + 'IDP_Hooks_custom_refinfo', + 'IDP_Hooks_decorate_name3', + 'IDP_Hooks_del_cref', + 'IDP_Hooks_del_dref', + 'IDP_Hooks_del_func', + 'IDP_Hooks_delay_slot_insn', + 'IDP_Hooks_determined_main', + 'IDP_Hooks_endbinary', + 'IDP_Hooks_equal_reglocs', + 'IDP_Hooks_extlang_changed', + 'IDP_Hooks_func_bounds', + 'IDP_Hooks_gen_asm_or_lst', + 'IDP_Hooks_gen_regvar_def', + 'IDP_Hooks_get_autocmt', + 'IDP_Hooks_get_bg_color', + 'IDP_Hooks_get_dbr_opnum', + 'IDP_Hooks_get_default_enum_size', + 'IDP_Hooks_get_fastcall_regs3', + 'IDP_Hooks_get_func_cvtarg_map', + 'IDP_Hooks_get_jump_target', + 'IDP_Hooks_get_macro_insn_head', + 'IDP_Hooks_get_operand_info', + 'IDP_Hooks_get_operand_string', + 'IDP_Hooks_get_reg_info2', + 'IDP_Hooks_get_reg_name', + 'IDP_Hooks_get_simd_types', + 'IDP_Hooks_get_stkarg_offset2', + 'IDP_Hooks_get_stkvar_scale_factor', + 'IDP_Hooks_get_thiscall_regs3', + 'IDP_Hooks_get_varcall_regs3', + 'IDP_Hooks_get_vxd_name', + 'IDP_Hooks_hook', + 'IDP_Hooks_init', + 'IDP_Hooks_insn_reads_tbit', + 'IDP_Hooks_is_alloca_probe', + 'IDP_Hooks_is_basic_block_end', + 'IDP_Hooks_is_call_insn', + 'IDP_Hooks_is_indirect_jump', + 'IDP_Hooks_is_insn_table_jump', + 'IDP_Hooks_is_jump_func', + 'IDP_Hooks_is_ret_insn', + 'IDP_Hooks_is_sane_insn', + 'IDP_Hooks_kernel_config_loaded', + 'IDP_Hooks_load_idasgn', + 'IDP_Hooks_loader', + 'IDP_Hooks_loader_elf_machine', + 'IDP_Hooks_loader_finished', + 'IDP_Hooks_make_code', + 'IDP_Hooks_make_data', + 'IDP_Hooks_max_ptr_size', + 'IDP_Hooks_may_be_func', + 'IDP_Hooks_may_show_sreg', + 'IDP_Hooks_might_change_sp', + 'IDP_Hooks_move_segm', + 'IDP_Hooks_moving_segm', + 'IDP_Hooks_newasm', + 'IDP_Hooks_newbinary', + 'IDP_Hooks_newfile', + 'IDP_Hooks_newprc', + 'IDP_Hooks_newseg', + 'IDP_Hooks_obsolete_get_operand_info', + 'IDP_Hooks_obsolete_makemicro', + 'IDP_Hooks_oldfile', + 'IDP_Hooks_out_3byte', + 'IDP_Hooks_out_src_file_lnnum', + 'IDP_Hooks_outlabel', + 'IDP_Hooks_preprocess_chart', + 'IDP_Hooks_register_custom_fixup', + 'IDP_Hooks_reglink', + 'IDP_Hooks_rename', + 'IDP_Hooks_renamed', + 'IDP_Hooks_savebase', + 'IDP_Hooks_set_compiler', + 'IDP_Hooks_set_func_end', + 'IDP_Hooks_set_func_start', + 'IDP_Hooks_set_proc_options', + 'IDP_Hooks_setsgr', + 'IDP_Hooks_setup_til', + 'IDP_Hooks_shadow_args_size', + 'IDP_Hooks_str2reg', + 'IDP_Hooks_term', + 'IDP_Hooks_til_for_file', + 'IDP_Hooks_treat_hindering_item', + 'IDP_Hooks_undefine', + 'IDP_Hooks_unhook', + 'IDP_Hooks_use_arg_types3', + 'IDP_Hooks_use_regarg_type3', + 'IDP_Hooks_use_stkarg_type3', + 'IDP_Hooks_validate_flirt_func', + 'IDP_Hooks_verify_noreturn', + 'IDP_Hooks_verify_sp', + 'InstrIsSet', + 'MakeBorder', + 'MakeLine', + 'MakeNull', + 'MakeSolidBorder', + 'OutBadInstruction', + 'OutChar', + 'OutImmChar', + 'OutLine', + 'OutLong', + 'OutMnem', + 'OutValue', + 'QueueDel', + 'QueueGetMessage', + 'QueueGetType', + 'QueueIsPresent', + 'QueueMark', + 'QueueSet', + 'SetDefaultRegisterValue', + 'UI_Hooks_current_tform_changed', + 'UI_Hooks_database_inited', + 'UI_Hooks_debugger_menu_change', + 'UI_Hooks_finish_populating_tform_popup', + 'UI_Hooks_get_custom_viewer_hint', + 'UI_Hooks_get_ea_hint', + 'UI_Hooks_get_item_hint', + 'UI_Hooks_hook', + 'UI_Hooks_idcstart', + 'UI_Hooks_idcstop', + 'UI_Hooks_plugin_loaded', + 'UI_Hooks_plugin_unloading', + 'UI_Hooks_populating_tform_popup', + 'UI_Hooks_postprocess', + 'UI_Hooks_preprocess', + 'UI_Hooks_range', + 'UI_Hooks_ready_to_run', + 'UI_Hooks_resume', + 'UI_Hooks_saved', + 'UI_Hooks_saving', + 'UI_Hooks_suspend', + 'UI_Hooks_term', + 'UI_Hooks_tform_invisible', + 'UI_Hooks_tform_visible', + 'UI_Hooks_unhook', + 'UI_Hooks_updated_actions', + 'UI_Hooks_updating_actions', + 'VarAssign', + 'VarCopy', + 'VarDelAttr', + 'VarDeref', + 'VarFirstAttr', + 'VarGetAttr', + 'VarGetClassName', + 'VarGetSlice', + 'VarInt64', + 'VarLastAttr', + 'VarMove', + 'VarNextAttr', + 'VarObject', + 'VarPrevAttr', + 'VarPrint', + 'VarRef', + 'VarSetAttr', + 'VarSetSlice', + 'VarString2', + 'VarSwap', + '_askaddr', + '_askaddr__varargs__', + '_asklong', + '_asklong__varargs__', + '_askseg', + '_askseg__varargs__', + '_decompile', + 'a2funcoff', + 'accepts_udts', + 'action_ctx_base_t_action_get', + 'action_ctx_base_t_action_set', + 'action_ctx_base_t_chooser_selection_get', + 'action_ctx_base_t_chooser_selection_set', + 'action_ctx_base_t_cur_ea_get', + 'action_ctx_base_t_cur_ea_set', + 'action_ctx_base_t_cur_enum_get', + 'action_ctx_base_t_cur_enum_set', + 'action_ctx_base_t_cur_extracted_ea_get', + 'action_ctx_base_t_cur_extracted_ea_set', + 'action_ctx_base_t_cur_fchunk_get', + 'action_ctx_base_t_cur_fchunk_set', + 'action_ctx_base_t_cur_flags_get', + 'action_ctx_base_t_cur_flags_set', + 'action_ctx_base_t_cur_func_get', + 'action_ctx_base_t_cur_func_set', + 'action_ctx_base_t_cur_seg_get', + 'action_ctx_base_t_cur_seg_set', + 'action_ctx_base_t_cur_strmem_get', + 'action_ctx_base_t_cur_strmem_set', + 'action_ctx_base_t_cur_struc_get', + 'action_ctx_base_t_cur_struc_set', + 'action_ctx_base_t_form_get', + 'action_ctx_base_t_form_set', + 'action_ctx_base_t_form_title_get', + 'action_ctx_base_t_form_title_set', + 'action_ctx_base_t_form_type_get', + 'action_ctx_base_t_form_type_set', + 'action_ctx_base_t_has_flag', + 'action_ctx_base_t_reset', + 'action_desc_t_cb_get', + 'action_desc_t_cb_set', + 'action_desc_t_icon_get', + 'action_desc_t_icon_set', + 'action_desc_t_label_get', + 'action_desc_t_label_set', + 'action_desc_t_name_get', + 'action_desc_t_name_set', + 'action_desc_t_owner_get', + 'action_desc_t_owner_set', + 'action_desc_t_shortcut_get', + 'action_desc_t_shortcut_set', + 'action_desc_t_tooltip_get', + 'action_desc_t_tooltip_set', + 'add_auto_stkpnt', + 'add_auto_stkpnt2', + 'add_bpt', + 'add_bpt__SWIG_0', + 'add_bpt__SWIG_1', + 'add_byte', + 'add_chooser_command', + 'add_chooser_command__SWIG_0', + 'add_chooser_command__SWIG_1', + 'add_const', + 'add_cref', + 'add_custom_viewer_popup_item', + 'add_dref', + 'add_encoding', + 'add_entry', + 'add_enum', + 'add_enum_member', + 'add_frame', + 'add_func', + 'add_func_ex', + 'add_hidden_area', + 'add_hotkey', + 'add_idc_class', + 'add_idc_gvar', + 'add_idc_hotkey', + 'add_long', + 'add_long_cmt', + 'add_long_cmt__varargs__', + 'add_menu_item', + 'add_output_popup', + 'add_pgm_cmt', + 'add_pgm_cmt__varargs__', + 'add_qword', + 'add_regarg', + 'add_regarg2', + 'add_regvar', + 'add_segm', + 'add_segm_ex', + 'add_segment_translation', + 'add_sourcefile', + 'add_spaces', + 'add_stkvar2', + 'add_stkvar3', + 'add_struc', + 'add_struc_member', + 'add_test_feature', + 'add_til', + 'add_til2', + 'add_user_stkpnt', + 'add_virt_module', + 'add_word', + 'addon_count', + 'addon_info_t_cb_get', + 'addon_info_t_cb_set', + 'addon_info_t_custom_data_get', + 'addon_info_t_custom_data_set', + 'addon_info_t_custom_size_get', + 'addon_info_t_custom_size_set', + 'addon_info_t_freeform_get', + 'addon_info_t_freeform_set', + 'addon_info_t_id_get', + 'addon_info_t_id_set', + 'addon_info_t_name_get', + 'addon_info_t_name_set', + 'addon_info_t_producer_get', + 'addon_info_t_producer_set', + 'addon_info_t_url_get', + 'addon_info_t_url_set', + 'addon_info_t_version_get', + 'addon_info_t_version_set', + 'alignflag', + 'alloc_type_ordinal', + 'alloc_type_ordinals', + 'allocate_selector', + 'aloc_visitor_t_visit_location', + 'analyze_area', + 'analyzer_options', + 'ansi2idb', + 'appcall', + 'append_argloc', + 'append_cmt', + 'append_complex_n', + 'append_da', + 'append_de', + 'append_dt', + 'append_func_tail', + 'append_name', + 'append_struct_fields2', + 'append_varloc', + 'apply_callee_tinfo', + 'apply_cdecl', + 'apply_cdecl2', + 'apply_idasgn', + 'apply_idasgn_to', + 'apply_named_type', + 'apply_once_tinfo_and_name', + 'apply_once_type_and_name', + 'apply_startup_sig', + 'apply_tinfo', + 'apply_tinfo2', + 'apply_tinfo_to_stkarg', + 'apply_type', + 'apply_type2', + 'apply_type_to_stkarg', + 'area_t___eq__', + 'area_t___gt__', + 'area_t___lt__', + 'area_t___ne__', + 'area_t__print', + 'area_t_clear', + 'area_t_compare', + 'area_t_contains', + 'area_t_contains__SWIG_0', + 'area_t_contains__SWIG_1', + 'area_t_empty', + 'area_t_endEA_get', + 'area_t_endEA_set', + 'area_t_extend', + 'area_t_intersect', + 'area_t_overlaps', + 'area_t_print', + 'area_t_size', + 'area_t_startEA_get', + 'area_t_startEA_set', + 'area_visitor2_t_visit_area', + 'areacb_t_create', + 'areacb_t_create_area', + 'areacb_t_del_area', + 'areacb_t_del_area_cmt', + 'areacb_t_first_area_ptr', + 'areacb_t_for_all_areas2', + 'areacb_t_get_area', + 'areacb_t_get_area_cmt', + 'areacb_t_get_area_num', + 'areacb_t_get_area_qty', + 'areacb_t_get_netnode', + 'areacb_t_get_next_area', + 'areacb_t_get_prev_area', + 'areacb_t_get_type', + 'areacb_t_getn_area', + 'areacb_t_kill', + 'areacb_t_last_area_ptr', + 'areacb_t_link', + 'areacb_t_make_hole', + 'areacb_t_may_end_at', + 'areacb_t_may_lock_area', + 'areacb_t_may_start_at', + 'areacb_t_next_area_ptr', + 'areacb_t_prepare_to_create', + 'areacb_t_prev_area_ptr', + 'areacb_t_resize_areas', + 'areacb_t_save', + 'areacb_t_set_area_cmt', + 'areacb_t_set_end', + 'areacb_t_set_start', + 'areacb_t_terminate', + 'areacb_t_update', + 'areacb_t_zero', + 'areaset_t___eq__', + 'areaset_t___ne__', + 'areaset_t__print', + 'areaset_t_add', + 'areaset_t_add__SWIG_0', + 'areaset_t_add__SWIG_1', + 'areaset_t_add__SWIG_2', + 'areaset_t_begin', + 'areaset_t_begin__SWIG_0', + 'areaset_t_begin__SWIG_1', + 'areaset_t_cached_area', + 'areaset_t_clear', + 'areaset_t_contains', + 'areaset_t_contains__SWIG_0', + 'areaset_t_contains__SWIG_1', + 'areaset_t_empty', + 'areaset_t_end', + 'areaset_t_end__SWIG_0', + 'areaset_t_end__SWIG_1', + 'areaset_t_find_area', + 'areaset_t_getarea', + 'areaset_t_has_common', + 'areaset_t_has_common__SWIG_0', + 'areaset_t_has_common__SWIG_1', + 'areaset_t_includes', + 'areaset_t_intersect', + 'areaset_t_is_equal', + 'areaset_t_is_subset_of', + 'areaset_t_lastarea', + 'areaset_t_nareas', + 'areaset_t_next_addr', + 'areaset_t_next_area', + 'areaset_t_prev_addr', + 'areaset_t_prev_area', + 'areaset_t_sub', + 'areaset_t_sub__SWIG_0', + 'areaset_t_sub__SWIG_1', + 'areaset_t_sub__SWIG_2', + 'areaset_t_swap', + 'argloc_t___eq__', + 'argloc_t___ge__', + 'argloc_t___gt__', + 'argloc_t___le__', + 'argloc_t___lt__', + 'argloc_t___ne__', + 'argloc_t__consume_rrel', + 'argloc_t__consume_scattered', + 'argloc_t__set_badloc', + 'argloc_t__set_biggest', + 'argloc_t__set_custom', + 'argloc_t__set_ea', + 'argloc_t__set_reg1', + 'argloc_t__set_reg2', + 'argloc_t__set_stkoff', + 'argloc_t_advance', + 'argloc_t_atype', + 'argloc_t_calc_offset', + 'argloc_t_compare', + 'argloc_t_consume_rrel', + 'argloc_t_consume_scattered', + 'argloc_t_get_biggest', + 'argloc_t_get_custom', + 'argloc_t_get_ea', + 'argloc_t_get_reginfo', + 'argloc_t_get_rrel', + 'argloc_t_get_rrel__SWIG_0', + 'argloc_t_get_rrel__SWIG_1', + 'argloc_t_is_badloc', + 'argloc_t_is_custom', + 'argloc_t_is_ea', + 'argloc_t_is_fragmented', + 'argloc_t_is_reg', + 'argloc_t_is_reg1', + 'argloc_t_is_reg2', + 'argloc_t_is_rrel', + 'argloc_t_is_scattered', + 'argloc_t_is_stkoff', + 'argloc_t_reg1', + 'argloc_t_reg2', + 'argloc_t_regoff', + 'argloc_t_scattered', + 'argloc_t_scattered__SWIG_0', + 'argloc_t_scattered__SWIG_1', + 'argloc_t_set_badloc', + 'argloc_t_set_ea', + 'argloc_t_set_reg1', + 'argloc_t_set_reg2', + 'argloc_t_set_stkoff', + 'argloc_t_stkoff', + 'argloc_t_swap', + 'arglocs_overlap', + 'argpart_t___lt__', + 'argpart_t_bad_offset', + 'argpart_t_bad_size', + 'argpart_t_off_get', + 'argpart_t_off_set', + 'argpart_t_size_get', + 'argpart_t_size_set', + 'argpart_t_swap', + 'array_parameters_t_alignment_get', + 'array_parameters_t_alignment_set', + 'array_parameters_t_flags_get', + 'array_parameters_t_flags_set', + 'array_parameters_t_lineitems_get', + 'array_parameters_t_lineitems_set', + 'array_type_data_t_base_get', + 'array_type_data_t_base_set', + 'array_type_data_t_elem_type_get', + 'array_type_data_t_elem_type_set', + 'array_type_data_t_nelems_get', + 'array_type_data_t_nelems_set', + 'array_type_data_t_swap', + 'asciflag', + 'asgop', + 'asgop_revert', + 'ask_for_feedback', + 'ask_for_feedback__varargs__', + 'ask_selector', + 'askbuttons_c', + 'askbuttons_c__varargs__', + 'askfile2_c', + 'askfile2_c__varargs__', + 'askfile2_cv', + 'askfile_c', + 'askfile_c__varargs__', + 'askident', + 'askident__varargs__', + 'askqstr', + 'askqstr__varargs__', + 'askstr', + 'askstr__varargs__', + 'asktext', + 'askyn_c', + 'askyn_c__varargs__', + 'asm_t_XlatAsciiOutput_get', + 'asm_t_XlatAsciiOutput_set', + 'asm_t__UNUSED1_was_atomprefix_get', + 'asm_t__UNUSED1_was_atomprefix_set', + 'asm_t__UNUSED2_was_checkarg_operations_get', + 'asm_t__UNUSED2_was_checkarg_operations_set', + 'asm_t_a_3byte_get', + 'asm_t_a_3byte_set', + 'asm_t_a_align_get', + 'asm_t_a_align_set', + 'asm_t_a_ascii_get', + 'asm_t_a_ascii_set', + 'asm_t_a_band_get', + 'asm_t_a_band_set', + 'asm_t_a_bnot_get', + 'asm_t_a_bnot_set', + 'asm_t_a_bor_get', + 'asm_t_a_bor_set', + 'asm_t_a_bss_get', + 'asm_t_a_bss_set', + 'asm_t_a_byte_get', + 'asm_t_a_byte_set', + 'asm_t_a_comdef_get', + 'asm_t_a_comdef_set', + 'asm_t_a_curip_get', + 'asm_t_a_curip_set', + 'asm_t_a_double_get', + 'asm_t_a_double_set', + 'asm_t_a_dups_get', + 'asm_t_a_dups_set', + 'asm_t_a_dword_get', + 'asm_t_a_dword_set', + 'asm_t_a_equ_get', + 'asm_t_a_equ_set', + 'asm_t_a_extrn_get', + 'asm_t_a_extrn_set', + 'asm_t_a_float_get', + 'asm_t_a_float_set', + 'asm_t_a_include_fmt_get', + 'asm_t_a_include_fmt_set', + 'asm_t_a_mod_get', + 'asm_t_a_mod_set', + 'asm_t_a_oword_get', + 'asm_t_a_oword_set', + 'asm_t_a_packreal_get', + 'asm_t_a_packreal_set', + 'asm_t_a_public_get', + 'asm_t_a_public_set', + 'asm_t_a_qword_get', + 'asm_t_a_qword_set', + 'asm_t_a_rva_get', + 'asm_t_a_rva_set', + 'asm_t_a_seg_get', + 'asm_t_a_seg_set', + 'asm_t_a_shl_get', + 'asm_t_a_shl_set', + 'asm_t_a_shr_get', + 'asm_t_a_shr_set', + 'asm_t_a_sizeof_fmt_get', + 'asm_t_a_sizeof_fmt_set', + 'asm_t_a_tbyte_get', + 'asm_t_a_tbyte_set', + 'asm_t_a_vstruc_fmt_get', + 'asm_t_a_vstruc_fmt_set', + 'asm_t_a_weak_get', + 'asm_t_a_weak_set', + 'asm_t_a_word_get', + 'asm_t_a_word_set', + 'asm_t_a_xor_get', + 'asm_t_a_xor_set', + 'asm_t_a_yword_get', + 'asm_t_a_yword_set', + 'asm_t_accsep_get', + 'asm_t_accsep_set', + 'asm_t_ascsep_get', + 'asm_t_ascsep_set', + 'asm_t_badworks_get', + 'asm_t_badworks_set', + 'asm_t_cmnt2_get', + 'asm_t_cmnt2_set', + 'asm_t_cmnt_get', + 'asm_t_cmnt_set', + 'asm_t_end_get', + 'asm_t_end_set', + 'asm_t_esccodes_get', + 'asm_t_esccodes_set', + 'asm_t_flag2_get', + 'asm_t_flag2_set', + 'asm_t_flag_get', + 'asm_t_flag_set', + 'asm_t_header_get', + 'asm_t_header_set', + 'asm_t_help_get', + 'asm_t_help_set', + 'asm_t_high16_get', + 'asm_t_high16_set', + 'asm_t_high8_get', + 'asm_t_high8_set', + 'asm_t_lbrace_get', + 'asm_t_lbrace_set', + 'asm_t_low16_get', + 'asm_t_low16_set', + 'asm_t_low8_get', + 'asm_t_low8_set', + 'asm_t_name_get', + 'asm_t_name_set', + 'asm_t_origin_get', + 'asm_t_origin_set', + 'asm_t_rbrace_get', + 'asm_t_rbrace_set', + 'asm_t_uflag_get', + 'asm_t_uflag_set', + 'assemble', + 'attach_action_to_menu', + 'attach_action_to_popup', + 'attach_action_to_popup__SWIG_0', + 'attach_action_to_popup__SWIG_1', + 'attach_action_to_toolbar', + 'attach_dynamic_action_to_popup', + 'attach_process', + 'autoCancel', + 'autoGetName', + 'autoIsOk', + 'autoMark', + 'autoStep', + 'autoUnmark', + 'autoWait', + 'auto_apply_type', + 'auto_display_t_ea_get', + 'auto_display_t_ea_set', + 'auto_display_t_state_get', + 'auto_display_t_state_set', + 'auto_display_t_type_get', + 'auto_display_t_type_set', + 'auto_get', + 'auto_make_code', + 'auto_make_proc', + 'auto_mark_range', + 'banner', + 'base2file', + 'beep', + 'begin_type_updating', + 'bgcolors_t_epilog_color_get', + 'bgcolors_t_epilog_color_set', + 'bgcolors_t_prolog_color_get', + 'bgcolors_t_prolog_color_set', + 'bgcolors_t_switch_color_get', + 'bgcolors_t_switch_color_set', + 'bin_search', + 'binflag', + 'bitfield_type_data_t___eq__', + 'bitfield_type_data_t___ge__', + 'bitfield_type_data_t___gt__', + 'bitfield_type_data_t___le__', + 'bitfield_type_data_t___lt__', + 'bitfield_type_data_t___ne__', + 'bitfield_type_data_t_compare', + 'bitfield_type_data_t_is_unsigned_get', + 'bitfield_type_data_t_is_unsigned_set', + 'bitfield_type_data_t_nbytes_get', + 'bitfield_type_data_t_nbytes_set', + 'bitfield_type_data_t_swap', + 'bitfield_type_data_t_width_get', + 'bitfield_type_data_t_width_set', + 'bnot_data_flag', + 'bookmarks_t_erase', + 'bookmarks_t_find_index', + 'bookmarks_t_get', + 'bookmarks_t_get_desc', + 'bookmarks_t_mark', + 'bookmarks_t_size', + 'boolvec_t___eq__', + 'boolvec_t___getitem__', + 'boolvec_t___len__', + 'boolvec_t___ne__', + 'boolvec_t___setitem__', + 'boolvec_t__del', + 'boolvec_t_add_unique', + 'boolvec_t_at', + 'boolvec_t_back', + 'boolvec_t_back__SWIG_0', + 'boolvec_t_back__SWIG_1', + 'boolvec_t_begin', + 'boolvec_t_begin__SWIG_0', + 'boolvec_t_begin__SWIG_1', + 'boolvec_t_capacity', + 'boolvec_t_clear', + 'boolvec_t_empty', + 'boolvec_t_end', + 'boolvec_t_end__SWIG_0', + 'boolvec_t_end__SWIG_1', + 'boolvec_t_erase', + 'boolvec_t_erase__SWIG_0', + 'boolvec_t_erase__SWIG_1', + 'boolvec_t_extract', + 'boolvec_t_find', + 'boolvec_t_find__SWIG_0', + 'boolvec_t_find__SWIG_1', + 'boolvec_t_front', + 'boolvec_t_front__SWIG_0', + 'boolvec_t_front__SWIG_1', + 'boolvec_t_grow', + 'boolvec_t_has', + 'boolvec_t_inject', + 'boolvec_t_insert', + 'boolvec_t_pop_back', + 'boolvec_t_push_back', + 'boolvec_t_push_back__SWIG_0', + 'boolvec_t_push_back__SWIG_1', + 'boolvec_t_qclear', + 'boolvec_t_reserve', + 'boolvec_t_resize', + 'boolvec_t_resize__SWIG_0', + 'boolvec_t_resize__SWIG_1', + 'boolvec_t_size', + 'boolvec_t_swap', + 'boolvec_t_truncate', + 'boundaries_begin', + 'boundaries_clear', + 'boundaries_end', + 'boundaries_erase', + 'boundaries_find', + 'boundaries_first', + 'boundaries_free', + 'boundaries_insert', + 'boundaries_iterator_t___eq__', + 'boundaries_iterator_t___ne__', + 'boundaries_iterator_t_x_get', + 'boundaries_iterator_t_x_set', + 'boundaries_new', + 'boundaries_next', + 'boundaries_prev', + 'boundaries_second', + 'boundaries_size', + 'boundaries_t_at', + 'boundaries_t_size', + 'bpt_location_t___eq__', + 'bpt_location_t___ge__', + 'bpt_location_t___gt__', + 'bpt_location_t___le__', + 'bpt_location_t___lt__', + 'bpt_location_t___ne__', + 'bpt_location_t_compare', + 'bpt_location_t_ea', + 'bpt_location_t_index_get', + 'bpt_location_t_index_set', + 'bpt_location_t_info_get', + 'bpt_location_t_info_set', + 'bpt_location_t_is_empty_path', + 'bpt_location_t_lineno', + 'bpt_location_t_loctype_get', + 'bpt_location_t_loctype_set', + 'bpt_location_t_offset', + 'bpt_location_t_path', + 'bpt_location_t_set_abs_bpt', + 'bpt_location_t_set_rel_bpt', + 'bpt_location_t_set_src_bpt', + 'bpt_location_t_set_sym_bpt', + 'bpt_location_t_symbol', + 'bpt_location_t_type', + 'bpt_t_badbpt', + 'bpt_t_cb_get', + 'bpt_t_cb_set', + 'bpt_t_cndidx_get', + 'bpt_t_cndidx_set', + 'bpt_t_condition_get', + 'bpt_t_condition_set', + 'bpt_t_ea_get', + 'bpt_t_ea_set', + 'bpt_t_elang_get', + 'bpt_t_elang_set', + 'bpt_t_enabled', + 'bpt_t_flags_get', + 'bpt_t_flags_set', + 'bpt_t_get_size', + 'bpt_t_is_absbpt', + 'bpt_t_is_active', + 'bpt_t_is_compiled', + 'bpt_t_is_hwbpt', + 'bpt_t_is_inactive', + 'bpt_t_is_low_level', + 'bpt_t_is_page_bpt', + 'bpt_t_is_partially_active', + 'bpt_t_is_relbpt', + 'bpt_t_is_srcbpt', + 'bpt_t_is_symbpt', + 'bpt_t_is_tracemodebpt', + 'bpt_t_is_traceoffbpt', + 'bpt_t_is_traceonbpt', + 'bpt_t_listbpt', + 'bpt_t_loc_get', + 'bpt_t_loc_set', + 'bpt_t_pass_count_get', + 'bpt_t_pass_count_set', + 'bpt_t_props_get', + 'bpt_t_props_set', + 'bpt_t_set_abs_bpt', + 'bpt_t_set_rel_bpt', + 'bpt_t_set_src_bpt', + 'bpt_t_set_sym_bpt', + 'bpt_t_set_trace_action', + 'bpt_t_size_get', + 'bpt_t_size_set', + 'bpt_t_type_get', + 'bpt_t_type_set', + 'bpt_vec_t___getitem__', + 'bpt_vec_t___len__', + 'bpt_vec_t___setitem__', + 'bpt_vec_t_at', + 'bpt_vec_t_back', + 'bpt_vec_t_back__SWIG_0', + 'bpt_vec_t_back__SWIG_1', + 'bpt_vec_t_begin', + 'bpt_vec_t_begin__SWIG_0', + 'bpt_vec_t_begin__SWIG_1', + 'bpt_vec_t_capacity', + 'bpt_vec_t_clear', + 'bpt_vec_t_empty', + 'bpt_vec_t_end', + 'bpt_vec_t_end__SWIG_0', + 'bpt_vec_t_end__SWIG_1', + 'bpt_vec_t_erase', + 'bpt_vec_t_erase__SWIG_0', + 'bpt_vec_t_erase__SWIG_1', + 'bpt_vec_t_extract', + 'bpt_vec_t_front', + 'bpt_vec_t_front__SWIG_0', + 'bpt_vec_t_front__SWIG_1', + 'bpt_vec_t_grow', + 'bpt_vec_t_inject', + 'bpt_vec_t_insert', + 'bpt_vec_t_pop_back', + 'bpt_vec_t_push_back', + 'bpt_vec_t_push_back__SWIG_0', + 'bpt_vec_t_push_back__SWIG_1', + 'bpt_vec_t_qclear', + 'bpt_vec_t_reserve', + 'bpt_vec_t_resize', + 'bpt_vec_t_resize__SWIG_0', + 'bpt_vec_t_resize__SWIG_1', + 'bpt_vec_t_size', + 'bpt_vec_t_swap', + 'bpt_vec_t_truncate', + 'bring_debugger_to_front', + 'build_array_type', + 'build_func_type', + 'build_func_type2', + 'build_funcarg_info', + 'build_snapshot_tree', + 'build_stkvar_name', + 'build_stkvar_xrefs', + 'byteflag', + 'bytesize', + 'calc_argloc_info', + 'calc_bg_color', + 'calc_c_cpp_name4', + 'calc_def_align', + 'calc_default_idaplace_flags', + 'calc_func_nargs', + 'calc_idasgn_state', + 'calc_idc_expr', + 'calc_max_align', + 'calc_max_children_qty', + 'calc_max_item_end', + 'calc_max_number_of_children', + 'calc_min_align', + 'calc_number_of_children', + 'calc_prefix_color', + 'calc_probable_base_by_value', + 'calc_reference_basevalue', + 'calc_reference_target', + 'calc_stkvar_struc_offset', + 'calc_switch_cases', + 'calc_switch_cases__SWIG_0', + 'calc_switch_cases__SWIG_1', + 'calc_target', + 'calc_thunk_func_target', + 'calc_type_size', + 'calc_varloc_info', + 'calcexpr', + 'call_helper', + 'call_helper__varargs__', + 'call_idc_method', + 'call_nav_colorizer', + 'call_script_method', + 'call_stack_info_t___eq__', + 'call_stack_info_t___ne__', + 'call_stack_info_t_callea_get', + 'call_stack_info_t_callea_set', + 'call_stack_info_t_fp_get', + 'call_stack_info_t_fp_set', + 'call_stack_info_t_funcea_get', + 'call_stack_info_t_funcea_set', + 'call_stack_info_t_funcok_get', + 'call_stack_info_t_funcok_set', + 'call_stack_t_dirty_get', + 'call_stack_t_dirty_set', + 'call_system', + 'callregs_init_regs', + 'callregs_t_fpregs_get', + 'callregs_t_fpregs_set', + 'callregs_t_gpregs_get', + 'callregs_t_gpregs_set', + 'callregs_t_init_regs', + 'callregs_t_nregs_get', + 'callregs_t_nregs_set', + 'callregs_t_policy_get', + 'callregs_t_policy_set', + 'callregs_t_regcount', + 'callregs_t_reginds', + 'callregs_t_reset', + 'callregs_t_set', + 'can_be_off32', + 'can_define_item', + 'can_exc_continue', + 'cancel_exec_request', + 'carg_t___eq__', + 'carg_t___ge__', + 'carg_t___gt__', + 'carg_t___le__', + 'carg_t___lt__', + 'carg_t___ne__', + 'carg_t_compare', + 'carg_t_consume_cexpr', + 'carg_t_formal_type_get', + 'carg_t_formal_type_set', + 'carg_t_is_vararg_get', + 'carg_t_is_vararg_set', + 'carglist_t___eq__', + 'carglist_t___ge__', + 'carglist_t___gt__', + 'carglist_t___le__', + 'carglist_t___lt__', + 'carglist_t___ne__', + 'carglist_t_compare', + 'carglist_t_functype_get', + 'carglist_t_functype_set', + 'cases_and_targets_t_cases_get', + 'cases_and_targets_t_cases_set', + 'cases_and_targets_t_targets_get', + 'cases_and_targets_t_targets_set', + 'casevec_t___eq__', + 'casevec_t___getitem__', + 'casevec_t___len__', + 'casevec_t___ne__', + 'casevec_t___setitem__', + 'casevec_t__del', + 'casevec_t_add_unique', + 'casevec_t_at', + 'casevec_t_back', + 'casevec_t_back__SWIG_0', + 'casevec_t_back__SWIG_1', + 'casevec_t_begin', + 'casevec_t_begin__SWIG_0', + 'casevec_t_begin__SWIG_1', + 'casevec_t_capacity', + 'casevec_t_clear', + 'casevec_t_empty', + 'casevec_t_end', + 'casevec_t_end__SWIG_0', + 'casevec_t_end__SWIG_1', + 'casevec_t_erase', + 'casevec_t_erase__SWIG_0', + 'casevec_t_erase__SWIG_1', + 'casevec_t_extract', + 'casevec_t_find', + 'casevec_t_find__SWIG_0', + 'casevec_t_find__SWIG_1', + 'casevec_t_front', + 'casevec_t_front__SWIG_0', + 'casevec_t_front__SWIG_1', + 'casevec_t_grow', + 'casevec_t_has', + 'casevec_t_inject', + 'casevec_t_insert', + 'casevec_t_pop_back', + 'casevec_t_push_back', + 'casevec_t_push_back__SWIG_0', + 'casevec_t_push_back__SWIG_1', + 'casevec_t_qclear', + 'casevec_t_reserve', + 'casevec_t_resize', + 'casevec_t_resize__SWIG_0', + 'casevec_t_resize__SWIG_1', + 'casevec_t_size', + 'casevec_t_swap', + 'casevec_t_truncate', + 'casm_t___eq__', + 'casm_t___ge__', + 'casm_t___gt__', + 'casm_t___le__', + 'casm_t___lt__', + 'casm_t___ne__', + 'casm_t_compare', + 'casm_t_one_insn', + 'cblock_t___eq__', + 'cblock_t___ge__', + 'cblock_t___gt__', + 'cblock_t___le__', + 'cblock_t___lt__', + 'cblock_t___ne__', + 'cblock_t_compare', + 'ccase_t___eq__', + 'ccase_t___ge__', + 'ccase_t___gt__', + 'ccase_t___le__', + 'ccase_t___lt__', + 'ccase_t___ne__', + 'ccase_t_compare', + 'ccase_t_size', + 'ccase_t_value', + 'ccase_t_values_get', + 'ccase_t_values_set', + 'ccases_t___eq__', + 'ccases_t___ge__', + 'ccases_t___gt__', + 'ccases_t___le__', + 'ccases_t___lt__', + 'ccases_t___ne__', + 'ccases_t_compare', + 'cdo_t___eq__', + 'cdo_t___ge__', + 'cdo_t___gt__', + 'cdo_t___le__', + 'cdo_t___lt__', + 'cdo_t___ne__', + 'cdo_t_compare', + 'ceinsn_t_expr_get', + 'ceinsn_t_expr_set', + 'cexpr_t___eq__', + 'cexpr_t___ge__', + 'cexpr_t___gt__', + 'cexpr_t___le__', + 'cexpr_t___lt__', + 'cexpr_t___ne__', + 'cexpr_t_a_get', + 'cexpr_t_assign', + 'cexpr_t_calc_type', + 'cexpr_t_cleanup', + 'cexpr_t_compare', + 'cexpr_t_contains_comma', + 'cexpr_t_contains_comma_or_insn_or_label', + 'cexpr_t_contains_insn', + 'cexpr_t_contains_insn_or_label', + 'cexpr_t_contains_operator', + 'cexpr_t_cpadone', + 'cexpr_t_equal_effect', + 'cexpr_t_exflags_get', + 'cexpr_t_exflags_set', + 'cexpr_t_find_num_op', + 'cexpr_t_find_num_op__SWIG_0', + 'cexpr_t_find_num_op__SWIG_1', + 'cexpr_t_find_op', + 'cexpr_t_find_op__SWIG_0', + 'cexpr_t_find_op__SWIG_1', + 'cexpr_t_fpc_get', + 'cexpr_t_get_1num_op', + 'cexpr_t_get_const_value', + 'cexpr_t_get_high_nbit_bound', + 'cexpr_t_get_low_nbit_bound', + 'cexpr_t_get_ptr_or_array', + 'cexpr_t_get_type_sign', + 'cexpr_t_has_side_effects', + 'cexpr_t_helper_get', + 'cexpr_t_insn_get', + 'cexpr_t_is_call_arg_of', + 'cexpr_t_is_call_object_of', + 'cexpr_t_is_child_of', + 'cexpr_t_is_const_value', + 'cexpr_t_is_cstr', + 'cexpr_t_is_fpop', + 'cexpr_t_is_negative_const', + 'cexpr_t_is_nice_cond', + 'cexpr_t_is_nice_expr', + 'cexpr_t_is_non_zero_const', + 'cexpr_t_is_odd_lvalue', + 'cexpr_t_is_zero_const', + 'cexpr_t_m_get', + 'cexpr_t_maybe_ptr', + 'cexpr_t_n_get', + 'cexpr_t_numval', + 'cexpr_t_obj_ea_get', + 'cexpr_t_print1', + 'cexpr_t_ptrsize_get', + 'cexpr_t_put_number', + 'cexpr_t_refwidth_get', + 'cexpr_t_replace_by', + 'cexpr_t_requires_lvalue', + 'cexpr_t_set_cpadone', + 'cexpr_t_string_get', + 'cexpr_t_swap', + 'cexpr_t_theother', + 'cexpr_t_theother__SWIG_0', + 'cexpr_t_theother__SWIG_1', + 'cexpr_t_type_get', + 'cexpr_t_type_set', + 'cexpr_t_v_get', + 'cexpr_t_x_get', + 'cexpr_t_y_get', + 'cexpr_t_z_get', + 'cfg_get_cc_header_path', + 'cfg_get_cc_parm', + 'cfg_get_cc_predefined_macros', + 'cfor_t___eq__', + 'cfor_t___ge__', + 'cfor_t___gt__', + 'cfor_t___le__', + 'cfor_t___lt__', + 'cfor_t___ne__', + 'cfor_t_compare', + 'cfor_t_init_get', + 'cfor_t_init_set', + 'cfor_t_step_get', + 'cfor_t_step_set', + 'cfunc_parentee_t_calc_rvalue_type', + 'cfunc_parentee_t_func_get', + 'cfunc_parentee_t_func_set', + 'cfunc_t___str__', + 'cfunc_t_argidx_get', + 'cfunc_t_body_get', + 'cfunc_t_body_set', + 'cfunc_t_build_c_tree', + 'cfunc_t_del_orphan_cmts', + 'cfunc_t_entry_ea_get', + 'cfunc_t_entry_ea_set', + 'cfunc_t_find_label', + 'cfunc_t_gather_derefs', + 'cfunc_t_get_boundaries', + 'cfunc_t_get_eamap', + 'cfunc_t_get_func_type', + 'cfunc_t_get_line_item', + 'cfunc_t_get_lvars', + 'cfunc_t_get_pseudocode', + 'cfunc_t_get_user_cmt', + 'cfunc_t_get_user_iflags', + 'cfunc_t_get_user_union_selection', + 'cfunc_t_get_warnings', + 'cfunc_t_has_orphan_cmts', + 'cfunc_t_hdrlines_get', + 'cfunc_t_hdrlines_set', + 'cfunc_t_maturity_get', + 'cfunc_t_maturity_set', + 'cfunc_t_mba_get', + 'cfunc_t_mba_set', + 'cfunc_t_numforms_get', + 'cfunc_t_numforms_set', + 'cfunc_t_print_dcl', + 'cfunc_t_print_dcl2', + 'cfunc_t_print_func', + 'cfunc_t_refcnt_get', + 'cfunc_t_refcnt_set', + 'cfunc_t_release', + 'cfunc_t_remove_unused_labels', + 'cfunc_t_save_user_cmts', + 'cfunc_t_save_user_iflags', + 'cfunc_t_save_user_labels', + 'cfunc_t_save_user_numforms', + 'cfunc_t_save_user_unions', + 'cfunc_t_set_user_cmt', + 'cfunc_t_set_user_iflags', + 'cfunc_t_set_user_union_selection', + 'cfunc_t_statebits_get', + 'cfunc_t_statebits_set', + 'cfunc_t_treeitems_get', + 'cfunc_t_treeitems_set', + 'cfunc_t_user_cmts_get', + 'cfunc_t_user_cmts_set', + 'cfunc_t_user_iflags_get', + 'cfunc_t_user_iflags_set', + 'cfunc_t_user_labels_get', + 'cfunc_t_user_labels_set', + 'cfunc_t_user_unions_get', + 'cfunc_t_user_unions_set', + 'cfunc_t_verify', + 'cfuncptr_t___deref__', + 'cfuncptr_t___ref__', + 'cfuncptr_t___str__', + 'cfuncptr_t_argidx_get', + 'cfuncptr_t_body_get', + 'cfuncptr_t_body_set', + 'cfuncptr_t_build_c_tree', + 'cfuncptr_t_del_orphan_cmts', + 'cfuncptr_t_entry_ea_get', + 'cfuncptr_t_entry_ea_set', + 'cfuncptr_t_find_label', + 'cfuncptr_t_gather_derefs', + 'cfuncptr_t_get_boundaries', + 'cfuncptr_t_get_eamap', + 'cfuncptr_t_get_func_type', + 'cfuncptr_t_get_line_item', + 'cfuncptr_t_get_lvars', + 'cfuncptr_t_get_pseudocode', + 'cfuncptr_t_get_user_cmt', + 'cfuncptr_t_get_user_iflags', + 'cfuncptr_t_get_user_union_selection', + 'cfuncptr_t_get_warnings', + 'cfuncptr_t_has_orphan_cmts', + 'cfuncptr_t_hdrlines_get', + 'cfuncptr_t_hdrlines_set', + 'cfuncptr_t_maturity_get', + 'cfuncptr_t_maturity_set', + 'cfuncptr_t_mba_get', + 'cfuncptr_t_mba_set', + 'cfuncptr_t_numforms_get', + 'cfuncptr_t_numforms_set', + 'cfuncptr_t_print_dcl', + 'cfuncptr_t_print_dcl2', + 'cfuncptr_t_print_func', + 'cfuncptr_t_refcnt_get', + 'cfuncptr_t_refcnt_set', + 'cfuncptr_t_release', + 'cfuncptr_t_remove_unused_labels', + 'cfuncptr_t_reset', + 'cfuncptr_t_save_user_cmts', + 'cfuncptr_t_save_user_iflags', + 'cfuncptr_t_save_user_labels', + 'cfuncptr_t_save_user_numforms', + 'cfuncptr_t_save_user_unions', + 'cfuncptr_t_set_user_cmt', + 'cfuncptr_t_set_user_iflags', + 'cfuncptr_t_set_user_union_selection', + 'cfuncptr_t_statebits_get', + 'cfuncptr_t_statebits_set', + 'cfuncptr_t_treeitems_get', + 'cfuncptr_t_treeitems_set', + 'cfuncptr_t_user_cmts_get', + 'cfuncptr_t_user_cmts_set', + 'cfuncptr_t_user_iflags_get', + 'cfuncptr_t_user_iflags_set', + 'cfuncptr_t_user_labels_get', + 'cfuncptr_t_user_labels_set', + 'cfuncptr_t_user_unions_get', + 'cfuncptr_t_user_unions_set', + 'cfuncptr_t_verify', + 'cgoto_t___eq__', + 'cgoto_t___ge__', + 'cgoto_t___gt__', + 'cgoto_t___le__', + 'cgoto_t___lt__', + 'cgoto_t___ne__', + 'cgoto_t_compare', + 'cgoto_t_label_num_get', + 'cgoto_t_label_num_set', + 'change_encoding_name', + 'change_segment_status', + 'change_storage_type', + 'channel_redir_t_fd_get', + 'channel_redir_t_fd_set', + 'channel_redir_t_file_get', + 'channel_redir_t_file_set', + 'channel_redir_t_flags_get', + 'channel_redir_t_flags_set', + 'channel_redir_t_is_append', + 'channel_redir_t_is_input', + 'channel_redir_t_is_output', + 'channel_redir_t_is_quoted', + 'channel_redir_t_length_get', + 'channel_redir_t_length_set', + 'channel_redir_t_start_get', + 'channel_redir_t_start_set', + 'charflag', + 'check_bpt', + 'check_process_exit', + 'check_skip_type', + 'check_type_trait', + 'check_type_trait__SWIG_0', + 'check_type_trait__SWIG_1', + 'choose2_activate', + 'choose2_add_command', + 'choose2_close', + 'choose2_create', + 'choose2_find', + 'choose2_get_embedded', + 'choose2_get_embedded_selection', + 'choose2_refresh', + 'choose_choose', + 'choose_enter', + 'choose_entry', + 'choose_enum', + 'choose_enum_by_value', + 'choose_func', + 'choose_getl', + 'choose_idasgn', + 'choose_local_tinfo', + 'choose_local_type', + 'choose_name', + 'choose_named_type2', + 'choose_segm', + 'choose_segreg', + 'choose_sizer', + 'choose_srcp', + 'choose_stkvar_xref', + 'choose_struc', + 'choose_til', + 'choose_trace_file', + 'choose_xref', + 'chunksize', + 'chunkstart', + 'cif_t___eq__', + 'cif_t___ge__', + 'cif_t___gt__', + 'cif_t___le__', + 'cif_t___lt__', + 'cif_t___ne__', + 'cif_t_assign', + 'cif_t_cleanup', + 'cif_t_compare', + 'cif_t_ielse_get', + 'cif_t_ielse_set', + 'cif_t_ithen_get', + 'cif_t_ithen_set', + 'cinsn_t___eq__', + 'cinsn_t___ge__', + 'cinsn_t___gt__', + 'cinsn_t___le__', + 'cinsn_t___lt__', + 'cinsn_t___ne__', + 'cinsn_t__print', + 'cinsn_t_assign', + 'cinsn_t_casm_get', + 'cinsn_t_cblock_get', + 'cinsn_t_cdo_get', + 'cinsn_t_cexpr_get', + 'cinsn_t_cfor_get', + 'cinsn_t_cgoto_get', + 'cinsn_t_cif_get', + 'cinsn_t_cleanup', + 'cinsn_t_collect_free_breaks', + 'cinsn_t_collect_free_continues', + 'cinsn_t_compare', + 'cinsn_t_contains_free_break', + 'cinsn_t_contains_free_continue', + 'cinsn_t_contains_insn', + 'cinsn_t_create_if', + 'cinsn_t_creturn_get', + 'cinsn_t_cswitch_get', + 'cinsn_t_cwhile_get', + 'cinsn_t_is_ordinary_flow', + 'cinsn_t_new_insn', + 'cinsn_t_print1', + 'cinsn_t_replace_by', + 'cinsn_t_swap', + 'cinsn_t_zero', + 'cinsnptrvec_t___eq__', + 'cinsnptrvec_t___getitem__', + 'cinsnptrvec_t___len__', + 'cinsnptrvec_t___ne__', + 'cinsnptrvec_t___setitem__', + 'cinsnptrvec_t__del', + 'cinsnptrvec_t_add_unique', + 'cinsnptrvec_t_at', + 'cinsnptrvec_t_back', + 'cinsnptrvec_t_back__SWIG_0', + 'cinsnptrvec_t_back__SWIG_1', + 'cinsnptrvec_t_begin', + 'cinsnptrvec_t_begin__SWIG_0', + 'cinsnptrvec_t_begin__SWIG_1', + 'cinsnptrvec_t_capacity', + 'cinsnptrvec_t_clear', + 'cinsnptrvec_t_empty', + 'cinsnptrvec_t_end', + 'cinsnptrvec_t_end__SWIG_0', + 'cinsnptrvec_t_end__SWIG_1', + 'cinsnptrvec_t_erase', + 'cinsnptrvec_t_erase__SWIG_0', + 'cinsnptrvec_t_erase__SWIG_1', + 'cinsnptrvec_t_extract', + 'cinsnptrvec_t_find', + 'cinsnptrvec_t_find__SWIG_0', + 'cinsnptrvec_t_find__SWIG_1', + 'cinsnptrvec_t_front', + 'cinsnptrvec_t_front__SWIG_0', + 'cinsnptrvec_t_front__SWIG_1', + 'cinsnptrvec_t_has', + 'cinsnptrvec_t_inject', + 'cinsnptrvec_t_insert', + 'cinsnptrvec_t_pop_back', + 'cinsnptrvec_t_push_back', + 'cinsnptrvec_t_push_back__SWIG_0', + 'cinsnptrvec_t_push_back__SWIG_1', + 'cinsnptrvec_t_qclear', + 'cinsnptrvec_t_reserve', + 'cinsnptrvec_t_resize', + 'cinsnptrvec_t_resize__SWIG_0', + 'cinsnptrvec_t_resize__SWIG_1', + 'cinsnptrvec_t_size', + 'cinsnptrvec_t_swap', + 'cinsnptrvec_t_truncate', + 'citem_cmt_t___str__', + 'citem_cmt_t_c_str', + 'citem_cmt_t_used_get', + 'citem_cmt_t_used_set', + 'citem_locator_t___eq__', + 'citem_locator_t___ge__', + 'citem_locator_t___gt__', + 'citem_locator_t___le__', + 'citem_locator_t___lt__', + 'citem_locator_t___ne__', + 'citem_locator_t_compare', + 'citem_locator_t_ea_get', + 'citem_locator_t_ea_set', + 'citem_locator_t_op_get', + 'citem_locator_t_op_set', + 'citem_t_cexpr_get', + 'citem_t_cinsn_get', + 'citem_t_contains_label', + 'citem_t_ea_get', + 'citem_t_ea_set', + 'citem_t_find_parent_of', + 'citem_t_find_parent_of__SWIG_0', + 'citem_t_find_parent_of__SWIG_1', + 'citem_t_index_get', + 'citem_t_index_set', + 'citem_t_is_expr', + 'citem_t_label_num_get', + 'citem_t_label_num_set', + 'citem_t_op_get', + 'citem_t_op_set', + 'citem_t_print1', + 'citem_t_swap', + 'cleanup_appcall', + 'cleanup_varloc', + 'clearBreak', + 'clear_cached_cfuncs', + 'clear_func_struct', + 'clear_requests_queue', + 'clear_tinfo_t', + 'clear_trace', + 'cloop_t_assign', + 'cloop_t_body_get', + 'cloop_t_body_set', + 'cloop_t_cleanup', + 'close_chooser', + 'close_linput', + 'close_pseudocode', + 'close_tform', + 'clr__bnot0', + 'clr__bnot1', + 'clr__invsign0', + 'clr__invsign1', + 'clr_abits', + 'clr_align_flow', + 'clr_colored_item', + 'clr_fixed_spd', + 'clr_has_lname', + 'clr_has_ti', + 'clr_has_ti0', + 'clr_has_ti1', + 'clr_libitem', + 'clr_lzero', + 'clr_lzero0', + 'clr_lzero1', + 'clr_node_info2', + 'clr_noret', + 'clr_notcode', + 'clr_retfp', + 'clr_terse_struc', + 'clr_tilcmt', + 'clr_usemodsp', + 'clr_usersp', + 'clr_userti', + 'clr_zstroff', + 'cnumber_t___eq__', + 'cnumber_t___ge__', + 'cnumber_t___gt__', + 'cnumber_t___le__', + 'cnumber_t___lt__', + 'cnumber_t___ne__', + 'cnumber_t__print', + 'cnumber_t__value_get', + 'cnumber_t__value_set', + 'cnumber_t_assign', + 'cnumber_t_compare', + 'cnumber_t_nf_get', + 'cnumber_t_nf_set', + 'cnumber_t_value', + 'codeSeg', + 'codeflag', + 'compact_til', + 'compare', + 'compare__SWIG_0', + 'compare__SWIG_1', + 'compare__SWIG_12', + 'compare__SWIG_13', + 'compare__SWIG_14', + 'compare__SWIG_15', + 'compare__SWIG_16', + 'compare__SWIG_17', + 'compare__SWIG_18', + 'compare__SWIG_19', + 'compare__SWIG_2', + 'compare__SWIG_20', + 'compare__SWIG_21', + 'compare__SWIG_22', + 'compare__SWIG_23', + 'compare__SWIG_24', + 'compare__SWIG_25', + 'compare__SWIG_26', + 'compare__SWIG_27', + 'compare__SWIG_28', + 'compare__SWIG_29', + 'compare__SWIG_3', + 'compare__SWIG_30', + 'compare__SWIG_4', + 'compare__SWIG_5', + 'compare__SWIG_6', + 'compare__SWIG_7', + 'compare_tinfo', + 'compare_typsrc', + 'compile_script_file', + 'compile_script_func', + 'compiler_info_t_cm_get', + 'compiler_info_t_cm_set', + 'compiler_info_t_defalign_get', + 'compiler_info_t_defalign_set', + 'compiler_info_t_id_get', + 'compiler_info_t_id_set', + 'compiler_info_t_size_b_get', + 'compiler_info_t_size_b_set', + 'compiler_info_t_size_e_get', + 'compiler_info_t_size_e_set', + 'compiler_info_t_size_i_get', + 'compiler_info_t_size_i_set', + 'compiler_info_t_size_l_get', + 'compiler_info_t_size_l_set', + 'compiler_info_t_size_ll_get', + 'compiler_info_t_size_ll_set', + 'compiler_info_t_size_s_get', + 'compiler_info_t_size_s_set', + 'const_aloc_visitor_t_visit_location', + 'const_visitor_t_visit_const', + 'const_vloc_visitor_t_visit_location', + 'construct_macro', + 'contains_fixups', + 'continue_process', + 'convert_argloc_to_varloc', + 'convert_encoding', + 'convert_pt_flags_to_hti', + 'convert_varloc_to_argloc', + 'copy_srareas', + 'copy_tinfo_t', + 'copy_varloc', + 'create_bytearray_linput', + 'create_code_viewer', + 'create_custom_fixup', + 'create_ea_viewer', + 'create_field_name', + 'create_generic_linput', + 'create_generic_linput64', + 'create_helper', + 'create_helper__varargs__', + 'create_insn', + 'create_memory_linput', + 'create_numbered_type_name', + 'create_numbered_type_reference', + 'create_source_viewer', + 'create_switch_table', + 'create_switch_xrefs', + 'create_tform', + 'create_tinfo', + 'create_typedef', + 'create_typedef__SWIG_0', + 'create_typedef__SWIG_1', + 'creturn_t___eq__', + 'creturn_t___ge__', + 'creturn_t___gt__', + 'creturn_t___le__', + 'creturn_t___lt__', + 'creturn_t___ne__', + 'creturn_t_compare', + 'cswitch_t___eq__', + 'cswitch_t___ge__', + 'cswitch_t___gt__', + 'cswitch_t___le__', + 'cswitch_t___lt__', + 'cswitch_t___ne__', + 'cswitch_t_cases_get', + 'cswitch_t_cases_set', + 'cswitch_t_compare', + 'cswitch_t_mvnf_get', + 'cswitch_t_mvnf_set', + 'ctext_position_t___eq__', + 'ctext_position_t___ge__', + 'ctext_position_t___gt__', + 'ctext_position_t___le__', + 'ctext_position_t___lt__', + 'ctext_position_t___ne__', + 'ctext_position_t_compare', + 'ctext_position_t_in_ctree', + 'ctext_position_t_lnnum_get', + 'ctext_position_t_lnnum_set', + 'ctext_position_t_x_get', + 'ctext_position_t_x_set', + 'ctext_position_t_y_get', + 'ctext_position_t_y_set', + 'ctree_anchor_t_get_index', + 'ctree_anchor_t_get_itp', + 'ctree_anchor_t_is_blkcmt_anchor', + 'ctree_anchor_t_is_citem_anchor', + 'ctree_anchor_t_is_itp_anchor', + 'ctree_anchor_t_is_lvar_anchor', + 'ctree_anchor_t_is_valid_anchor', + 'ctree_anchor_t_value_get', + 'ctree_anchor_t_value_set', + 'ctree_item_t_citype_get', + 'ctree_item_t_citype_set', + 'ctree_item_t_e_get', + 'ctree_item_t_f_get', + 'ctree_item_t_get_ea', + 'ctree_item_t_get_label_num', + 'ctree_item_t_get_lvar', + 'ctree_item_t_get_memptr', + 'ctree_item_t_i_get', + 'ctree_item_t_is_citem', + 'ctree_item_t_it_get', + 'ctree_item_t_l_get', + 'ctree_item_t_loc_get', + 'ctree_items_t___eq__', + 'ctree_items_t___getitem__', + 'ctree_items_t___len__', + 'ctree_items_t___ne__', + 'ctree_items_t___setitem__', + 'ctree_items_t__del', + 'ctree_items_t_add_unique', + 'ctree_items_t_at', + 'ctree_items_t_back', + 'ctree_items_t_back__SWIG_0', + 'ctree_items_t_back__SWIG_1', + 'ctree_items_t_begin', + 'ctree_items_t_begin__SWIG_0', + 'ctree_items_t_begin__SWIG_1', + 'ctree_items_t_capacity', + 'ctree_items_t_clear', + 'ctree_items_t_empty', + 'ctree_items_t_end', + 'ctree_items_t_end__SWIG_0', + 'ctree_items_t_end__SWIG_1', + 'ctree_items_t_erase', + 'ctree_items_t_erase__SWIG_0', + 'ctree_items_t_erase__SWIG_1', + 'ctree_items_t_extract', + 'ctree_items_t_find', + 'ctree_items_t_find__SWIG_0', + 'ctree_items_t_find__SWIG_1', + 'ctree_items_t_front', + 'ctree_items_t_front__SWIG_0', + 'ctree_items_t_front__SWIG_1', + 'ctree_items_t_has', + 'ctree_items_t_inject', + 'ctree_items_t_insert', + 'ctree_items_t_pop_back', + 'ctree_items_t_push_back', + 'ctree_items_t_push_back__SWIG_0', + 'ctree_items_t_push_back__SWIG_1', + 'ctree_items_t_qclear', + 'ctree_items_t_reserve', + 'ctree_items_t_resize', + 'ctree_items_t_resize__SWIG_0', + 'ctree_items_t_resize__SWIG_1', + 'ctree_items_t_size', + 'ctree_items_t_swap', + 'ctree_items_t_truncate', + 'ctree_parentee_t_recalc_parent_types', + 'ctree_visitor_t_apply_to', + 'ctree_visitor_t_apply_to_exprs', + 'ctree_visitor_t_clr_prune', + 'ctree_visitor_t_clr_restart', + 'ctree_visitor_t_cv_flags_get', + 'ctree_visitor_t_cv_flags_set', + 'ctree_visitor_t_is_postorder', + 'ctree_visitor_t_leave_expr', + 'ctree_visitor_t_leave_insn', + 'ctree_visitor_t_maintain_parents', + 'ctree_visitor_t_must_prune', + 'ctree_visitor_t_must_restart', + 'ctree_visitor_t_only_insns', + 'ctree_visitor_t_parent_expr', + 'ctree_visitor_t_parent_insn', + 'ctree_visitor_t_parents_get', + 'ctree_visitor_t_parents_set', + 'ctree_visitor_t_prune_now', + 'ctree_visitor_t_set_restart', + 'ctree_visitor_t_visit_expr', + 'ctree_visitor_t_visit_insn', + 'curloc_copy_current_location', + 'curloc_ea_get', + 'curloc_ea_set', + 'curloc_flags_get', + 'curloc_flags_set', + 'curloc_get', + 'curloc_get_entry', + 'curloc_hide_if_necessary', + 'curloc_jump', + 'curloc_jump_push', + 'curloc_linkTo', + 'curloc_lnnum_get', + 'curloc_lnnum_set', + 'curloc_mark', + 'curloc_markdesc', + 'curloc_markedpos', + 'curloc_pop', + 'curloc_setx', + 'curloc_size', + 'curloc_target_get', + 'curloc_target_set', + 'curloc_unhide_if_necessary', + 'curloc_x_get', + 'curloc_x_set', + 'curloc_y_get', + 'curloc_y_set', + 'custflag', + 'custfmtflag', + 'custom_data_type_ids_t_dtid_get', + 'custom_data_type_ids_t_dtid_set', + 'custom_data_type_ids_t_fids_get', + 'custom_data_type_ids_t_fids_set', + 'custom_viewer_jump', + 'cwhile_t___eq__', + 'cwhile_t___ge__', + 'cwhile_t___gt__', + 'cwhile_t___le__', + 'cwhile_t___lt__', + 'cwhile_t___ne__', + 'cwhile_t_compare', + 'dataSeg', + 'dataSeg_op', + 'dataSeg_opreg', + 'dbg_add_bpt_tev', + 'dbg_add_call_tev', + 'dbg_add_debug_event', + 'dbg_add_insn_tev', + 'dbg_add_many_tevs', + 'dbg_add_ret_tev', + 'dbg_add_tev', + 'dbg_add_thread', + 'dbg_appcall', + 'dbg_can_query', + 'dbg_del_thread', + 'dbg_get_input_path', + 'dbg_get_memory_info', + 'dbg_get_name', + 'dbg_get_registers', + 'dbg_get_thread_sreg_base', + 'dbg_is_loaded', + 'dbg_read_memory', + 'dbg_write_memory', + 'debapp_attrs_t_addrsize_get', + 'debapp_attrs_t_addrsize_set', + 'debapp_attrs_t_cbsize_get', + 'debapp_attrs_t_cbsize_set', + 'debapp_attrs_t_platform_get', + 'debapp_attrs_t_platform_set', + 'debug_event_t_bpt_ea', + 'debug_event_t_bpt_get', + 'debug_event_t_bpt_set', + 'debug_event_t_ea_get', + 'debug_event_t_ea_set', + 'debug_event_t_eid_get', + 'debug_event_t_eid_set', + 'debug_event_t_exc_get', + 'debug_event_t_exc_set', + 'debug_event_t_exit_code_get', + 'debug_event_t_exit_code_set', + 'debug_event_t_handled_get', + 'debug_event_t_handled_set', + 'debug_event_t_info_get', + 'debug_event_t_info_set', + 'debug_event_t_modinfo_get', + 'debug_event_t_modinfo_set', + 'debug_event_t_pid_get', + 'debug_event_t_pid_set', + 'debug_event_t_tid_get', + 'debug_event_t_tid_set', + 'decflag', + 'decode_insn', + 'decode_preceding_insn', + 'decode_prev_insn', + 'decompile_many', + 'default_compiler', + 'define_exception', + 'delValue', + 'del_absbase', + 'del_aflags', + 'del_alignment', + 'del_array_parameters', + 'del_bpt', + 'del_bpt__SWIG_0', + 'del_bpt__SWIG_1', + 'del_bptgrp', + 'del_const', + 'del_cref', + 'del_custom_data_type_ids', + 'del_debug_names', + 'del_dref', + 'del_encoding', + 'del_enum', + 'del_enum_member', + 'del_extra_cmt', + 'del_fixup', + 'del_frame', + 'del_func', + 'del_func_cmt', + 'del_global_name', + 'del_hidden_area', + 'del_hotkey', + 'del_idasgn', + 'del_idc_hotkey', + 'del_ind_purged', + 'del_item_color', + 'del_jumptable_info', + 'del_local_name', + 'del_member_tinfo', + 'del_menu_item', + 'del_named_type', + 'del_node_info2', + 'del_numbered_type', + 'del_refinfo', + 'del_regvar', + 'del_segm', + 'del_segment_cmt', + 'del_segment_translations', + 'del_selector', + 'del_source_linnum', + 'del_sourcefile', + 'del_srarea', + 'del_stkpnt', + 'del_struc', + 'del_struc_member', + 'del_struc_members', + 'del_switch_info_ex', + 'del_switch_parent', + 'del_til', + 'del_tinfo2', + 'del_tinfo2__SWIG_0', + 'del_tinfo2__SWIG_1', + 'del_tinfo_attr', + 'del_virt_module', + 'delay_slot_insn', + 'delete_DBG_Hooks', + 'delete_IDB_Hooks', + 'delete_IDP_Hooks', + 'delete_UI_Hooks', + 'delete___qmutex_t', + '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_area_t', + 'delete_area_visitor2_t', + 'delete_areacb_t', + 'delete_areaset_t', + 'delete_areavec_t', + 'delete_argloc_t', + 'delete_argpart_t', + 'delete_array_parameters_t', + 'delete_array_type_data_t', + 'delete_asm_t', + 'delete_auto_display_t', + 'delete_bgcolors_t', + 'delete_bitfield_type_data_t', + 'delete_boolvec_t', + 'delete_boundaries_iterator_t', + 'delete_boundaries_t', + 'delete_bpt_location_t', + 'delete_bpt_t', + 'delete_bpt_vec_t', + 'delete_call_stack_info_t', + 'delete_call_stack_t', + 'delete_callregs_t', + 'delete_carg_t', + 'delete_carglist_t', + 'delete_cases_and_targets_t', + 'delete_casevec_t', + 'delete_casm_t', + 'delete_cblock_t', + 'delete_ccase_t', + 'delete_ccases_t', + 'delete_cdo_t', + 'delete_ceinsn_t', + 'delete_cexpr_t', + 'delete_cfor_t', + 'delete_cfunc_parentee_t', + 'delete_cfunc_t', + 'delete_cfuncptr_t', + 'delete_cgoto_t', + 'delete_channel_redir_t', + 'delete_cif_t', + 'delete_cinsn_t', + 'delete_cinsnptrvec_t', + 'delete_citem_cmt_t', + 'delete_citem_locator_t', + 'delete_citem_t', + 'delete_cloop_t', + 'delete_cnumber_t', + 'delete_compiler_info_t', + 'delete_const_aloc_visitor_t', + 'delete_const_visitor_t', + 'delete_const_vloc_visitor_t', + 'delete_creturn_t', + 'delete_cswitch_t', + 'delete_ctext_position_t', + 'delete_ctree_anchor_t', + 'delete_ctree_item_t', + 'delete_ctree_items_t', + 'delete_ctree_parentee_t', + 'delete_ctree_visitor_t', + 'delete_curloc', + 'delete_custom_data_type_ids_t', + 'delete_cwhile_t', + 'delete_debapp_attrs_t', + 'delete_debug_event_t', + 'delete_disasm_line_t', + 'delete_disasm_text_t', + 'delete_e_breakpoint_t', + 'delete_e_exception_t', + 'delete_ea_array', + 'delete_ea_name_t', + 'delete_ea_pointer', + 'delete_eamap_iterator_t', + 'delete_eamap_t', + 'delete_enum_const_t', + 'delete_enum_member_t', + 'delete_enum_member_visitor_t', + 'delete_enum_type_data_t', + 'delete_enumplace_t', + 'delete_eval_ctx_t', + 'delete_exception_info_t', + 'delete_extra_cmts', + 'delete_fixup_data_t', + 'delete_fnumber_t', + 'delete_func_item_iterator_t', + 'delete_func_parent_iterator_t', + 'delete_func_t', + 'delete_func_tail_iterator_t', + 'delete_func_type_data_t', + 'delete_func_type_info_t', + 'delete_funcarg_info_t', + 'delete_funcarg_t', + 'delete_funcargvec_t', + 'delete_generic_linput64_t', + 'delete_generic_linput_t', + 'delete_get_strmem_t', + 'delete_graph_location_info_t', + 'delete_hexrays_failure_t', + 'delete_hexwarn_t', + 'delete_hexwarns_t', + 'delete_hidden_area_t', + 'delete_highlighter_cbs_t', + 'delete_history_item_t', + 'delete_history_t', + 'delete_ida_false_type', + 'delete_ida_lowertype_helper_t', + 'delete_ida_true_type', + 'delete_idainfo', + 'delete_idaplace_t', + 'delete_idc_global_t', + 'delete_idc_value_t', + 'delete_idd_opinfo_old_t', + 'delete_idp_desc_t', + 'delete_idp_name_t', + 'delete_ids_array', + 'delete_instant_dbgopts_t', + 'delete_int64vec_t', + 'delete_int_pointer', + 'delete_intvec_t', + 'delete_jumptable_info_t', + 'delete_linput_buffer_t', + 'delete_llabel_t', + 'delete_loader_input_t', + 'delete_loader_t', + 'delete_location_t', + 'delete_locchange_md_t', + 'delete_lochist_entry_t', + 'delete_lochist_t', + 'delete_lock_area', + 'delete_lock_func', + 'delete_lock_segment', + 'delete_lock_segreg', + 'delete_lowertype_helper_t', + 'delete_lvar_locator_t', + 'delete_lvar_mapping_iterator_t', + 'delete_lvar_mapping_t', + 'delete_lvar_saved_info_t', + 'delete_lvar_saved_infos_t', + 'delete_lvar_t', + 'delete_lvar_uservec_t', + 'delete_lvars_t', + 'delete_member_t', + 'delete_module_info_t', + 'delete_netnode', + 'delete_node_info_t', + 'delete_node_iterator', + 'delete_number_format_t', + 'delete_operand_locator_t', + 'delete_operator_info_t', + 'delete_opinfo_t', + 'delete_place_t', + 'delete_plugin_info_t', + 'delete_process_info_t', + 'delete_ptr_type_data_t', + 'delete_qbasic_block_t', + 'delete_qfile_t', + 'delete_qflow_chart_t', + 'delete_qlist_cinsn_t', + 'delete_qlist_cinsn_t_iterator', + 'delete_qmutex_locker_t', + 'delete_qrefcnt_obj_t', + 'delete_qvector_carg_t', + 'delete_qvector_ccase_t', + 'delete_qvector_history_t', + 'delete_qvector_lvar_t', + 'delete_qvector_snapshotvec_t', + 'delete_refinfo_t', + 'delete_reg_info_t', + 'delete_regarg_t', + 'delete_regobj_t', + 'delete_regobjs_t', + 'delete_regval_t', + 'delete_regvar_t', + 'delete_renderer_info_t', + 'delete_renderer_pos_info_t', + 'delete_rrel_t', + 'delete_scattered_aloc_t', + 'delete_scattered_vloc_t', + 'delete_segm_move_info_t', + 'delete_segm_move_info_vec_t', + 'delete_segm_move_infos_t', + 'delete_segment_t', + 'delete_segreg_area_t', + 'delete_segreg_t', + 'delete_sel_array', + 'delete_sel_pointer', + 'delete_simd_info_t', + 'delete_simpleline_place_t', + 'delete_simpleline_t', + 'delete_snapshot_t', + 'delete_stkpnt_t', + 'delete_strarray_t', + 'delete_string_info_t', + 'delete_strpath_t', + 'delete_struc_t', + 'delete_struct_field_visitor_t', + 'delete_structplace_t', + 'delete_strvec_t', + 'delete_strwinsetup_t', + 'delete_sval_pointer', + 'delete_tev_info_t', + 'delete_text_options_t', + 'delete_text_sink_t', + 'delete_tid_array', + 'delete_til_symbol_t', + 'delete_til_t', + 'delete_tinfo_t', + 'delete_tinfo_visitor_t', + 'delete_treeloc_t', + 'delete_twinpos_t', + 'delete_type_attr_t', + 'delete_type_mapper_t', + 'delete_type_mods_t', + 'delete_type_pair_t', + 'delete_type_pair_vec_t', + 'delete_type_visitor_t', + 'delete_typedef_type_data_t', + 'delete_uchar_array', + 'delete_udt_member_t', + 'delete_udt_type_data_t', + 'delete_udtmembervec_t', + 'delete_ui_requests_t', + 'delete_unreferenced_stkvars', + 'delete_user_cmts_iterator_t', + 'delete_user_cmts_t', + 'delete_user_iflags_iterator_t', + 'delete_user_iflags_t', + 'delete_user_labels_iterator_t', + 'delete_user_labels_t', + 'delete_user_lvar_modifier_t', + 'delete_user_numforms_iterator_t', + 'delete_user_numforms_t', + 'delete_user_unions_iterator_t', + 'delete_user_unions_t', + 'delete_uval_array', + 'delete_uvalvec_t', + 'delete_valstr_t', + 'delete_valstrs_deprecated2_t', + 'delete_valstrs_deprecated_t', + 'delete_valstrs_t', + 'delete_var_ref_t', + 'delete_varloc_t', + 'delete_varpart_t', + 'delete_vc_printer_t', + 'delete_vd_failure_t', + 'delete_vd_interr_t', + 'delete_vd_printer_t', + 'delete_vdloc_t', + 'delete_vdui_t', + 'delete_vloc_visitor_t', + 'delete_wrong_stkvar_ops', + 'delete_xrefblk_t', + 'delete_xreflist_entry_t', + 'delete_xreflist_t', + 'demangle_name', + 'demangle_name2', + 'deref_ptr', + 'deref_ptr2', + 'dereference', + 'describe', + 'describe__varargs__', + 'deserialize_tinfo', + 'detach_action_from_menu', + 'detach_action_from_popup', + 'detach_action_from_toolbar', + 'detach_process', + 'diff_trace_file', + 'disable_flags', + 'disable_script_timeout', + 'disasm_line_t_at_get', + 'disasm_line_t_at_set', + 'disasm_line_t_bg_color_get', + 'disasm_line_t_bg_color_set', + 'disasm_line_t_is_default_get', + 'disasm_line_t_is_default_set', + 'disasm_line_t_line_get', + 'disasm_line_t_line_set', + 'disasm_line_t_prefix_color_get', + 'disasm_line_t_prefix_color_set', + 'disasm_text_t___getitem__', + 'disasm_text_t___len__', + 'disasm_text_t___setitem__', + 'disasm_text_t_at', + 'disasm_text_t_back', + 'disasm_text_t_back__SWIG_0', + 'disasm_text_t_back__SWIG_1', + 'disasm_text_t_begin', + 'disasm_text_t_begin__SWIG_0', + 'disasm_text_t_begin__SWIG_1', + 'disasm_text_t_capacity', + 'disasm_text_t_clear', + 'disasm_text_t_empty', + 'disasm_text_t_end', + 'disasm_text_t_end__SWIG_0', + 'disasm_text_t_end__SWIG_1', + 'disasm_text_t_erase', + 'disasm_text_t_erase__SWIG_0', + 'disasm_text_t_erase__SWIG_1', + 'disasm_text_t_extract', + 'disasm_text_t_front', + 'disasm_text_t_front__SWIG_0', + 'disasm_text_t_front__SWIG_1', + 'disasm_text_t_grow', + 'disasm_text_t_inject', + 'disasm_text_t_insert', + 'disasm_text_t_pop_back', + 'disasm_text_t_push_back', + 'disasm_text_t_push_back__SWIG_0', + 'disasm_text_t_push_back__SWIG_1', + 'disasm_text_t_qclear', + 'disasm_text_t_reserve', + 'disasm_text_t_resize', + 'disasm_text_t_resize__SWIG_0', + 'disasm_text_t_resize__SWIG_1', + 'disasm_text_t_size', + 'disasm_text_t_swap', + 'disasm_text_t_truncate', + 'disown_DBG_Hooks', + 'disown_IDB_Hooks', + 'disown_IDP_Hooks', + 'disown_UI_Hooks', + 'disown_aloc_visitor_t', + 'disown_area_visitor2_t', + 'disown_cfunc_parentee_t', + 'disown_const_aloc_visitor_t', + 'disown_ctree_parentee_t', + 'disown_ctree_visitor_t', + 'disown_enum_member_visitor_t', + 'disown_highlighter_cbs_t', + 'disown_struct_field_visitor_t', + 'disown_text_sink_t', + 'disown_tinfo_visitor_t', + 'disown_user_lvar_modifier_t', + 'display_complex_call_chart', + 'display_copyright_warning', + 'display_flow_graph', + 'display_gdl', + 'display_simple_call_chart', + 'do16bit', + 'do32bit', + 'do3byte', + 'doASCI', + 'doAlign', + 'doByte', + 'doCustomData', + 'doDouble', + 'doDwrd', + 'doExtra', + 'doFloat', + 'doImmd', + 'doOwrd', + 'doPackReal', + 'doQwrd', + 'doStruct', + 'doTbyt', + 'doVar', + 'doWord', + 'doYwrd', + 'doZwrd', + 'do_data_ex', + 'do_name_anyway', + 'do_unknown', + 'do_unknown_range', + 'dosysfile', + 'doubleflag', + 'dstr_tinfo', + 'dto_copy_from_inf', + 'dto_copy_to_inf', + 'dto_init', + 'dummy_ptrtype', + 'dump_func_type_data', + 'dwrdflag', + 'e_breakpoint_t_hea_get', + 'e_breakpoint_t_hea_set', + 'e_breakpoint_t_kea_get', + 'e_breakpoint_t_kea_set', + 'e_exception_t_can_cont_get', + 'e_exception_t_can_cont_set', + 'e_exception_t_code_get', + 'e_exception_t_code_set', + 'e_exception_t_ea_get', + 'e_exception_t_ea_set', + 'e_exception_t_info_get', + 'e_exception_t_info_set', + 'ea_array___getitem__', + 'ea_array___setitem__', + 'ea_array_cast', + 'ea_array_frompointer', + 'ea_name_t_ea_get', + 'ea_name_t_ea_set', + 'ea_name_t_name_get', + 'ea_name_t_name_set', + 'ea_pointer_assign', + 'ea_pointer_cast', + 'ea_pointer_frompointer', + 'ea_pointer_value', + 'ea_viewer_history_push_and_jump', + 'eamap_begin', + 'eamap_clear', + 'eamap_end', + 'eamap_erase', + 'eamap_find', + 'eamap_first', + 'eamap_free', + 'eamap_insert', + 'eamap_iterator_t___eq__', + 'eamap_iterator_t___ne__', + 'eamap_iterator_t_x_get', + 'eamap_iterator_t_x_set', + 'eamap_new', + 'eamap_next', + 'eamap_prev', + 'eamap_second', + 'eamap_size', + 'eamap_t_at', + 'eamap_t_size', + 'echsize', + 'echsize64', + 'eclose', + 'ecreate', + 'ecreateT', + 'edit_manual_regions', + 'enable_bblk_trace', + 'enable_bpt', + 'enable_bpt__SWIG_0', + 'enable_bpt__SWIG_1', + 'enable_chooser_item_attrs', + 'enable_extlang_python', + 'enable_flags', + 'enable_func_trace', + 'enable_insn_trace', + 'enable_manual_regions', + 'enable_menu_item', + 'enable_python_cli', + 'enable_step_trace', + 'encoding_from_strtype', + 'end_type_updating', + 'enum_const_t_serial_get', + 'enum_const_t_serial_set', + 'enum_const_t_tid_get', + 'enum_const_t_tid_set', + 'enum_import_names', + 'enum_member_t___eq__', + 'enum_member_t___ne__', + 'enum_member_t_cmt_get', + 'enum_member_t_cmt_set', + 'enum_member_t_name_get', + 'enum_member_t_name_set', + 'enum_member_t_swap', + 'enum_member_t_value_get', + 'enum_member_t_value_set', + 'enum_member_visitor_t_visit_enum_member', + 'enum_type_data_t_bte_get', + 'enum_type_data_t_bte_set', + 'enum_type_data_t_calc_mask', + 'enum_type_data_t_calc_nbytes', + 'enum_type_data_t_group_sizes_get', + 'enum_type_data_t_group_sizes_set', + 'enum_type_data_t_is_64bit', + 'enum_type_data_t_is_char', + 'enum_type_data_t_is_hex', + 'enum_type_data_t_is_sdec', + 'enum_type_data_t_is_udec', + 'enum_type_data_t_swap', + 'enum_type_data_t_taenum_bits_get', + 'enum_type_data_t_taenum_bits_set', + 'enumerate_files', + 'enumflag', + 'enumplace_t_bmask_get', + 'enumplace_t_bmask_set', + 'enumplace_t_idx_get', + 'enumplace_t_idx_set', + 'enumplace_t_serial_get', + 'enumplace_t_serial_set', + 'enumplace_t_value_get', + 'enumplace_t_value_set', + 'equal_bytes', + 'error', + 'error__varargs__', + 'eseek', + 'eseek64', + 'eval_ctx_t_ea_get', + 'eval_ctx_t_ea_set', + 'exception_info_t_break_on', + 'exception_info_t_code_get', + 'exception_info_t_code_set', + 'exception_info_t_desc_get', + 'exception_info_t_desc_set', + 'exception_info_t_flags_get', + 'exception_info_t_flags_set', + 'exception_info_t_handle', + 'exception_info_t_name_get', + 'exception_info_t_name_set', + 'execute', + 'execute_sync', + 'execute_ui_requests', + 'exist__SWIG_0', + 'exit_process', + 'expand_argv', + 'expand_struc', + 'extend_sign', + 'extlang_call_method_exists', + 'extlang_compile_file_exists', + 'extlang_run_statements_exists', + 'extlang_set_attr_exists', + 'extlang_unload_procmod', + 'extract_and_convert_old_argloc', + 'extract_module_from_archive', + 'extract_name', + 'extract_name2', + 'extract_old_argloc', + 'extract_old_argloc__SWIG_0', + 'extract_old_argloc__SWIG_1', + 'extract_varloc', + 'f_any', + 'f_hasRef', + 'f_has_dummy_name', + 'f_has_name', + 'f_has_user_name', + 'f_is3byte', + 'f_isASCII', + 'f_isAlign', + 'f_isByte', + 'f_isCode', + 'f_isCustom', + 'f_isData', + 'f_isDouble', + 'f_isDwrd', + 'f_isFloat', + 'f_isHead', + 'f_isNotTail', + 'f_isOwrd', + 'f_isPackReal', + 'f_isQwrd', + 'f_isStruct', + 'f_isTail', + 'f_isTbyt', + 'f_isUnknown', + 'f_isWord', + 'f_isYwrd', + 'file2base', + 'find_binary', + 'find_bpt', + 'find_byte', + 'find_byter', + 'find_code', + 'find_custom_data_format', + 'find_custom_data_type', + 'find_data', + 'find_defined', + 'find_error', + 'find_extlang_by_ext', + 'find_extlang_by_name', + 'find_free_selector', + 'find_func_bounds', + 'find_idc_class', + 'find_idc_gvar', + 'find_imm', + 'find_not_func', + 'find_notype', + 'find_regvar', + 'find_regvar__SWIG_0', + 'find_regvar__SWIG_1', + 'find_selector', + 'find_text', + 'find_tform', + 'find_tinfo_udt_member', + 'find_unknown', + 'find_void', + 'first_named_type', + 'fixup_data_t_displacement_get', + 'fixup_data_t_displacement_set', + 'fixup_data_t_get_type', + 'fixup_data_t_is_custom', + 'fixup_data_t_off_get', + 'fixup_data_t_off_set', + 'fixup_data_t_sel_get', + 'fixup_data_t_sel_set', + 'fixup_data_t_type_get', + 'fixup_data_t_type_set', + 'floatflag', + 'fltflag', + 'flush_buffers', + 'fnumber_t___eq__', + 'fnumber_t___ge__', + 'fnumber_t___gt__', + 'fnumber_t___le__', + 'fnumber_t___lt__', + 'fnumber_t___ne__', + 'fnumber_t__print', + 'fnumber_t_compare', + 'fnumber_t_dereference_const_uint16', + 'fnumber_t_dereference_uint16', + 'fnumber_t_fnum_get', + 'fnumber_t_fnum_set', + 'fnumber_t_nbytes_get', + 'fnumber_t_nbytes_set', + 'fopenA', + 'fopenM', + 'fopenRB', + 'fopenRT', + 'fopenWB', + 'fopenWT', + 'for_all_arglocs', + 'for_all_const_arglocs', + 'for_all_const_varlocs', + 'for_all_consts', + 'for_all_enum_members', + 'for_all_types', + 'for_all_varlocs', + 'formchgcbfa_close', + 'formchgcbfa_enable_field', + 'formchgcbfa_get_field_value', + 'formchgcbfa_get_focused_field', + 'formchgcbfa_move_field', + 'formchgcbfa_refresh_field', + 'formchgcbfa_set_field_value', + 'formchgcbfa_set_focused_field', + 'formchgcbfa_show_field', + 'frame_off_args', + 'frame_off_lvars', + 'frame_off_retaddr', + 'frame_off_savregs', + 'free_argv', + 'free_custom_icon', + 'free_til', + 'freechunk', + 'func_contains', + 'func_does_return', + 'func_has_stkframe_hole', + 'func_item_iterator_decode_preceding_insn', + 'func_item_iterator_decode_prev_insn', + 'func_item_iterator_next', + 'func_item_iterator_prev', + 'func_item_iterator_t_chunk', + 'func_item_iterator_t_current', + 'func_item_iterator_t_decode_preceding_insn', + 'func_item_iterator_t_decode_prev_insn', + 'func_item_iterator_t_first', + 'func_item_iterator_t_last', + 'func_item_iterator_t_next', + 'func_item_iterator_t_next_addr', + 'func_item_iterator_t_next_code', + 'func_item_iterator_t_next_data', + 'func_item_iterator_t_next_head', + 'func_item_iterator_t_next_not_tail', + 'func_item_iterator_t_prev', + 'func_item_iterator_t_prev_addr', + 'func_item_iterator_t_prev_code', + 'func_item_iterator_t_prev_data', + 'func_item_iterator_t_prev_head', + 'func_item_iterator_t_prev_not_tail', + 'func_item_iterator_t_set', + 'func_item_iterator_t_set_range', + 'func_parent_iterator_set', + 'func_parent_iterator_set2', + 'func_parent_iterator_t_first', + 'func_parent_iterator_t_last', + 'func_parent_iterator_t_next', + 'func_parent_iterator_t_parent', + 'func_parent_iterator_t_prev', + 'func_parent_iterator_t_reset_fnt', + 'func_parent_iterator_t_set', + 'func_setend', + 'func_setstart', + 'func_t_analyzed_sp', + 'func_t_argsize_get', + 'func_t_argsize_set', + 'func_t_color_get', + 'func_t_color_set', + 'func_t_does_return', + 'func_t_flags_get', + 'func_t_flags_set', + 'func_t_fpd_get', + 'func_t_fpd_set', + 'func_t_frame_get', + 'func_t_frame_set', + 'func_t_frregs_get', + 'func_t_frregs_set', + 'func_t_frsize_get', + 'func_t_frsize_set', + 'func_t_is_far', + 'func_t_llabelqty_get', + 'func_t_llabelqty_set', + 'func_t_llabels_get', + 'func_t_llabels_set', + 'func_t_owner_get', + 'func_t_owner_set', + 'func_t_pntqty_get', + 'func_t_pntqty_set', + 'func_t_points_get', + 'func_t_points_set', + 'func_t_referers_get', + 'func_t_referers_set', + 'func_t_refqty_get', + 'func_t_refqty_set', + 'func_t_regargqty_get', + 'func_t_regargqty_set', + 'func_t_regargs_get', + 'func_t_regargs_set', + 'func_t_regvarqty_get', + 'func_t_regvarqty_set', + 'func_t_regvars_get', + 'func_t_regvars_set', + 'func_t_tailqty_get', + 'func_t_tailqty_set', + 'func_t_tails_get', + 'func_t_tails_set', + 'func_tail_iterator_set', + 'func_tail_iterator_set2', + 'func_tail_iterator_set_ea', + 'func_tail_iterator_t_chunk', + 'func_tail_iterator_t_first', + 'func_tail_iterator_t_last', + 'func_tail_iterator_t_main', + 'func_tail_iterator_t_next', + 'func_tail_iterator_t_prev', + 'func_tail_iterator_t_set', + 'func_tail_iterator_t_set_ea', + 'func_tail_iterator_t_set_range', + 'func_type_data_t_cc_get', + 'func_type_data_t_cc_set', + 'func_type_data_t_dump', + 'func_type_data_t_flags_get', + 'func_type_data_t_flags_set', + 'func_type_data_t_get_call_method', + 'func_type_data_t_guess_cc', + 'func_type_data_t_is_high', + 'func_type_data_t_is_vararg_cc', + 'func_type_data_t_retloc_get', + 'func_type_data_t_retloc_set', + 'func_type_data_t_rettype_get', + 'func_type_data_t_rettype_set', + 'func_type_data_t_spoiled_get', + 'func_type_data_t_spoiled_set', + 'func_type_data_t_stkargs_get', + 'func_type_data_t_stkargs_set', + 'func_type_data_t_swap', + 'func_type_info_t_basetype_get', + 'func_type_info_t_basetype_set', + 'func_type_info_t_cc_get', + 'func_type_info_t_cc_set', + 'func_type_info_t_flags_get', + 'func_type_info_t_flags_set', + 'func_type_info_t_retfields_get', + 'func_type_info_t_retfields_set', + 'func_type_info_t_retloc_get', + 'func_type_info_t_retloc_set', + 'func_type_info_t_rettype_get', + 'func_type_info_t_rettype_set', + 'func_type_info_t_spoiled_get', + 'func_type_info_t_spoiled_set', + 'func_type_info_t_stkargs_get', + 'func_type_info_t_stkargs_set', + 'funcarg_info_t_argloc_get', + 'funcarg_info_t_argloc_set', + 'funcarg_info_t_fields_get', + 'funcarg_info_t_fields_set', + 'funcarg_info_t_name_get', + 'funcarg_info_t_name_set', + 'funcarg_info_t_type_get', + 'funcarg_info_t_type_set', + 'funcarg_t___eq__', + 'funcarg_t___ne__', + 'funcarg_t_argloc_get', + 'funcarg_t_argloc_set', + 'funcarg_t_cmt_get', + 'funcarg_t_cmt_set', + 'funcarg_t_flags_get', + 'funcarg_t_flags_set', + 'funcarg_t_name_get', + 'funcarg_t_name_set', + 'funcarg_t_type_get', + 'funcarg_t_type_set', + 'funcargvec_t___eq__', + 'funcargvec_t___getitem__', + 'funcargvec_t___len__', + 'funcargvec_t___ne__', + 'funcargvec_t___setitem__', + 'funcargvec_t__del', + 'funcargvec_t_add_unique', + 'funcargvec_t_at', + 'funcargvec_t_back', + 'funcargvec_t_back__SWIG_0', + 'funcargvec_t_back__SWIG_1', + 'funcargvec_t_begin', + 'funcargvec_t_begin__SWIG_0', + 'funcargvec_t_begin__SWIG_1', + 'funcargvec_t_capacity', + 'funcargvec_t_clear', + 'funcargvec_t_empty', + 'funcargvec_t_end', + 'funcargvec_t_end__SWIG_0', + 'funcargvec_t_end__SWIG_1', + 'funcargvec_t_erase', + 'funcargvec_t_erase__SWIG_0', + 'funcargvec_t_erase__SWIG_1', + 'funcargvec_t_extract', + 'funcargvec_t_find', + 'funcargvec_t_find__SWIG_0', + 'funcargvec_t_find__SWIG_1', + 'funcargvec_t_front', + 'funcargvec_t_front__SWIG_0', + 'funcargvec_t_front__SWIG_1', + 'funcargvec_t_grow', + 'funcargvec_t_has', + 'funcargvec_t_inject', + 'funcargvec_t_insert', + 'funcargvec_t_pop_back', + 'funcargvec_t_push_back', + 'funcargvec_t_push_back__SWIG_0', + 'funcargvec_t_push_back__SWIG_1', + 'funcargvec_t_qclear', + 'funcargvec_t_reserve', + 'funcargvec_t_resize', + 'funcargvec_t_resize__SWIG_0', + 'funcargvec_t_resize__SWIG_1', + 'funcargvec_t_size', + 'funcargvec_t_swap', + 'funcargvec_t_truncate', + 'gen_abssym', + 'gen_cmt_line', + 'gen_cmt_line__varargs__', + 'gen_collapsed_line', + 'gen_collapsed_line__varargs__', + 'gen_complex_call_chart', + 'gen_comvar', + 'gen_decorate_name3', + 'gen_disasm_text', + 'gen_exe_file', + 'gen_extern', + 'gen_file', + 'gen_fix_fixups', + 'gen_flow_graph', + 'gen_gdl', + 'gen_name_decl', + 'gen_simple_call_chart', + 'gen_spcdef', + 'gen_use_arg_tinfos', + 'generate_big_comment', + 'generate_disasm_line', + 'generate_disassembly', + 'generate_many_lines', + 'generic_linput64_t_blocksize_get', + 'generic_linput64_t_blocksize_set', + 'generic_linput64_t_filesize_get', + 'generic_linput64_t_filesize_set', + 'generic_linput64_t_read64', + 'generic_linput_t_blocksize_get', + 'generic_linput_t_blocksize_set', + 'generic_linput_t_filesize_get', + 'generic_linput_t_filesize_set', + 'generic_linput_t_read', + 'getDefaultRadix', + 'getFlags', + 'getRadix', + 'getRadixEA', + 'getSR', + 'get_16bit', + 'get_32bit', + 'get_3byte', + 'get_64bit', + 'get_absbase', + 'get_action_checkable', + 'get_action_checked', + 'get_action_icon', + 'get_action_label', + 'get_action_shortcut', + 'get_action_state', + 'get_action_tooltip', + 'get_action_visibility', + 'get_addon_info', + 'get_addon_info_idx', + 'get_aflags', + 'get_alias_target', + 'get_alignment', + 'get_argloc_r1', + 'get_argloc_r2', + 'get_array_parameters', + 'get_ascii_contents', + 'get_ascii_contents2', + 'get_asm_inc_file', + 'get_auto_plugins', + 'get_base_type', + 'get_basic_file_type', + 'get_bblk_trace_options', + 'get_best_fit_member', + 'get_bmask_cmt', + 'get_bmask_name', + 'get_bmask_node', + 'get_bpt', + 'get_bpt_group', + 'get_bpt_qty', + 'get_bpt_tev_ea', + 'get_bptloc_string', + 'get_byte', + 'get_c_header_path', + 'get_c_macros', + 'get_call_tev_callee', + 'get_chooser_obj', + 'get_cmt', + 'get_colored_demangled_name', + 'get_colored_demangled_name__SWIG_0', + 'get_colored_demangled_name__SWIG_1', + 'get_colored_long_name', + 'get_colored_name', + 'get_colored_name__SWIG_0', + 'get_colored_name__SWIG_1', + 'get_colored_short_name', + 'get_comp', + 'get_compiler_abbr', + 'get_compiler_name', + 'get_compilers', + 'get_complex_n', + 'get_const', + 'get_const_bmask', + 'get_const_by_name', + 'get_const_cmt', + 'get_const_enum', + 'get_const_name', + 'get_const_serial', + 'get_const_value', + 'get_ctype_name', + 'get_curline', + 'get_current_idasgn', + 'get_current_tform', + 'get_current_thread', + 'get_current_viewer', + 'get_cursor', + 'get_custom_data_format', + 'get_custom_data_formats', + 'get_custom_data_type', + 'get_custom_data_type_ids', + 'get_custom_data_types', + 'get_custom_viewer_curline', + 'get_custom_viewer_place', + 'get_data_elsize', + 'get_data_type_size', + 'get_data_value', + 'get_db_byte', + 'get_dbg_byte', + 'get_dbg_memory_info', + 'get_debug_event', + 'get_debug_name2', + 'get_debug_name_ea', + 'get_debug_names', + 'get_debugger_event_cond', + 'get_default_encoding_idx', + 'get_default_reftype', + 'get_defsr', + 'get_demangled_name', + 'get_demangled_name__SWIG_0', + 'get_demangled_name__SWIG_1', + 'get_dtyp_by_size', + 'get_dtyp_flag', + 'get_dtyp_size', + 'get_ea_name', + 'get_ea_viewer_history_info', + 'get_effective_spd', + 'get_encoding_name', + 'get_encodings_count', + 'get_entry', + 'get_entry_forwarder', + 'get_entry_name', + 'get_entry_ordinal', + 'get_entry_qty', + 'get_enum', + 'get_enum_base_type', + 'get_enum_cmt', + 'get_enum_flag', + 'get_enum_id', + 'get_enum_idx', + 'get_enum_member', + 'get_enum_member_bmask', + 'get_enum_member_by_name', + 'get_enum_member_cmt', + 'get_enum_member_enum', + 'get_enum_member_expr2', + 'get_enum_member_name', + 'get_enum_member_serial', + 'get_enum_member_value', + 'get_enum_name', + 'get_enum_qty', + 'get_enum_size', + 'get_enum_type_ordinal', + 'get_enum_width', + 'get_event_bpt_hea', + 'get_event_exc_code', + 'get_event_exc_ea', + 'get_event_exc_info', + 'get_event_info', + 'get_event_module_base', + 'get_event_module_name', + 'get_event_module_size', + 'get_extlang_fileext', + 'get_extra_cmt', + 'get_fchunk', + 'get_fchunk_num', + 'get_fchunk_qty', + 'get_fchunk_referer', + 'get_file_type_name', + 'get_fileregion_ea', + 'get_fileregion_offset', + 'get_first_bmask', + 'get_first_const', + 'get_first_cref_from', + 'get_first_cref_to', + 'get_first_dref_from', + 'get_first_dref_to', + 'get_first_enum_member', + 'get_first_fcref_from', + 'get_first_fcref_to', + 'get_first_fixup_ea', + 'get_first_free_extra_cmtidx', + 'get_first_module', + 'get_first_seg', + 'get_first_serial_const', + 'get_first_serial_enum_member', + 'get_first_struc_idx', + 'get_fixup', + 'get_fixup_base', + 'get_fixup_desc', + 'get_fixup_extdef_ea', + 'get_fixup_extdef_ea__SWIG_0', + 'get_fixup_extdef_ea__SWIG_1', + 'get_fixup_segdef_sel', + 'get_fixup_segdef_sel__SWIG_0', + 'get_fixup_segdef_sel__SWIG_1', + 'get_flags_by_size', + 'get_flags_ex', + 'get_flags_novalue', + 'get_float_type', + 'get_forced_operand', + 'get_frame', + 'get_frame__SWIG_0', + 'get_frame__SWIG_1', + 'get_frame_part', + 'get_frame_retsize', + 'get_frame_size', + 'get_full_byte', + 'get_full_data_elsize', + 'get_full_long', + 'get_full_type', + 'get_full_word', + 'get_func', + 'get_func_bitness', + 'get_func_bits', + 'get_func_by_frame', + 'get_func_bytes', + 'get_func_cc', + 'get_func_chunknum', + 'get_func_cmt', + 'get_func_cvtarg_map', + 'get_func_limits', + 'get_func_name', + 'get_func_name2', + 'get_func_nargs', + 'get_func_num', + 'get_func_qty', + 'get_func_rettype', + 'get_func_trace_options', + 'get_funcarg_size', + 'get_group_selector', + 'get_grp_bpts', + 'get_hexdump_ea', + 'get_hexrays_version', + 'get_hidden_area', + 'get_hidden_area_num', + 'get_hidden_area_qty', + 'get_highlighted_identifier', + 'get_idainfo_by_type', + 'get_idainfo_by_type2', + 'get_idainfo_by_type3', + 'get_idasgn_desc', + 'get_idasgn_desc_with_matches', + 'get_idasgn_qty', + 'get_idasgn_title', + 'get_idc_filename', + 'get_idcpath', + 'get_idp_name', + 'get_ids_modnode', + 'get_imagebase', + 'get_import_module_name', + 'get_import_module_qty', + 'get_ind_purged', + 'get_inf_structure', + 'get_input_file_path', + 'get_insn_tev_reg_mem', + 'get_insn_tev_reg_result', + 'get_insn_tev_reg_val', + 'get_insn_trace_options', + 'get_int_type_by_width_and_sign', + 'get_item_color', + 'get_item_end', + 'get_item_flag', + 'get_item_head', + 'get_item_size', + 'get_jumptable_info', + 'get_kernel_version', + 'get_key_code', + 'get_last_bmask', + 'get_last_const', + 'get_last_enum_member', + 'get_last_seg', + 'get_last_serial_const', + 'get_last_serial_enum_member', + 'get_last_struc_idx', + 'get_linput_type', + 'get_long', + 'get_long_name', + 'get_long_queue_name', + 'get_manual_insn', + 'get_manual_regions', + 'get_many_bytes', + 'get_many_bytes_ex', + 'get_max_ascii_length', + 'get_max_offset', + 'get_member', + 'get_member_by_fullname', + 'get_member_by_id', + 'get_member_by_name', + 'get_member_cmt', + 'get_member_fullname', + 'get_member_name', + 'get_member_name2', + 'get_member_size', + 'get_member_struc', + 'get_member_ti', + 'get_member_tinfo', + 'get_member_tinfo2', + 'get_member_type', + 'get_min_spd_ea', + 'get_name', + 'get_name_base_ea', + 'get_name_color', + 'get_name_ea', + 'get_name_expr', + 'get_name_of_named_type', + 'get_name_value', + 'get_named_type', + 'get_named_type64', + 'get_next_bmask', + 'get_next_const', + 'get_next_cref_from', + 'get_next_cref_to', + 'get_next_dref_from', + 'get_next_dref_to', + 'get_next_enum_member', + 'get_next_fchunk', + 'get_next_fcref_from', + 'get_next_fcref_to', + 'get_next_fixup_ea', + 'get_next_func', + 'get_next_func_addr', + 'get_next_hidden_area', + 'get_next_member_idx', + 'get_next_module', + 'get_next_seg', + 'get_next_serial_const', + 'get_next_serial_enum_member', + 'get_next_struc_idx', + 'get_nice_colored_name', + 'get_nlist_ea', + 'get_nlist_idx', + 'get_nlist_name', + 'get_nlist_size', + 'get_node_info', + 'get_node_info2', + 'get_numbered_type', + 'get_numbered_type_name', + 'get_offbase', + 'get_offset_expr', + 'get_offset_expression', + 'get_op_signness', + 'get_op_tinfo2', + 'get_operand_immvals', + 'get_opinfo', + 'get_opnum', + 'get_optype_flags0', + 'get_optype_flags1', + 'get_or_guess_member_tinfo', + 'get_or_guess_member_tinfo2', + 'get_or_guess_member_type', + 'get_ordinal_from_idb_type', + 'get_ordinal_qty', + 'get_original_byte', + 'get_original_long', + 'get_original_qword', + 'get_original_word', + 'get_output_curline', + 'get_output_cursor', + 'get_output_selected_text', + 'get_place_class', + 'get_place_class_id', + 'get_place_class_template', + 'get_plugin_options', + 'get_prev_bmask', + 'get_prev_const', + 'get_prev_enum_member', + 'get_prev_fchunk', + 'get_prev_fixup_ea', + 'get_prev_func', + 'get_prev_func_addr', + 'get_prev_hidden_area', + 'get_prev_member_idx', + 'get_prev_seg', + 'get_prev_serial_const', + 'get_prev_serial_enum_member', + 'get_prev_srarea', + 'get_prev_struc_idx', + 'get_process_info', + 'get_process_options', + 'get_process_qty', + 'get_process_state', + 'get_ptr_object_size', + 'get_qword', + 'get_referred_ordinal', + 'get_refinfo', + 'get_reftype_by_size', + 'get_reg_info2', + 'get_reg_name', + 'get_reg_val', + 'get_reg_vals', + 'get_ret_tev_return', + 'get_root_filename', + 'get_running_notification', + 'get_running_request', + 'get_scattered_varloc', + 'get_screen_ea', + 'get_segm_base', + 'get_segm_by_name', + 'get_segm_by_sel', + 'get_segm_class', + 'get_segm_name', + 'get_segm_name__SWIG_0', + 'get_segm_name__SWIG_1', + 'get_segm_para', + 'get_segm_qty', + 'get_segment_alignment', + 'get_segment_cmt', + 'get_segment_combination', + 'get_segment_translations', + 'get_segreg', + 'get_selector_qty', + 'get_short_name', + 'get_short_queue_name', + 'get_sig_filename', + 'get_source_linnum', + 'get_sourcefile', + 'get_sp_delta', + 'get_spd', + 'get_special_folder', + 'get_spoil_cnt', + 'get_sptr', + 'get_srarea', + 'get_srarea2', + 'get_srarea_num', + 'get_srareas_qty', + 'get_srareas_qty2', + 'get_step_trace_options', + 'get_stkarg_offset', + 'get_stkvar', + 'get_stock_tinfo', + 'get_str_encoding_idx', + 'get_str_term1', + 'get_str_term2', + 'get_str_type_code', + 'get_strlist_item', + 'get_strlist_qty', + 'get_strmem', + 'get_strmem2', + 'get_strmem_by_name', + 'get_strmem_t_delta_get', + 'get_strmem_t_delta_set', + 'get_strmem_t_flags_get', + 'get_strmem_t_flags_set', + 'get_strmem_t_fnames_get', + 'get_strmem_t_fnames_set', + 'get_strmem_t_ftype_get', + 'get_strmem_t_ftype_set', + 'get_strmem_t_index_get', + 'get_strmem_t_index_set', + 'get_strmem_t_name_get', + 'get_strmem_t_name_set', + 'get_strmem_t_offset_get', + 'get_strmem_t_offset_set', + 'get_strmem_t_sname_get', + 'get_strmem_t_sname_set', + 'get_stroff_path', + 'get_struc', + 'get_struc_by_idx', + 'get_struc_cmt', + 'get_struc_first_offset', + 'get_struc_id', + 'get_struc_idx', + 'get_struc_last_offset', + 'get_struc_name', + 'get_struc_next_offset', + 'get_struc_prev_offset', + 'get_struc_qty', + 'get_struc_size', + 'get_struc_size__SWIG_0', + 'get_struc_size__SWIG_1', + 'get_switch_info_ex', + 'get_switch_parent', + 'get_tab_size', + 'get_tev_ea', + 'get_tev_event', + 'get_tev_info', + 'get_tev_memory_info', + 'get_tev_qty', + 'get_tev_reg_mem_ea', + 'get_tev_reg_mem_qty', + 'get_tev_reg_val', + 'get_tev_tid', + 'get_tev_type', + 'get_tform_idaview', + 'get_tform_title', + 'get_tform_type', + 'get_tform_vdui', + 'get_thread_qty', + 'get_tilpath', + 'get_tinfo', + 'get_tinfo2', + 'get_tinfo_attr', + 'get_tinfo_attrs', + 'get_tinfo_details', + 'get_tinfo_pdata', + 'get_tinfo_property', + 'get_tinfo_size', + 'get_trace_base_address', + 'get_trace_file_desc', + 'get_trace_platform', + 'get_true_name', + 'get_true_name__SWIG_0', + 'get_true_name__SWIG_1', + 'get_true_segm_name', + 'get_type', + 'get_type_flags', + 'get_type_ordinal', + 'get_type_sign', + 'get_typeinfo', + 'get_unk_type', + 'get_user_idadir', + 'get_user_strlist_options', + 'get_utf8_char', + 'get_view_renderer_type', + 'get_viewer_place_type', + 'get_viewer_user_data', + 'get_visible_name', + 'get_word', + 'get_zero_areas', + 'getdspace', + 'getn_bpt', + 'getn_enum', + 'getn_fchunk', + 'getn_func', + 'getn_hidden_area', + 'getn_selector', + 'getn_srarea', + 'getn_srarea2', + 'getn_thread', + 'getnseg', + 'getseg', + 'getsysfile', + 'gettof', + 'graph_location_info_t___eq__', + 'graph_location_info_t___ne__', + 'graph_location_info_t_orgx_get', + 'graph_location_info_t_orgx_set', + 'graph_location_info_t_orgy_get', + 'graph_location_info_t_orgy_set', + 'graph_location_info_t_zoom_get', + 'graph_location_info_t_zoom_set', + 'graph_trace', + 'guess_func_cc', + 'guess_func_tinfo', + 'guess_func_tinfo2', + 'guess_table_address', + 'guess_table_size', + 'guess_tinfo', + 'guess_tinfo2', + 'handle_debug_event', + 'hasExtra', + 'hasRef', + 'hasValue', + 'has_any_name', + 'has_auto_name', + 'has_cached_cfunc', + 'has_cmt', + 'has_dummy_name', + 'has_external_refs', + 'has_lname', + 'has_name', + 'has_ti', + 'has_ti0', + 'has_ti1', + 'has_user_name', + 'have_set_options', + 'hexflag', + 'hexrays_failure_t_code_get', + 'hexrays_failure_t_code_set', + 'hexrays_failure_t_desc', + 'hexrays_failure_t_errea_get', + 'hexrays_failure_t_errea_set', + 'hexrays_failure_t_str_get', + 'hexrays_failure_t_str_set', + 'hexwarn_t___eq__', + 'hexwarn_t___ge__', + 'hexwarn_t___gt__', + 'hexwarn_t___le__', + 'hexwarn_t___lt__', + 'hexwarn_t___ne__', + 'hexwarn_t_compare', + 'hexwarn_t_ea_get', + 'hexwarn_t_ea_set', + 'hexwarn_t_id_get', + 'hexwarn_t_id_set', + 'hexwarn_t_text_get', + 'hexwarn_t_text_set', + 'hexwarns_t___eq__', + 'hexwarns_t___getitem__', + 'hexwarns_t___len__', + 'hexwarns_t___ne__', + 'hexwarns_t___setitem__', + 'hexwarns_t__del', + 'hexwarns_t_add_unique', + 'hexwarns_t_at', + 'hexwarns_t_back', + 'hexwarns_t_back__SWIG_0', + 'hexwarns_t_back__SWIG_1', + 'hexwarns_t_begin', + 'hexwarns_t_begin__SWIG_0', + 'hexwarns_t_begin__SWIG_1', + 'hexwarns_t_capacity', + 'hexwarns_t_clear', + 'hexwarns_t_empty', + 'hexwarns_t_end', + 'hexwarns_t_end__SWIG_0', + 'hexwarns_t_end__SWIG_1', + 'hexwarns_t_erase', + 'hexwarns_t_erase__SWIG_0', + 'hexwarns_t_erase__SWIG_1', + 'hexwarns_t_extract', + 'hexwarns_t_find', + 'hexwarns_t_find__SWIG_0', + 'hexwarns_t_find__SWIG_1', + 'hexwarns_t_front', + 'hexwarns_t_front__SWIG_0', + 'hexwarns_t_front__SWIG_1', + 'hexwarns_t_grow', + 'hexwarns_t_has', + 'hexwarns_t_inject', + 'hexwarns_t_insert', + 'hexwarns_t_pop_back', + 'hexwarns_t_push_back', + 'hexwarns_t_push_back__SWIG_0', + 'hexwarns_t_push_back__SWIG_1', + 'hexwarns_t_qclear', + 'hexwarns_t_reserve', + 'hexwarns_t_resize', + 'hexwarns_t_resize__SWIG_0', + 'hexwarns_t_resize__SWIG_1', + 'hexwarns_t_size', + 'hexwarns_t_swap', + 'hexwarns_t_truncate', + 'hidden_area_t_color_get', + 'hidden_area_t_color_set', + 'hidden_area_t_description_get', + 'hidden_area_t_description_set', + 'hidden_area_t_footer_get', + 'hidden_area_t_footer_set', + 'hidden_area_t_header_get', + 'hidden_area_t_header_set', + 'hidden_area_t_visible_get', + 'hidden_area_t_visible_set', + 'hide_all_bpts', + 'hide_border', + 'hide_item', + 'hide_name', + 'hide_wait_box', + 'highlighter_cbs_t_cur_block_state', + 'highlighter_cbs_t_prev_block_state', + 'highlighter_cbs_t_set_block_state', + 'highlighter_cbs_t_set_style', + 'history_item_t_ea_get', + 'history_item_t_ea_set', + 'history_t_pop', + 'history_t_push', + 'history_t_top', + 'history_t_top__SWIG_0', + 'history_t_top__SWIG_1', + 'ida_lowertype_helper_t_func_has_stkframe_hole', + 'ida_lowertype_helper_t_get_func_purged_bytes', + 'idadir', + 'idainfo_ASCIIbreak_get', + 'idainfo_ASCIIbreak_set', + 'idainfo_ASCIIpref_get', + 'idainfo_ASCIIpref_set', + 'idainfo_ASCIIsernum_get', + 'idainfo_ASCIIsernum_set', + 'idainfo_ASCIIzeroes_get', + 'idainfo_ASCIIzeroes_set', + 'idainfo_abibits_get', + 'idainfo_abibits_set', + 'idainfo_abiname_get', + 'idainfo_abiname_set', + 'idainfo_af2_get', + 'idainfo_af2_set', + 'idainfo_af_get', + 'idainfo_af_set', + 'idainfo_appcall_options_get', + 'idainfo_appcall_options_set', + 'idainfo_apptype_get', + 'idainfo_apptype_set', + 'idainfo_asciiflags_get', + 'idainfo_asciiflags_set', + 'idainfo_asmtype_get', + 'idainfo_asmtype_set', + 'idainfo_baseaddr_get', + 'idainfo_baseaddr_set', + 'idainfo_beginEA_get', + 'idainfo_beginEA_set', + 'idainfo_big_arg_align', + 'idainfo_binSize_get', + 'idainfo_binSize_set', + 'idainfo_cc_get', + 'idainfo_cc_set', + 'idainfo_comment_get', + 'idainfo_comment_set', + 'idainfo_corestart_get', + 'idainfo_corestart_set', + 'idainfo_database_change_count_get', + 'idainfo_database_change_count_set', + 'idainfo_datatypes_get', + 'idainfo_datatypes_set', + 'idainfo_demnames_get', + 'idainfo_demnames_set', + 'idainfo_fcoresiz_get', + 'idainfo_fcoresiz_set', + 'idainfo_filetype_get', + 'idainfo_filetype_set', + 'idainfo_get_demname_form', + 'idainfo_get_proc_name', + 'idainfo_graph_view_get', + 'idainfo_graph_view_set', + 'idainfo_highoff_get', + 'idainfo_highoff_set', + 'idainfo_indent_get', + 'idainfo_indent_set', + 'idainfo_is_32bit', + 'idainfo_is_64bit', + 'idainfo_is_dll', + 'idainfo_is_flat_off32', + 'idainfo_is_mem_aligned4', + 'idainfo_is_snapshot', + 'idainfo_lenxref_get', + 'idainfo_lenxref_set', + 'idainfo_lflags_get', + 'idainfo_lflags_set', + 'idainfo_like_binary', + 'idainfo_listnames_get', + 'idainfo_listnames_set', + 'idainfo_loading_idc', + 'idainfo_long_demnames_get', + 'idainfo_long_demnames_set', + 'idainfo_lowoff_get', + 'idainfo_lowoff_set', + 'idainfo_lprefix_get', + 'idainfo_lprefix_set', + 'idainfo_lprefixlen_get', + 'idainfo_lprefixlen_set', + 'idainfo_main_get', + 'idainfo_main_set', + 'idainfo_margin_get', + 'idainfo_margin_set', + 'idainfo_maxEA_get', + 'idainfo_maxEA_set', + 'idainfo_maxref_get', + 'idainfo_maxref_set', + 'idainfo_mf_get', + 'idainfo_mf_set', + 'idainfo_minEA_get', + 'idainfo_minEA_set', + 'idainfo_namelen_get', + 'idainfo_namelen_set', + 'idainfo_nametype_get', + 'idainfo_nametype_set', + 'idainfo_omaxEA_get', + 'idainfo_omaxEA_set', + 'idainfo_ominEA_get', + 'idainfo_ominEA_set', + 'idainfo_ostype_get', + 'idainfo_ostype_set', + 'idainfo_pack_stkargs', + 'idainfo_procName_get', + 'idainfo_procName_set', + 'idainfo_readonly_idb', + 'idainfo_refcmtnum_get', + 'idainfo_refcmtnum_set', + 'idainfo_reserved_get', + 'idainfo_reserved_set', + 'idainfo_s_assume_get', + 'idainfo_s_assume_set', + 'idainfo_s_auto_get', + 'idainfo_s_auto_set', + 'idainfo_s_checkarg_get', + 'idainfo_s_checkarg_set', + 'idainfo_s_cmtflg_get', + 'idainfo_s_cmtflg_set', + 'idainfo_s_entab_get', + 'idainfo_s_entab_set', + 'idainfo_s_genflags_get', + 'idainfo_s_genflags_set', + 'idainfo_s_limiter_get', + 'idainfo_s_limiter_set', + 'idainfo_s_null_get', + 'idainfo_s_null_set', + 'idainfo_s_org_get', + 'idainfo_s_org_set', + 'idainfo_s_packbase_get', + 'idainfo_s_packbase_set', + 'idainfo_s_prefflag_get', + 'idainfo_s_prefflag_set', + 'idainfo_s_prefseg_get', + 'idainfo_s_prefseg_set', + 'idainfo_s_reserved5_get', + 'idainfo_s_reserved5_set', + 'idainfo_s_showauto_get', + 'idainfo_s_showauto_set', + 'idainfo_s_showbads_get', + 'idainfo_s_showbads_set', + 'idainfo_s_showpref_get', + 'idainfo_s_showpref_set', + 'idainfo_s_void_get', + 'idainfo_s_void_set', + 'idainfo_s_xrefflag_get', + 'idainfo_s_xrefflag_set', + 'idainfo_set_proc_name', + 'idainfo_short_demnames_get', + 'idainfo_short_demnames_set', + 'idainfo_size_ldbl_get', + 'idainfo_size_ldbl_set', + 'idainfo_specsegs_get', + 'idainfo_specsegs_set', + 'idainfo_stack_ldbl', + 'idainfo_stack_varargs', + 'idainfo_startIP_get', + 'idainfo_startIP_set', + 'idainfo_startSP_get', + 'idainfo_startSP_set', + 'idainfo_start_cs_get', + 'idainfo_start_cs_set', + 'idainfo_start_ss_get', + 'idainfo_start_ss_set', + 'idainfo_strtype_get', + 'idainfo_strtype_set', + 'idainfo_tag_get', + 'idainfo_tag_set', + 'idainfo_tribyte_order_get', + 'idainfo_tribyte_order_set', + 'idainfo_type_xrefnum_get', + 'idainfo_type_xrefnum_set', + 'idainfo_use_allasm', + 'idainfo_version_get', + 'idainfo_version_set', + 'idainfo_wide_high_byte_first_get', + 'idainfo_wide_high_byte_first_set', + 'idainfo_xrefnum_get', + 'idainfo_xrefnum_set', + 'idaplace_t_ea_get', + 'idaplace_t_ea_set', + 'idb2scr', + 'idc_get_local_type', + 'idc_get_local_type_name', + 'idc_get_local_type_raw', + 'idc_get_type', + 'idc_get_type_raw', + 'idc_global_t_name_get', + 'idc_global_t_name_set', + 'idc_global_t_value_get', + 'idc_global_t_value_set', + 'idc_guess_type', + 'idc_parse_decl', + 'idc_parse_types', + 'idc_print_type', + 'idc_set_local_type', + 'idc_value_t__create_empty_string', + 'idc_value_t__set_long', + 'idc_value_t__set_string', + 'idc_value_t__set_string__SWIG_0', + 'idc_value_t__set_string__SWIG_1', + 'idc_value_t__set_string__SWIG_2', + 'idc_value_t_c_str', + 'idc_value_t_clear', + 'idc_value_t_create_empty_string', + 'idc_value_t_e_get', + 'idc_value_t_e_set', + 'idc_value_t_funcidx_get', + 'idc_value_t_funcidx_set', + 'idc_value_t_i64_get', + 'idc_value_t_i64_set', + 'idc_value_t_is_convertible', + 'idc_value_t_is_integral', + 'idc_value_t_is_zero', + 'idc_value_t_num_get', + 'idc_value_t_num_set', + 'idc_value_t_obj_get', + 'idc_value_t_obj_set', + 'idc_value_t_pvoid_get', + 'idc_value_t_pvoid_set', + 'idc_value_t_qstr', + 'idc_value_t_qstr__SWIG_0', + 'idc_value_t_qstr__SWIG_1', + 'idc_value_t_reserve_get', + 'idc_value_t_reserve_set', + 'idc_value_t_set_float', + 'idc_value_t_set_int64', + 'idc_value_t_set_long', + 'idc_value_t_set_pvoid', + 'idc_value_t_set_string', + 'idc_value_t_set_string__SWIG_0', + 'idc_value_t_set_string__SWIG_1', + 'idc_value_t_set_string__SWIG_2', + 'idc_value_t_str_get', + 'idc_value_t_str_set', + 'idc_value_t_swap', + 'idc_value_t_u_str', + 'idc_value_t_vtype_get', + 'idc_value_t_vtype_set', + 'idd_opinfo_old_t_addr_get', + 'idd_opinfo_old_t_addr_set', + 'idd_opinfo_old_t_modified_get', + 'idd_opinfo_old_t_modified_set', + 'idd_opinfo_old_t_value_get', + 'idd_opinfo_old_t_value_set', + 'idp_desc_t_checked_get', + 'idp_desc_t_checked_set', + 'idp_desc_t_family_get', + 'idp_desc_t_family_set', + 'idp_desc_t_is_script_get', + 'idp_desc_t_is_script_set', + 'idp_desc_t_mtime_get', + 'idp_desc_t_mtime_set', + 'idp_desc_t_names_get', + 'idp_desc_t_names_set', + 'idp_desc_t_path_get', + 'idp_desc_t_path_set', + 'idp_name_t_hidden_get', + 'idp_name_t_hidden_set', + 'idp_name_t_lname_get', + 'idp_name_t_lname_set', + 'idp_name_t_sname_get', + 'idp_name_t_sname_set', + 'ids_array___getitem__', + 'ids_array___len__', + 'ids_array___setitem__', + 'ids_array_data_get', + 'import_type', + 'info', + 'info__varargs__', + 'init_hexrays_plugin', + 'init_output_buffer', + 'init_process', + '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', + 'install_command_interpreter', + 'install_extlang', + 'install_hexrays_callback', + 'instant_dbgopts_t__pass_get', + 'instant_dbgopts_t__pass_set', + 'instant_dbgopts_t_attach_get', + 'instant_dbgopts_t_attach_set', + 'instant_dbgopts_t_debmod_get', + 'instant_dbgopts_t_debmod_set', + 'instant_dbgopts_t_env_get', + 'instant_dbgopts_t_env_set', + 'instant_dbgopts_t_event_id_get', + 'instant_dbgopts_t_event_id_set', + 'instant_dbgopts_t_host_get', + 'instant_dbgopts_t_host_set', + 'instant_dbgopts_t_pid_get', + '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_back', + 'int64vec_t_back__SWIG_0', + 'int64vec_t_back__SWIG_1', + '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_front', + 'int64vec_t_front__SWIG_0', + 'int64vec_t_front__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', + 'int_pointer_value', + 'intel_data', + 'internal_get_sreg_base', + 'internal_ioctl', + 'internal_register_place_class', + 'intvec_t___eq__', + 'intvec_t___getitem__', + 'intvec_t___len__', + 'intvec_t___ne__', + 'intvec_t___setitem__', + 'intvec_t__del', + 'intvec_t_add_unique', + 'intvec_t_at', + 'intvec_t_back', + 'intvec_t_back__SWIG_0', + 'intvec_t_back__SWIG_1', + 'intvec_t_begin', + 'intvec_t_begin__SWIG_0', + 'intvec_t_begin__SWIG_1', + 'intvec_t_capacity', + 'intvec_t_clear', + 'intvec_t_empty', + 'intvec_t_end', + 'intvec_t_end__SWIG_0', + 'intvec_t_end__SWIG_1', + 'intvec_t_erase', + 'intvec_t_erase__SWIG_0', + 'intvec_t_erase__SWIG_1', + 'intvec_t_extract', + 'intvec_t_find', + 'intvec_t_find__SWIG_0', + 'intvec_t_find__SWIG_1', + 'intvec_t_front', + 'intvec_t_front__SWIG_0', + 'intvec_t_front__SWIG_1', + 'intvec_t_grow', + 'intvec_t_has', + 'intvec_t_inject', + 'intvec_t_insert', + 'intvec_t_pop_back', + 'intvec_t_push_back', + 'intvec_t_push_back__SWIG_0', + 'intvec_t_push_back__SWIG_1', + 'intvec_t_qclear', + 'intvec_t_reserve', + 'intvec_t_resize', + 'intvec_t_resize__SWIG_0', + 'intvec_t_resize__SWIG_1', + 'intvec_t_size', + 'intvec_t_swap', + 'intvec_t_truncate', + 'invalidate_dbgmem_config', + 'invalidate_dbgmem_contents', + 'is3byte', + 'isASCII', + 'isAlign', + 'isByte', + 'isChar', + 'isChar0', + 'isChar1', + 'isCode', + 'isCustFmt', + 'isCustFmt0', + 'isCustFmt1', + 'isCustom', + 'isData', + 'isDefArg', + 'isDefArg0', + 'isDefArg1', + 'isDouble', + 'isDwrd', + 'isEnabled', + 'isEnum', + 'isEnum0', + 'isEnum1', + 'isFloat', + 'isFloat0', + 'isFloat1', + 'isFlow', + 'isFltnum', + 'isFop', + 'isFop0', + 'isFop1', + 'isFunc', + 'isHead', + 'isImmd', + 'isLoaded', + 'isNotTail', + 'isNum', + 'isNum0', + 'isNum1', + 'isOff', + 'isOff0', + 'isOff1', + 'isOwrd', + 'isPackReal', + 'isQwrd', + 'isSeg', + 'isSeg0', + 'isSeg1', + 'isStkvar', + 'isStkvar0', + 'isStkvar1', + 'isStroff', + 'isStroff0', + 'isStroff1', + 'isStruct', + 'isTail', + 'isTbyt', + 'isUnknown', + 'isVar', + 'isVoid', + 'isWord', + 'isYwrd', + 'isZwrd', + 'is__bnot0', + 'is__bnot1', + 'is__invsign0', + 'is__invsign1', + 'is_action_enabled', + 'is_additive', + 'is_align_flow', + 'is_align_insn', + 'is_allowed_on_small_struni', + 'is_anonymous_member_name', + 'is_assignment', + 'is_autosync', + 'is_autosync__SWIG_0', + 'is_autosync__SWIG_1', + 'is_basic_block_end', + 'is_bblk_trace_enabled', + 'is_bf', + 'is_binary', + 'is_bitop', + 'is_bnot', + 'is_bnot_data', + 'is_bool_type', + 'is_break_consumer', + 'is_call_insn', + 'is_castable2', + 'is_chooser_tform', + 'is_code_far', + 'is_colored_item', + 'is_commutative', + 'is_comp_unsure', + 'is_control_tty', + 'is_data_far', + 'is_debugger_busy', + 'is_debugger_memory', + 'is_debugger_on', + 'is_dummy_member_name', + 'is_enum_fromtil', + 'is_enum_hidden', + 'is_finally_visible_func', + 'is_finally_visible_item', + 'is_finally_visible_segm', + 'is_fixed_spd', + 'is_forced_operand', + 'is_func_entry', + 'is_func_locked', + 'is_func_tail', + 'is_func_trace_enabled', + 'is_funcarg_off', + 'is_gcc', + 'is_gcc32', + 'is_gcc64', + 'is_ghost_enum', + 'is_hidden_border', + 'is_hidden_item', + 'is_idaq', + 'is_ident_char', + 'is_in_nlist', + 'is_indirect_jump_insn', + 'is_insn_trace_enabled', + 'is_invsign', + 'is_libitem', + 'is_logical', + 'is_loop', + 'is_lvalue', + 'is_lzero', + 'is_lzero0', + 'is_lzero1', + 'is_main_thread', + 'is_manual_insn', + 'is_member_id', + 'is_miniidb', + 'is_msg_inited', + 'is_multiplicative', + 'is_name_defined_locally', + 'is_nonbool_type', + 'is_noret', + 'is_noret_block', + 'is_notcode', + 'is_one_bit_mask', + 'is_ordinal_name', + 'is_paf', + 'is_pascal', + 'is_place_class_ea_capable', + 'is_prepost', + 'is_ptr_or_array', + 'is_public_name', + 'is_purging_cc', + 'is_reg2_argloc', + 'is_reg_argloc', + 'is_reg_custom', + 'is_reg_float', + 'is_reg_integer', + 'is_relational', + 'is_resolved_type_struni', + 'is_restype_array', + 'is_restype_bitfld', + 'is_restype_complex', + 'is_restype_const', + 'is_restype_enum', + 'is_restype_floating', + 'is_restype_func', + 'is_restype_ptr', + 'is_restype_struct', + 'is_restype_struni', + 'is_restype_union', + 'is_restype_void', + 'is_ret_block', + 'is_ret_insn', + 'is_retfp', + 'is_same_data_type', + 'is_sdacl_byte', + 'is_segm_locked', + 'is_segreg_locked', + 'is_signed_data', + 'is_small_struni', + 'is_spec_ea', + 'is_spec_segm', + 'is_special_member', + 'is_stack_argloc', + 'is_step_trace_enabled', + 'is_tah_byte', + 'is_terse_struc', + 'is_tilcmt', + 'is_trusted_idb', + 'is_type_arithmetic', + 'is_type_array', + 'is_type_bitfld', + 'is_type_bool', + 'is_type_char', + 'is_type_complex', + 'is_type_const', + 'is_type_correct', + 'is_type_double', + 'is_type_enum', + 'is_type_ext_arithmetic', + 'is_type_ext_integral', + 'is_type_float', + 'is_type_floating', + 'is_type_func', + 'is_type_int', + 'is_type_int128', + 'is_type_int16', + 'is_type_int32', + 'is_type_int64', + 'is_type_integral', + 'is_type_ldouble', + 'is_type_only_size', + 'is_type_paf', + 'is_type_partial', + 'is_type_ptr', + 'is_type_ptr_or_array', + 'is_type_resolvable', + 'is_type_scalar2', + 'is_type_struct', + 'is_type_struni', + 'is_type_sue', + 'is_type_typedef', + 'is_type_uchar', + 'is_type_uint', + 'is_type_uint128', + 'is_type_uint16', + 'is_type_uint32', + 'is_type_uint64', + 'is_type_union', + 'is_type_unk', + 'is_type_unknown', + 'is_type_void', + 'is_type_void_obsolete', + 'is_type_voiddef', + 'is_type_volatile', + 'is_typeid_last', + 'is_uname', + 'is_unary', + 'is_unicode', + 'is_union', + 'is_user_cc', + 'is_usersp', + 'is_userti', + 'is_valid_full_type', + 'is_valid_trace_file', + 'is_valid_typename', + 'is_vararg_cc', + 'is_varmember', + 'is_varsize_item', + 'is_varstr', + 'is_visible_char', + 'is_visible_func', + 'is_visible_item', + 'is_visible_segm', + 'is_weak_name', + 'is_zstroff', + 'isident', + 'jumptable_info_t_size_get', + 'jumptable_info_t_size_set', + 'jumptable_info_t_table_get', + 'jumptable_info_t_table_set', + 'jumpto', + 'jumpto__SWIG_0', + 'jumpto__SWIG_1', + 'leading_zero_important', + 'lexcompare_tinfo', + 'linput_buffer_t_eof', + 'linput_buffer_t_read', + 'list_bptgrps', + 'list_bptgrps__SWIG_0', + 'list_bptgrps__SWIG_1', + 'llabel_t_ea_get', + 'llabel_t_ea_set', + 'llabel_t_name_get', + 'llabel_t_name_set', + 'lnot', + 'load_and_run_plugin', + 'load_binary_file', + 'load_dbg_dbginfo', + 'load_debugger', + 'load_ids_module', + 'load_loader_module', + 'load_plugin', + 'load_til', + 'load_til__SWIG_0', + 'load_til__SWIG_1', + 'load_til_header', + 'load_til_header__SWIG_0', + 'load_til_header__SWIG_1', + 'load_trace_file', + 'loader_input_t___idc_cvt_id___get', + 'loader_input_t___idc_cvt_id___set', + 'loader_input_t_close', + 'loader_input_t_file2base', + 'loader_input_t_filename', + 'loader_input_t_from_cobject', + 'loader_input_t_from_fp', + 'loader_input_t_from_linput', + 'loader_input_t_get_char', + 'loader_input_t_get_linput', + 'loader_input_t_gets', + 'loader_input_t_getz', + 'loader_input_t_open', + 'loader_input_t_open_memory', + 'loader_input_t_opened', + 'loader_input_t_read', + 'loader_input_t_readbytes', + 'loader_input_t_seek', + 'loader_input_t_set_linput', + 'loader_input_t_size', + 'loader_input_t_tell', + 'loader_t__UNUSED1_was_init_loader_options_get', + 'loader_t__UNUSED1_was_init_loader_options_set', + 'loader_t_flags_get', + 'loader_t_flags_set', + 'loader_t_version_get', + 'loader_t_version_set', + 'location_t_copy_current_location', + 'location_t_get', + 'location_t_get_entry', + 'location_t_gli_get', + 'location_t_gli_set', + 'location_t_jump', + 'location_t_jump_nopush', + 'location_t_linkTo', + 'location_t_mark', + 'location_t_pop', + 'location_t_push_and_jump', + 'locchange_md_t_is_sync', + 'locchange_md_t_reason', + 'lochist_entry_t___eq__', + 'lochist_entry_t___ne__', + 'lochist_entry_t_acquire_place', + 'lochist_entry_t_is_valid', + 'lochist_entry_t_place', + 'lochist_entry_t_place__SWIG_0', + 'lochist_entry_t_place__SWIG_1', + 'lochist_entry_t_plce_get', + 'lochist_entry_t_plce_set', + 'lochist_entry_t_renderer_info', + 'lochist_entry_t_renderer_info__SWIG_0', + 'lochist_entry_t_renderer_info__SWIG_1', + 'lochist_entry_t_rinfo_get', + 'lochist_entry_t_rinfo_set', + 'lochist_entry_t_set_place', + 'lochist_t_back', + 'lochist_t_clear', + 'lochist_t_current_index', + 'lochist_t_fwd', + 'lochist_t_get', + 'lochist_t_get_current', + 'lochist_t_get_place_id', + 'lochist_t_get_template_place', + 'lochist_t_init', + 'lochist_t_is_history_enabled', + 'lochist_t_jump', + 'lochist_t_netcode', + 'lochist_t_save', + 'lochist_t_seek', + 'lochist_t_set', + 'lochist_t_set_current', + 'lochist_t_size', + 'lookup_key_code', + 'lower_type', + 'lower_type2', + 'lowertype_helper_t_func_has_stkframe_hole', + 'lowertype_helper_t_get_func_purged_bytes', + 'lvar_locator_t___eq__', + 'lvar_locator_t___ge__', + 'lvar_locator_t___gt__', + 'lvar_locator_t___le__', + 'lvar_locator_t___lt__', + 'lvar_locator_t___ne__', + 'lvar_locator_t_compare', + 'lvar_locator_t_defea_get', + '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_is_reg1', + 'lvar_locator_t_is_reg2', + 'lvar_locator_t_is_reg_var', + 'lvar_locator_t_is_scattered', + 'lvar_locator_t_is_stk_var', + 'lvar_locator_t_location_get', + 'lvar_locator_t_location_set', + 'lvar_mapping_begin', + 'lvar_mapping_clear', + 'lvar_mapping_end', + 'lvar_mapping_erase', + 'lvar_mapping_find', + 'lvar_mapping_first', + 'lvar_mapping_free', + 'lvar_mapping_insert', + 'lvar_mapping_iterator_t___eq__', + 'lvar_mapping_iterator_t___ne__', + 'lvar_mapping_iterator_t_x_get', + 'lvar_mapping_iterator_t_x_set', + 'lvar_mapping_new', + 'lvar_mapping_next', + 'lvar_mapping_prev', + 'lvar_mapping_second', + 'lvar_mapping_size', + 'lvar_mapping_t_at', + 'lvar_mapping_t_size', + 'lvar_off', + 'lvar_saved_info_t___eq__', + 'lvar_saved_info_t___ne__', + 'lvar_saved_info_t_clear_keep', + '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_kept', + '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_keep', + 'lvar_saved_info_t_type_get', + 'lvar_saved_info_t_type_set', + 'lvar_saved_infos_t___eq__', + 'lvar_saved_infos_t___getitem__', + 'lvar_saved_infos_t___len__', + 'lvar_saved_infos_t___ne__', + 'lvar_saved_infos_t___setitem__', + 'lvar_saved_infos_t__del', + 'lvar_saved_infos_t_add_unique', + 'lvar_saved_infos_t_at', + 'lvar_saved_infos_t_back', + 'lvar_saved_infos_t_back__SWIG_0', + 'lvar_saved_infos_t_back__SWIG_1', + 'lvar_saved_infos_t_begin', + 'lvar_saved_infos_t_begin__SWIG_0', + 'lvar_saved_infos_t_begin__SWIG_1', + 'lvar_saved_infos_t_capacity', + 'lvar_saved_infos_t_clear', + 'lvar_saved_infos_t_empty', + 'lvar_saved_infos_t_end', + 'lvar_saved_infos_t_end__SWIG_0', + 'lvar_saved_infos_t_end__SWIG_1', + 'lvar_saved_infos_t_erase', + 'lvar_saved_infos_t_erase__SWIG_0', + 'lvar_saved_infos_t_erase__SWIG_1', + 'lvar_saved_infos_t_extract', + 'lvar_saved_infos_t_find', + 'lvar_saved_infos_t_find__SWIG_0', + 'lvar_saved_infos_t_find__SWIG_1', + 'lvar_saved_infos_t_front', + 'lvar_saved_infos_t_front__SWIG_0', + 'lvar_saved_infos_t_front__SWIG_1', + 'lvar_saved_infos_t_grow', + 'lvar_saved_infos_t_has', + 'lvar_saved_infos_t_inject', + 'lvar_saved_infos_t_insert', + 'lvar_saved_infos_t_pop_back', + 'lvar_saved_infos_t_push_back', + 'lvar_saved_infos_t_push_back__SWIG_0', + 'lvar_saved_infos_t_push_back__SWIG_1', + 'lvar_saved_infos_t_qclear', + 'lvar_saved_infos_t_reserve', + 'lvar_saved_infos_t_resize', + 'lvar_saved_infos_t_resize__SWIG_0', + 'lvar_saved_infos_t_resize__SWIG_1', + 'lvar_saved_infos_t_size', + 'lvar_saved_infos_t_swap', + 'lvar_saved_infos_t_truncate', + 'lvar_t_accepts_type', + 'lvar_t_clear_used', + 'lvar_t_clr_arg_var', + 'lvar_t_clr_fake_var', + 'lvar_t_clr_floating_var', + 'lvar_t_clr_mapdst_var', + 'lvar_t_clr_mreg_done', + 'lvar_t_clr_overlapped_var', + 'lvar_t_clr_spoiled_var', + 'lvar_t_clr_unknown_width', + 'lvar_t_clr_user_info', + 'lvar_t_clr_user_name', + 'lvar_t_clr_user_type', + 'lvar_t_cmt_get', + 'lvar_t_cmt_set', + 'lvar_t_defblk_get', + 'lvar_t_defblk_set', + 'lvar_t_divisor_get', + 'lvar_t_divisor_set', + 'lvar_t_has_common', + 'lvar_t_has_common_bit', + 'lvar_t_has_nice_name', + 'lvar_t_has_user_info', + 'lvar_t_has_user_name', + 'lvar_t_has_user_type', + 'lvar_t_is_arg_var', + 'lvar_t_is_fake_var', + 'lvar_t_is_floating_var', + 'lvar_t_is_mapdst_var', + 'lvar_t_is_overlapped_var', + 'lvar_t_is_result_var', + 'lvar_t_is_spoiled_var', + 'lvar_t_is_unknown_width', + 'lvar_t_mreg_done', + 'lvar_t_name_get', + 'lvar_t_name_set', + 'lvar_t_set_arg_var', + 'lvar_t_set_fake_var', + 'lvar_t_set_final_lvar_type', + 'lvar_t_set_floating_var', + 'lvar_t_set_lvar_type', + 'lvar_t_set_mapdst_var', + 'lvar_t_set_mreg_done', + 'lvar_t_set_non_typed', + 'lvar_t_set_overlapped_var', + 'lvar_t_set_reg_name', + 'lvar_t_set_spoiled_var', + 'lvar_t_set_typed', + 'lvar_t_set_unknown_width', + 'lvar_t_set_used', + 'lvar_t_set_user_name', + 'lvar_t_set_user_type', + 'lvar_t_set_width', + 'lvar_t_tif_get', + 'lvar_t_tif_set', + 'lvar_t_type', + 'lvar_t_type__SWIG_0', + 'lvar_t_type__SWIG_1', + 'lvar_t_typed', + 'lvar_t_used', + 'lvar_t_width_get', + 'lvar_t_width_set', + 'lvar_uservec_t_find_info', + 'lvar_uservec_t_keep_info', + 'lvar_uservec_t_lmaps_get', + 'lvar_uservec_t_lmaps_set', + 'lvar_uservec_t_lvvec_get', + 'lvar_uservec_t_lvvec_set', + 'lvar_uservec_t_sizes_get', + 'lvar_uservec_t_sizes_set', + 'lvar_uservec_t_stkoff_delta_get', + 'lvar_uservec_t_stkoff_delta_set', + 'lvar_uservec_t_swap', + 'lvar_uservec_t_ulv_flags_get', + 'lvar_uservec_t_ulv_flags_set', + 'lvars_t_find', + 'lvars_t_find_input_lvar', + 'lvars_t_find_lvar', + 'lvars_t_find_stkvar', + 'make_array_type', + 'make_ascii_string', + 'make_name_auto', + 'make_name_non_public', + 'make_name_non_weak', + 'make_name_public', + 'make_name_user', + 'make_name_weak', + 'make_num', + 'make_old_argloc', + 'make_pointer', + 'make_ref', + 'make_visible_name', + 'mark_cfunc_dirty', + 'may_create_stkvars', + 'may_trace_sp', + 'mem2base', + 'member_t_by_til', + 'member_t_eoff_get', + 'member_t_eoff_set', + 'member_t_flag_get', + 'member_t_flag_set', + 'member_t_get_soff', + 'member_t_has_ti', + 'member_t_has_union', + 'member_t_id_get', + 'member_t_id_set', + 'member_t_props_get', + 'member_t_props_set', + 'member_t_soff_get', + 'member_t_soff_set', + 'member_t_unimem', + 'micro_err_format', + 'modify_user_lvars', + 'module_info_t_base_get', + 'module_info_t_base_set', + 'module_info_t_name_get', + 'module_info_t_name_set', + 'module_info_t_rebase_to_get', + 'module_info_t_rebase_to_set', + 'module_info_t_size_get', + 'module_info_t_size_set', + 'move_bpt_to_grp', + 'move_segm', + 'move_segm_start', + 'msg', + 'nbits', + 'negated_relation', + 'netnode___eq__', + 'netnode___eq____SWIG_0', + 'netnode___eq____SWIG_1', + 'netnode___ne__', + 'netnode___ne____SWIG_0', + 'netnode___ne____SWIG_1', + 'netnode_alt1st', + 'netnode_alt1st_idx8', + 'netnode_altdel', + 'netnode_altdel__SWIG_0', + 'netnode_altdel__SWIG_1', + 'netnode_altdel_all', + 'netnode_altdel_idx8', + 'netnode_altlast', + 'netnode_altlast_idx8', + 'netnode_altnxt', + 'netnode_altnxt_idx8', + 'netnode_altprev', + 'netnode_altprev_idx8', + 'netnode_altset', + 'netnode_altset_idx8', + 'netnode_altshift', + 'netnode_altval', + 'netnode_altval_idx8', + 'netnode_blobsize', + 'netnode_char1st', + 'netnode_char1st_idx8', + 'netnode_chardel', + 'netnode_chardel_idx8', + 'netnode_charlast', + 'netnode_charlast_idx8', + 'netnode_charnxt', + 'netnode_charnxt_idx8', + 'netnode_charprev', + 'netnode_charprev_idx8', + 'netnode_charset', + 'netnode_charset_idx8', + 'netnode_charshift', + 'netnode_charval', + 'netnode_charval_idx8', + 'netnode_copyto', + 'netnode_create', + 'netnode_create__SWIG_0', + 'netnode_create__SWIG_1', + 'netnode_delblob', + 'netnode_delvalue', + 'netnode_end', + 'netnode_get_name', + 'netnode_getblob', + 'netnode_hash1st', + 'netnode_hashdel', + 'netnode_hashdel_all', + 'netnode_hashlast', + 'netnode_hashnxt', + 'netnode_hashprev', + 'netnode_hashset', + 'netnode_hashset_buf', + 'netnode_hashset_idx', + 'netnode_hashstr', + 'netnode_hashstr_buf', + 'netnode_hashval', + 'netnode_hashval_long', + 'netnode_index', + 'netnode_kill', + 'netnode_long_value', + 'netnode_moveto', + 'netnode_name', + 'netnode_next', + 'netnode_prev', + 'netnode_rename', + 'netnode_set', + 'netnode_set_long', + 'netnode_setblob', + 'netnode_start', + 'netnode_sup1st', + 'netnode_sup1st_idx8', + 'netnode_supdel', + 'netnode_supdel__SWIG_0', + 'netnode_supdel__SWIG_1', + 'netnode_supdel_all', + 'netnode_supdel_idx8', + 'netnode_supdel_range', + 'netnode_supdel_range_idx8', + 'netnode_suplast', + 'netnode_suplast_idx8', + 'netnode_supnxt', + 'netnode_supnxt_idx8', + 'netnode_supprev', + 'netnode_supprev_idx8', + 'netnode_supset', + 'netnode_supset_idx8', + 'netnode_supshift', + 'netnode_supstr', + 'netnode_supstr_idx8', + 'netnode_supval', + 'netnode_supval_idx8', + 'netnode_valobj', + 'netnode_valstr', + 'netnode_value_exists', + 'new_DBG_Hooks', + 'new_IDB_Hooks', + 'new_IDP_Hooks', + 'new_UI_Hooks', + 'new___qmutex_t', + '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_area_t', + 'new_area_t__SWIG_0', + 'new_area_t__SWIG_1', + 'new_area_visitor2_t', + 'new_areacb_t', + 'new_areaset_t', + 'new_areaset_t__SWIG_0', + 'new_areaset_t__SWIG_1', + 'new_areaset_t__SWIG_2', + 'new_areavec_t', + 'new_argloc_t', + 'new_argloc_t__SWIG_0', + 'new_argloc_t__SWIG_1', + 'new_argpart_t', + 'new_array_parameters_t', + 'new_array_type_data_t', + 'new_asm_t', + 'new_auto_display_t', + 'new_bgcolors_t', + 'new_bitfield_type_data_t', + 'new_block', + 'new_boolvec_t', + 'new_boolvec_t__SWIG_0', + 'new_boolvec_t__SWIG_1', + 'new_boundaries_iterator_t', + 'new_boundaries_t', + 'new_bpt_location_t', + 'new_bpt_t', + 'new_bpt_vec_t', + 'new_bpt_vec_t__SWIG_0', + 'new_bpt_vec_t__SWIG_1', + 'new_call_stack_info_t', + 'new_call_stack_t', + 'new_callregs_t', + 'new_callregs_t__SWIG_0', + 'new_callregs_t__SWIG_1', + 'new_carg_t', + 'new_carglist_t', + 'new_carglist_t__SWIG_0', + 'new_carglist_t__SWIG_1', + 'new_cases_and_targets_t', + 'new_casevec_t', + 'new_casevec_t__SWIG_0', + 'new_casevec_t__SWIG_1', + 'new_casm_t', + 'new_casm_t__SWIG_0', + 'new_casm_t__SWIG_1', + 'new_cblock_t', + 'new_ccase_t', + 'new_ccases_t', + 'new_cdo_t', + 'new_ceinsn_t', + 'new_cexpr_t', + 'new_cexpr_t__SWIG_0', + 'new_cexpr_t__SWIG_1', + 'new_cexpr_t__SWIG_2', + 'new_cexpr_t__SWIG_3', + 'new_cexpr_t__SWIG_4', + 'new_cfor_t', + 'new_cfunc_parentee_t', + 'new_cfuncptr_t', + 'new_cfuncptr_t__SWIG_0', + 'new_cfuncptr_t__SWIG_1', + 'new_cgoto_t', + 'new_channel_redir_t', + 'new_cif_t', + 'new_cif_t__SWIG_0', + 'new_cif_t__SWIG_1', + 'new_cinsn_t', + 'new_cinsn_t__SWIG_0', + 'new_cinsn_t__SWIG_1', + 'new_cinsnptrvec_t', + 'new_cinsnptrvec_t__SWIG_0', + 'new_cinsnptrvec_t__SWIG_1', + 'new_citem_cmt_t', + 'new_citem_cmt_t__SWIG_0', + 'new_citem_cmt_t__SWIG_1', + 'new_citem_locator_t', + 'new_citem_locator_t__SWIG_0', + 'new_citem_locator_t__SWIG_1', + 'new_citem_locator_t__SWIG_2', + 'new_citem_t', + 'new_citem_t__SWIG_0', + 'new_citem_t__SWIG_1', + 'new_cloop_t', + 'new_cloop_t__SWIG_0', + 'new_cloop_t__SWIG_1', + 'new_cloop_t__SWIG_2', + 'new_cnumber_t', + 'new_compiler_info_t', + 'new_const_aloc_visitor_t', + 'new_creturn_t', + 'new_cswitch_t', + 'new_ctext_position_t', + 'new_ctree_anchor_t', + 'new_ctree_item_t', + 'new_ctree_items_t', + 'new_ctree_items_t__SWIG_0', + 'new_ctree_items_t__SWIG_1', + 'new_ctree_parentee_t', + 'new_ctree_visitor_t', + 'new_curloc', + 'new_curloc__SWIG_0', + 'new_curloc__SWIG_1', + 'new_custom_data_type_ids_t', + 'new_cwhile_t', + 'new_debapp_attrs_t', + 'new_debug_event_t', + 'new_disasm_line_t', + 'new_disasm_line_t__SWIG_0', + 'new_disasm_line_t__SWIG_1', + 'new_disasm_text_t', + 'new_disasm_text_t__SWIG_0', + 'new_disasm_text_t__SWIG_1', + 'new_e_breakpoint_t', + 'new_e_exception_t', + 'new_ea_array', + 'new_ea_name_t', + 'new_ea_name_t__SWIG_0', + 'new_ea_name_t__SWIG_1', + 'new_ea_pointer', + 'new_eamap_iterator_t', + 'new_eamap_t', + 'new_enum_const_t', + 'new_enum_member_t', + 'new_enum_member_visitor_t', + 'new_enum_type_data_t', + 'new_eval_ctx_t', + 'new_exception_info_t', + 'new_exception_info_t__SWIG_0', + 'new_exception_info_t__SWIG_1', + 'new_fixup_data_t', + 'new_fnumber_t', + 'new_func_item_iterator_t', + 'new_func_item_iterator_t__SWIG_0', + 'new_func_item_iterator_t__SWIG_1', + 'new_func_parent_iterator_t', + 'new_func_parent_iterator_t__SWIG_0', + 'new_func_parent_iterator_t__SWIG_1', + 'new_func_t', + 'new_func_tail_iterator_t', + 'new_func_tail_iterator_t__SWIG_0', + 'new_func_tail_iterator_t__SWIG_1', + 'new_func_type_data_t', + 'new_func_type_info_t', + 'new_funcarg_info_t', + 'new_funcarg_t', + 'new_funcargvec_t', + 'new_funcargvec_t__SWIG_0', + 'new_funcargvec_t__SWIG_1', + 'new_get_strmem_t', + 'new_graph_location_info_t', + 'new_hexrays_failure_t', + 'new_hexrays_failure_t__SWIG_0', + 'new_hexrays_failure_t__SWIG_1', + 'new_hexrays_failure_t__SWIG_2', + 'new_hexwarn_t', + 'new_hexwarns_t', + 'new_hexwarns_t__SWIG_0', + 'new_hexwarns_t__SWIG_1', + 'new_hidden_area_t', + 'new_highlighter_cbs_t', + 'new_history_item_t', + 'new_history_t', + 'new_ida_false_type', + 'new_ida_lowertype_helper_t', + 'new_ida_true_type', + 'new_idainfo', + 'new_idc_global_t', + 'new_idc_global_t__SWIG_0', + 'new_idc_global_t__SWIG_1', + 'new_idc_value_t', + 'new_idc_value_t__SWIG_0', + 'new_idc_value_t__SWIG_1', + 'new_idc_value_t__SWIG_2', + 'new_idc_value_t__SWIG_3', + 'new_idd_opinfo_old_t', + 'new_idp_desc_t', + 'new_idp_name_t', + 'new_ids_array', + 'new_instant_dbgopts_t', + 'new_int64vec_t', + 'new_int64vec_t__SWIG_0', + 'new_int64vec_t__SWIG_1', + 'new_int_pointer', + 'new_intvec_t', + 'new_intvec_t__SWIG_0', + 'new_intvec_t__SWIG_1', + 'new_jumptable_info_t', + 'new_linput_buffer_t', + 'new_llabel_t', + 'new_loader_input_t', + 'new_loader_t', + 'new_location_t', + 'new_location_t__SWIG_0', + 'new_location_t__SWIG_1', + 'new_locchange_md_t', + 'new_lochist_entry_t', + 'new_lochist_entry_t__SWIG_0', + 'new_lochist_entry_t__SWIG_1', + 'new_lochist_entry_t__SWIG_2', + 'new_lochist_t', + 'new_lock_area', + 'new_lock_func', + 'new_lock_segment', + 'new_lock_segreg', + 'new_lvar_locator_t', + 'new_lvar_locator_t__SWIG_0', + 'new_lvar_locator_t__SWIG_1', + 'new_lvar_mapping_iterator_t', + 'new_lvar_mapping_t', + 'new_lvar_saved_info_t', + 'new_lvar_saved_infos_t', + 'new_lvar_saved_infos_t__SWIG_0', + 'new_lvar_saved_infos_t__SWIG_1', + 'new_lvar_uservec_t', + 'new_lvars_t', + 'new_member_t', + 'new_module_info_t', + 'new_netnode', + 'new_netnode__SWIG_0', + 'new_netnode__SWIG_1', + 'new_netnode__SWIG_2', + 'new_node_info_t', + 'new_node_iterator', + 'new_number_format_t', + 'new_operand_locator_t', + 'new_operand_locator_t__SWIG_0', + 'new_operand_locator_t__SWIG_1', + 'new_operator_info_t', + 'new_opinfo_t', + 'new_plugin_info_t', + 'new_process_info_t', + 'new_ptr_type_data_t', + 'new_qbasic_block_t', + 'new_qfile_t', + 'new_qfile_t__SWIG_0', + 'new_qfile_t__SWIG_1', + 'new_qflow_chart_t', + 'new_qflow_chart_t__SWIG_0', + 'new_qflow_chart_t__SWIG_1', + 'new_qlist_cinsn_t', + 'new_qlist_cinsn_t__SWIG_0', + 'new_qlist_cinsn_t__SWIG_1', + 'new_qlist_cinsn_t_iterator', + 'new_qmutex_locker_t', + 'new_qstring_printer_t', + 'new_qvector_carg_t', + 'new_qvector_carg_t__SWIG_0', + 'new_qvector_carg_t__SWIG_1', + 'new_qvector_ccase_t', + 'new_qvector_ccase_t__SWIG_0', + 'new_qvector_ccase_t__SWIG_1', + 'new_qvector_history_t', + 'new_qvector_history_t__SWIG_0', + 'new_qvector_history_t__SWIG_1', + 'new_qvector_lvar_t', + 'new_qvector_lvar_t__SWIG_0', + 'new_qvector_lvar_t__SWIG_1', + 'new_qvector_snapshotvec_t', + 'new_qvector_snapshotvec_t__SWIG_0', + 'new_qvector_snapshotvec_t__SWIG_1', + 'new_refinfo_t', + 'new_reg_info_t', + 'new_regarg_t', + 'new_regobj_t', + 'new_regobjs_t', + 'new_regval_t', + 'new_regval_t__SWIG_0', + 'new_regval_t__SWIG_1', + 'new_regvar_t', + 'new_renderer_info_t', + 'new_renderer_pos_info_t', + 'new_rrel_t', + 'new_scattered_aloc_t', + 'new_scattered_vloc_t', + 'new_segm_move_info_t', + 'new_segm_move_info_vec_t', + 'new_segm_move_info_vec_t__SWIG_0', + 'new_segm_move_info_vec_t__SWIG_1', + 'new_segm_move_infos_t', + 'new_segment_t', + 'new_segreg_area_t', + 'new_segreg_t', + 'new_sel_array', + 'new_sel_pointer', + 'new_simd_info_t', + 'new_simpleline_t', + 'new_simpleline_t__SWIG_0', + 'new_simpleline_t__SWIG_1', + 'new_simpleline_t__SWIG_2', + 'new_simpleline_t__SWIG_3', + 'new_snapshot_t', + 'new_stkpnt_t', + 'new_strarray_t', + 'new_string_info_t', + 'new_string_info_t__SWIG_0', + 'new_string_info_t__SWIG_1', + 'new_strpath_t', + 'new_struct_field_visitor_t', + 'new_strvec_t', + 'new_strvec_t__SWIG_0', + 'new_strvec_t__SWIG_1', + 'new_strwinsetup_t', + 'new_sval_pointer', + 'new_tev_info_t', + 'new_text_options_t', + 'new_text_sink_t', + 'new_tid_array', + 'new_til', + 'new_til_symbol_t', + 'new_til_t', + 'new_tinfo_t', + 'new_tinfo_t__SWIG_0', + 'new_tinfo_t__SWIG_1', + 'new_tinfo_visitor_t', + 'new_treeloc_t', + 'new_twinpos_t', + 'new_twinpos_t__SWIG_0', + 'new_twinpos_t__SWIG_1', + 'new_twinpos_t__SWIG_2', + 'new_type_attr_t', + 'new_type_mods_t', + 'new_type_pair_t', + 'new_type_pair_t__SWIG_0', + 'new_type_pair_t__SWIG_1', + 'new_type_pair_t__SWIG_2', + 'new_type_pair_vec_t', + 'new_typedef_type_data_t', + 'new_typedef_type_data_t__SWIG_0', + 'new_typedef_type_data_t__SWIG_1', + 'new_uchar_array', + 'new_udt_member_t', + 'new_udt_type_data_t', + 'new_udtmembervec_t', + 'new_udtmembervec_t__SWIG_0', + 'new_udtmembervec_t__SWIG_1', + 'new_ui_requests_t', + 'new_user_cmts_iterator_t', + 'new_user_cmts_t', + 'new_user_iflags_iterator_t', + 'new_user_iflags_t', + 'new_user_labels_iterator_t', + 'new_user_labels_t', + 'new_user_lvar_modifier_t', + 'new_user_numforms_iterator_t', + 'new_user_numforms_t', + '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_deprecated2_t', + 'new_valstrs_deprecated_t', + 'new_valstrs_t', + 'new_var_ref_t', + 'new_varloc_t', + 'new_varloc_t__SWIG_0', + 'new_varloc_t__SWIG_1', + 'new_varpart_t', + 'new_vc_printer_t', + 'new_vd_failure_t', + 'new_vd_failure_t__SWIG_0', + 'new_vd_failure_t__SWIG_1', + 'new_vd_failure_t__SWIG_2', + 'new_vd_failure_t__SWIG_3', + 'new_vd_interr_t', + 'new_vd_interr_t__SWIG_0', + 'new_vd_interr_t__SWIG_1', + 'new_vd_printer_t', + 'new_vdloc_t', + 'new_xrefblk_t', + 'new_xreflist_entry_t', + 'new_xreflist_t', + 'new_xreflist_t__SWIG_0', + 'new_xreflist_t__SWIG_1', + 'next_head', + 'next_inited', + 'next_named_type', + 'next_not_tail', + 'next_unknown', + 'nextaddr', + 'nextchunk', + 'nextthat', + 'noExtra', + 'noImmd', + 'noType', + 'noUsed', + 'noUsed__SWIG_0', + 'noUsed__SWIG_1', + 'node_info_t_bg_color_get', + 'node_info_t_bg_color_set', + 'node_info_t_ea_get', + 'node_info_t_ea_set', + 'node_info_t_frame_color_get', + 'node_info_t_frame_color_set', + 'node_info_t_get_flags_for_valid', + 'node_info_t_text_get', + 'node_info_t_text_set', + 'node_info_t_valid_bg_color', + 'node_info_t_valid_ea', + 'node_info_t_valid_frame_color', + 'node_info_t_valid_text', + 'node_iterator___eq__', + 'node_iterator___ne__', + 'node_iterator___ref__', + 'nomem', + 'nomem__varargs__', + 'notify_when', + 'number_format_t_flags_get', + 'number_format_t_flags_set', + 'number_format_t_getRadix', + 'number_format_t_isChar', + 'number_format_t_isDec', + 'number_format_t_isEnum', + 'number_format_t_isHex', + 'number_format_t_isNum', + 'number_format_t_isOct', + 'number_format_t_isStroff', + 'number_format_t_is_fixed', + 'number_format_t_needs_to_be_inverted', + 'number_format_t_opnum_get', + 'number_format_t_opnum_set', + 'number_format_t_org_nbytes_get', + 'number_format_t_org_nbytes_set', + 'number_format_t_props_get', + 'number_format_t_props_set', + 'number_format_t_serial_get', + 'number_format_t_serial_set', + 'number_format_t_type_name_get', + 'number_format_t_type_name_set', + 'numflag', + 'octflag', + 'offflag', + 'op_adds_xrefs', + 'op_bin', + 'op_chr', + 'op_custfmt', + 'op_dec', + 'op_enum', + 'op_flt', + 'op_hex', + 'op_num', + 'op_oct', + 'op_offset', + 'op_offset_ex', + 'op_seg', + 'op_stkvar', + 'op_stroff', + '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', + 'op_uses_x', + 'op_uses_y', + 'op_uses_z', + 'openM', + 'openR', + 'openRT', + 'open_bpts_window', + 'open_calls_window', + 'open_disasm_window', + 'open_enums_window', + 'open_exports_window', + 'open_frame_window', + 'open_funcs_window', + 'open_hexdump_window', + 'open_imports_window', + 'open_linput', + 'open_loctypes_window', + 'open_modules_window', + 'open_names_window', + 'open_navband_window', + 'open_notepad_window', + 'open_problems_window', + 'open_pseudocode', + 'open_segments_window', + 'open_segregs_window', + 'open_selectors_window', + 'open_signatures_window', + 'open_stack_window', + 'open_strings_window', + 'open_structs_window', + 'open_tform', + 'open_threads_window', + 'open_tils_window', + 'open_trace_window', + 'open_url', + 'open_xrefs_window', + 'operand_locator_t___eq__', + 'operand_locator_t___ge__', + 'operand_locator_t___gt__', + 'operand_locator_t___le__', + 'operand_locator_t___lt__', + 'operand_locator_t___ne__', + 'operand_locator_t_compare', + 'operand_locator_t_ea_get', + 'operand_locator_t_ea_set', + 'operand_locator_t_opnum_get', + 'operand_locator_t_opnum_set', + 'operator_info_t_fixtype_get', + 'operator_info_t_fixtype_set', + 'operator_info_t_flags_get', + 'operator_info_t_flags_set', + 'operator_info_t_precedence_get', + 'operator_info_t_precedence_set', + 'operator_info_t_text_get', + 'operator_info_t_text_set', + 'operator_info_t_valency_get', + 'operator_info_t_valency_set', + 'opinfo_t_cd_get', + 'opinfo_t_cd_set', + 'opinfo_t_ec_get', + 'opinfo_t_ec_set', + 'opinfo_t_path_get', + 'opinfo_t_path_set', + 'opinfo_t_ri_get', + 'opinfo_t_ri_set', + 'opinfo_t_strtype_get', + 'opinfo_t_strtype_set', + 'opinfo_t_tid_get', + 'opinfo_t_tid_set', + 'optimize_argloc', + 'optimize_varloc', + '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', + 'owrdflag', + 'pack_idcobj_to_bv', + 'pack_idcobj_to_idb', + 'pack_object_to_bv', + 'pack_object_to_idb', + 'packrealflag', + 'parse_command_line3', + 'parse_dbgopts', + 'parse_decl', + 'parse_decl2', + 'parse_decls', + 'parse_reg_name', + 'parse_types2', + 'partial_type_num', + 'patch_byte', + 'patch_long', + 'patch_many_bytes', + 'patch_qword', + 'patch_word', + 'peek_auto_queue', + 'ph_get_cnbits', + 'ph_get_dnbits', + 'ph_get_flag', + 'ph_get_high_fixup_bits', + 'ph_get_icode_return', + 'ph_get_id', + 'ph_get_instruc', + 'ph_get_instruc_end', + 'ph_get_instruc_start', + 'ph_get_operand_info', + 'ph_get_regCodeSreg', + 'ph_get_regDataSreg', + 'ph_get_regFirstSreg', + 'ph_get_regLastSreg', + 'ph_get_regnames', + 'ph_get_segreg_size', + 'ph_get_tbyte_size', + 'ph_get_version', + 'place_t__print', + 'place_t_adjust', + 'place_t_as_enumplace_t', + 'place_t_as_idaplace_t', + 'place_t_as_simpleline_place_t', + 'place_t_as_structplace_t', + 'place_t_beginning', + 'place_t_clone', + 'place_t_compare', + 'place_t_copyfrom', + 'place_t_ending', + 'place_t_enter', + 'place_t_generate', + 'place_t_id', + 'place_t_leave', + 'place_t_lnnum_get', + 'place_t_lnnum_set', + 'place_t_makeplace', + 'place_t_name', + 'place_t_next', + 'place_t_prev', + 'place_t_rebase', + 'place_t_toea', + 'place_t_touval', + 'plan_to_apply_idasgn', + 'plgform_close', + 'plgform_new', + 'plgform_show', + 'plugin_info_t_arg_get', + 'plugin_info_t_arg_set', + 'plugin_info_t_comment_get', + 'plugin_info_t_comment_set', + 'plugin_info_t_dllmem_get', + 'plugin_info_t_dllmem_set', + 'plugin_info_t_entry_get', + 'plugin_info_t_entry_set', + 'plugin_info_t_flags_get', + 'plugin_info_t_flags_set', + 'plugin_info_t_hotkey_get', + 'plugin_info_t_hotkey_set', + 'plugin_info_t_name_get', + 'plugin_info_t_name_set', + 'plugin_info_t_next_get', + 'plugin_info_t_next_set', + 'plugin_info_t_org_hotkey_get', + 'plugin_info_t_org_hotkey_set', + 'plugin_info_t_org_name_get', + 'plugin_info_t_org_name_set', + 'plugin_info_t_path_get', + 'plugin_info_t_path_set', + 'prev_head', + 'prev_inited', + 'prev_not_tail', + 'prev_unknown', + 'prevaddr', + 'prevchunk', + 'prevthat', + 'print_argloc', + 'print_ascii_string_type', + 'print_decls', + 'print_tinfo', + 'print_type', + 'print_type2', + 'print_type3', + 'print_type_to_qstring', + 'print_varloc', + 'print_vdloc', + 'printf_line', + 'printf_line__varargs__', + 'process_info_t_name_get', + 'process_info_t_name_set', + 'process_info_t_pid_get', + 'process_info_t_pid_set', + 'process_ui_action', + 'ptr_type_data_t___eq__', + 'ptr_type_data_t___ne__', + 'ptr_type_data_t_based_ptr_size_get', + 'ptr_type_data_t_based_ptr_size_set', + 'ptr_type_data_t_closure_get', + 'ptr_type_data_t_closure_set', + 'ptr_type_data_t_is_code_ptr', + 'ptr_type_data_t_obj_type_get', + 'ptr_type_data_t_obj_type_set', + 'ptr_type_data_t_swap', + 'ptr_type_data_t_taptr_bits_get', + 'ptr_type_data_t_taptr_bits_set', + 'put_byte', + 'put_dbg_byte', + 'put_long', + 'put_many_bytes', + 'put_qword', + 'put_word', + 'py_get_AskUsingForm', + 'py_get_OpenForm', + 'py_get_call_idc_func', + 'py_get_global_cmd_link', + 'py_load_custom_icon_data', + 'py_load_custom_icon_fn', + 'py_menu_item_callback', + 'py_register_compiled_form', + 'py_set_idc_func_ex', + 'py_ss_restore_callback', + 'py_unregister_compiled_form', + 'pycim_get_tcustom_control', + 'pycim_get_tform', + 'pyg_add_command', + 'pyg_close', + 'pyg_select_node', + 'pyg_show', + 'pygc_create_groups', + 'pygc_del_nodes_infos', + 'pygc_delete_groups', + 'pygc_get_current_renderer_type', + 'pygc_get_node_info', + 'pygc_refresh', + 'pygc_set_current_renderer_type', + 'pygc_set_groups_visibility', + 'pygc_set_node_info', + 'pygc_set_nodes_infos', + 'pyidag_bind', + 'pyidag_unbind', + 'pyscv_add_line', + 'pyscv_add_popup_menu', + 'pyscv_clear_lines', + 'pyscv_clear_popup_menu', + 'pyscv_close', + 'pyscv_count', + 'pyscv_del_line', + 'pyscv_delete', + 'pyscv_edit_line', + 'pyscv_get_current_line', + 'pyscv_get_current_word', + 'pyscv_get_line', + 'pyscv_get_pos', + 'pyscv_get_selection', + 'pyscv_get_tcustom_control', + 'pyscv_get_tform', + 'pyscv_init', + 'pyscv_insert_line', + 'pyscv_is_focused', + 'pyscv_jumpto', + 'pyscv_patch_line', + 'pyscv_refresh', + 'pyscv_refresh_current', + 'pyscv_show', + 'pyw_register_idc_func', + 'pyw_unregister_idc_func', + 'qatoll', + 'qcontrol_tty', + 'qdetach_tty', + 'qexit', + 'qfile_t___idc_cvt_id___get', + 'qfile_t___idc_cvt_id___set', + 'qfile_t_close', + 'qfile_t_filename', + 'qfile_t_flush', + 'qfile_t_from_cobject', + 'qfile_t_from_fp', + 'qfile_t_get_char', + 'qfile_t_get_fp', + 'qfile_t_gets', + 'qfile_t_open', + 'qfile_t_opened', + 'qfile_t_put_char', + 'qfile_t_puts', + 'qfile_t_read', + 'qfile_t_readbytes', + 'qfile_t_seek', + 'qfile_t_size', + 'qfile_t_tell', + 'qfile_t_tmpfile', + 'qfile_t_write', + 'qfile_t_writebytes', + 'qflow_chart_t___getitem__', + 'qflow_chart_t_append_to_flowchart', + 'qflow_chart_t_bounds_get', + 'qflow_chart_t_bounds_set', + 'qflow_chart_t_calc_block_type', + 'qflow_chart_t_create', + 'qflow_chart_t_create__SWIG_0', + 'qflow_chart_t_create__SWIG_1', + 'qflow_chart_t_flags_get', + 'qflow_chart_t_flags_set', + 'qflow_chart_t_get_node_label', + 'qflow_chart_t_is_noret_block', + 'qflow_chart_t_is_ret_block', + 'qflow_chart_t_npred', + 'qflow_chart_t_nproper_get', + 'qflow_chart_t_nproper_set', + 'qflow_chart_t_nsucc', + 'qflow_chart_t_pfn_get', + 'qflow_chart_t_pfn_set', + 'qflow_chart_t_pred', + 'qflow_chart_t_print_names', + 'qflow_chart_t_print_node_attributes', + 'qflow_chart_t_refresh', + 'qflow_chart_t_size', + 'qflow_chart_t_succ', + 'qflow_chart_t_title_get', + 'qflow_chart_t_title_set', + 'qfsize', + 'qfsize64', + 'qlgetz', + 'qlgetz64', + 'qlist_cinsn_t___eq__', + 'qlist_cinsn_t___ne__', + 'qlist_cinsn_t_back', + 'qlist_cinsn_t_back__SWIG_0', + 'qlist_cinsn_t_back__SWIG_1', + 'qlist_cinsn_t_begin', + 'qlist_cinsn_t_clear', + 'qlist_cinsn_t_empty', + 'qlist_cinsn_t_end', + 'qlist_cinsn_t_erase', + 'qlist_cinsn_t_erase__SWIG_0', + 'qlist_cinsn_t_erase__SWIG_1', + 'qlist_cinsn_t_erase__SWIG_2', + 'qlist_cinsn_t_front', + 'qlist_cinsn_t_front__SWIG_0', + 'qlist_cinsn_t_front__SWIG_1', + 'qlist_cinsn_t_insert', + 'qlist_cinsn_t_insert__SWIG_0', + 'qlist_cinsn_t_insert__SWIG_1', + 'qlist_cinsn_t_insert__SWIG_3', + 'qlist_cinsn_t_iterator_cur_get', + 'qlist_cinsn_t_iterator_next', + 'qlist_cinsn_t_pop_back', + 'qlist_cinsn_t_pop_front', + 'qlist_cinsn_t_push_back', + 'qlist_cinsn_t_push_back__SWIG_0', + 'qlist_cinsn_t_push_back__SWIG_1', + 'qlist_cinsn_t_push_front', + 'qlist_cinsn_t_rbegin', + 'qlist_cinsn_t_rbegin__SWIG_0', + 'qlist_cinsn_t_rbegin__SWIG_1', + 'qlist_cinsn_t_rend', + 'qlist_cinsn_t_rend__SWIG_0', + 'qlist_cinsn_t_rend__SWIG_1', + 'qlist_cinsn_t_size', + 'qlist_cinsn_t_swap', + 'qlseek64', + 'qlsize64', + 'qltell64', + 'qrefcnt_obj_t_refcnt_get', + 'qrefcnt_obj_t_refcnt_set', + 'qrefcnt_obj_t_release', + 'qsplitpath', + 'qstring_printer_t__print', + 'qstring_printer_t__print__varargs__', + 'qstring_printer_t_get_s', + 'qstring_printer_t_s_get', + 'qstring_printer_t_s_set', + 'qstring_printer_t_with_tags_get', + 'qstring_printer_t_with_tags_set', + 'qstrvec_t_add', + 'qstrvec_t_addressof', + 'qstrvec_t_assign', + 'qstrvec_t_clear', + 'qstrvec_t_create', + 'qstrvec_t_destroy', + 'qstrvec_t_from_list', + 'qstrvec_t_get', + 'qstrvec_t_get_clink', + 'qstrvec_t_get_clink_ptr', + 'qstrvec_t_insert', + 'qstrvec_t_remove', + 'qstrvec_t_set', + 'qstrvec_t_size', + 'qswap', + 'quote_cmdline_arg', + 'qvector_carg_t___eq__', + 'qvector_carg_t___getitem__', + 'qvector_carg_t___len__', + 'qvector_carg_t___ne__', + 'qvector_carg_t___setitem__', + 'qvector_carg_t__del', + 'qvector_carg_t_add_unique', + 'qvector_carg_t_at', + 'qvector_carg_t_back', + 'qvector_carg_t_back__SWIG_0', + 'qvector_carg_t_back__SWIG_1', + 'qvector_carg_t_begin', + 'qvector_carg_t_begin__SWIG_0', + 'qvector_carg_t_begin__SWIG_1', + 'qvector_carg_t_capacity', + 'qvector_carg_t_clear', + 'qvector_carg_t_empty', + 'qvector_carg_t_end', + 'qvector_carg_t_end__SWIG_0', + 'qvector_carg_t_end__SWIG_1', + 'qvector_carg_t_erase', + 'qvector_carg_t_erase__SWIG_0', + 'qvector_carg_t_erase__SWIG_1', + 'qvector_carg_t_extract', + 'qvector_carg_t_find', + 'qvector_carg_t_find__SWIG_0', + 'qvector_carg_t_find__SWIG_1', + 'qvector_carg_t_front', + 'qvector_carg_t_front__SWIG_0', + 'qvector_carg_t_front__SWIG_1', + 'qvector_carg_t_grow', + 'qvector_carg_t_has', + 'qvector_carg_t_inject', + 'qvector_carg_t_insert', + 'qvector_carg_t_pop_back', + 'qvector_carg_t_push_back', + 'qvector_carg_t_push_back__SWIG_0', + 'qvector_carg_t_push_back__SWIG_1', + 'qvector_carg_t_qclear', + 'qvector_carg_t_reserve', + 'qvector_carg_t_resize', + 'qvector_carg_t_resize__SWIG_0', + 'qvector_carg_t_resize__SWIG_1', + 'qvector_carg_t_size', + 'qvector_carg_t_swap', + 'qvector_carg_t_truncate', + 'qvector_ccase_t___eq__', + 'qvector_ccase_t___getitem__', + 'qvector_ccase_t___len__', + 'qvector_ccase_t___ne__', + 'qvector_ccase_t___setitem__', + 'qvector_ccase_t__del', + 'qvector_ccase_t_add_unique', + 'qvector_ccase_t_at', + 'qvector_ccase_t_back', + 'qvector_ccase_t_back__SWIG_0', + 'qvector_ccase_t_back__SWIG_1', + 'qvector_ccase_t_begin', + 'qvector_ccase_t_begin__SWIG_0', + 'qvector_ccase_t_begin__SWIG_1', + 'qvector_ccase_t_capacity', + 'qvector_ccase_t_clear', + 'qvector_ccase_t_empty', + 'qvector_ccase_t_end', + 'qvector_ccase_t_end__SWIG_0', + 'qvector_ccase_t_end__SWIG_1', + 'qvector_ccase_t_erase', + 'qvector_ccase_t_erase__SWIG_0', + 'qvector_ccase_t_erase__SWIG_1', + 'qvector_ccase_t_extract', + 'qvector_ccase_t_find', + 'qvector_ccase_t_find__SWIG_0', + 'qvector_ccase_t_find__SWIG_1', + 'qvector_ccase_t_front', + 'qvector_ccase_t_front__SWIG_0', + 'qvector_ccase_t_front__SWIG_1', + 'qvector_ccase_t_grow', + 'qvector_ccase_t_has', + 'qvector_ccase_t_inject', + 'qvector_ccase_t_insert', + 'qvector_ccase_t_pop_back', + 'qvector_ccase_t_push_back', + 'qvector_ccase_t_push_back__SWIG_0', + 'qvector_ccase_t_push_back__SWIG_1', + 'qvector_ccase_t_qclear', + 'qvector_ccase_t_reserve', + 'qvector_ccase_t_resize', + 'qvector_ccase_t_resize__SWIG_0', + 'qvector_ccase_t_resize__SWIG_1', + 'qvector_ccase_t_size', + 'qvector_ccase_t_swap', + 'qvector_ccase_t_truncate', + 'qvector_history_t___eq__', + 'qvector_history_t___getitem__', + 'qvector_history_t___len__', + 'qvector_history_t___ne__', + 'qvector_history_t___setitem__', + 'qvector_history_t__del', + 'qvector_history_t_add_unique', + 'qvector_history_t_at', + 'qvector_history_t_back', + 'qvector_history_t_back__SWIG_0', + 'qvector_history_t_back__SWIG_1', + 'qvector_history_t_begin', + 'qvector_history_t_begin__SWIG_0', + 'qvector_history_t_begin__SWIG_1', + 'qvector_history_t_capacity', + 'qvector_history_t_clear', + 'qvector_history_t_empty', + 'qvector_history_t_end', + 'qvector_history_t_end__SWIG_0', + 'qvector_history_t_end__SWIG_1', + 'qvector_history_t_erase', + 'qvector_history_t_erase__SWIG_0', + 'qvector_history_t_erase__SWIG_1', + 'qvector_history_t_extract', + 'qvector_history_t_find', + 'qvector_history_t_find__SWIG_0', + 'qvector_history_t_find__SWIG_1', + 'qvector_history_t_front', + 'qvector_history_t_front__SWIG_0', + 'qvector_history_t_front__SWIG_1', + 'qvector_history_t_grow', + 'qvector_history_t_has', + 'qvector_history_t_inject', + 'qvector_history_t_insert', + 'qvector_history_t_pop_back', + 'qvector_history_t_push_back', + 'qvector_history_t_push_back__SWIG_0', + 'qvector_history_t_push_back__SWIG_1', + 'qvector_history_t_qclear', + 'qvector_history_t_reserve', + 'qvector_history_t_resize', + 'qvector_history_t_resize__SWIG_0', + 'qvector_history_t_resize__SWIG_1', + 'qvector_history_t_size', + 'qvector_history_t_swap', + 'qvector_history_t_truncate', + 'qvector_lvar_t___eq__', + 'qvector_lvar_t___getitem__', + 'qvector_lvar_t___len__', + 'qvector_lvar_t___ne__', + 'qvector_lvar_t___setitem__', + 'qvector_lvar_t__del', + 'qvector_lvar_t_add_unique', + 'qvector_lvar_t_at', + 'qvector_lvar_t_back', + 'qvector_lvar_t_back__SWIG_0', + 'qvector_lvar_t_back__SWIG_1', + 'qvector_lvar_t_begin', + 'qvector_lvar_t_begin__SWIG_0', + 'qvector_lvar_t_begin__SWIG_1', + 'qvector_lvar_t_capacity', + 'qvector_lvar_t_clear', + 'qvector_lvar_t_empty', + 'qvector_lvar_t_end', + 'qvector_lvar_t_end__SWIG_0', + 'qvector_lvar_t_end__SWIG_1', + 'qvector_lvar_t_erase', + 'qvector_lvar_t_erase__SWIG_0', + 'qvector_lvar_t_erase__SWIG_1', + 'qvector_lvar_t_extract', + 'qvector_lvar_t_find', + 'qvector_lvar_t_find__SWIG_0', + 'qvector_lvar_t_find__SWIG_1', + 'qvector_lvar_t_front', + 'qvector_lvar_t_front__SWIG_0', + 'qvector_lvar_t_front__SWIG_1', + 'qvector_lvar_t_grow', + 'qvector_lvar_t_has', + 'qvector_lvar_t_inject', + 'qvector_lvar_t_insert', + 'qvector_lvar_t_pop_back', + 'qvector_lvar_t_push_back', + 'qvector_lvar_t_push_back__SWIG_0', + 'qvector_lvar_t_push_back__SWIG_1', + 'qvector_lvar_t_qclear', + 'qvector_lvar_t_reserve', + 'qvector_lvar_t_resize', + 'qvector_lvar_t_resize__SWIG_0', + 'qvector_lvar_t_resize__SWIG_1', + 'qvector_lvar_t_size', + 'qvector_lvar_t_swap', + 'qvector_lvar_t_truncate', + 'qvector_reserve', + 'qvector_snapshotvec_t___eq__', + 'qvector_snapshotvec_t___getitem__', + 'qvector_snapshotvec_t___len__', + 'qvector_snapshotvec_t___ne__', + 'qvector_snapshotvec_t___setitem__', + 'qvector_snapshotvec_t__del', + 'qvector_snapshotvec_t_add_unique', + 'qvector_snapshotvec_t_at', + 'qvector_snapshotvec_t_back', + 'qvector_snapshotvec_t_back__SWIG_0', + 'qvector_snapshotvec_t_back__SWIG_1', + 'qvector_snapshotvec_t_begin', + 'qvector_snapshotvec_t_begin__SWIG_0', + 'qvector_snapshotvec_t_begin__SWIG_1', + 'qvector_snapshotvec_t_capacity', + 'qvector_snapshotvec_t_clear', + 'qvector_snapshotvec_t_empty', + 'qvector_snapshotvec_t_end', + 'qvector_snapshotvec_t_end__SWIG_0', + 'qvector_snapshotvec_t_end__SWIG_1', + 'qvector_snapshotvec_t_erase', + 'qvector_snapshotvec_t_erase__SWIG_0', + 'qvector_snapshotvec_t_erase__SWIG_1', + 'qvector_snapshotvec_t_extract', + 'qvector_snapshotvec_t_find', + 'qvector_snapshotvec_t_find__SWIG_0', + 'qvector_snapshotvec_t_find__SWIG_1', + 'qvector_snapshotvec_t_front', + 'qvector_snapshotvec_t_front__SWIG_0', + 'qvector_snapshotvec_t_front__SWIG_1', + 'qvector_snapshotvec_t_has', + 'qvector_snapshotvec_t_inject', + 'qvector_snapshotvec_t_insert', + 'qvector_snapshotvec_t_pop_back', + 'qvector_snapshotvec_t_push_back', + 'qvector_snapshotvec_t_push_back__SWIG_0', + 'qvector_snapshotvec_t_push_back__SWIG_1', + 'qvector_snapshotvec_t_qclear', + 'qvector_snapshotvec_t_reserve', + 'qvector_snapshotvec_t_resize', + 'qvector_snapshotvec_t_resize__SWIG_0', + 'qvector_snapshotvec_t_resize__SWIG_1', + 'qvector_snapshotvec_t_size', + 'qvector_snapshotvec_t_swap', + 'qvector_snapshotvec_t_truncate', + 'qwait_timed', + 'qwrdflag', + 'read_dbg_memory', + 'read_regargs', + 'read_selection', + 'read_tinfo_bitfield_value', + 'readbytes', + 'readsel2', + 'reanalyze_callers', + 'reanalyze_function', + 'rebase_program', + 'rebuild_nlist', + 'recalc_spd', + 'refinfo_t_base_get', + 'refinfo_t_base_set', + 'refinfo_t_flags_get', + 'refinfo_t_flags_set', + 'refinfo_t_init', + 'refinfo_t_is_custom', + 'refinfo_t_is_pastend', + 'refinfo_t_is_rvaoff', + 'refinfo_t_is_signed', + 'refinfo_t_is_subtract', + 'refinfo_t_no_base_xref', + 'refinfo_t_set_type', + 'refinfo_t_target_get', + 'refinfo_t_target_set', + 'refinfo_t_tdelta_get', + 'refinfo_t_tdelta_set', + 'refinfo_t_type', + 'refresh_chooser', + 'refresh_debugger_memory', + 'refresh_idaview', + 'refresh_idaview_anyway', + 'refresh_lists', + 'refresh_navband', + 'refresh_strlist', + 'reg_data_type', + 'reg_delete', + 'reg_delete_subkey', + 'reg_delete_tree', + 'reg_exists', + 'reg_flush', + 'reg_info_t___eq__', + 'reg_info_t___ge__', + 'reg_info_t___gt__', + 'reg_info_t___le__', + 'reg_info_t___lt__', + 'reg_info_t___ne__', + 'reg_info_t_compare', + 'reg_info_t_reg_get', + 'reg_info_t_reg_set', + 'reg_info_t_size_get', + 'reg_info_t_size_set', + 'reg_load', + 'reg_read_binary', + 'reg_read_bool', + 'reg_read_int', + 'reg_read_string', + 'reg_read_strlist', + 'reg_subkey_exists', + 'reg_subkey_subkeys', + 'reg_subkey_values', + 'reg_update_filestrlist', + 'reg_update_strlist', + 'reg_write_binary', + 'reg_write_bool', + 'reg_write_int', + 'reg_write_string', + 'regarg_t_name_get', + 'regarg_t_name_set', + 'regarg_t_reg_get', + 'regarg_t_reg_set', + 'regarg_t_type_get', + 'regarg_t_type_set', + 'register_action', + 'register_addon', + 'register_and_attach_to_menu', + 'register_custom_data_format', + 'register_custom_data_type', + 'register_timer', + 'regobj_t_regidx_get', + 'regobj_t_regidx_set', + 'regobj_t_relocate_get', + 'regobj_t_relocate_set', + 'regobj_t_size', + 'regobj_t_value_get', + 'regobj_t_value_set', + 'regval_t___eq__', + 'regval_t___ne__', + 'regval_t__set_bytes', + 'regval_t__set_bytes__SWIG_0', + 'regval_t__set_bytes__SWIG_1', + 'regval_t__set_bytes__SWIG_2', + 'regval_t__set_float', + 'regval_t__set_int', + 'regval_t_bytes', + 'regval_t_bytes__SWIG_0', + 'regval_t_bytes__SWIG_1', + 'regval_t_clear', + 'regval_t_fval_get', + 'regval_t_fval_set', + 'regval_t_get_data', + 'regval_t_get_data__SWIG_0', + 'regval_t_get_data__SWIG_1', + 'regval_t_get_data_size', + 'regval_t_ival_get', + 'regval_t_ival_set', + 'regval_t_rvtype_get', + 'regval_t_rvtype_set', + 'regval_t_set_bytes', + 'regval_t_set_bytes__SWIG_0', + 'regval_t_set_bytes__SWIG_1', + 'regval_t_set_bytes__SWIG_2', + 'regval_t_set_float', + 'regval_t_set_int', + 'regval_t_swap', + 'regvar_t_canon_get', + 'regvar_t_canon_set', + 'regvar_t_cmt_get', + 'regvar_t_cmt_set', + 'regvar_t_user_get', + 'regvar_t_user_set', + 'reload_file', + 'reloc_value', + 'relocate_relobj', + 'remove_command_interpreter', + 'remove_extlang', + 'remove_func_tail', + 'remove_hexrays_callback', + 'remove_pointer', + 'remove_tinfo_pointer', + 'remove_type_pointer', + 'rename_bptgrp', + 'rename_entry', + 'rename_named_type', + 'rename_regvar', + 'renderer_info_t___eq__', + 'renderer_info_t___ne__', + 'renderer_info_t_clear', + 'renderer_info_t_gli_get', + 'renderer_info_t_gli_set', + 'renderer_info_t_pos_get', + 'renderer_info_t_pos_set', + 'renderer_info_t_rtype_get', + 'renderer_info_t_rtype_set', + 'renderer_pos_info_t___eq__', + 'renderer_pos_info_t___ne__', + 'renderer_pos_info_t_cx_get', + 'renderer_pos_info_t_cx_set', + 'renderer_pos_info_t_cy_get', + 'renderer_pos_info_t_cy_set', + 'renderer_pos_info_t_node_get', + 'renderer_pos_info_t_node_set', + 'renderer_pos_info_t_sx_get', + 'renderer_pos_info_t_sx_set', + 'reorder_dummy_names', + 'repaint_custom_viewer', + 'replace_subtypes', + 'replace_subtypes2', + 'replace_tabs', + 'replace_wait_box', + 'replace_wait_box__varargs__', + 'request_add_bpt', + 'request_add_bpt__SWIG_0', + 'request_add_bpt__SWIG_1', + 'request_attach_process', + 'request_clear_trace', + 'request_continue_process', + 'request_del_bpt', + 'request_del_bpt__SWIG_0', + 'request_del_bpt__SWIG_1', + 'request_detach_process', + 'request_enable_bblk_trace', + 'request_enable_bpt', + 'request_enable_bpt__SWIG_0', + 'request_enable_bpt__SWIG_1', + 'request_enable_func_trace', + 'request_enable_insn_trace', + 'request_enable_step_trace', + 'request_exit_process', + 'request_refresh', + 'request_resume_thread', + 'request_run_to', + 'request_select_thread', + 'request_set_bblk_trace_options', + 'request_set_func_trace_options', + 'request_set_insn_trace_options', + 'request_set_reg_val', + 'request_set_resume_mode', + 'request_set_step_trace_options', + 'request_start_process', + 'request_step_into', + 'request_step_over', + 'request_step_until_ret', + 'request_suspend_process', + 'request_suspend_thread', + 'resolve_complex_type2', + 'resolve_typedef2', + 'restore_database_snapshot', + 'restore_user_cmts', + 'restore_user_iflags', + 'restore_user_labels', + 'restore_user_lvar_settings', + 'restore_user_numforms', + 'restore_user_unions', + 'resume_thread', + 'retrieve_exceptions', + 'retrieve_input_file_crc32', + 'retrieve_input_file_md5', + 'retrieve_input_file_sha256', + 'retrieve_input_file_size', + 'retrieve_member_info', + 'revert_ida_decisions', + 'rrel_t_off_get', + 'rrel_t_off_set', + 'rrel_t_reg_get', + 'rrel_t_reg_set', + 'run_plugin', + 'run_requests', + 'run_statements', + 'run_to', + 'save_database', + 'save_database_ex', + 'save_struc', + 'save_struc2', + 'save_tinfo', + 'save_trace_file', + 'save_user_cmts', + 'save_user_iflags', + 'save_user_labels', + 'save_user_lvar_settings', + 'save_user_numforms', + 'save_user_unions', + 'score_tinfo', + 'scr2idb', + 'search_down', + 'segflag', + 'segm_adjust_diff', + 'segm_adjust_ea', + 'segm_move_info_t___eq__', + 'segm_move_info_t___ne__', + 'segm_move_info_t__from_get', + 'segm_move_info_t__from_set', + 'segm_move_info_t_size_get', + 'segm_move_info_t_size_set', + 'segm_move_info_t_to_get', + 'segm_move_info_t_to_set', + 'segm_move_info_vec_t___eq__', + 'segm_move_info_vec_t___getitem__', + 'segm_move_info_vec_t___len__', + 'segm_move_info_vec_t___ne__', + 'segm_move_info_vec_t___setitem__', + 'segm_move_info_vec_t__del', + 'segm_move_info_vec_t_add_unique', + 'segm_move_info_vec_t_at', + 'segm_move_info_vec_t_back', + 'segm_move_info_vec_t_back__SWIG_0', + 'segm_move_info_vec_t_back__SWIG_1', + 'segm_move_info_vec_t_begin', + 'segm_move_info_vec_t_begin__SWIG_0', + 'segm_move_info_vec_t_begin__SWIG_1', + 'segm_move_info_vec_t_capacity', + 'segm_move_info_vec_t_clear', + 'segm_move_info_vec_t_empty', + 'segm_move_info_vec_t_end', + 'segm_move_info_vec_t_end__SWIG_0', + 'segm_move_info_vec_t_end__SWIG_1', + 'segm_move_info_vec_t_erase', + 'segm_move_info_vec_t_erase__SWIG_0', + 'segm_move_info_vec_t_erase__SWIG_1', + 'segm_move_info_vec_t_extract', + 'segm_move_info_vec_t_find', + 'segm_move_info_vec_t_find__SWIG_0', + 'segm_move_info_vec_t_find__SWIG_1', + 'segm_move_info_vec_t_front', + 'segm_move_info_vec_t_front__SWIG_0', + 'segm_move_info_vec_t_front__SWIG_1', + 'segm_move_info_vec_t_grow', + 'segm_move_info_vec_t_has', + 'segm_move_info_vec_t_inject', + 'segm_move_info_vec_t_insert', + 'segm_move_info_vec_t_pop_back', + 'segm_move_info_vec_t_push_back', + 'segm_move_info_vec_t_push_back__SWIG_0', + 'segm_move_info_vec_t_push_back__SWIG_1', + 'segm_move_info_vec_t_qclear', + 'segm_move_info_vec_t_reserve', + 'segm_move_info_vec_t_resize', + 'segm_move_info_vec_t_resize__SWIG_0', + 'segm_move_info_vec_t_resize__SWIG_1', + 'segm_move_info_vec_t_size', + 'segm_move_info_vec_t_swap', + 'segm_move_info_vec_t_truncate', + 'segm_move_infos_t_find', + 'segment_t_abits', + 'segment_t_abytes', + 'segment_t_align_get', + 'segment_t_align_set', + 'segment_t_bitness_get', + 'segment_t_bitness_set', + 'segment_t_clr_comorg', + 'segment_t_clr_ob_ok', + 'segment_t_color_get', + 'segment_t_color_set', + 'segment_t_comb_get', + 'segment_t_comb_set', + 'segment_t_comorg', + 'segment_t_defsr_get', + 'segment_t_defsr_set', + 'segment_t_endEA_get', + 'segment_t_endEA_set', + 'segment_t_flags_get', + 'segment_t_flags_set', + 'segment_t_is_hidden_segtype', + 'segment_t_is_loader_segm', + 'segment_t_is_visible_segm', + 'segment_t_name_get', + 'segment_t_name_set', + 'segment_t_ob_ok', + 'segment_t_orgbase_get', + 'segment_t_orgbase_set', + 'segment_t_perm_get', + 'segment_t_perm_set', + 'segment_t_sclass_get', + 'segment_t_sclass_set', + 'segment_t_sel_get', + 'segment_t_sel_set', + 'segment_t_set_comorg', + 'segment_t_set_debugger_segm', + 'segment_t_set_hidden_segtype', + 'segment_t_set_loader_segm', + 'segment_t_set_ob_ok', + 'segment_t_set_visible_segm', + 'segment_t_startEA_get', + 'segment_t_startEA_set', + 'segment_t_type_get', + 'segment_t_type_set', + 'segment_t_update', + 'segment_t_use32', + 'segment_t_use64', + 'segreg_area_t_tag_get', + 'segreg_area_t_tag_set', + 'segreg_area_t_val_get', + 'segreg_area_t_val_set', + 'segreg_t_reg', + 'segreg_t_setregs', + 'segreg_t_settags', + 'segreg_t_tag', + 'segreg_t_undefregs', + 'segtype', + 'sel2ea', + 'sel_array___getitem__', + 'sel_array___setitem__', + 'sel_array_cast', + 'sel_array_frompointer', + 'sel_pointer_assign', + 'sel_pointer_cast', + 'sel_pointer_frompointer', + 'sel_pointer_value', + 'select_extlang', + 'select_thread', + 'send_database', + 'serialize_tinfo', + 'setBreak', + 'setFlags', + 'setStat', + 'set__bnot0', + 'set__bnot1', + 'set__invsign0', + 'set__invsign1', + 'set_abi_name', + 'set_abits', + 'set_absbase', + 'set_aflags', + 'set_align_flow', + 'set_alignment', + 'set_array_parameters', + 'set_asm_inc_file', + 'set_auto_plugins', + 'set_bblk_trace_options', + 'set_bmask_cmt', + 'set_bmask_name', + 'set_bpt_group', + 'set_bptloc_group', + 'set_bptloc_string', + 'set_c_header_path', + 'set_c_macros', + 'set_cmt', + 'set_code_viewer_handler', + 'set_code_viewer_is_source', + 'set_code_viewer_line_handlers', + 'set_code_viewer_lines_alignment', + 'set_code_viewer_lines_icon_margin', + 'set_code_viewer_lines_radix', + 'set_code_viewer_user_data', + 'set_colored_item', + 'set_compiler', + 'set_compiler2', + 'set_compiler_id', + 'set_complex_n', + 'set_const_cmt', + 'set_const_name', + 'set_custom_data_type_ids', + 'set_custom_viewer_qt_aware', + 'set_dbg_default_options', + 'set_dbg_options', + 'set_dbg_options__SWIG_0', + 'set_dbg_options__SWIG_1', + 'set_debug_name', + 'set_debugger_event_cond', + 'set_debugger_options', + 'set_default_dataseg', + 'set_default_encoding_idx', + 'set_default_segreg_value', + 'set_defsr', + 'set_dock_pos', + 'set_dummy_name', + 'set_entry_forwarder', + 'set_enum_bf', + 'set_enum_cmt', + 'set_enum_fromtil', + 'set_enum_ghost', + 'set_enum_hidden', + 'set_enum_idx', + 'set_enum_member_cmt', + 'set_enum_member_name', + 'set_enum_name', + 'set_enum_type_ordinal', + 'set_enum_width', + 'set_fixed_spd', + 'set_fixup', + 'set_fixup_ex', + 'set_forced_operand', + 'set_frame_size', + 'set_func_cmt', + 'set_func_name_if_jumpfunc', + 'set_func_trace_options', + 'set_group_selector', + 'set_has_lname', + 'set_has_ti', + 'set_has_ti0', + 'set_has_ti1', + 'set_header_path', + 'set_highlight_trace_options', + 'set_ids_modnode', + 'set_imagebase', + 'set_insn_trace_options', + 'set_int_dbg_options', + 'set_item_color', + 'set_jumptable_info', + 'set_libitem', + 'set_lzero', + 'set_lzero0', + 'set_lzero1', + 'set_manual_insn', + 'set_member_cmt', + 'set_member_name', + 'set_member_ti', + 'set_member_tinfo', + 'set_member_tinfo2', + 'set_member_type', + 'set_menu_item_icon', + 'set_name', + 'set_name__SWIG_0', + 'set_name__SWIG_1', + 'set_named_type64', + 'set_nav_colorizer', + 'set_node_info', + 'set_node_info2', + 'set_noret', + 'set_noret_insn', + 'set_notcode', + 'set_numbered_type', + 'set_offset', + 'set_op_tinfo2', + 'set_op_type', + 'set_opinfo', + 'set_process_options', + 'set_process_state', + 'set_processor_type', + 'set_purged', + 'set_refinfo', + 'set_refinfo_ex', + 'set_reg_val', + 'set_reg_val__SWIG_0', + 'set_reg_val__SWIG_1', + 'set_regvar_cmt', + 'set_remote_debugger', + 'set_resume_mode', + 'set_retfp', + 'set_root_filename', + 'set_scattered_varloc', + 'set_script_timeout', + 'set_segm_addressing', + 'set_segm_base', + 'set_segm_class', + 'set_segm_end', + 'set_segm_name', + 'set_segm_name__varargs__', + 'set_segm_start', + 'set_segment_cmt', + 'set_segment_translations', + 'set_selector', + 'set_source_linnum', + 'set_spoils', + 'set_sreg_at_next_code', + 'set_step_trace_options', + 'set_strlist_options', + 'set_struc_align', + 'set_struc_cmt', + 'set_struc_hidden', + 'set_struc_idx', + 'set_struc_listed', + 'set_struc_name', + 'set_switch_info_ex', + 'set_switch_parent', + 'set_tail_owner', + 'set_target_assembler', + 'set_terse_struc', + 'set_tilcmt', + 'set_tinfo', + 'set_tinfo2', + 'set_tinfo_attr', + 'set_tinfo_attrs', + 'set_tinfo_property', + 'set_trace_base_address', + 'set_trace_file_desc', + 'set_trace_platform', + 'set_trace_size', + 'set_type', + 'set_type_alias', + 'set_typeinfo', + 'set_usemodsp', + 'set_user_defined_prefix', + 'set_usersp', + 'set_userti', + 'set_view_renderer_type', + 'set_visible_func', + 'set_visible_item', + 'set_visible_segm', + 'set_zstroff', + 'setup_selector', + 'should_create_stkvars', + 'should_trace_sp', + 'showAddr', + 'showAllComments', + 'showAuto', + 'showComments', + 'showRepeatables', + 'show_name', + 'show_wait_box', + 'show_wait_box__varargs__', + 'signed_data_flag', + 'simd_info_t_match_pattern', + 'simd_info_t_memtype_get', + 'simd_info_t_memtype_set', + 'simd_info_t_name_get', + 'simd_info_t_name_set', + 'simd_info_t_size_get', + 'simd_info_t_size_set', + 'simd_info_t_tif_get', + 'simd_info_t_tif_set', + 'simpleline_place_t_n_get', + 'simpleline_place_t_n_set', + 'simpleline_t_bgcolor_get', + 'simpleline_t_bgcolor_set', + 'simpleline_t_color_get', + 'simpleline_t_color_set', + 'simpleline_t_line_get', + 'simpleline_t_line_set', + 'sizeof_ldbl', + 'skip_spoiled_info', + 'skip_varloc', + 'snapshot_t___eq__', + 'snapshot_t___ge__', + 'snapshot_t___gt__', + 'snapshot_t___le__', + 'snapshot_t___lt__', + 'snapshot_t___ne__', + 'snapshot_t_children_get', + 'snapshot_t_children_set', + 'snapshot_t_clear', + 'snapshot_t_desc_get', + 'snapshot_t_desc_set', + 'snapshot_t_filename_get', + 'snapshot_t_filename_set', + 'snapshot_t_flags_get', + 'snapshot_t_flags_set', + 'snapshot_t_id_get', + 'snapshot_t_id_set', + 'splitSRarea1', + 'split_old_argloc', + 'split_srarea', + 'start_process', + 'std_gen_func_header', + 'std_gen_segm_footer', + 'step_into', + 'step_over', + 'step_until_ret', + 'stkpnt_t___lt__', + 'stkpnt_t_ea_get', + 'stkpnt_t_ea_set', + 'stkpnt_t_spd_get', + 'stkpnt_t_spd_set', + 'stkvarflag', + 'store_exceptions', + 'store_til', + 'str2ea', + 'str2reg', + 'str2regf', + 'str2user', + 'strarray', + 'strarray_t_code_get', + 'strarray_t_code_set', + 'strarray_t_text_get', + 'strarray_t_text_set', + 'string_info_t___lt__', + 'string_info_t_ea_get', + 'string_info_t_ea_set', + 'string_info_t_length_get', + 'string_info_t_length_set', + 'string_info_t_type_get', + 'string_info_t_type_set', + 'strlwr', + 'stroff_as_size', + 'stroffflag', + 'strpath_t___getIds', + 'strpath_t_delta_get', + 'strpath_t_delta_set', + 'strpath_t_ids_get', + 'strpath_t_ids_set', + 'strpath_t_len_get', + 'strpath_t_len_set', + 'struc_t_age_get', + 'struc_t_age_set', + 'struc_t_from_til', + 'struc_t_get_alignment', + 'struc_t_get_member', + 'struc_t_has_union', + 'struc_t_id_get', + 'struc_t_id_set', + 'struc_t_is_choosable', + 'struc_t_is_ghost', + 'struc_t_is_hidden', + 'struc_t_is_union', + 'struc_t_is_varstr', + 'struc_t_members_get', + 'struc_t_members_set', + 'struc_t_memqty_get', + 'struc_t_memqty_set', + 'struc_t_ordinal_get', + 'struc_t_ordinal_set', + 'struc_t_props_get', + 'struc_t_props_set', + 'struc_t_set_alignment', + 'struc_t_set_ghost', + 'struct_field_visitor_t_visit_field', + 'structplace_t_idx_get', + 'structplace_t_idx_set', + 'structplace_t_offset_get', + 'structplace_t_offset_set', + 'struflag', + 'strupr', + 'strvec_t___getitem__', + 'strvec_t___len__', + 'strvec_t___setitem__', + 'strvec_t_at', + 'strvec_t_back', + 'strvec_t_back__SWIG_0', + 'strvec_t_back__SWIG_1', + 'strvec_t_begin', + 'strvec_t_begin__SWIG_0', + 'strvec_t_begin__SWIG_1', + 'strvec_t_capacity', + 'strvec_t_clear', + 'strvec_t_empty', + 'strvec_t_end', + 'strvec_t_end__SWIG_0', + 'strvec_t_end__SWIG_1', + 'strvec_t_erase', + 'strvec_t_erase__SWIG_0', + 'strvec_t_erase__SWIG_1', + 'strvec_t_extract', + 'strvec_t_front', + 'strvec_t_front__SWIG_0', + 'strvec_t_front__SWIG_1', + 'strvec_t_grow', + 'strvec_t_inject', + 'strvec_t_insert', + 'strvec_t_pop_back', + 'strvec_t_push_back', + 'strvec_t_push_back__SWIG_0', + 'strvec_t_push_back__SWIG_1', + 'strvec_t_qclear', + 'strvec_t_reserve', + 'strvec_t_resize', + 'strvec_t_resize__SWIG_0', + 'strvec_t_resize__SWIG_1', + 'strvec_t_size', + 'strvec_t_swap', + 'strvec_t_truncate', + 'strwinsetup_t_display_only_existing_strings_get', + 'strwinsetup_t_display_only_existing_strings_set', + 'strwinsetup_t_ea1_get', + 'strwinsetup_t_ea1_set', + 'strwinsetup_t_ea2_get', + 'strwinsetup_t_ea2_set', + 'strwinsetup_t_ignore_heads_get', + 'strwinsetup_t_ignore_heads_set', + 'strwinsetup_t_is_initialized', + 'strwinsetup_t_minlen_get', + 'strwinsetup_t_minlen_set', + 'strwinsetup_t_only_7bit_get', + 'strwinsetup_t_only_7bit_set', + 'strwinsetup_t_strtypes_get', + 'strwinsetup_t_strtypes_set', + 'suspend_process', + 'suspend_thread', + 'sval_pointer_assign', + 'sval_pointer_cast', + 'sval_pointer_frompointer', + 'sval_pointer_value', + 'switch_info_ex_t_assign', + 'switch_info_ex_t_create', + 'switch_info_ex_t_destroy', + 'switch_info_ex_t_get_custom', + 'switch_info_ex_t_get_defjump', + 'switch_info_ex_t_get_elbase', + 'switch_info_ex_t_get_flags', + 'switch_info_ex_t_get_flags2', + 'switch_info_ex_t_get_ind_lowcase', + 'switch_info_ex_t_get_jcases', + 'switch_info_ex_t_get_jumps', + 'switch_info_ex_t_get_ncases', + 'switch_info_ex_t_get_regdtyp', + 'switch_info_ex_t_get_regnum', + 'switch_info_ex_t_get_startea', + 'switch_info_ex_t_get_values_lowcase', + 'switch_info_ex_t_set_custom', + 'switch_info_ex_t_set_defjump', + 'switch_info_ex_t_set_elbase', + 'switch_info_ex_t_set_flags', + 'switch_info_ex_t_set_flags2', + 'switch_info_ex_t_set_ind_lowcase', + 'switch_info_ex_t_set_jcases', + 'switch_info_ex_t_set_jumps', + 'switch_info_ex_t_set_ncases', + 'switch_info_ex_t_set_regdtyp', + 'switch_info_ex_t_set_regnum', + 'switch_info_ex_t_set_startea', + 'switch_info_ex_t_set_values_lowcase', + 'switchto_tform', + 'tag_addr', + 'tag_advance', + 'tag_remove', + 'tag_skipcode', + 'tag_skipcodes', + 'tag_strlen', + 'take_database_snapshot', + 'take_memory_snapshot', + 'tbytflag', + 'term_hexrays_plugin', + 'term_output_buffer', + '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', + 'text_options_t_copy_from_inf', + 'text_options_t_copy_to_inf', + 'text_options_t_graph_get', + 'text_options_t_graph_set', + 'text_options_t_text_get', + 'text_options_t_text_set', + 'text_sink_t__print', + 'textctrl_info_t_assign', + 'textctrl_info_t_create', + 'textctrl_info_t_destroy', + 'textctrl_info_t_get_clink', + 'textctrl_info_t_get_clink_ptr', + 'textctrl_info_t_get_flags', + 'textctrl_info_t_get_tabsize', + 'textctrl_info_t_get_text', + 'textctrl_info_t_set_flags', + 'textctrl_info_t_set_tabsize', + 'textctrl_info_t_set_text', + 'tid_array___getitem__', + 'tid_array___setitem__', + 'tid_array_cast', + 'tid_array_frompointer', + 'til2idb', + 'til_symbol_t_name_get', + 'til_symbol_t_name_set', + 'til_symbol_t_til_get', + 'til_symbol_t_til_set', + 'til_t_base', + 'til_t_cc_get', + 'til_t_cc_set', + 'til_t_desc_get', + 'til_t_desc_set', + 'til_t_flags_get', + 'til_t_flags_set', + 'til_t_is_dirty', + 'til_t_name_get', + 'til_t_name_set', + 'til_t_nbases_get', + 'til_t_nbases_set', + 'til_t_nrefs_get', + 'til_t_nrefs_set', + 'til_t_nstreams_get', + 'til_t_nstreams_set', + 'til_t_set_dirty', + 'til_t_streams_get', + 'til_t_streams_set', + 'tinfo_t___eq__', + 'tinfo_t___ge__', + 'tinfo_t___gt__', + 'tinfo_t___le__', + 'tinfo_t___lt__', + 'tinfo_t___ne__', + 'tinfo_t___str__', + 'tinfo_t__print', + 'tinfo_t_calc_purged_bytes', + 'tinfo_t_calc_score', + 'tinfo_t_calc_udt_aligns', + 'tinfo_t_change_sign', + 'tinfo_t_clear', + 'tinfo_t_clr_const', + 'tinfo_t_clr_const_volatile', + 'tinfo_t_clr_volatile', + 'tinfo_t_compare', + 'tinfo_t_compare_with', + 'tinfo_t_convert_array_to_ptr', + 'tinfo_t_create_array', + 'tinfo_t_create_array__SWIG_0', + 'tinfo_t_create_array__SWIG_1', + 'tinfo_t_create_bitfield', + 'tinfo_t_create_bitfield__SWIG_0', + 'tinfo_t_create_bitfield__SWIG_1', + 'tinfo_t_create_enum', + 'tinfo_t_create_forward_decl', + 'tinfo_t_create_func', + 'tinfo_t_create_ptr', + 'tinfo_t_create_ptr__SWIG_0', + 'tinfo_t_create_ptr__SWIG_1', + 'tinfo_t_create_simple_type', + 'tinfo_t_create_typedef', + 'tinfo_t_create_typedef__SWIG_0', + 'tinfo_t_create_typedef__SWIG_1', + 'tinfo_t_create_typedef__SWIG_2', + 'tinfo_t_create_udt', + 'tinfo_t_del_attr', + 'tinfo_t_del_attrs', + 'tinfo_t_deserialize', + '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', + 'tinfo_t_find_udt_member', + 'tinfo_t_get_array_details', + 'tinfo_t_get_array_element', + 'tinfo_t_get_array_nelems', + 'tinfo_t_get_attr', + 'tinfo_t_get_attrs', + 'tinfo_t_get_bitfield_details', + 'tinfo_t_get_declalign', + 'tinfo_t_get_decltype', + 'tinfo_t_get_enum_base_type', + 'tinfo_t_get_enum_details', + 'tinfo_t_get_final_ordinal', + 'tinfo_t_get_final_type_name', + 'tinfo_t_get_func_details', + 'tinfo_t_get_modifiers', + 'tinfo_t_get_named_type', + 'tinfo_t_get_nargs', + 'tinfo_t_get_next_type_name', + 'tinfo_t_get_nth_arg', + 'tinfo_t_get_numbered_type', + 'tinfo_t_get_onemember_type', + 'tinfo_t_get_ordinal', + 'tinfo_t_get_pointed_object', + 'tinfo_t_get_ptr_details', + 'tinfo_t_get_ptrarr_object', + 'tinfo_t_get_ptrarr_objsize', + 'tinfo_t_get_realtype', + 'tinfo_t_get_rettype', + 'tinfo_t_get_sign', + 'tinfo_t_get_size', + 'tinfo_t_get_stock', + 'tinfo_t_get_til', + 'tinfo_t_get_type_name', + 'tinfo_t_get_udt_details', + 'tinfo_t_get_udt_nmembers', + 'tinfo_t_get_unpadded_size', + 'tinfo_t_has_details', + 'tinfo_t_is_arithmetic', + 'tinfo_t_is_array', + 'tinfo_t_is_bitfield', + 'tinfo_t_is_bool', + 'tinfo_t_is_castable_to', + 'tinfo_t_is_char', + 'tinfo_t_is_complex', + 'tinfo_t_is_const', + 'tinfo_t_is_correct', + 'tinfo_t_is_decl_array', + 'tinfo_t_is_decl_bitfield', + 'tinfo_t_is_decl_bool', + 'tinfo_t_is_decl_char', + 'tinfo_t_is_decl_complex', + 'tinfo_t_is_decl_const', + 'tinfo_t_is_decl_double', + 'tinfo_t_is_decl_enum', + 'tinfo_t_is_decl_float', + 'tinfo_t_is_decl_floating', + 'tinfo_t_is_decl_func', + 'tinfo_t_is_decl_int128', + 'tinfo_t_is_decl_int16', + 'tinfo_t_is_decl_int32', + 'tinfo_t_is_decl_int64', + 'tinfo_t_is_decl_last', + 'tinfo_t_is_decl_ldouble', + 'tinfo_t_is_decl_paf', + 'tinfo_t_is_decl_partial', + 'tinfo_t_is_decl_ptr', + 'tinfo_t_is_decl_struct', + 'tinfo_t_is_decl_sue', + 'tinfo_t_is_decl_typedef', + 'tinfo_t_is_decl_uchar', + 'tinfo_t_is_decl_udt', + 'tinfo_t_is_decl_uint', + 'tinfo_t_is_decl_uint128', + 'tinfo_t_is_decl_uint16', + 'tinfo_t_is_decl_uint32', + 'tinfo_t_is_decl_uint64', + 'tinfo_t_is_decl_union', + 'tinfo_t_is_decl_unknown', + 'tinfo_t_is_decl_void', + 'tinfo_t_is_decl_volatile', + 'tinfo_t_is_double', + 'tinfo_t_is_empty_udt', + 'tinfo_t_is_enum', + 'tinfo_t_is_ext_arithmetic', + 'tinfo_t_is_ext_integral', + 'tinfo_t_is_float', + 'tinfo_t_is_floating', + 'tinfo_t_is_forward_decl', + 'tinfo_t_is_from_subtil', + 'tinfo_t_is_func', + 'tinfo_t_is_funcptr', + 'tinfo_t_is_high_func', + 'tinfo_t_is_int128', + 'tinfo_t_is_int16', + 'tinfo_t_is_int32', + 'tinfo_t_is_int64', + 'tinfo_t_is_integral', + 'tinfo_t_is_ldouble', + 'tinfo_t_is_manually_castable_to', + 'tinfo_t_is_one_fpval', + 'tinfo_t_is_paf', + 'tinfo_t_is_partial', + 'tinfo_t_is_ptr', + 'tinfo_t_is_ptr_or_array', + 'tinfo_t_is_purging_cc', + 'tinfo_t_is_pvoid', + 'tinfo_t_is_scalar', + '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_typeref', + 'tinfo_t_is_uchar', + 'tinfo_t_is_udt', + 'tinfo_t_is_uint', + 'tinfo_t_is_uint128', + 'tinfo_t_is_uint16', + 'tinfo_t_is_uint32', + 'tinfo_t_is_uint64', + 'tinfo_t_is_union', + 'tinfo_t_is_unknown', + 'tinfo_t_is_unsigned', + 'tinfo_t_is_user_cc', + 'tinfo_t_is_vararg_cc', + '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_serialize', + 'tinfo_t_set_attr', + 'tinfo_t_set_attrs', + 'tinfo_t_set_const', + 'tinfo_t_set_declalign', + 'tinfo_t_set_modifiers', + 'tinfo_t_set_numbered_type', + 'tinfo_t_set_volatile', + 'tinfo_t_swap', + 'tinfo_t_write_bitfield_value', + 'tinfo_visitor_t_apply_to', + 'tinfo_visitor_t_prune_now', + 'tinfo_visitor_t_state_get', + 'tinfo_visitor_t_state_set', + 'tinfo_visitor_t_visit_type', + 'toEA', + 'toggle_bnot', + 'toggle_lzero', + 'toggle_sign', + 'treeloc_t___eq__', + 'treeloc_t___lt__', + 'treeloc_t_ea_get', + 'treeloc_t_ea_set', + 'treeloc_t_itp_get', + 'treeloc_t_itp_set', + 'tribyteflag', + 'try_to_add_libfunc', + 'twinpos_t___eq__', + 'twinpos_t___ne__', + 'twinpos_t_at_get', + 'twinpos_t_at_set', + 'twinpos_t_x_get', + 'twinpos_t_x_set', + 'type_attr_t_key_get', + 'type_attr_t_key_set', + 'type_attr_t_value_get', + 'type_attr_t_value_set', + 'type_mapper_t_map_type', + 'type_mods_t_clear', + 'type_mods_t_cmt_get', + 'type_mods_t_cmt_set', + 'type_mods_t_flags_get', + 'type_mods_t_flags_set', + 'type_mods_t_has_cmt', + 'type_mods_t_has_info', + 'type_mods_t_has_name', + 'type_mods_t_has_type', + 'type_mods_t_name_get', + 'type_mods_t_name_set', + 'type_mods_t_set_new_cmt', + 'type_mods_t_set_new_name', + 'type_mods_t_set_new_type', + 'type_mods_t_type_get', + 'type_mods_t_type_set', + 'type_pair_t_type1_get', + 'type_pair_t_type1_set', + 'type_pair_t_type2_get', + 'type_pair_t_type2_set', + 'type_visitor_t_visit_type', + 'typedef_type_data_t_is_ordref_get', + 'typedef_type_data_t_is_ordref_set', + 'typedef_type_data_t_resolve_get', + 'typedef_type_data_t_resolve_set', + 'typedef_type_data_t_swap', + 'typedef_type_data_t_til_get', + 'typedef_type_data_t_til_set', + 'typeflag', + 'ua_add_cref', + 'ua_add_dref', + 'ua_add_off_drefs', + 'ua_add_off_drefs2', + 'ua_ana0', + 'ua_code', + 'ua_dodata', + 'ua_dodata2', + 'ua_mnem', + 'ua_next_byte', + 'ua_next_long', + 'ua_next_qword', + 'ua_next_word', + 'ua_outop', + 'ua_outop2', + 'ua_stkvar2', + 'uchar_array___getitem__', + 'uchar_array___setitem__', + 'uchar_array_cast', + 'uchar_array_frompointer', + 'udt_member_t___eq__', + 'udt_member_t___lt__', + 'udt_member_t___ne__', + 'udt_member_t_begin', + 'udt_member_t_clr_baseclass', + 'udt_member_t_clr_unaligned', + 'udt_member_t_clr_virtbase', + 'udt_member_t_cmt_get', + 'udt_member_t_cmt_set', + 'udt_member_t_effalign_get', + 'udt_member_t_effalign_set', + 'udt_member_t_end', + 'udt_member_t_fda_get', + 'udt_member_t_fda_set', + 'udt_member_t_is_baseclass', + 'udt_member_t_is_bitfield', + 'udt_member_t_is_unaligned', + 'udt_member_t_is_virtbase', + 'udt_member_t_is_zero_bitfield', + 'udt_member_t_name_get', + 'udt_member_t_name_set', + 'udt_member_t_offset_get', + 'udt_member_t_offset_set', + 'udt_member_t_set_baseclass', + 'udt_member_t_set_unaligned', + 'udt_member_t_set_virtbase', + 'udt_member_t_size_get', + 'udt_member_t_size_set', + 'udt_member_t_swap', + 'udt_member_t_tafld_bits_get', + 'udt_member_t_tafld_bits_set', + 'udt_member_t_type_get', + 'udt_member_t_type_set', + 'udt_type_data_t_effalign_get', + 'udt_type_data_t_effalign_set', + 'udt_type_data_t_is_cppobj', + 'udt_type_data_t_is_msstruct', + 'udt_type_data_t_is_unaligned', + 'udt_type_data_t_is_union_get', + 'udt_type_data_t_is_union_set', + 'udt_type_data_t_pack_get', + 'udt_type_data_t_pack_set', + 'udt_type_data_t_sda_get', + 'udt_type_data_t_sda_set', + 'udt_type_data_t_swap', + 'udt_type_data_t_taudt_bits_get', + 'udt_type_data_t_taudt_bits_set', + 'udt_type_data_t_total_size_get', + 'udt_type_data_t_total_size_set', + 'udt_type_data_t_unpadded_size_get', + 'udt_type_data_t_unpadded_size_set', + 'udtmembervec_t___eq__', + 'udtmembervec_t___getitem__', + 'udtmembervec_t___len__', + 'udtmembervec_t___ne__', + 'udtmembervec_t___setitem__', + 'udtmembervec_t__del', + 'udtmembervec_t_add_unique', + 'udtmembervec_t_at', + 'udtmembervec_t_back', + 'udtmembervec_t_back__SWIG_0', + 'udtmembervec_t_back__SWIG_1', + 'udtmembervec_t_begin', + 'udtmembervec_t_begin__SWIG_0', + 'udtmembervec_t_begin__SWIG_1', + 'udtmembervec_t_capacity', + 'udtmembervec_t_clear', + 'udtmembervec_t_empty', + 'udtmembervec_t_end', + 'udtmembervec_t_end__SWIG_0', + 'udtmembervec_t_end__SWIG_1', + 'udtmembervec_t_erase', + 'udtmembervec_t_erase__SWIG_0', + 'udtmembervec_t_erase__SWIG_1', + 'udtmembervec_t_extract', + 'udtmembervec_t_find', + 'udtmembervec_t_find__SWIG_0', + 'udtmembervec_t_find__SWIG_1', + 'udtmembervec_t_front', + 'udtmembervec_t_front__SWIG_0', + 'udtmembervec_t_front__SWIG_1', + 'udtmembervec_t_grow', + 'udtmembervec_t_has', + 'udtmembervec_t_inject', + 'udtmembervec_t_insert', + 'udtmembervec_t_pop_back', + 'udtmembervec_t_push_back', + 'udtmembervec_t_push_back__SWIG_0', + 'udtmembervec_t_push_back__SWIG_1', + 'udtmembervec_t_qclear', + 'udtmembervec_t_reserve', + 'udtmembervec_t_resize', + 'udtmembervec_t_resize__SWIG_0', + 'udtmembervec_t_resize__SWIG_1', + 'udtmembervec_t_size', + 'udtmembervec_t_swap', + 'udtmembervec_t_truncate', + 'ui_load_new_file', + 'ui_run_debugger', + 'umsg', + 'unhide_border', + 'unhide_item', + 'unmark_selection', + 'unpack_idcobj_from_bv', + 'unpack_idcobj_from_idb', + 'unpack_object_from_bv', + 'unpack_object_from_idb', + 'unregister_action', + 'unregister_custom_data_format', + 'unregister_custom_data_type', + 'unregister_timer', + 'update_action_checkable', + 'update_action_checked', + 'update_action_icon', + 'update_action_label', + 'update_action_shortcut', + 'update_action_state', + 'update_action_tooltip', + 'update_action_visibility', + 'update_bpt', + 'update_extra_cmt', + 'update_fpd', + 'update_func', + 'update_hidden_area', + 'update_segm', + 'user_cmts_begin', + 'user_cmts_clear', + 'user_cmts_end', + 'user_cmts_erase', + 'user_cmts_find', + 'user_cmts_first', + 'user_cmts_free', + 'user_cmts_insert', + 'user_cmts_iterator_t___eq__', + 'user_cmts_iterator_t___ne__', + 'user_cmts_iterator_t_x_get', + 'user_cmts_iterator_t_x_set', + 'user_cmts_new', + 'user_cmts_next', + 'user_cmts_prev', + 'user_cmts_second', + 'user_cmts_size', + 'user_cmts_t_at', + 'user_cmts_t_size', + 'user_iflags_begin', + 'user_iflags_clear', + 'user_iflags_end', + 'user_iflags_erase', + 'user_iflags_find', + 'user_iflags_first', + 'user_iflags_free', + 'user_iflags_insert', + 'user_iflags_iterator_t___eq__', + 'user_iflags_iterator_t___ne__', + 'user_iflags_iterator_t_x_get', + 'user_iflags_iterator_t_x_set', + 'user_iflags_new', + 'user_iflags_next', + 'user_iflags_prev', + 'user_iflags_second', + 'user_iflags_size', + 'user_iflags_t_at', + 'user_iflags_t_size', + 'user_labels_begin', + 'user_labels_clear', + 'user_labels_end', + 'user_labels_erase', + 'user_labels_find', + 'user_labels_first', + 'user_labels_free', + 'user_labels_insert', + 'user_labels_iterator_t___eq__', + 'user_labels_iterator_t___ne__', + 'user_labels_iterator_t_x_get', + 'user_labels_iterator_t_x_set', + 'user_labels_new', + 'user_labels_next', + 'user_labels_prev', + 'user_labels_second', + 'user_labels_size', + 'user_labels_t_at', + 'user_labels_t_size', + 'user_lvar_modifier_t_modify_lvars', + 'user_numforms_begin', + 'user_numforms_clear', + 'user_numforms_end', + 'user_numforms_erase', + 'user_numforms_find', + 'user_numforms_first', + 'user_numforms_free', + 'user_numforms_insert', + 'user_numforms_iterator_t___eq__', + 'user_numforms_iterator_t___ne__', + 'user_numforms_iterator_t_x_get', + 'user_numforms_iterator_t_x_set', + 'user_numforms_new', + 'user_numforms_next', + 'user_numforms_prev', + 'user_numforms_second', + 'user_numforms_size', + 'user_numforms_t_at', + 'user_numforms_t_size', + 'user_unions_begin', + 'user_unions_clear', + 'user_unions_end', + 'user_unions_erase', + 'user_unions_find', + 'user_unions_first', + 'user_unions_free', + 'user_unions_insert', + 'user_unions_iterator_t___eq__', + 'user_unions_iterator_t___ne__', + 'user_unions_iterator_t_x_get', + 'user_unions_iterator_t_x_set', + 'user_unions_new', + 'user_unions_next', + 'user_unions_prev', + 'user_unions_second', + 'user_unions_size', + 'user_unions_t_at', + 'user_unions_t_size', + 'uses_modsp', + 'uval_array___getitem__', + '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_back', + 'uvalvec_t_back__SWIG_0', + 'uvalvec_t_back__SWIG_1', + '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_front', + 'uvalvec_t_front__SWIG_0', + 'uvalvec_t_front__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', + 'validate_name2', + 'validate_name3', + 'valstr_t_info_get', + 'valstr_t_info_set', + 'valstr_t_length_get', + 'valstr_t_length_set', + 'valstr_t_members_get', + 'valstr_t_members_set', + 'valstr_t_oneline_get', + 'valstr_t_oneline_set', + 'valstr_t_props_get', + 'valstr_t_props_set', + 'var_ref_t___eq__', + 'var_ref_t___ge__', + 'var_ref_t___gt__', + 'var_ref_t___le__', + 'var_ref_t___lt__', + 'var_ref_t___ne__', + 'var_ref_t_compare', + 'var_ref_t_idx_get', + 'var_ref_t_idx_set', + 'var_ref_t_mba_get', + 'var_ref_t_mba_set', + 'varloc_t__consume_scattered', + 'varloc_t__set_badloc', + 'varloc_t__set_reg1', + 'varloc_t__set_reg2', + 'varloc_t__set_stkoff', + 'varloc_t_advance', + 'varloc_t_calc_offset', + 'varloc_t_consume_scattered', + 'varloc_t_get_value', + 'varloc_t_is_badloc', + 'varloc_t_is_fragmented', + 'varloc_t_is_reg', + 'varloc_t_is_reg1', + 'varloc_t_is_reg2', + 'varloc_t_is_scattered', + 'varloc_t_is_stkoff', + 'varloc_t_reg1', + 'varloc_t_reg2', + 'varloc_t_regoff', + 'varloc_t_scattered', + 'varloc_t_scattered__SWIG_0', + 'varloc_t_scattered__SWIG_1', + 'varloc_t_set_badloc', + 'varloc_t_set_reg1', + 'varloc_t_set_reg2', + 'varloc_t_set_stkoff', + 'varloc_t_stkoff', + 'varloc_t_swap', + 'varloc_t_type', + 'varpart_t_bad_offset', + 'varpart_t_bad_size', + 'varpart_t_off_get', + 'varpart_t_off_set', + 'varpart_t_size_get', + 'varpart_t_size_set', + 'vaskqstr', + 'vc_printer_t_func_get', + 'vc_printer_t_func_set', + 'vc_printer_t_lastchar_get', + 'vc_printer_t_lastchar_set', + 'vc_printer_t_oneliner', + 'vcall_helper', + 'vcreate_helper', + 'vd_failure_t_desc', + 'vd_failure_t_hf_get', + 'vd_failure_t_hf_set', + 'vd_printer_t__print', + 'vd_printer_t__print__varargs__', + 'vd_printer_t_hdrlines_get', + 'vd_printer_t_hdrlines_set', + 'vdloc_t__set_reg1', + 'vdloc_t_reg1', + 'vdloc_t_set_reg1', + 'vdui_t_calc_cmt_type', + 'vdui_t_cfunc_get', + 'vdui_t_cfunc_set', + 'vdui_t_clear', + 'vdui_t_collapse_item', + 'vdui_t_collapse_lvars', + 'vdui_t_cpos_get', + 'vdui_t_cpos_set', + 'vdui_t_ct_get', + 'vdui_t_ct_set', + 'vdui_t_ctree_to_disasm', + 'vdui_t_cv_get', + 'vdui_t_cv_set', + 'vdui_t_del_orphan_cmts', + 'vdui_t_edit_cmt', + 'vdui_t_edit_func_cmt', + 'vdui_t_flags_get', + 'vdui_t_flags_set', + 'vdui_t_form_get', + 'vdui_t_form_set', + 'vdui_t_get_current_item', + 'vdui_t_get_current_label', + 'vdui_t_get_number', + 'vdui_t_head_get', + 'vdui_t_head_set', + 'vdui_t_in_ctree', + 'vdui_t_invert_bits', + 'vdui_t_invert_sign', + 'vdui_t_item_get', + 'vdui_t_item_set', + 'vdui_t_jump_enter', + 'vdui_t_last_code_get', + 'vdui_t_last_code_set', + 'vdui_t_locked', + 'vdui_t_map_lvar', + 'vdui_t_mba_get', + 'vdui_t_mba_set', + 'vdui_t_refresh_cpos', + 'vdui_t_refresh_ctext', + 'vdui_t_refresh_view', + 'vdui_t_rename_global', + 'vdui_t_rename_label', + 'vdui_t_rename_lvar', + 'vdui_t_rename_strmem', + 'vdui_t_set_global_type', + 'vdui_t_set_locked', + 'vdui_t_set_lvar_cmt', + 'vdui_t_set_lvar_type', + 'vdui_t_set_num_enum', + 'vdui_t_set_num_radix', + 'vdui_t_set_num_stroff', + 'vdui_t_set_strmem_type', + 'vdui_t_set_valid', + 'vdui_t_set_visible', + 'vdui_t_split_item', + 'vdui_t_switch_to', + 'vdui_t_tail_get', + 'vdui_t_tail_set', + 'vdui_t_ui_edit_lvar_cmt', + 'vdui_t_ui_map_lvar', + 'vdui_t_ui_rename_lvar', + 'vdui_t_ui_set_lvar_type', + 'vdui_t_ui_unmap_lvar', + 'vdui_t_valid', + 'vdui_t_view_idx_get', + 'vdui_t_view_idx_set', + 'vdui_t_visible', + 'verify_argloc', + 'verify_tinfo', + 'verify_varloc', + 'vinterr', + 'visit_patched_bytes', + 'visit_stroff_fields', + 'visit_subtypes', + 'vloc_visitor_t_visit_location', + 'vumsg', + 'wait_for_next_event', + 'warning', + 'warning__varargs__', + 'wasBreak', + 'was_ida_decision', + 'wordflag', + 'write_dbg_memory', + 'write_tinfo_bitfield_value', + 'writebytes', + 'xrefblk_t_first_from', + 'xrefblk_t_first_to', + 'xrefblk_t_frm_get', + 'xrefblk_t_frm_set', + 'xrefblk_t_iscode_get', + 'xrefblk_t_iscode_set', + 'xrefblk_t_next_from', + 'xrefblk_t_next_from__SWIG_0', + 'xrefblk_t_next_from__SWIG_1', + 'xrefblk_t_next_to', + 'xrefblk_t_next_to__SWIG_0', + 'xrefblk_t_next_to__SWIG_1', + 'xrefblk_t_to_get', + 'xrefblk_t_to_set', + 'xrefblk_t_type_get', + 'xrefblk_t_type_set', + 'xrefblk_t_user_get', + 'xrefblk_t_user_set', + 'xrefchar', + 'xreflist_entry_t___eq__', + 'xreflist_entry_t___ne__', + 'xreflist_entry_t_ea_get', + 'xreflist_entry_t_ea_set', + 'xreflist_entry_t_opnum_get', + 'xreflist_entry_t_opnum_set', + 'xreflist_entry_t_type_get', + 'xreflist_entry_t_type_set', + 'xreflist_t___eq__', + 'xreflist_t___getitem__', + 'xreflist_t___len__', + 'xreflist_t___ne__', + 'xreflist_t___setitem__', + 'xreflist_t__del', + 'xreflist_t_add_unique', + 'xreflist_t_at', + 'xreflist_t_back', + 'xreflist_t_back__SWIG_0', + 'xreflist_t_back__SWIG_1', + 'xreflist_t_begin', + 'xreflist_t_begin__SWIG_0', + 'xreflist_t_begin__SWIG_1', + 'xreflist_t_capacity', + 'xreflist_t_clear', + 'xreflist_t_empty', + 'xreflist_t_end', + 'xreflist_t_end__SWIG_0', + 'xreflist_t_end__SWIG_1', + 'xreflist_t_erase', + 'xreflist_t_erase__SWIG_0', + 'xreflist_t_erase__SWIG_1', + 'xreflist_t_extract', + 'xreflist_t_find', + 'xreflist_t_find__SWIG_0', + 'xreflist_t_find__SWIG_1', + 'xreflist_t_front', + 'xreflist_t_front__SWIG_0', + 'xreflist_t_front__SWIG_1', + 'xreflist_t_grow', + 'xreflist_t_has', + 'xreflist_t_inject', + 'xreflist_t_insert', + 'xreflist_t_pop_back', + 'xreflist_t_push_back', + 'xreflist_t_push_back__SWIG_0', + 'xreflist_t_push_back__SWIG_1', + 'xreflist_t_qclear', + 'xreflist_t_reserve', + 'xreflist_t_resize', + 'xreflist_t_resize__SWIG_0', + 'xreflist_t_resize__SWIG_1', + 'xreflist_t_size', + 'xreflist_t_swap', + 'xreflist_t_truncate', + 'ywrdflag', + 'zwrdflag']} \ No newline at end of file diff --git a/build.py b/build.py old mode 100644 new mode 100755 index aebd330..5f07f7b --- a/build.py +++ b/build.py @@ -9,41 +9,20 @@ # For detailed copyright information see the file COPYING in # the root of the distribution archive. #--------------------------------------------------------------------- -# build.py - Custom build script +# build.py - Makefile wrapper script #--------------------------------------------------------------------- -import os -import platform -import shutil -import sys -import types -import zipfile -import glob -from distutils import sysconfig +import os, argparse -from argparse import ArgumentParser, RawTextHelpFormatter - -# Start of user configurable options -IDA_MAJOR_VERSION = 6 -IDA_MINOR_VERSION = 8 - -IDA_SDK = "" -if 'IDA' in os.environ: - IDA_SDK = os.environ['IDA'] -else: - candidate = os.path.join("..", "..", "include") - if os.path.exists(candidate): - IDA_SDK = candidate - -parser = ArgumentParser(epilog=""" -Since a very specific version of SWiG is expected in order to produce reliable -bindings, and if your platform doesn't provide that version by default and you +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. -For example, this is how to build against IDA 6.8 on linux, with a SWiG 2.0.12 +For example, this is how to build against IDA 6.9 on linux, with a SWiG 2.0.12 installation located in /opt/my-swig/: -python build.py --ida-sdk /path/to/idasdk68/ \\ +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 @@ -55,565 +34,46 @@ Notes: to the '.../2.0.12/python/' subdirectory should be placed before the more global '.../2.0.12/' directory. """, - formatter_class=RawTextHelpFormatter) -parser.add_argument("--ida-sdk", type=str, help="Path to the IDA SDK", default=IDA_SDK) -parser.add_argument("--swig-bin", type=str, help="Path to the SWIG binary", default="") -parser.add_argument("--swig-inc", type=str, help="Path(s) to the SWIG includes directory(ies)", default="") + 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("--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("--ea64", help="Build 64-bit EA version of the plugin", default=False, action="store_true") parser.add_argument("--debug", help="Build debug version of the plugin", default=False, action="store_true") +parser.add_argument("--python-home", help="Python home, where the 'include' directory can be found", default=None) parser.add_argument("-v", "--verbose", help="Verbose mode", default=False, action="store_true") args = parser.parse_args() -IDA_SDK = args.ida_sdk -assert os.path.exists(IDA_SDK), "Could not find IDA SDK include path (looked in: \"%s\")" % IDA_SDK +_probe = os.path.join("..", "..", "include", "pro.h") +assert os.path.exists(_probe), "Could not find IDA SDK include path (looked for: \"%s\")" % _probe -SWIG_BIN = args.swig_bin or "swig" -SWIG_INC = [] -if args.swig_inc: - SWIG_INC = map(lambda p: "-I%s" % p, args.swig_inc.split(os.pathsep)) -# End of user configurable options - -# IDAPython version -VERSION_MAJOR = 1 -VERSION_MINOR = 7 -VERSION_PATCH = 2 - -# Determine Python version -PYTHON_MAJOR_VERSION = int(platform.python_version()[0]) -PYTHON_MINOR_VERSION = int(platform.python_version()[2]) - -# Find Python headers -PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY') - -# Swig command-line parameters -SWIG_OPTIONS = ['-modern', '-python', '-threads', '-c++', '-w451', '-shadow', '-D__GNUC__'] -SWIG_OPTIONS.extend(SWIG_INC) - -# Common macros for all compilations -COMMON_MACROS = [ - ("VER_MAJOR", "%d" % VERSION_MAJOR), - ("VER_MINOR", "%d" % VERSION_MINOR), - ("VER_PATCH", "%d" % VERSION_PATCH), - "__IDP__", - ("MAXSTR", "1024"), - "USE_DANGEROUS_FUNCTIONS", - "USE_STANDARD_FILE_FUNCTIONS" ] - -# Common includes for all compilations -COMMON_INCLUDES = [ ".", "swig" ] - -# ----------------------------------------------------------------------- -# List files for the binary distribution -BINDIST_MANIFEST = [ - "README.md", - "COPYING.txt", - "CHANGES.txt", - "AUTHORS.txt", - "STATUS.txt", - "python.cfg", - "docs/notes.txt", - "examples/chooser.py", - "examples/colours.py", - "examples/ex_idphook_asm.py", - "examples/ex_uirequests.py", - "examples/debughook.py", - "examples/ex_cli.py", - "examples/ex1.idc", - "examples/ex_custdata.py", - "examples/ex1_idaapi.py", - "examples/ex1_idautils.py", - "examples/hotkey.py", - "examples/structure.py", - "examples/ex_gdl_qflow_chart.py", - "examples/ex_strings.py", - "examples/ex_actions.py", - "examples/ex_func_chooser.py", - "examples/ex_choose2.py", - "examples/ex_debug_names.py", - "examples/ex_graph.py", - "examples/ex_hotkey.py", - "examples/ex_patch.py", - "examples/ex_expr.py", - "examples/ex_timer.py", - "examples/ex_dbg.py", - "examples/ex_custview.py", - "examples/ex_prefix_plugin.py", - "examples/ex_pyside.py", - "examples/ex_pyqt.py", - "examples/ex_askusingform.py", - "examples/ex_uihook.py", - "examples/ex_idphook_asm.py", - "examples/ex_imports.py" -] - -# ----------------------------------------------------------------------- -# List files for the source distribution (appended to binary list) -SRCDIST_MANIFEST = [ - "BUILDING.txt", - "python.cpp", - "basetsd.h", - "build.py", - "python.cfg", - "swig/allins.i", - "swig/area.i", - "swig/auto.i", - "swig/bytes.i", - "swig/dbg.i", - "swig/diskio.i", - "swig/entry.i", - "swig/enum.i", - "swig/expr.i", - "swig/fixup.i", - "swig/frame.i", - "swig/funcs.i", - "swig/gdl.i", - "swig/ida.i", - "swig/idaapi.i", - "swig/idd.i", - "swig/idp.i", - "swig/ints.i", - "swig/kernwin.i", - "swig/lines.i", - "swig/loader.i", - "swig/moves.i", - "swig/nalt.i", - "swig/name.i", - "swig/netnode.i", - "swig/offset.i", - "swig/pro.i", - "swig/queue.i", - "swig/search.i", - "swig/segment.i", - "swig/srarea.i", - "swig/strlist.i", - "swig/struct.i", - "swig/typeconv.i", - "swig/typeinf.i", - "swig/ua.i", - "swig/xref.i", - "swig/graph.i", - "swig/fpro.i", - "swig/hexrays.i", -] - -def run(proc_argv): +def run(proc_argv, env=None): import subprocess if args.verbose: - print "Running subprocess with argv: %s" % proc_argv - subprocess.check_call(proc_argv) + print "Running subprocess with argv: %s (env=%s)" % (proc_argv, env) + subprocess.check_call(proc_argv, env=env) return 0 -# ----------------------------------------------------------------------- -class BuilderBase: - """ Base class for builders """ - def __init__(self): - pass - - - def compile(self, source, objectname=None, includes=[], macros=[]): - """ - Compile the source file - """ - allmacros = [] - allmacros.extend(COMMON_MACROS) - allmacros.extend(self.basemacros) - allmacros.extend(macros) - defines_argv = self._build_command_string(allmacros, self.define_directive) - - allincludes = [] - allincludes.extend(COMMON_INCLUDES) - allincludes.extend(includes) - includes_argv = self._build_command_string(allincludes, self.include_directive) - - if not objectname: - objectname = source + self.object_extension - - argv = [self.compiler] - argv.extend(self.compiler_parameters) - argv.extend(self.compiler_out_string(objectname)) - argv.extend(self.compiler_in_string(source + self.source_extension)) - argv.extend(includes_argv) - argv.extend(defines_argv) - return run(argv) - - - def link(self, objects, outfile, libpaths=[], libraries=[], extra_parameters=None): - """ Link the binary from objects and libraries """ - - argv = [self.linker] - argv.extend(self.linker_parameters) - argv.extend(self.linker_out_string(outfile)) - argv.extend(map(lambda o: o + self.object_extension, objects)) - argv.extend(map(lambda l: "%s%s" % (self.libpath_directive, l), libpaths)) - argv.extend(libraries) - argv.extend(extra_parameters) - return run(argv) - - - def _build_command_string(self, tokens, directive): - out = [] - for token in tokens: - if type(token) == types.TupleType: - out.append('%s%s=%s' % (directive, token[0], token[1])) - else: - out.append('%s%s' % (directive, token)) - return out - - -# ----------------------------------------------------------------------- -class GCCBuilder(BuilderBase): - """ Generic GCC compiler class """ - def __init__(self): - self.include_directive = "-I" - self.define_directive = "-D" - self.libpath_directive = "-L" - self.compiler_parameters = ["-m32", "-fpermissive", "-Wno-write-strings"] - self.linker_parameters = ["-m32", "-shared"] - self.basemacros = [ ] - self.compiler = "g++" - self.linker = "g++" - self.source_extension = ".cpp" - self.object_extension = ".o" - - def compiler_in_string(self, filename): - return ["-c", filename] - - def compiler_out_string(self, filename): - return ["-o", filename] - - def linker_out_string(self, filename): - return ["-o", filename] - - -# ----------------------------------------------------------------------- -class MSVCBuilder(BuilderBase): - """ Generic Visual C compiler class """ - def __init__(self): - self.include_directive = "/I" - self.define_directive = "/D" - self.libpath_directive = "/LIBPATH:" - self.compiler_parameters = ["/nologo", "/EHsc"] - self.linker_parameters = ["/nologo", "/dll", "/export:PLUGIN"] - self.basemacros = [ "WIN32", - "_USRDLL", - "__NT__" ] - self.compiler = "cl" - self.linker = "link" - self.source_extension = ".cpp" - self.object_extension = ".obj" - - def compiler_in_string(self, filename): - return ["/c", filename] - - def compiler_out_string(self, filename): - return ["/Fo%s" % filename] - - def linker_out_string(self, filename): - return ["/out:%s" % filename] - -# ----------------------------------------------------------------------- -def build_distribution(manifest, distrootdir, ea64, nukeold): - """ Create a distibution to a directory and a ZIP file """ - # (Re)create the output directory - if args.verbose: - print "Distribution is in: %s" % distrootdir - if nukeold and os.path.exists(distrootdir): - shutil.rmtree(distrootdir) - if not os.path.exists(distrootdir): - os.makedirs(distrootdir) - - # Also make a ZIP archive of the build - zippath = distrootdir + ".zip" - zip = zipfile.ZipFile(zippath, nukeold and "w" or "a", zipfile.ZIP_DEFLATED) - - # Copy files, one by one - for f in manifest: - if type(f) == types.TupleType: - srcfilepath = f[0] - srcfilename = os.path.basename(srcfilepath) - dstdir = os.path.join(distrootdir, f[1]) - dstfilepath = os.path.join(dstdir, srcfilename) - else: - srcfilepath = f - srcfilename = os.path.basename(f) - srcdir = os.path.dirname(f) - if srcdir == "": - dstdir = distrootdir - else: - dstdir = os.path.join(distrootdir, srcdir) - - if not os.path.exists(dstdir): - os.makedirs(dstdir) - - dstfilepath = os.path.join(dstdir, srcfilename) - shutil.copyfile(srcfilepath, dstfilepath) - zip.write(dstfilepath) - - zip.close() - - -# ----------------------------------------------------------------------- -def build_plugin( - platform, - idasdkdir, - plugin_name, - ea64): - """ Build the plugin from the SWIG wrapper and plugin main source """ - - global SWIG_OPTIONS - - # Get the arguments - with_hexrays = args.with_hexrays - - # Path to the IDA SDK headers - ida_include_directory = os.path.join(idasdkdir, "include") - - builder = None - # Platform-specific settings for the Linux build - if platform == "linux": - builder = GCCBuilder() - platform_macros = [ "__LINUX__" ] - python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "lib") - python_library = ["-Bdynamic", "-lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)] - ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_linux_gcc_64" or "x86_linux_gcc_32") - ida_lib = "" - extra_link_parameters = ["-s"] - builder.compiler_parameters.append("-O2") - # Platform-specific settings for the Windows build - elif platform == "win32": - builder = MSVCBuilder() - platform_macros = [ "__NT__" ] - python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "libs") - python_library = ["python%d%d.lib" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)] - ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_win_vc_64" or "x86_win_vc_32") - ida_lib = "ida.lib" - SWIG_OPTIONS.append("-D__NT__") - extra_link_parameters = [] - if not args.debug: - builder.compiler_parameters.append("-Ox") - # Platform-specific settings for the Mac OS X build - elif platform == "macosx": - builder = GCCBuilder() - builder.linker_parameters.append("-dynamiclib") - platform_macros = [ "__MAC__" ] - python_libpath = "." - python_library = ["-framework", "Python"] - ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_mac_gcc_64" or "x86_mac_gcc_32") - ida_lib = ea64 and "-lida64" or "-lida" - extra_link_parameters = ["-s"] - builder.compiler_parameters.append("-O3") - - assert builder, "Unknown platform! No idea how to build here..." - - # Enable EA64 for the compiler if necessary - if ea64: - platform_macros.append("__EA64__") - - # Build with Hex-Rays decompiler - if with_hexrays: - platform_macros.append("WITH_HEXRAYS") - SWIG_OPTIONS.append('-DWITH_HEXRAYS') - - platform_macros.append("NDEBUG") - - if not '--no-early-load' in sys.argv: - platform_macros.append("PLUGINFIX") - - # Turn off obsolete functions - #platform_macros.append("NO_OBSOLETE_FUNCS") - - # Build the wrapper from the interface files - swig_argv = [SWIG_BIN] - swig_argv.extend(SWIG_OPTIONS) - swig_argv.extend(["-Iswig", "-o", "idaapi.cpp"]) - if ea64: - swig_argv.append("-D__EA64__") - swig_argv.append("-I%s" % ida_include_directory) - swig_argv.append("idaapi.i") -# swigcmd = "%s %s -Iswig -o idaapi.cpp %s -I%s idaapi.i" % (SWIG_BIN, SWIG_OPTIONS, ea64flag, ida_include_directory) - res = run(swig_argv) - assert res == 0, "Failed to build the wrapper with SWIG" - - # If we are running on windows, we have to patch some directors' - # virtual methods, so they have the right calling convention. - # Without that, compilation just won't succeed. - if platform == "win32": - res = run(["python", "patch_directors_cc.py", "-f", "idaapi.h"]) - assert res == 0, "Failed to patch directors' calling conventions" - - # Compile the wrapper - res = builder.compile("idaapi", - includes=[ PYTHON_INCLUDE_DIRECTORY, ida_include_directory ], - macros=platform_macros) - assert res == 0, "Failed to build the wrapper module" - - # Compile the main plugin source - res = builder.compile("python", - includes=[ PYTHON_INCLUDE_DIRECTORY, ida_include_directory ], - macros=platform_macros) - assert res == 0, "Failed to build the main plugin object" - - # Link the final binary - libs = [] - libs.extend(python_library) - libs.append(ida_lib) - res = builder.link( ["idaapi", "python"], - plugin_name, - [ python_libpath, ida_libpath ], - libs, - extra_link_parameters) - assert res == 0, "Failed to link the plugin binary" - -# ----------------------------------------------------------------------- -def detect_platform(ea64): - # Detect the platform - system = platform.system() - - if system == "Windows" or system == "Microsoft": - system = "Windows" - platform_string = "win32" - plugin_name = ea64 and "python.p64" or "python.plw" - - elif system == "Linux": - platform_string = "linux" - plugin_name = ea64 and "python.plx64" or "python.plx" - - elif system == "Darwin": - platform_string = "macosx" - plugin_name = ea64 and "python.pmc64" or "python.pmc" - else: - print "Unknown platform!" - sys.exit(-1) - - return (system, platform_string, plugin_name) - -# ----------------------------------------------------------------------- -def build_binary_package(ea64, nukeold): - system, platform_string, plugin_name = detect_platform(ea64) - BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR, - VERSION_MINOR, - VERSION_PATCH, - IDA_MAJOR_VERSION, - IDA_MINOR_VERSION, - PYTHON_MAJOR_VERSION, - PYTHON_MINOR_VERSION, - platform_string) - # Build the plugin - build_plugin(platform_string, IDA_SDK, plugin_name, ea64) - - # Build the binary distribution - binmanifest = [] - if nukeold: - binmanifest.extend(BINDIST_MANIFEST) - - if not ea64 or nukeold: - binmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py", "idaapi.py"]) - - binmanifest.append((plugin_name, "plugins")) - - build_distribution(binmanifest, BINDISTDIR, ea64, nukeold) - - -# ----------------------------------------------------------------------- -def build_source_package(): - """ Build a directory and a ZIP file with all the sources """ - SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR, - VERSION_MINOR, - VERSION_PATCH) - # Build the source distribution - srcmanifest = [] - srcmanifest.extend(BINDIST_MANIFEST) - srcmanifest.extend(SRCDIST_MANIFEST) - srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"]) - build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True) - -# ----------------------------------------------------------------------- -def gen_docs(z = False): - print "Generating documentation....." - old_dir = os.getcwd() - try: - curdir = os.getcwd() + os.sep - docdir = 'idapython-reference-%d.%d.%d' % (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH) - sys.path.append(curdir + 'python') - sys.path.append(curdir + 'tools') - sys.path.append(curdir + 'docs') - import epydoc.cli - import swigdocs - os.chdir('docs') - PYWRAPS_FN = 'pywraps' - swigdocs.gen_docs(outfn = PYWRAPS_FN + '.py') - epydoc.cli.optparse.sys.argv = [ 'epydoc', - '--no-sourcecode', - '-u', 'http://code.google.com/p/idapython/', - '--navlink', 'IDAPython Reference', - '--no-private', - '--simple-term', - '-o', docdir, - '--html', - 'idc', 'idautils', PYWRAPS_FN, 'idaapi'] - # Generate the documentation - epydoc.cli.cli() - - print "Documentation generated!" - - # Clean temp files - for f in [PYWRAPS_FN + '.py', PYWRAPS_FN + '.pyc']: - if os.path.exists(f): - os.unlink(f) - - if z: - z = docdir + '-doc.zip' - zip = zipfile.ZipFile(z, "w", zipfile.ZIP_DEFLATED) - for fn in glob.glob(docdir + os.sep + '*'): - zip.write(fn) - zip.close() - print "Documentation compressed to", z - except Exception, e: - print 'Failed to generate documentation:', e - finally: - os.chdir(old_dir) - return - -# ----------------------------------------------------------------------- -def usage(): - print """IDAPython build script. - -Available switches: - --doc: - Generate documentation into the 'docs' directory - --zip: - Used with '--doc' switch. It will compress the generated documentation - --ea64: - Builds also the 64bit version of the plugin - --with-hexrays: - Build with the Hex-Rays Decompiler wrappings - --no-early-load: - The plugin will be compiled as normal plugin - This switch disables processor, plugin and loader scripts -""" - # ----------------------------------------------------------------------- def main(): - if '--help' in sys.argv: - return usage() - elif '--doc' in sys.argv: - return gen_docs(z = '--zip' in sys.argv) - # # Parse options - # options = parse_options(sys.argv) - # ea64 = options[S_EA64] - - # Always build the non __EA64__ version - build_binary_package(ea64=False, nukeold=True) - - # Rebuild package with __EA64__ if needed + argv = ["make"] + env = os.environ.copy() + env["OUT_OF_TREE_BUILD"] = "1" if args.ea64: - build_binary_package(ea64=True, nukeold=False) - - # Always build the source package - build_source_package() + env["__EA64__"] = "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.with_hexrays: + env["HAS_HEXRAYS"] = "1" + if args.python_home: + env["IDAPYTHON_PYTHONHOME"] = args.python_home + if args.verbose: + argv.append("-d") + run(argv, env=env) # ----------------------------------------------------------------------- if __name__ == "__main__": diff --git a/chkapi.py b/chkapi.py new file mode 100644 index 0000000..1b884f5 --- /dev/null +++ b/chkapi.py @@ -0,0 +1,312 @@ +from __future__ import with_statement + +import sys, optparse, re, pprint + +ignorable_api_contents = [ + "qwait" + ] + +class TextStream: + def __init__(self, text): + self.text = text + self.point = 0 + self.maxpoint = len(self.text) + self.line_nr = 0 + self.char_nr = 0 + self.curline = None + + def line(self): + pt = self.point + self.advance_to_newline() + return self.text[pt : self.point] + + def char(self): + c, self.point = self.text[self.point], self.point + 1 + if c == '\n': + self.line_nr += 1 + self.char_nr = 0 + return c + + def advance_to_newline(self): + p = self.point + while self.text[p] != '\n': + p += 1 + p += 1 + self.line_nr += 1 + self.char_nr = 0 + self.point = p + + def empty(self): + return self.point >= self.maxpoint + + +if __name__ == "__main__": + + p = optparse.OptionParser(description='Check the generated idaapi_include.cpp file') + p.add_option('-v', "--verbose", dest="verbose", action="store_true") + p.add_option('-f', "--file", dest="path", type="string") + p.add_option('-x', "--with-hexrays", dest="with_hexrays", action="store_true") + p.add_option('-r', "--report-contents", dest="report_contents", type="string") + opts, _ = p.parse_args(sys.argv[1:]) + + api_contents = { + "functions" : [] + } + + if not opts.path: + p.print_help() + sys.exit(1) + + functions_coherence_base = { + # + # qstrvec_t: Specialized, internal, clink'ed object. + # + "_wrap_qstrvec_t_assign" : { + "mustcall" : "qstrvec_t_assign" + }, + "_wrap_qstrvec_t_addressof" : { + "mustcall" : "qstrvec_t_addressof" + }, + "_wrap_qstrvec_t_set" : { + "mustcall" : "qstrvec_t_set" + }, + "_wrap_qstrvec_t_from_list" : { + "mustcall" : "qstrvec_t_from_list" + }, + "_wrap_qstrvec_t_size" : { + "mustcall" : "qstrvec_t_size" + }, + "_wrap_qstrvec_t_get" : { + "mustcall" : "qstrvec_t_get" + }, + "_wrap_qstrvec_t_add" : { + "mustcall" : "qstrvec_t_add" + }, + "_wrap_qstrvec_t_clear" : { + "mustcall" : "qstrvec_t_clear" + }, + "_wrap_qstrvec_t_insert" : { + "mustcall" : "qstrvec_t_insert" + }, + "_wrap_qstrvec_t_remove" : { + "mustcall" : "qstrvec_t_remove" + }, + + # + # Misc. + # + "_wrap_areacb_t_get_type" : { + "mustcall" : "get_type", + }, + "_wrap_tinfo_t_deserialize__SWIG_2" : { + "mustcall" : "tinfo_t_deserialize__SWIG_2", + }, + "_wrap_get_bpt_group" : { + "mustcall" : "PyString_FromStringAndSize", + }, + "_wrap_get_jumptable_info" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_get_array_parameters" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_read_dbg_memory" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_write_dbg_memory" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_get_grp_bpts" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_generic_linput_t_read" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_generic_linput64_t_read64" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_linput_buffer_t_read" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_get_ptr_object_size" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_tag_strlen" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_get_next_member_idx" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + "_wrap_get_prev_member_idx" : { + "string" : "resultobj = PyLong_FromLongLong(result)", + }, + # char[ANY] out typemap + "_wrap_idainfo_tag_get" : { + "nostring" : " --size;", + }, + # char[ANY] varout typemap + "Swig_var_database_idb_get" : { + "nostring" : " --size;", + }, + } + + functions_coherence_hexrays = { + "_wrap_cfuncptr_t___str__" : { + "mustcall" : ["cfunc_t___str__", "PyString_FromStringAndSize"], + }, + "_wrap_cfunc_t___str__" : { + "mustcall" : ["cfunc_t___str__", "PyString_FromStringAndSize"], + }, + "_wrap_hexrays_failure_t_desc" : { + "mustcall" : "PyString_FromStringAndSize", + }, + "_wrap_vd_failure_t_desc" : { + "mustcall" : "PyString_FromStringAndSize", + }, + "_wrap_create_field_name" : { + "mustcall" : "PyString_FromStringAndSize", + }, + "delete_qrefcnt_t_Sl_cfunc_t_Sg_" : { + "mustcall" : "hexrays_deregister_python_cfuncptr_t_instance", + }, + "_wrap__decompile" : { + "mustcall" : "hexrays_register_python_cfuncptr_t_instance", + }, + "_wrap_vdui_t_cfunc_get" : { + "mustcall" : "hexrays_register_python_cfuncptr_t_instance", + }, + # + # qvector + # + "_wrap_strvec_t___len__" : { + "mustcall" : "qvector_Sl_simpleline_t_Sg____len__", + }, + "_wrap_strvec_t___setitem__" : { + "mustcall" : "qvector_Sl_simpleline_t_Sg____setitem__", + }, + "_wrap_strvec_t___getitem__" : { + "mustcall" : "qvector_Sl_simpleline_t_Sg____getitem__", + }, + # + # vdui_t::cfunc + # + "_wrap_vdui_t_cfunc_get" : { + "string" : "SWIGTYPE_p_qrefcnt_tT_cfunc_t_t", # proper typemap must be used + }, + } + + functions_coherence = functions_coherence_base.copy() + if opts.with_hexrays: + functions_coherence.update(functions_coherence_hexrays) + + # Mark all functions as not-spotted. + for fname in functions_coherence.keys(): + chk = functions_coherence[fname] + chk["spotted"] = False + + # Read and go through lines + with open(opts.path, "r") as f: + ts = TextStream(f.read()) + + def dbg(msg): + if opts.verbose: + print("DEBUG: %s" % msg) + + def is_fundecl(line): + if len(line) <= 2: + return False + if line[0:1].isspace(): + return False + if line[len(line)-1:] != "{": + return False + if line.find("(") == -1 or line.find(")") == -1: + return False + return True + + def collect_funbody_lines(ts): + pt = ts.point + braces_cnt = 1 + while True: + c = ts.char() + if c == "{": + braces_cnt = braces_cnt + 1 + elif c == "}": + braces_cnt = braces_cnt - 1 + if braces_cnt == 0: + break; + # TODO: Skip strings! + return ts.text[pt : ts.point].split("\n") + + api_fname_regex = re.compile(".*PyObject \\*_wrap_([^\\(]*)\\(.*\\).*") + + # Process lines + STATE_UNKNOWN = 0 + STATE_IN_FUN = 1 + state = STATE_UNKNOWN + while not ts.empty(): + line = ts.line().rstrip() + # dbg("Line: '%s'" % line) + if is_fundecl(line): + # dbg("Entering function (from line %d: '%s')" % (ts.line_nr, line)) + state = STATE_IN_FUN + funstart = line + match = api_fname_regex.match(funstart) + if match: + fname = match.group(1) + if fname not in ignorable_api_contents: + api_contents["functions"].append(fname) + funlines = collect_funbody_lines(ts) + # Do we care about this function? + check_for = None + for fname in functions_coherence.keys(): + if funstart.find(fname + "(") > -1: + check_for = fname + break + if check_for: + dbg("Checking function at line %d: '%s'" % (ts.line_nr, check_for)) + chk = functions_coherence[check_for] + chk["spotted"] = True + def look_for_stuff(stuff, isFuncall, lookForPresence=True): + if isinstance(stuff, str): + stuff = [stuff] + for bit in stuff: + found = False + bit_pat = ("%s(" % bit) if isFuncall else bit + dbg("Thing to look for: '%s'" % bit_pat) + for funline in funlines: + # dbg("Testing line: '%s'" % funline) + if funline.find(bit_pat) > -1: + found = True + break + if lookForPresence: + if not found: + raise Exception("Couldn't find '%s', from function '%s' (lines: %s)" % + (bit_pat, check_for, "\n".join([""] + funlines))) + else: + if found: + raise Exception("Did find unwanted '%s', from function '%s' (lines: %s)" % + (bit_pat, check_for, "\n".join([""] + funlines))) + + if "mustcall" in chk: + look_for_stuff(chk["mustcall"], True) + if "string" in chk: + look_for_stuff(chk["string"], False) + if "nostring" in chk: + look_for_stuff(chk["nostring"], False, lookForPresence=False) + + # Ensure all functions were spotted. + for fname in functions_coherence.keys(): + chk = functions_coherence[fname] + if not chk["spotted"]: + raise Exception("Couldn't spot function '%s'" % fname) + + # Report contents + if opts.report_contents: + # NB: we use "wb" here so that the endlines + # are written as-is, in Unix format + # and so 'diff' does not report bogus changes + # against the file from repository + with open(opts.report_contents, "wb") as f: + api_contents["functions"].sort() + f.write(pprint.pformat(api_contents)) + diff --git a/hrdoc.py b/hrdoc.py old mode 100644 new mode 100755 diff --git a/idaapi.cpp b/idaapi.cpp new file mode 100644 index 0000000..6ca3913 --- /dev/null +++ b/idaapi.cpp @@ -0,0 +1,4 @@ +// This file just includes the correct idaapi_include.cpp file +// We need it because we can not compile a file from a subdirectory + +#include diff --git a/makefile b/makefile new file mode 100644 index 0000000..3b4aeb0 --- /dev/null +++ b/makefile @@ -0,0 +1,380 @@ + +# +# 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'. +# Thus, we have to settle for a makefile-wide policy of either: +# - terminating dir paths with '/', in which case we have to write: +# $(SOMEDIR)somefile, or +# - not terminating dir paths with '/', in which case it becomes: +# $(SOMEDIR)/somefile +# In other makefiles sitting in IDA's source tree, we use the first approach, +# but this one demands the second: not only is this more natural for +# 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()) +# + +ifdef __X64__ + ifdef __LINUX__ + LINUX64=1 + endif +endif + +ifdef LINUX64 +all: + @echo "Not building Python for Linux x64" +else + +PROC=python +STRIPOBJS=idaapi.cpp +API_CONTENTS=api_contents.txt +CFGFILE=python.cfg + +IDA_INCLUDE=../../include + +STAGING=./staging +ST_SWIG=$(STAGING)/swig +ST_SDK=$(STAGING)/idasdk +ST_PYW=$(STAGING)/pywraps +ST_PARSED_HEADERS=$(STAGING)/parsed_notifications/xml + +ifdef __NT__ + SYSNAME=win +else +.NOTPARALLEL: +endif +ifdef __LINUX__ + SYSNAME=linux + DEFS=-D__LINUX__ + PYTHON32_LIBRARY_PATH?=/usr/lib + PYTHON32_LIBRARY_INCLUDE=-L$(PYTHON32_LIBRARY_PATH) +endif +ifdef __BSD__ + SYSNAME=bsd + DEFS=-D__BSD__ +endif +ifdef __MAC__ + SYSNAME=mac + DEFS=-D__MAC__ +endif + +O1=idaapi +ADDITIONAL_GOALS=pyfiles config $(TEST_IDC) + +__USE_RTTI__=1 +include ../plugin.mak + +# 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)) +endif + +# used python version +PYTHON_VERSION_MAJOR?=2 +PYTHON_VERSION_MINOR?=7 + +# output directory for python scripts + +ifeq ($(OUT_OF_TREE_BUILD),) + SCRIPTDIR=$(R)python + DEPLOY_INIT_PY=$(SCRIPTDIR)/init.py + DEPLOY_IDC_PY=$(SCRIPTDIR)/idc.py + DEPLOY_IDAUTILS_PY=$(SCRIPTDIR)/idautils.py + DEPLOY_PYTHON_CFG=$(C)python.cfg + TEST_IDC=test_idc +else + SCRIPTDIR=python +endif + +ifdef __NT__ # os and compiler specific flags +ifneq ($(UCRT_INCLUDE),) + I_UCRT_INCLUDE=/I$(UCRT_INCLUDE) +endif + PYTHON_ROOT?=c: + PYTHON_DIR=$(PYTHON_ROOT)/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR) + IDAPYTHON_CFLAGS=-w -Z7 /EHsc /bigobj /I$(MSVCDIR)Include $(I_UCRT_INCLUDE) + ifdef __X64__ + PYTHONLIB=vcx64_python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib -nodefaultlib:python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib + else + PYTHONLIB=$(PYTHON_DIR)/libs/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib + endif + _SWIGFLAGS=-D__NT__ -DWIN32 -D_USRDLL -I$(PYTHON_DIR)/include + SWIGINCLUDES?= # nothing + OSFLAGS=$(_SWIGFLAGS) -UNO_OBSOLETE_FUNCS +else # unix/mac + ifdef __LINUX__ + # use the precompiled 2.7 + ifeq ($(OUT_OF_TREE_BUILD),) + PYDIR=$(shell pwd)/precompiled + PYLIBDIR=$(PYDIR) + # copy these files to IDA's directory + PYLIBFILES=$(shell find precompiled/lib -type f) + PRECOMPILED_COPY=$(R)$(PYTHONLIBNAME) $(patsubst precompiled/%,$(SCRIPTDIR)/%,$(PYLIBFILES)) + else + PYDIR=$(IDAPYTHON_PYTHONHOME) + PYLIBDIR=$(PYDIR)/lib + endif + PYTHON32_INCLUDE:=-I$(PYDIR)/include/python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) + PYTHONLIBNAME=libpython$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR).so.1.0 + PYTHONLIB=$(PYLIBDIR)/$(PYTHONLIBNAME) -ldl + else + PYVER=$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) + PYTHON32_INCLUDE:=$(shell python$(PYVER)-config --includes) + PYTHONLIB:=$(shell python$(PYVER)-config --ldflags) + MACDEFINES=-DMACSDKVER=$(MACSDKVER) + endif + IDAPYTHON_CFLAGS=-w -g + OSFLAGS=$(SYS) -g $(PYTHON32_INCLUDE) $(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 +SWIGFLAGS=$(_SWIGFLAGS) $(SWIGINCLUDES) + +ADDITIONAL_LIBS=$(PYTHONLIB) + +.PHONY: pyfiles docs $(TEST_IDC) staging_dirs clean check_python +config: $(C)python.cfg + +clean: + rm -rf $(STAGING)/ obj/ + +pyfiles: $(SCRIPTDIR)/idautils.py \ + $(SCRIPTDIR)/idc.py \ + $(SCRIPTDIR)/init.py \ + $(SCRIPTDIR)/idaapi.py + +GENHOOKS=tools/genhooks/ + +$(DEPLOY_INIT_PY): python/init.py + $(CP) $? $@ + +$(DEPLOY_IDC_PY): python/idc.py + $(CP) $? $@ + +$(DEPLOY_IDAUTILS_PY): python/idautils.py + $(CP) $? $@ + +$(SCRIPTDIR)/idaapi.py: $(F)idaapi.py + $(PYTHON) inject_pydoc.py swig/ $? $@ + +$(SCRIPTDIR)/lib/%: precompiled/lib/% + mkdir -p $(@D) + cp $< $@ + @chmod +w $@ + +$(DEPLOY_PYTHON_CFG): $(CFGFILE) + $(CP) $? $@ + +$(R)$(PYTHONLIBNAME): $(PYDIR)/$(PYTHONLIBNAME) + $(CP) $? $@ + +# ------------------------------------------------------------------------- +# Hooks generation +$(ST_PARSED_HEADERS)/structprocessor__t.xml: $(I)idp.hpp $(GENHOOKS)doxy_gen_notifs.cfg | $(ST_SDK_TARGETS) + @$(DOXYGEN_BIN) $(GENHOOKS)doxy_gen_notifs.cfg + +$(ST_PARSED_HEADERS)/dbg_8hpp.xml: $(I)dbg.hpp $(GENHOOKS)doxy_gen_notifs.cfg | $(ST_SDK_TARGETS) + @$(DOXYGEN_BIN) $(GENHOOKS)doxy_gen_notifs.cfg + +$(ST_PARSED_HEADERS)/kernwin_8hpp.xml: $(I)kernwin.hpp $(GENHOOKS)doxy_gen_notifs.cfg | $(ST_SDK_TARGETS) + @$(DOXYGEN_BIN) $(GENHOOKS)doxy_gen_notifs.cfg + +$(ST_PARSED_HEADERS)/namespaceidb__event.xml: $(I)kernwin.hpp $(GENHOOKS)doxy_gen_notifs.cfg | $(ST_SDK_TARGETS) + @$(DOXYGEN_BIN) $(GENHOOKS)doxy_gen_notifs.cfg + +# +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_PARSED_HEADERS)" ] ; then mkdir -p 2>/dev/null $(ST_PARSED_HEADERS) ; fi + +# ------------------------------------------------------------------------- +# Rules for preparing 'staging/idasdk/*.h[pp]' +# +SDK_SOURCES=$(wildcard $(IDA_INCLUDE)/*.h) $(wildcard $(IDA_INCLUDE)/*.hpp) +ST_SDK_TARGETS=$(SDK_SOURCES:$(IDA_INCLUDE)/%=$(ST_SDK)/%) +$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h | staging_dirs + @$(CP) $^ $@ && chmod +rw $@ +$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp | staging_dirs + @$(CP) $^ $@ && chmod +rw $@ + + +# ------------------------------------------------------------------------- +# Rules for preparing 'staging/pywraps/*' +# +PYW_SOURCES=$(wildcard pywraps/*.hpp) $(wildcard pywraps/*.py) +ST_PYW_TARGETS=$(PYW_SOURCES:pywraps/%=$(ST_PYW)/%) +$(ST_PYW)/%.hpp: pywraps/%.hpp | staging_dirs + @$(CP) $^ $@ && chmod +rw $@ +$(ST_PYW)/%.py: pywraps/%.py | staging_dirs + @$(CP) $^ $@ && chmod +rw $@ + + +ifneq ($(OUT_OF_TREE_BUILD),) + # envvar HAS_HEXRAYS must have been set by build.py if needed +else + + # force hexrays bindings + HAS_HEXRAYS=1 + + # 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 \ + $(ST_PARSED_HEADERS)/structprocessor__t.xml | staging_dirs $(SDK_SOURCES) + @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e idp_notify \ + -r int -n 0 -m hookgenIDP -q "processor_t::" \ + -R $(GENHOOKS)recipe_idphooks.py + $(ST_PYW)/py_idbhooks.hpp: pywraps/py_idbhooks.hpp \ + $(I)idp.hpp \ + $(GENHOOKS)genhooks.py \ + $(GENHOOKS)recipe_idbhooks.py \ + $(ST_PARSED_HEADERS)/namespaceidb__event.xml | 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 + $(ST_PYW)/py_dbg.hpp: pywraps/py_dbg.hpp \ + $(I)dbg.hpp \ + $(GENHOOKS)genhooks.py \ + $(GENHOOKS)recipe_dbghooks.py \ + $(ST_PARSED_HEADERS)/dbg_8hpp.xml | 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 + $(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \ + $(I)kernwin.hpp \ + $(GENHOOKS)genhooks.py \ + $(GENHOOKS)recipe_uihooks.py \ + $(ST_PARSED_HEADERS)/kernwin_8hpp.xml | 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_" +endif # OUT_OF_TREE_BUILD + +ifneq ($(HAS_HEXRAYS),) + WITH_HEXRAYS=-DWITH_HEXRAYS + WITH_HEXRAYS_CHKAPI=--with-hexrays +endif + + +# ------------------------------------------------------------------------- +# Rules for preparing 'staging/swig/*.i' +# +# Note: At the time we define those rules, we cannot go and look in +# staging/pywraps/ just yet, as those will/might not have been deployed at +# that point (i.e., when building from scratch.) +# Thus, we must find the dependencies in pywraps/, and then re-route them to +# staging/pywraps/ +SWIG_SOURCES=$(wildcard swig/*.i) +ST_SWIG_TARGETS=$(SWIG_SOURCES:swig/%.i=$(ST_SWIG)/%.i) +find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $1)).*) +define make-deploy-swig-file-rule +$1: $(subst staging/,,$1) $(addprefix staging/,$(call find-pywraps-deps,$1)) | $(ST_PYW_TARGETS) + @$(PYTHON) tools/deploy.py --pywraps $(ST_PYW) --template $$(subst staging/,,$$@) --output $$@ --module $$(subst .i,,$$(notdir $$@)) +endef +$(foreach tgt,$(ST_SWIG_TARGETS),$(eval $(call make-deploy-swig-file-rule,$(tgt)))) + + +# 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); } }") + +# idaapi.py is created together with idaapi_include.cpp +$(F)idaapi.py: | $(F)idaapi_include.cpp +# idaapi_include.h is created together with idaapi_include.cpp +patched_idaapi_include_h: patch_directors_cc.py | $(F)idaapi_include.h +ifdef __NT__ + @$(PYTHON) patch_directors_cc.py -f $(F)idaapi_include.h +endif + +$(F)idaapi_include.h: | $(F)idaapi_include.cpp +$(F)idaapi_include.cpp: $(PRECOMPILED_COPY) \ + $(ST_SDK_TARGETS) \ + $(ST_PYW_TARGETS) \ + $(ST_SWIG_TARGETS) \ + pywraps.hpp | objdir + @ ! (grep __EA64__ swig/* | grep -v typeconv.i) || \ + (echo "ERROR: __EA64__ macro is foribidden in swig subdirectory (to ensure the same api for both ida versions)" && false) +ifneq ($(SWIG_VERSION_ACTUAL),$(SWIG_VERSION)) + $(error Expected SWIG version "$(SWIG_VERSION)", but got "$(SWIG_VERSION_ACTUAL)" (from $(SWIG))) +endif + $(SWIG) -modern $(WITH_HEXRAYS) -python -threads -c++ -shadow \ + $(MACDEFINES) -D__GNUC__ $(SWIGFLAGS) $(SWITCH64) -I$(ST_SWIG) \ + -outdir $(F) -o $@ -I$(ST_SDK) $(ST_SWIG)/idaapi.i || \ + { $(RM) $(F)idaapi_include.*; exit 1 ;} + $(PYTHON) chkapi.py $(WITH_HEXRAYS_CHKAPI) -f $@ -r $(API_CONTENTS).new + @(diff $(API_CONTENTS) $(API_CONTENTS).new) > /dev/null || \ + (rm -f $@ $(F)idaapi_include.h && \ + echo "API CONTENTS CHANGED! update api_contents.txt or fix the API" && \ + echo "(New API: $(API_CONTENTS).new) ***" && \ + (diff -U 1 -w $(API_CONTENTS) $(API_CONTENTS).new && false)) + + +# Python version +CFLAGS= $(CCOPT) $(OSFLAGS) -D__EXPR_SRC -I. -I$(ST_SWIG) -I$(ST_SDK) -I$(F) \ + -DVER_MAJOR="1" -DVER_MINOR="7" -DVER_PATCH="0" -D__IDP__ \ + -DUSE_STANDARD_FILE_FUNCTIONS $(IDAPYTHON_CFLAGS) \ + $(SWITCH64) $(ARCH_CFLAGS) $(WITH_HEXRAYS) + +# the html files are produced in docs\hr-html directory +docs: hrdoc.py hrdoc.cfg hrdoc.css + idaq -Shrdoc.py -t + +# Test that all functions that are present in ftable.cpp +# are present in idc.py (and therefore made available by +# the idapython). +ifdef __NT__ + IDA_CMD=TVHEADLESS=1 $(R)idaw$(X64SUFF)$(SUFF64) +else + IDA_CMD=TVHEADLESS=1 $(R)idal$(X64SUFF)$(SUFF64) +endif + +# the demo version of ida does not have the -B command line option +ifeq ($(OUT_OF_TREE_BUILD),) + ISDEMO=$(shell grep "define DEMO$$" $(IDA_INCLUDE)/commerc.hpp) + ifeq ($(ISDEMO),) + BATCH_SWITCH=-B + endif +endif + +$(TEST_IDC): $(F)idctest.log +$(F)idctest.log: $(RS)idc/idc.idc | $(BINARY) pyfiles $(PRECOMPILED_COPY) +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 + +# MAKEDEP dependency list ------------------ +$(F)idaapi$(O) : $(F)idaapi_include.cpp $(I)allins.hpp $(I)area.hpp \ + $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp $(I)dbg.hpp \ + $(I)diskio.hpp $(I)entry.hpp $(I)enum.hpp $(I)err.h \ + $(I)expr.hpp $(I)fixup.hpp $(I)fpro.h $(I)frame.hpp \ + $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)ints.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)moves.hpp $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)queue.hpp \ + $(I)search.hpp $(I)segment.hpp $(I)sistack.hpp \ + $(I)srarea.hpp $(I)strlist.hpp $(I)struct.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + idaapi.cpp pywraps.hpp | patched_idaapi_include_h $(ST_SDK_TARGETS) +$(F)python$(O) : $(I)area.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)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)xref.hpp python.cpp pywraps.hpp | $(ST_SDK_TARGETS) +endif diff --git a/patch_directors_cc.py b/patch_directors_cc.py index 0745018..0bc3fb3 100644 --- a/patch_directors_cc.py +++ b/patch_directors_cc.py @@ -13,15 +13,11 @@ if __name__ == "__main__": sys.exit(1) patches = [ - # misc + # text_sink_t "virtual int idaapi print", - # user_lvar_visitor_t - "virtual int idaapi handle_retrieved_info", - "virtual int idaapi handle_retrieved_mapping", - "virtual int idaapi get_info_qty_for_saving", - "virtual bool idaapi get_info_for_saving", - "virtual lvar_mapping_t const *idaapi get_info_mapping_for_saving", + # user_lvar_modifier_t + "virtual bool idaapi modify_lvars", # ctree_visitor_t "virtual int idaapi visit_insn", @@ -40,6 +36,30 @@ if __name__ == "__main__": "virtual int idaapi visit_expr", "virtual int idaapi leave_insn", "virtual int idaapi leave_expr", + + # enum_member_visitor_t + "virtual int idaapi visit_enum_member", + + # struct_field_visitor_t + "virtual int idaapi visit_field", + + # tinfo_visitor_t + "virtual int idaapi visit_type", + + # aloc_visitor_t + "virtual int idaapi visit_location", + + # const_aloc_visitor_t + "virtual int idaapi visit_location", + + # area_visitor2_t + "virtual int idaapi visit_area", + + # highlighter_cbs_t + "virtual void idaapi set_style", + "virtual int32 idaapi prev_block_state", + "virtual int32 idaapi cur_block_state", + "virtual void idaapi set_block_state", ] path = opts.path diff --git a/python.cfg b/python.cfg index d71cccc..1ecd270 100644 --- a/python.cfg +++ b/python.cfg @@ -1,9 +1,9 @@ // Alert before loading automatic scripts found in current directory // swig_runtime_dataN, sitecustomize and usercustomize -ALERT_AUTO_SCRIPTS = 1 +ALERT_AUTO_SCRIPTS = YES // Remove current directory from import search path -REMOVE_CWD_SYS_PATH = 1 +REMOVE_CWD_SYS_PATH = YES // Script timeout (in seconds) // (A value of 0 disables the timeout) diff --git a/python.cpp b/python.cpp index 56e200d..879f278 100644 --- a/python.cpp +++ b/python.cpp @@ -30,8 +30,10 @@ #include #include #include +#include #ifdef WITH_HEXRAYS +//-V::730 Not all members of a class are initialized inside the constructor #include hexdsp_t *hexdsp = NULL; #endif @@ -213,7 +215,7 @@ pycall_res_t::pycall_res_t(PyObject *pyo) //------------------------------------------------------------------------- pycall_res_t::~pycall_res_t() { - if (PyErr_Occurred()) + if ( PyErr_Occurred() ) PyErr_Print(); } @@ -380,41 +382,12 @@ static error_t idaapi idc_runpythonstatement( } //-------------------------------------------------------------------------- -const char *idaapi set_python_options( - const char *keyword, - int value_type, - const void *value) +static const cfgopt_t opts[] = { - do - { - if ( value_type == IDPOPT_NUM ) - { - if ( qstrcmp(keyword, "SCRIPT_TIMEOUT") == 0 ) - { - script_timeout = int(*(uval_t *)value); - break; - } - else if ( qstrcmp(keyword, "ALERT_AUTO_SCRIPTS") == 0 ) - { - g_alert_auto_scripts = *(uval_t *)value != 0; - break; - } - else if ( qstrcmp(keyword, "REMOVE_CWD_SYS_PATH") == 0 ) - { - g_remove_cwd_sys_path = *(uval_t *)value != 0; - break; - } - else if ( qstrcmp(keyword, "USE_LOCAL_PYTHON") == 0 ) - { - msg("\"USE_LOCAL_PYTHON\" is deprecated. IDA will always use " - "its own Python libraries if directory python/lib/ exists.\n"); - break; - } - } - return IDPOPT_BADKEY; - } while (false); - return IDPOPT_OK; -} + cfgopt_t("SCRIPT_TIMEOUT", &script_timeout, 0, INT_MAX), + cfgopt_t("ALERT_AUTO_SCRIPTS", &g_alert_auto_scripts, true), + cfgopt_t("REMOVE_CWD_SYS_PATH", &g_remove_cwd_sys_path, true), +}; //------------------------------------------------------------------------- // Check for the presence of a file in IDADIR/python and complain on error @@ -438,12 +411,18 @@ static bool check_python_dir() } } + // on linux, PyQt needs to drop python/lib/python2.7/lib-dynload/sip.so, + // thus we can't rely on the mere presence of 'lib'. However, we know + // the bundled python drops python/lib/python27.zip. Let's look for that. +#ifdef __LINUX__ + qmakepath(filepath, sizeof(filepath), g_idapython_dir, "lib", "python27.zip", NULL); + if ( qfileexist(filepath) ) +#else qmakepath(filepath, sizeof(filepath), g_idapython_dir, "lib", NULL); if ( qisdir(filepath) ) - { -#ifdef _DEBUG - msg("Found \"%s\"; assuming local Python.\n", filepath); #endif + { + deb(IDA_DEBUG_PLUGIN, "Found \"%s\"; assuming local Python.\n", filepath); g_use_local_python = true; } @@ -577,10 +556,12 @@ static bool IDAPython_ExecFile( strrpl(script, '\\', '/'); newref_t py_script(PyString_FromString(script)); + borref_t py_false(Py_False); newref_t py_ret(PyObject_CallFunctionObjArgs( py_execscript.o, py_script.o, GetMainGlobals(), + py_false.o, NULL)); // Failure at this point means the script was interrupted @@ -597,7 +578,7 @@ static bool IDAPython_ExecFile( } bool ok = false; - if ( !interrupted ) + if ( !interrupted ) { PyObject *ret_o; if ( want_tuple ) @@ -822,9 +803,9 @@ ERR: //------------------------------------------------------------------------- // Compile callback for Python external language evaluator bool idaapi IDAPython_extlang_compile_file( - const char *filename, - char *errbuf, - size_t errbufsize) + const char *filename, + char *errbuf, + size_t errbufsize) { PYW_GIL_GET; begin_execution(); @@ -836,10 +817,10 @@ bool idaapi IDAPython_extlang_compile_file( //------------------------------------------------------------------------- // Load processor module callback for Python external language evaluator static bool idaapi IDAPython_extlang_loadprocmod( - const char *filename, - idc_value_t *procobj, - char *errbuf, - size_t errbufsize) + const char *filename, + idc_value_t *procobj, + char *errbuf, + size_t errbufsize) { PYW_GIL_GET; begin_execution(); @@ -1162,6 +1143,38 @@ bool idaapi IDAPython_extlang_call_method( } //------------------------------------------------------------------------- +struct python_highlighter_t : public ida_syntax_highlighter_t +{ + python_highlighter_t() : ida_syntax_highlighter_t() + { + open_strconst = '"'; + close_strconst = '"'; + open_chrconst = '\''; + close_chrconst = '\''; + escape_char = '\\'; + preprocessor_char = char(1); + literal_closer = '\0'; + text_color = HF_DEFAULT; + comment_color = HF_COMMENT; + string_color = HF_STRING; + preprocessor_color = HF_KEYWORD1; + style = HF_DEFAULT; + set_open_cmt("#"); + add_multi_line_comment("\"\"\"", "\"\"\""); + add_multi_line_comment("'''", "'''"); + add_keywords( + "and|as|assert|break|class|continue|def|" + "del|elif|else|except|exec|finally|" + "for|from|global|if|import|in|" + "is|lambda|not|or|pass|print|" + "raise|return|try|while|with|yield|" + "None|True|False",HF_KEYWORD1); + add_keywords("self", HF_KEYWORD2); + add_keywords("def", HF_KEYWORD3); + } +}; +static python_highlighter_t python_highlighter; + const extlang_t extlang_python = { sizeof(extlang_t), @@ -1179,6 +1192,7 @@ const extlang_t extlang_python = IDAPython_extlang_run_statements, IDAPython_extlang_loadprocmod, IDAPython_extlang_unloadprocmod, + &python_highlighter }; //------------------------------------------------------------------------- @@ -1334,7 +1348,7 @@ void convert_idc_args() if ( idc_args != NULL ) { idc_value_t attr; - char attr_name[20] = {"0"}; + char attr_name[20] = { "0" }; for ( int i=1; VarGetAttr(idc_args, attr_name, &attr) == eOk; i++ ) { PyList_Insert(py_args.o, i, PyString_FromString(attr.c_str())); @@ -1575,7 +1589,7 @@ bool IDAPython_Init(void) #endif // Read configuration value - read_user_config_file("python.cfg", set_python_options, NULL); + read_config_file("python.cfg", opts, qnumber(opts)); if ( g_alert_auto_scripts ) { if ( pywraps_check_autoscripts(tmp, sizeof(tmp)) diff --git a/pywraps.hpp b/pywraps.hpp index 36f604f..1e6a138 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -5,7 +5,6 @@ // Types #ifndef PYUL_DEFINED #define PYUL_DEFINED - typedef unsigned PY_LONG_LONG PY_ULONG_LONG; #ifdef __EA64__ typedef unsigned PY_LONG_LONG pyul_t; typedef PY_LONG_LONG pyl_t; @@ -15,6 +14,30 @@ #endif #endif + +// "A pointer can be explicitly converted to any integral type large +// enough to hold it. The mapping function is implementation-defined." +// — C++03 +// => G++ (and probably MSVC) will typically first sign-extend the pointer. +// +// int bar(void *p) { return foo(uint64(p)); } +// +// translates to: +// +// mov 0x8(%ebp),%eax +// mov %eax,%edx +// sar $0x1f,%edx ; <---- boom! +// mov %eax,(%esp) +// mov %edx,0x4(%esp) +// call 2d <_Z3barPv+0x16> + +#ifdef __X64__ +#define PTR2U64(Binding) (uint64(Binding)) +#else +#define PTR2U64(Binding) (uint64(uint32(Binding))) +#endif + + #ifdef __EA64__ #define PY_FMT64 "K" #define PY_SFMT64 "L" @@ -165,10 +188,10 @@ struct ref_t void decref() const { if ( o != NULL ) { QASSERT(30469, o->ob_refcnt > 0); Py_DECREF(o); } } bool operator==(PyObject *other) const { return o == other; } - bool operator!=(PyObject *other) const { return ! ((*this) == other); } + bool operator!=(PyObject *other) const { return !((*this) == other); } bool operator==(const ref_t &other) const { return o == other.o; } - bool operator!=(const ref_t &other) const { return ! ((*this) == other); } + bool operator!=(const ref_t &other) const { return !((*this) == other); } }; //------------------------------------------------------------------------- @@ -284,9 +307,6 @@ bool PyW_GetError(char *buf, size_t bufsz, bool clear_err = true); // This function is used when calling callbacks bool PyW_ShowCbErr(const char *cb_name); -// Utility function to create a class instance whose constructor takes zero arguments -ref_t create_idaapi_class_instance0(const char *clsname); - // Utility function to create linked class instances ref_t create_idaapi_linked_class_instance(const char *clsname, void *lnk); diff --git a/pywraps/deploy.bat b/pywraps/deploy.bat deleted file mode 100644 index 713b9d8..0000000 --- a/pywraps/deploy.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -deploy_all.py diff --git a/pywraps/deploy.py b/pywraps/deploy.py deleted file mode 100644 index ce349f9..0000000 --- a/pywraps/deploy.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -Deploy code snips into swig interface files - -(c) Hex-Rays -""" - -import sys -import re -import os - -# creates a regular expression -def make_re(tag, mod_name, prefix): - s = '%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s' % {'m': mod_name, 'tag': tag, 'p': prefix} - return (s, re.compile(s, re.DOTALL)) - -def convert_path(path_in): - parts = path_in.split('/') - return os.sep.join(parts) - -def deploy(mod_name, src_files, dest_file, silent = True): - dest_file = convert_path(dest_file) - src_files = map(convert_path, src_files) - # create regular expressions - templates = ( - ('pycode', make_re('pycode', mod_name, '#')), - ('code', make_re('code', mod_name, '//')), - ('inline', make_re('inline', mod_name, '//')) - ) - - if not os.path.exists(dest_file): - print "File", dest_file, "does not exist and will be skipped" - return - - if not os.access(dest_file, os.W_OK): - print "File", dest_file, "is not writable and will be skipped" - return - - # read dest file - dest_lines = "".join(file(dest_file, "r").readlines()) - - # read all source files into one buffer - src_lines = "".join(["".join(file(x, "r").readlines()) for x in src_files]) - - pcount = 0 - for desc, (expr_str, expr) in templates: - # find source pattern - matches = expr.findall(src_lines) - if not matches: - if not silent: - print "Failed to match <%s> source expression against '%s', skipping...!" % (desc, expr_str) - continue - - # find pattern in destination - dest = expr.search(dest_lines) - if not dest: - if not silent: - print "Failed to match <%s> destination expression against '%s', skipping..." % (desc, expr_str) - print dest_lines - sys.exit(0) - continue - - # accumulate all the strings to be replaced - replaces = [] - for src in matches: - replaces.append(src) - - dest_lines = dest_lines[:dest.start(1)] + "\n".join(replaces) + dest_lines[dest.end(1):] - pcount += 1 - - - f = file(dest_file, 'w') - if not f: - print "Failed to open destination file:", dest_file - return - f.write(dest_lines) - f.close() - - if pcount: - print "Deployed successfully: %s (%d)" % (dest_file, pcount) - else: - print "Nothing was deployed in: %s" % dest_file - - -def main(argv = None): - if not argv: - argv = sys.argv - if len(argv) != 4: - print "Usage deploy.py modname src_file1,src_file2,... dest_file" - return - - mod_name = argv[1] - src_files = argv[2].split(',') - dest_file = argv[3] - deploy(mod_name, src_files, dest_file) - -#main(['', 'py_graph', 'py_graph.hpp,py_graph.py', 'graph.i']) -if __name__ == '__main__': - main() diff --git a/pywraps/deploy_all.py b/pywraps/deploy_all.py index 2bedb56..90f859c 100644 --- a/pywraps/deploy_all.py +++ b/pywraps/deploy_all.py @@ -32,13 +32,13 @@ deploys = { "custview" : { "tag" : "py_custviewer", "src" : ["py_custview.py","py_custview.hpp"], - "tgt" : "../swig/kernwin.i" + "tgt" : "../swig/kernwin.i.in" }, "plgform" : { "tag" : "py_plgform", "src" : ["py_plgform.hpp","py_plgform.py"], - "tgt" : "../swig/kernwin.i" + "tgt" : "../swig/kernwin.i.in" }, "expr" : { @@ -50,7 +50,7 @@ deploys = { "cli" : { "tag" : "py_cli", "src" : ["py_cli.py","py_cli.hpp"], - "tgt" : "../swig/kernwin.i" + "tgt" : "../swig/kernwin.i.in" }, "Loader" : { @@ -62,7 +62,7 @@ deploys = { "kernwin, choose2, askusingform" : { "tag" : "py_kernwin", "src" : ["py_kernwin.hpp","py_kernwin.py","py_choose.hpp","py_choose2.hpp","py_choose2.py","py_askusingform.hpp","py_askusingform.py"], - "tgt" : "../swig/kernwin.i" + "tgt" : "../swig/kernwin.i.in" }, "idd" : { @@ -86,7 +86,7 @@ deploys = { "dbg" : { "tag" : "py_dbg", "src" : ["py_dbg.hpp"], - "tgt" : "../swig/dbg.i" + "tgt" : "../swig/dbg.i.in" }, "linput/diskio" : { @@ -134,7 +134,7 @@ deploys = { "idp" : { "tag" : "py_idp", "src" : ["py_idp.hpp"], - "tgt" : "../swig/idp.i" + "tgt" : "../swig/idp.i.in" }, "lines" : { @@ -149,6 +149,12 @@ deploys = { "tgt" : "../swig/registry.i" }, + "struct" : { + "tag" : "py_struct", + "src" : ["py_struct.hpp"], + "tgt" : "../swig/struct.i" + }, + "pc_win32_appcall" : { "tag" : "appcalltest", "src" : ["py_appcall.py"], diff --git a/pywraps/driver.cpp b/pywraps/driver.cpp deleted file mode 100644 index 33fdce9..0000000 --- a/pywraps/driver.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//-------------------------------------------------------------------------- -// IDA includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//-------------------------------------------------------------------------- -// PyWraps -#include -#include "pywraps.hpp" -#include "swig_stub.h" -#include "py_cvt.hpp" -#include "py_idaapi.hpp" -#include "py_graph.hpp" -#include "py_typeinf.hpp" -#include "py_bytes.hpp" -#include "py_linput.hpp" -#include "py_qfile.hpp" -#include "py_ua.hpp" -#include "py_custdata.hpp" -#include "py_notifywhen.hpp" -#include "py_dbg.hpp" -#include "py_choose2.hpp" -#include "py_plgform.hpp" -#include "py_cli.hpp" -#include "py_custview.hpp" -#include "py_lines.hpp" -#include "py_nalt.hpp" -#include "py_loader.hpp" -#include "py_idp.hpp" -#include "py_kernwin.hpp" -#include "py_askusingform.hpp" -#include "py_expr.hpp" - -//-------------------------------------------------------------------------- -qvector all_methods; -void driver_add_methods(PyMethodDef *methods) -{ - for ( ; methods->ml_name != NULL ; ++methods ) - all_methods.push_back(*methods); -} - -//-------------------------------------------------------------------------- -// Define a class and declare an instance so it gets executed on startup -// It will add the desired methods to the all_methods global variable -#define DRIVER_INIT_METHODS(name) \ - class init_##name##_driver_t \ - { \ - public: \ - init_##name##_driver_t() \ - { \ - driver_add_methods(py_methods_##name##); \ - } \ - } init_##name##_driver; - -//-------------------------------------------------------------------------- -// PyWraps test drivers -//#include "driver_kernwin.cpp" -//#include "driver_chooser.cpp" -#include "driver_expr.cpp" -//#include "driver_custview.cpp" -//#include "driver_notifywhen.cpp" -//#include "driver_custdata.cpp" -//#include "driver_graph.cpp" -//#include "driver_diskio.cpp" -//#include "driver_bytes.cpp" -//#include "driver_dbg.cpp" -//#include "driver_nalt.cpp" -//#include "driver_cli.cpp" - -//-------------------------------------------------------------------------- -//#define DRIVER_FIX - -#ifdef DRIVER_FIX - #define PLUGIN_FLAGS PLUGIN_FIX -#else - #define PLUGIN_FLAGS 0 -#endif - -//-------------------------------------------------------------------------- -void setup_pywraps() -{ - static bool installed = false; - if ( installed ) - { - msg("pywraps already installed\n"); - return; - } - static const PyMethodDef null_method = {0}; - all_methods.push_back(null_method); - Py_InitModule("pywraps", all_methods.begin()); - init_pywraps(); - msg("pywraps installed!\n"); - installed = true; -} - -//-------------------------------------------------------------------------- -void idaapi run(int /*arg*/) -{ - setup_pywraps(); -#ifdef DRIVER_RUN - driver_run(0); -#endif -} - -//-------------------------------------------------------------------------- -// -// Initialize. -// -int idaapi init(void) -{ -#ifndef DRIVER_FIX - setup_pywraps(); -#endif -#ifdef DRIVER_INIT - return driver_init(); -#else - return PLUGIN_KEEP; -#endif -} - -//-------------------------------------------------------------------------- -void idaapi term(void) -{ -#ifdef DRIVER_TERM - driver_term(); -#endif -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_FLAGS, // plugin flags - init, // initialize - - term, // terminate. this pointer may be NULL. - - run, // invoke plugin - - // long comment about the plugin - "PyWraps plugin", - - // it could appear in the status line - // or as a hint - "", // multiline help about the plugin - - "pywraps", // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/pywraps/driver_bytes.cpp b/pywraps/driver_bytes.cpp deleted file mode 100644 index 8dd61eb..0000000 --- a/pywraps/driver_bytes.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "py_bytes.hpp" - -//-------------------------------------------------------------------------- -static PyObject *ex_nextthat(PyObject *self, PyObject *args) -{ - PyObject *callback; - pyul_t addr, bound; - if ( !PyArg_ParseTuple(args, PY_FMT64 PY_FMT64 "O", &addr, &bound, &callback) ) - return NULL; - return Py_BuildValue("i", py_nextthat(pyul_t(addr), pyul_t(bound), callback)); -} - -//-------------------------------------------------------------------------- -static PyMethodDef py_methods_bytes[] = -{ - {"nextthat", ex_nextthat, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} -}; -DRIVER_INIT_METHODS(bytes); \ No newline at end of file diff --git a/pywraps/driver_chooser.cpp b/pywraps/driver_chooser.cpp deleted file mode 100644 index f18de18..0000000 --- a/pywraps/driver_chooser.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "py_choose2.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_find(PyObject *self, PyObject *args) -{ - char *title; - if ( !PyArg_ParseTuple(args, "s", &title) ) - return NULL; - else - return choose2_find(title); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_create(PyObject *self, PyObject *args) -{ - PyObject *obj; - int embedded; - if ( !PyArg_ParseTuple(args, "Oi", &obj, &embedded) ) - return NULL; - else - return PyInt_FromLong(choose2_create(obj, embedded == 1 ? true : false)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_activate(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - choose2_activate(obj); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_close(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - choose2_close(obj); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_refresh(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - choose2_refresh(obj); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_add_command(PyObject *self, PyObject *args) -{ - PyObject *obj; - char *caption; - int flags, menu_index, icon; - if ( !PyArg_ParseTuple(args, "Osiii", &obj, &caption, &flags, &menu_index, &icon) ) - return NULL; - else - return PyInt_FromLong(choose2_add_command(obj, caption, flags, menu_index, icon)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_get_test_embedded(PyObject *self, PyObject *args) -{ - return PyLong_FromSize_t(choose2_get_test_embedded()); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_get_embedded(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - else - return choose2_get_embedded(obj); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_get_embedded_selection(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - else - return choose2_get_embedded_selection(obj); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_chooser[] = -{ - {"py_choose2_find", ex_choose2_find, METH_VARARGS, ""}, - {"py_choose2_create", ex_choose2_create, METH_VARARGS, ""}, - {"py_choose2_close", ex_choose2_close, METH_VARARGS, ""}, - {"py_choose2_activate", ex_choose2_activate, METH_VARARGS, ""}, - {"py_choose2_refresh", ex_choose2_refresh, METH_VARARGS, ""}, - {"py_choose2_add_command", ex_choose2_add_command, METH_VARARGS, ""}, - {"py_choose2_get_test_embedded", ex_choose2_get_test_embedded, METH_VARARGS, ""}, - {"py_choose2_get_embedded", ex_choose2_get_embedded, METH_VARARGS, ""}, - {"py_choose2_get_embedded_selection", ex_choose2_get_embedded_selection, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} // End of methods -}; -DRIVER_INIT_METHODS(chooser); diff --git a/pywraps/driver_cli.cpp b/pywraps/driver_cli.cpp deleted file mode 100644 index 6b55c82..0000000 --- a/pywraps/driver_cli.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "py_custview.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_install_command_interpreter(PyObject *self, PyObject *args) -{ - PyObject *py_obj; - if ( !PyArg_ParseTuple(args, "O", &py_obj) ) - return NULL; - return PyInt_FromLong(py_install_command_interpreter(py_obj)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_remove_command_interpreter(PyObject *self, PyObject *args) -{ - int cli_idx; - if ( !PyArg_ParseTuple(args, "i", &cli_idx) ) - return NULL; - py_remove_command_interpreter(cli_idx); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_cli[] = -{ - {"install_command_interpreter", ex_install_command_interpreter, METH_VARARGS, ""}, - {"remove_command_interpreter", ex_remove_command_interpreter, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} -}; -DRIVER_INIT_METHODS(cli); \ No newline at end of file diff --git a/pywraps/driver_custdata.cpp b/pywraps/driver_custdata.cpp deleted file mode 100644 index 6f417da..0000000 --- a/pywraps/driver_custdata.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "py_custdata.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_register_custom_data_type(PyObject *self, PyObject *args) -{ - PyObject *py_dt; - if ( !PyArg_ParseTuple(args, "O", &py_dt) ) - return NULL; - return Py_BuildValue("i", py_register_custom_data_type(py_dt)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_unregister_custom_data_type(PyObject *self, PyObject *args) -{ - int dtid; - if ( !PyArg_ParseTuple(args, "i", &dtid) ) - return NULL; - return Py_BuildValue("i", py_unregister_custom_data_type(dtid)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_unregister_custom_data_format(PyObject *self, PyObject *args) -{ - int dtid, dfid; - if ( !PyArg_ParseTuple(args, "ii", &dtid, &dfid) ) - return NULL; - return Py_BuildValue("i", py_unregister_custom_data_format(dtid, dfid)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_register_custom_data_format(PyObject *self, PyObject *args) -{ - int dtid; - PyObject *py_df; - if ( !PyArg_ParseTuple(args, "iO", &dtid, &py_df) ) - return NULL; - return Py_BuildValue("i", py_register_custom_data_format(dtid, py_df)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_get_custom_data_format(PyObject *self, PyObject *args) -{ - int dtid, dfid; - if ( !PyArg_ParseTuple(args, "ii", &dtid, &dfid) ) - return NULL; - return py_get_custom_data_format(dtid, dfid); -} - -//------------------------------------------------------------------------- -static PyObject *ex_get_custom_data_type(PyObject *self, PyObject *args) -{ - int dtid; - if ( !PyArg_ParseTuple(args, "i", &dtid) ) - return NULL; - return py_get_custom_data_type(dtid); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_custdata[] = -{ - {"unregister_custom_data_format", ex_unregister_custom_data_format, METH_VARARGS, ""}, - {"register_custom_data_format", ex_register_custom_data_format, METH_VARARGS, ""}, - {"unregister_custom_data_type", ex_unregister_custom_data_type, METH_VARARGS, ""}, - {"register_custom_data_type", ex_register_custom_data_type, METH_VARARGS, ""}, - {"get_custom_data_format", ex_get_custom_data_format, METH_VARARGS, ""}, - {"get_custom_data_type", ex_get_custom_data_type, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; -//--------------------------------------------------------------------------- -class init_custdata_driver_t -{ -public: - init_custdata_driver_t() - { - driver_add_methods(py_methods_custdata); - } -} init_custdata_driver; diff --git a/pywraps/driver_custview.cpp b/pywraps/driver_custview.cpp deleted file mode 100644 index 4b8515b..0000000 --- a/pywraps/driver_custview.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include "py_custview.hpp" - -//-------------------------------------------------------------------------- -class my_custviewer: public customviewer_t -{ -private: - cvdata_simpleline_t data; - size_t id_n; - virtual bool on_popup_menu(size_t menu_id) - { - if ( menu_id == id_n ) - msg("popup menu N chosen!\n"); - return true; - } - virtual bool on_click(int shift) - { - msg("onclick; shift=%d\n", shift); - return true; - } - virtual void on_close() - { - id_n = 0; - msg("closed...\n"); - } - virtual bool on_keydown(int key, int shift) - { - switch ( key ) - { - case 'N': - warning("The hotkey 'N' has been pressed"); - return true; - case 'I': - { - int x, y; - place_t *pl = get_place(false, &x, &y); - if ( pl == NULL ) - return false; - msg("x=%d y=%d\n", x, y); - simpleline_t sl = *data.get_line(pl); - sl.bgcolor = bgcolor_t(~uint32(sl.bgcolor)); - data.set_line(data.to_lineno(pl), sl); - refresh_current(); - return true; - } - case 'A': - { - char buf[100]; - qsnprintf(buf, sizeof(buf), "This is line %d\n", data.count()); - data.add_line(buf); - msg("Added one more line...\n"); - return true; - } - case 'S': - { - twinpos_t p1, p2; - ::readsel2(_cv, &p1, &p2); - size_t y1 = data.to_lineno(p1.at); - size_t y2 = data.to_lineno(p2.at); - int x1 = p1.x; - int x2 = p2.x; - msg("(x1=%d y1=%d) (x2=%d y2=%d)", x1, y1, x2, y2); - return true; - } - case 'X': - data.set_minmax(); - return true; - case 'R': - refresh(); - msg("refreshing!\n"); - return true; - case IK_ESCAPE: - close(); - return true; - } - return false; - } - virtual void on_curpos_changed() - { - qstring word; - if ( get_current_word(false, word) ) - msg("Current word is: %s\n", word.c_str()); - } - virtual bool on_hint(place_t *place, int *important_lines, qstring &hint) - { - simpleline_t *line = data.get_line(place); - if ( line == NULL ) - return false; - *important_lines = 1; - hint = line->line; - return true; - } - -public: - void init_sample_lines() - { - strvec_t &lines = data.get_lines(); - static struct - { - const char *text; - bgcolor_t color; - } const sample_lines[] = - { - { "This is a sample text", 0xFFFFFF }, - { "It will be displayed in the custom view", 0xFFC0C0 }, - { COLSTR("This line will be colored as erroneous", SCOLOR_ERROR), 0xC0FFC0 }, - { COLSTR("Every", SCOLOR_AUTOCMT) " " - COLSTR("word", SCOLOR_DNAME) " " - COLSTR("can", SCOLOR_IMPNAME) " " - COLSTR("be", SCOLOR_NUMBER) " " - COLSTR("colored!", SCOLOR_EXTRA), 0xC0C0FF }, - { " No limit on the number of lines.", 0xC0FFFF }, - }; - for ( int i=0; iinit("My sample viewer!") ) - { - msg("Failed to create cv\n!"); - return; - } - g_cv->show(); -} - -#define DRIVER_INIT -int driver_init() -{ - g_cv = new my_custviewer(); - return PLUGIN_KEEP; -} - -#define DRIVER_TERM -void driver_term() -{ - g_cv->close(); - delete g_cv; -} diff --git a/pywraps/driver_dbg.cpp b/pywraps/driver_dbg.cpp deleted file mode 100644 index d662b27..0000000 --- a/pywraps/driver_dbg.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "py_dbg.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_getthreadsregbase(PyObject * /*self*/, PyObject *args) -{ - PyObject *py_tid, *py_sreg_value; - if ( !PyArg_ParseTuple(args, "OO", &py_tid, &py_sreg_value) ) - return NULL; - return dbg_get_thread_sreg_base(py_tid, py_sreg_value); -} - -//------------------------------------------------------------------------- -static PyObject *ex_readmemory(PyObject * /*self*/, PyObject *args) -{ - PyObject *py_ea, *py_size; - if ( !PyArg_ParseTuple(args, "OO", &py_ea, &py_size) ) - return NULL; - return dbg_read_memory(py_ea, py_size); -} - -//------------------------------------------------------------------------- -static PyObject *ex_writememory(PyObject * /*self*/, PyObject *args) -{ - PyObject *py_ea, *py_buf; - if ( !PyArg_ParseTuple(args, "OO", &py_ea, &py_buf) ) - return NULL; - return dbg_write_memory(py_ea, py_buf); -} - -//------------------------------------------------------------------------- -static PyObject *ex_getmeminfo(PyObject * /*self*/, PyObject *args) -{ - return dbg_get_memory_info(); -} - -//------------------------------------------------------------------------- -static PyObject *ex_getregs(PyObject *self, PyObject *args) -{ - return dbg_get_registers(); -} - -//------------------------------------------------------------------------- -static PyObject *ex_appcall(PyObject * /*self*/, PyObject *args) -{ - PyObject *app_args, *type, *fields; - int func_ea, tid; - if ( !PyArg_ParseTuple(args, "iiOOO", &func_ea, &tid, &type, &fields, &app_args) ) - return NULL; - return py_appcall(func_ea, tid, type, fields, app_args); -} - -//------------------------------------------------------------------------- -static PyObject *ex_pytoidc( - PyObject *self, - PyObject *args) -{ - if ( !PyArg_ParseTuple(args, "O", &self) ) - return NULL; - idc_value_t v; - int sn = 0; - borref_t self_ref(self); - if ( pyvar_to_idcvar(self_ref, &v, &sn) < CIP_OK ) - Py_RETURN_NONE; - Py_RETURN_TRUE; -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_dbg[] = -{ - {"getregs", ex_getregs, METH_VARARGS, ""}, - {"getmeminfo", ex_getmeminfo, METH_VARARGS, ""}, - {"readmemory", ex_readmemory, METH_VARARGS, ""}, - {"writememory", ex_writememory, METH_VARARGS, ""}, - {"getthreadsregbase", ex_getthreadsregbase, METH_VARARGS, ""}, - {"appcall", ex_appcall, METH_VARARGS, ""}, - {"pytoidc", ex_pytoidc, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; -DRIVER_INIT_METHODS(dbg); diff --git a/pywraps/driver_diskio.cpp b/pywraps/driver_diskio.cpp deleted file mode 100644 index 6945074..0000000 --- a/pywraps/driver_diskio.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "py_diskio.hpp" - -static PyObject *ex_enumfiles(PyObject * /*self*/, PyObject *args) -{ - PyObject *path, *fname, *callback; - if ( !PyArg_ParseTuple(args, "OOO", &path, &fname, &callback) ) - return NULL; - return py_enumerate_files(path, fname, callback); -} - -// -//static PyObject *ex_linput_close(PyObject * /*self*/, PyObject *args) -//{ -// PyObject *obj; -// if ( !PyArg_ParseTuple(args, "O", &obj) ) -// return NULL; -// pyl_close(obj); -// Py_RETURN_NONE; -//} -// -//static PyObject *ex_linput_open(PyObject *self, PyObject *args) -//{ -// PyObject *obj, *py_filename, *py_remote; -// if ( !PyArg_ParseTuple(args, "OOO", &obj, &py_filename, &py_remote) ) -// return NULL; -// return pyl_open(obj, py_filename, py_remote); -//} -// -//static PyObject *ex_linput_read(PyObject *self, PyObject *args) -//{ -// PyObject *obj, *py_size; -// if ( !PyArg_ParseTuple(args, "OO", &obj, &py_size) ) -// return NULL; -// return pyl_read(obj, py_size); -//} - -static PyMethodDef py_methods_diskio[] = -{ - {"enumfiles", ex_enumfiles, METH_VARARGS, ""}, - //{"tell", ex_linput_tell, METH_VARARGS, ""}, - //{"open", ex_linput_open, METH_VARARGS, ""}, - //{"size", ex_linput_tell, METH_VARARGS, ""}, - //{"read", ex_linput_read, METH_VARARGS, ""}, - //{"close", ex_linput_close, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; -DRIVER_INIT_METHODS(diskio); \ No newline at end of file diff --git a/pywraps/driver_expr.cpp b/pywraps/driver_expr.cpp deleted file mode 100644 index be2703c..0000000 --- a/pywraps/driver_expr.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "py_expr.hpp" - -#pragma warning(push) -#pragma warning(disable: 4244) - -//--------------------------------------------------------------------------- -static PyObject *ex_pyw_register_idc_func(PyObject *self, PyObject *args) -{ - char *name, *arg; - PyObject *py_fp; - if ( !PyArg_ParseTuple(args, "ssO", &name, &arg, &py_fp) ) - return NULL; - else - return PyLong_FromUnsignedLongLong(pyw_register_idc_func(name, arg, py_fp)); -} - -//--------------------------------------------------------------------------- -static PyObject *ex_pyw_unregister_idc_func(PyObject *self, PyObject *args) -{ - unsigned PY_LONG_LONG ctxptr; - if ( !PyArg_ParseTuple(args, "K", &ctxptr) ) - return NULL; - return PyLong_FromLong(pyw_unregister_idc_func(ctxptr)); -} - -static PyObject *ex_py_set_idc_func_ex(PyObject *self, PyObject *pyargs) -{ - const char *name; - unsigned PY_LONG_LONG fp_ptr; - const char *args; - int flags; - if ( !PyArg_ParseTuple(pyargs, "sKsi", &name, &fp_ptr, &args, &flags) ) - return NULL; - else - return PyLong_FromLong(py_set_idc_func_ex(name, fp_ptr, args, flags)); -} - -//--------------------------------------------------------------------------- -static PyObject *ex_py_get_call_idc_func(PyObject *self, PyObject *args) -{ - return PyLong_FromUnsignedLongLong(py_get_call_idc_func()); -} - -//------------------------------------------------------------------------- -#pragma warning(pop) - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_expr[] = -{ - {"pyw_register_idc_func", ex_pyw_register_idc_func, METH_VARARGS, ""}, - {"pyw_unregister_idc_func", ex_pyw_unregister_idc_func, METH_VARARGS, ""}, - {"py_get_call_idc_func", ex_py_get_call_idc_func, METH_VARARGS, ""}, - {"py_set_idc_func_ex", ex_py_set_idc_func_ex, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} // End of methods -}; -DRIVER_INIT_METHODS(expr); diff --git a/pywraps/driver_graph.cpp b/pywraps/driver_graph.cpp deleted file mode 100644 index c6d0ab1..0000000 --- a/pywraps/driver_graph.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "py_graph.hpp" - -//-------------------------------------------------------------------------- -//py_choose2_t *last_c2 = NULL; -static PyObject *ex_graph_show(PyObject * /*self*/, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - py_graph_t *ret = py_graph_t::Show(obj); - return PyBool_FromLong(ret == NULL ? 0 : 1); -} - -//-------------------------------------------------------------------------- -static PyObject *ex_graph_refresh(PyObject * /*self*/, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - py_graph_t::Refresh(obj); - Py_RETURN_NONE; -} - -//-------------------------------------------------------------------------- -static PyObject *ex_graph_addcmd(PyObject *self, PyObject *args) -{ - PyObject *obj; - const char *title, *hotkey; - if ( !PyArg_ParseTuple(args, "Oss", &obj, &title, &hotkey) ) - return NULL; - Py_ssize_t r = py_graph_t::AddCommand(obj, title, hotkey); - return Py_BuildValue("n", r); -} - -//-------------------------------------------------------------------------- -static PyMethodDef py_methods_graph[] = -{ - {"show", ex_graph_show, METH_VARARGS, ""}, - {"refresh", ex_graph_refresh, METH_VARARGS, ""}, - {"addcmd", ex_graph_addcmd, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; -DRIVER_INIT_METHODS(graph); \ No newline at end of file diff --git a/pywraps/driver_kernwin.cpp b/pywraps/driver_kernwin.cpp deleted file mode 100644 index c2346d1..0000000 --- a/pywraps/driver_kernwin.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "py_kernwin.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_add_menu_item(PyObject *self, PyObject *args) -{ - const char *menupath, *name, *hotkey; - PyObject *pyfunc, *pyargs; - int flags; - if ( !PyArg_ParseTuple(args, "sssiOO", &menupath, &name, &hotkey, &flags, &pyfunc, &pyargs) ) - return NULL; - return py_add_menu_item(menupath, name, hotkey, flags, pyfunc, pyargs); -} - -//------------------------------------------------------------------------- -static PyObject *ex_del_menu_item(PyObject *self, PyObject *args) -{ - if ( !PyArg_ParseTuple(args, "O", &self) ) - return NULL; - if ( py_del_menu_item(self) ) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_execute_sync(PyObject *self, PyObject *args) -{ - PyObject *pycall; - int reqf; - if ( !PyArg_ParseTuple(args, "Oi", &pycall, &reqf) ) - return NULL; - return PyInt_FromLong(py_execute_sync(pycall, reqf)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_add_hotkey(PyObject *self, PyObject *args) -{ - PyObject *pyfunc; - const char *hotkey; - if ( !PyArg_ParseTuple(args, "sO", &hotkey, &pyfunc) ) - return NULL; - else - return py_add_hotkey(hotkey, pyfunc); -} - -//------------------------------------------------------------------------- -static PyObject *ex_del_hotkey(PyObject *self, PyObject *args) -{ - PyObject *pyctx; - if ( !PyArg_ParseTuple(args, "O", &pyctx) ) - return NULL; - else - return PyInt_FromLong(py_del_hotkey(pyctx) ? 1 : 0); -} - -//------------------------------------------------------------------------- -static PyObject *ex_execute_ui_request(PyObject *self, PyObject *args) -{ - PyObject *py_list; - if ( !PyArg_ParseTuple(args, "O", &py_list) ) - return NULL; - else - return PyBool_FromLong(py_execute_ui_requests(py_list) ? 1 : 0); -} - - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_kernwin[] = -{ - {"py_del_menu_item", ex_del_menu_item, METH_VARARGS, ""}, - {"py_add_menu_item", ex_add_menu_item, METH_VARARGS, ""}, - {"py_execute_sync", ex_execute_sync, METH_VARARGS, ""}, - {"py_add_hotkey", ex_add_hotkey, METH_VARARGS, ""}, - {"py_del_hotkey", ex_del_hotkey, METH_VARARGS, ""}, - {"py_execute_ui_request", ex_execute_ui_request, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; -DRIVER_INIT_METHODS(kernwin); \ No newline at end of file diff --git a/pywraps/driver_nalt.cpp b/pywraps/driver_nalt.cpp deleted file mode 100644 index 4588b7e..0000000 --- a/pywraps/driver_nalt.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "py_nalt.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_get_switch_info_ex(PyObject *self, PyObject *args) -{ - pyul_t ea; - if ( !PyArg_ParseTuple(args, PY_FMT64, &ea) ) - return NULL; - return py_get_switch_info_ex(ea_t(ea)); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_nalt[] = -{ - {"get_switch_info_ex", ex_get_switch_info_ex, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} -}; -DRIVER_INIT_METHODS(nalt); diff --git a/pywraps/driver_notifywhen.cpp b/pywraps/driver_notifywhen.cpp deleted file mode 100644 index ea0cc12..0000000 --- a/pywraps/driver_notifywhen.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "py_notifywhen.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_notify_when(PyObject *self, PyObject *args) -{ - int when; - PyObject *py_callable; - if ( !PyArg_ParseTuple(args, "IO", &when, &py_callable) ) - return NULL; - return Py_BuildValue("i", notify_when(when, py_callable)); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_nw[] = -{ - {"notify_when", ex_notify_when, METH_VARARGS, ""}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; -DRIVER_INIT_METHODS(nw); - -#define DRIVER_INIT -int driver_init() -{ - bool ok = pywraps_nw_init(); - if ( !ok ) - return PLUGIN_SKIP; - pywraps_nw_notify(NW_INITIDA_SLOT); - return PLUGIN_KEEP; -} - -#define DRIVER_TERM -void driver_term() -{ - pywraps_nw_notify(NW_TERMIDA_SLOT); - pywraps_nw_term(); -} diff --git a/pywraps/link_gen.py b/pywraps/link_gen.py old mode 100644 new mode 100755 diff --git a/pywraps/py_appcall.py b/pywraps/py_appcall.py deleted file mode 100644 index 9750a27..0000000 --- a/pywraps/py_appcall.py +++ /dev/null @@ -1,1031 +0,0 @@ -try: - import pywraps - pywraps_there = True -except: - pywraps_there = False -import _idaapi -import random -import operator -import datetime - -if pywraps_there: - _idaapi.appcall = pywraps.appcall - from py_idaapi import * -else: - import idaapi - from idaapi import * - -# ---------------------------------------------------------------------------------------------------------------------------------------------- -# -import types - -# ----------------------------------------------------------------------- -class Appcall_array__(object): - """This class is used with Appcall.array() method""" - def __init__(self, tp): - self.__type = tp - - def pack(self, L): - """Packs a list or tuple into a byref buffer""" - t = type(L) - if not (t == types.ListType or t == types.TupleType): - raise ValueError, "Either a list or a tuple must be passed" - self.__size = len(L) - if self.__size == 1: - self.__typedobj = Appcall__.typedobj(self.__type + ";") - else: - self.__typedobj = Appcall__.typedobj("%s x[%d];" % (self.__type, self.__size)) - # Now store the object in a string buffer - ok, buf = self.__typedobj.store(L) - if ok: - return Appcall__.byref(buf) - else: - return None - - def try_to_convert_to_list(self, obj): - """Is this object a list? We check for the existance of attribute zero and attribute self.size-1""" - if not (hasattr(obj, "0") and hasattr(obj, str(self.__size-1))): - return obj - # at this point, we are sure we have an "idc list" - # let us convert to a Python list - return [getattr(obj, str(x)) for x in xrange(0, self.__size)] - - def unpack(self, buf, as_list=True): - """Unpacks an array back into a list or an object""" - # take the value from the special ref object - if isinstance(buf, PyIdc_cvt_refclass__): - buf = buf.value - - # we can only unpack from strings - if type(buf) != types.StringType: - raise ValueError, "Cannot unpack this type!" - # now unpack - ok, obj = self.__typedobj.retrieve(buf) - if not ok: - raise ValueError, "Failed while unpacking!" - if not as_list: - return obj - return self.try_to_convert_to_list(obj) - - -# ----------------------------------------------------------------------- -# Wrapper class for the appcall() -class Appcall_callable__(object): - """ - Helper class to issue appcalls using a natural syntax: - appcall.FunctionNameInTheDatabase(arguments, ....) - or - appcall["Function@8"](arguments, ...) - or - f8 = appcall["Function@8"] - f8(arg1, arg2, ...) - or - o = appcall.obj() - i = byref(5) - appcall.funcname(arg1, i, "hello", o) - """ - def __init__(self, ea, tp = None, fld = None): - """Initializes an appcall with a given function ea""" - self.__ea = ea - self.__type = tp - self.__fields = fld - self.__options = None # Appcall options - self.__timeout = None # Appcall timeout - - def __get_timeout(self): - return self.__timeout - - def __set_timeout(self, v): - self.__timeout = v - - timeout = property(__get_timeout, __set_timeout) - """An Appcall instance can change its timeout value with this attribute""" - - def __get_options(self): - return self.__options if self.__options != None else Appcall__.get_appcall_options() - - def __set_options(self, v): - if self.timeout: - # If timeout value is set, then put the timeout flag and encode the timeout value - v |= Appcall__.APPCALL_TIMEOUT | (self.timeout << 16) - else: - # Timeout is not set, then clear the timeout flag - v &= ~Appcall__.APPCALL_TIMEOUT - - self.__options = v - - options = property(__get_options, __set_options) - """Sets the Appcall options locally to this Appcall instance""" - - def __call__(self, *args): - """Make object callable. We redirect execution to idaapi.appcall()""" - if self.ea is None: - raise ValueError, "Object not callable!" - - # convert arguments to a list - arg_list = list(args) - - # Save appcall options and set new global options - old_opt = Appcall__.get_appcall_options() - Appcall__.set_appcall_options(self.options) - - # Do the Appcall (use the wrapped version) - e_obj = None - try: - r = _idaapi.appcall( - self.ea, - _idaapi.get_current_thread(), - self.type, - self.fields, - arg_list) - except Exception as e: - e_obj = e - - # Restore appcall options - Appcall__.set_appcall_options(old_opt) - - # Return or re-raise exception - if e_obj: - raise Exception, e_obj - - return r - - def __get_ea(self): - return self.__ea - - def __set_ea(self, val): - self.__ea = val - - ea = property(__get_ea, __set_ea) - """Returns or sets the EA associated with this object""" - - def __get_size(self): - if self.__type == None: - return -1 - r = _idaapi.calc_type_size(_idaapi.cvar.idati, self.__type) - if not r: - return -1 - return r - - size = property(__get_size) - """Returns the size of the type""" - - def __get_type(self): - return self.__type - - type = property(__get_type) - """Returns the typestring""" - - def __get_fields(self): - return self.__fields - - fields = property(__get_fields) - """Returns the field names""" - - - def retrieve(self, src=None, flags=0): - """ - Unpacks a typed object from the database if an ea is given or from a string if a string was passed - @param src: the address of the object or a string - @return: Returns a tuple of boolean and object or error number (Bool, Error | Object). - """ - - # Nothing passed? Take the address and unpack from the database - if src is None: - src = self.ea - - if type(src) == types.StringType: - return _idaapi.unpack_object_from_bv(_idaapi.cvar.idati, self.type, self.fields, src, flags) - else: - return _idaapi.unpack_object_from_idb(_idaapi.cvar.idati, self.type, self.fields, src, flags) - - def store(self, obj, dest_ea=None, base_ea=0, flags=0): - """ - Packs an object into a given ea if provided or into a string if no address was passed. - @param obj: The object to pack - @param dest_ea: If packing to idb this will be the store location - @param base_ea: If packing to a buffer, this will be the base that will be used to relocate the pointers - - @return: - - If packing to a string then a Tuple(Boolean, packed_string or error code) - - If packing to the database then a return code is returned (0 is success) - """ - - # no ea passed? thus pack to a string - if dest_ea is None: - return _idaapi.pack_object_to_bv(obj, - _idaapi.cvar.idati, - self.type, - self.fields, - base_ea, - flags) - else: - return _idaapi.pack_object_to_idb(obj, - _idaapi.cvar.idati, - self.type, - self.fields, - dest_ea, - flags) - -# ----------------------------------------------------------------------- -class Appcall_consts__(object): - """Helper class used by Appcall.Consts attribute - It is used to retrieve constants via attribute access""" - def __init__(self, default=0): - self.__default = default - - def __getattr__(self, attr): - return Appcall__.valueof(attr, self.__default) - -# ----------------------------------------------------------------------- -class Appcall__(object): - APPCALL_MANUAL = 0x1 - """ - Only set up the appcall, do not run it. - you should call CleanupAppcall() when finished - """ - - APPCALL_DEBEV = 0x2 - """ - Return debug event information - If this bit is set, exceptions during appcall - will generate idc exceptions with full - information about the exception - """ - - APPCALL_TIMEOUT = 0x4 - """ - Appcall with timeout - The timeout value in milliseconds is specified - in the high 2 bytes of the 'options' argument: - If timed out, errbuf will contain "timeout". - """ - - def __init__(self): - self.__consts = Appcall_consts__() - def __get_consts(self): - return self.__consts - Consts = property(__get_consts) - """Use Appcall.Consts.CONST_NAME to access constants""" - - @staticmethod - def __name_or_ea(name_or_ea): - """ - Function that accepts a name or an ea and checks if the address is enabled. - If a name is passed then idaapi.get_name_ea() is applied to retrieve the name - @return: - - Returns the resolved EA or - - Raises an exception if the address is not enabled - """ - - # a string? try to resolve it - if type(name_or_ea) == types.StringType: - ea = _idaapi.get_name_ea(_idaapi.BADADDR, name_or_ea) - else: - ea = name_or_ea - # could not resolve name or invalid address? - if ea == _idaapi.BADADDR or not _idaapi.isEnabled(ea): - raise ValueError, "Undefined function " + name_or_ea - return ea - - @staticmethod - def proto(name_or_ea, prototype, flags = None): - """ - Allows you to instantiate an appcall (callable object) with the desired prototype - @param name_or_ea: The name of the function (will be resolved with LocByName()) - @param prototype: - @return: - - On failure it raises an exception if the prototype could not be parsed - or the address is not resolvable - - Returns a callbable Appcall instance with the given prototypes and flags - """ - - # resolve and raise exception on error - ea = Appcall__.__name_or_ea(name_or_ea) - # parse the type - if flags is None: - flags = 1 | 2 | 4 # PT_SIL | PT_NDC | PT_TYP - - result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, prototype, flags) - if result is None: - raise ValueError, "Could not parse type: " + prototype - - # Return the callable method with type info - return Appcall_callable__(ea, result[1], result[2]) - - def __getattr__(self, name_or_ea): - """Allows you to call functions as if they were member functions (by returning a callable object)""" - # resolve and raise exception on error - ea = self.__name_or_ea(name_or_ea) - if ea == _idaapi.BADADDR: - raise ValueError, "Undefined function " + name - # Return the callable method - return Appcall_callable__(ea) - - def __getitem__(self, idx): - """ - Use self[func_name] syntax if the function name contains invalid characters for an attribute name - See __getattr___ - """ - return self.__getattr__(idx) - - @staticmethod - def valueof(name, default=0): - """ - Returns the numeric value of a given name string. - If the name could not be resolved then the default value will be returned - """ - t, v = _idaapi.get_name_value(_idaapi.BADADDR, name) - if t == 0: # NT_NONE - v = default - return v - - @staticmethod - def int64(v): - """Whenever a 64bit number is needed use this method to construct an object""" - return PyIdc_cvt_int64__(v) - - @staticmethod - def byref(val): - """ - Method to create references to immutable objects - Currently we support references to int/strings - Objects need not be passed by reference (this will be done automatically) - """ - return PyIdc_cvt_refclass__(val) - - @staticmethod - def buffer(str = None, size = 0, fill="\x00"): - """ - Creates a string buffer. The returned value (r) will be a byref object. - Use r.value to get the contents and r.size to get the buffer's size - """ - if str is None: - str = "" - left = size - len(str) - if left > 0: - str = str + (fill * left) - r = Appcall__.byref(str) - r.size = size - return r - - @staticmethod - def obj(**kwds): - """Returns an empty object or objects with attributes as passed via its keywords arguments""" - return object_t(**kwds) - - @staticmethod - def cstr(val): - return as_cstr(val) - - @staticmethod - def unicode(s): - return as_unicode(s) - - @staticmethod - def array(type_name): - """Defines an array type. Later you need to pack() / unpack()""" - return Appcall_array__(type_name) - - @staticmethod - def typedobj(typestr, ea=None): - """ - Parses a type string and returns an appcall object. - One can then use retrieve() member method - @param ea: Optional parameter that later can be used to retrieve the type - @return: Appcall object or raises ValueError exception - """ - # parse the type - result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, typestr, 1 | 2 | 4) # PT_SIL | PT_NDC | PT_TYP - if result is None: - raise ValueError, "Could not parse type: " + typestr - # Return the callable method with type info - return Appcall_callable__(ea, result[1], result[2]) - - @staticmethod - def set_appcall_options(opt): - """Method to change the Appcall options globally (not per Appcall)""" - old_opt = Appcall__.get_appcall_options() - _idaapi.cvar.inf.appcall_options = opt - return old_opt - - @staticmethod - def get_appcall_options(): - """Return the global Appcall options""" - return _idaapi.cvar.inf.appcall_options - - @staticmethod - def cleanup_appcall(tid = 0): - """Equivalent to IDC's CleanupAppcall()""" - return _idaapi.cleanup_appcall(tid) - -Appcall = Appcall__() -# - -# ---------------------------------------------------------------------------------------------------------------------------------------------- - -# -a = Appcall # Take a shortcut to Appcall -c = Appcall.Consts # take shortcut to constants - -# ----------------------------------------------------------------------- -# - Adds missing types -# - ... -def init(): - # add neeeded types - if a.valueof("ERROR_FILE_NOT_FOUND") == 0: - add_type("MACRO_ERROR") - - setattr(c, "ERROR_FILE_NOT_FOUND", 2) - - if a.valueof("MEM_COMMIT") == 0: - add_type("MACRO_PAGE") - - # open log file - global test_log - try: - test_log = file("python_test.log", "a") - except: - test_log = None - -# ----------------------------------------------------------------------- -def deinit(): - global test_log - test_log.close() - test_log = None - return 1 - -# ----------------------------------------------------------------------- -def logprint(s): - if not test_log: - print s - else: - test_log.write(s + "\n") - return 1 - -# ----------------------------------------------------------------------- -def add_type(t): - print "adding type:", t - idaapi.import_type(idaapi.cvar.idati, 0, t) - -# ----------------------------------------------------------------------- -def test_init(): - hmod = getmodulehandlew(a.unicode("kernel32.dll")) - print "k32hmod=%x" % hmod - if hmod == 0: - return -1 - p = getprocaddr(hmod, "VirtualAlloc") - if p == 0: - return -2 - print "VirtualAlloc->%x" % p - virtualalloc.ea = p - - p = getprocaddr(hmod, "VirtualFree") - if p == 0: - return -3 - print "VirtualFree->%x" % p - virtualfree.ea = p - - m = virtualalloc(0, c.MEM_COMMIT, 0x1000, c.PAGE_EXECUTE_READWRITE) - idc.RefreshDebuggerMemory() - print "%x: allocated memory\n" % m - global WRITE_AREA - WRITE_AREA = m - - return 1 - -# ----------------------------------------------------------------------- -def test_deinit(): - virtualfree(WRITE_AREA, 0, c.MEM_FREE) - -# ----------------------------------------------------------------------- -# Tests changedir/setdir/buffer creation (two methods) and cstr() -def test_enum_files(): - # create a buffer - savedpath = a.byref("\x00" * 260) - # get current directory - n = getcurdir(250, savedpath) - out = [] - out.append("curdir=%s" % savedpath.value[0:n]) - - # get windir - windir = a.buffer(size=260) # create a buffer using helper function - n = getwindir(windir, windir.size) - if n == 0: - return -1 # could not get current directory - - windir = windir.value[:n] - out.append("windir=%s" % windir) - - # change to windows folder - setcurdir(windir) - - # initiate find - fd = a.obj() - h = findfirst("*.exe", fd) - if h == -1: - return -2 # no files found! - - found = -6 - while True: - fn = a.cstr(fd.cFileName) - if "regedit" in fn: - found = 1 - out.append("fn=%s<" % fn) - fd = a.obj() # reset the FD object - ok = findnext(h, fd) - if not ok: - break - # - findclose(h) - - # restore cur dir - setcurdir(savedpath.value) - - # verify - t = a.buffer(size=260) - n = getcurdir(t.size, t) - if t.cstr() != savedpath.cstr(): - return -4 # could not restore cur dir - - out.append("curdir=%s<" % t.cstr()) -# print "all done!" -# for l in out: -# print l - - return found -# ----------------------------------------------------------------------- -def test_gpa(): - h = loadlib("user32.dll") - if h == 0: - print "failed to load library!" - return -1 - p = getprocaddr(h, "FindWindowA") - if p == 0: - print "failed to gpa!" - return -2 - findwin = a.proto(p, "int FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);") - hwnd = findwin("TIdaWindow", 0) - freelib(h) - print "%x: ok!->hwnd=%x" % (p, hwnd) - - return 1 - -# ----------------------------------------------------------------------- -def test_loaddll(): - h = loadlib("twain_32.dll") - if h == 0: - print "failed to load twain32 library!" - return -1 - return 1 - -# ----------------------------------------------------------------------- -# Packs a simple structure (into the database) and unpacks it back using the idaapi methods -def test_pck_idb_raw(): - name, tp, flds = idc.ParseType("struct { int a, b; char x[5];};", 0) - o = a.obj(a=15, b=17,x="hi") - idaapi.pack_object_to_idb(o, idaapi.cvar.idati, tp, flds, WRITE_AREA, 0) - - ok, obj = idaapi.unpack_object_from_idb(idaapi.cvar.idati, tp, flds, WRITE_AREA, 0) - if obj.a != 15 and obj.b != 17 and obj != "hi": - return -2 - return 1 - -# ----------------------------------------------------------------------- -# Packs a simple structure (into a string) and unpacks it back using the idaapi methods -def test_pck_bv_raw(): - name, tp, flds = idc.ParseType("struct { int a; char x[5]; int b;};", 0) - va,vb,vx = 15,17,"hi" - o = a.obj(a=va, b=vb,x=vx) - ok, s = idaapi.pack_object_to_bv(o, idaapi.cvar.idati, tp, flds, WRITE_AREA, 0) - if not ok: - return -1 - ok, obj = idaapi.unpack_object_from_idb(idaapi.cvar.idati, tp, flds, WRITE_AREA, 0) - if obj.a != va and obj.b != vb and obj.x != vx: - return -2 - return 1 - -# ----------------------------------------------------------------------- -# 1. Unpacks the DOS header at 0x400000 and verify the fields -# 2. Unpacks a string and see if it is unpacked correctly -def test_unpack_raw(): - name, tp, flds = idc.ParseType("IMAGE_DOS_HEADER;", 0) - ok, obj = idaapi.unpack_object_from_idb(idaapi.cvar.idati, tp, flds, 0x400000, 0) - if obj.e_magic != 23117 and obj.e_cblp != 144: - return -1 - - name, tp, flds = idc.ParseType("struct abc_t { int a, b;};", 0) - ok, obj = idaapi.unpack_object_from_bv(idaapi.cvar.idati, tp, flds, "\x01\x00\x00\x00\x02\x00\x00\x00", 0) - if obj.a != 1 and obj.b != 2: - return -2 - - return 1 - -# ----------------------------------------------------------------------- -# Packs/Unpacks a structure to the database using appcall facilities -def test_pck_idb(): - print "%x: ..." % WRITE_AREA - tp = a.typedobj("struct { int a, b; char x[5];};") - o = a.obj(a=16, b=17,x="zzzhi") - if tp.store(o, WRITE_AREA) != 0: - return -1 - idc.RefreshDebuggerMemory() - - ok, r = tp.retrieve(WRITE_AREA) - if not ok: - return -2 - if r.a != o.a and r.b != o.b and r.x != o.x: - return -3 - - return 1 - -# ----------------------------------------------------------------------- -# Packs/Unpacks a structure to/from a string -def test_pck_bv(): - tp = a.typedobj("struct { int a, b; char x[5];};") - o = a.obj(a=16, b=17,x="zzzhi") - ok, packed = tp.store(o) - if not ok: - return -1 - print "packed->", repr(packed) - ok, r = tp.retrieve(packed) - if not ok: - return -2 - - if r.a != o.a and r.b != o.b and r.x != o.x: - return -3 - - return 1 - -# ----------------------------------------------------------------------- -# Test work with local types -def test_local_types(): - (type, fields) = GetLocalTinfo(1) - if not type: - return -1 - - decl = GetLocalType(1, PRTYPE_MULTI) - if decl != "enum\n"\ - + "{\n"\ - + " FEATURE_OBJECT_CACHING = 0x0,\n"\ - + " FEATURE_ZONE_ELEVATION = 0x1,\n"\ - + " FEATURE_MIME_HANDLING = 0x2,\n"\ - + " FEATURE_MIME_SNIFFING = 0x3,\n"\ - + " FEATURE_WINDOW_RESTRICTIONS = 0x4,\n"\ - + " FEATURE_WEBOC_POPUPMANAGEMENT = 0x5,\n"\ - + " FEATURE_BEHAVIORS = 0x6,\n"\ - + " FEATURE_DISABLE_MK_PROTOCOL = 0x7,\n"\ - + " FEATURE_LOCALMACHINE_LOCKDOWN = 0x8,\n"\ - + " FEATURE_SECURITYBAND = 0x9,\n"\ - + " FEATURE_RESTRICT_ACTIVEXINSTALL = 0xA,\n"\ - + " FEATURE_VALIDATE_NAVIGATE_URL = 0xB,\n"\ - + " FEATURE_RESTRICT_FILEDOWNLOAD = 0xC,\n"\ - + " FEATURE_ADDON_MANAGEMENT = 0xD,\n"\ - + " FEATURE_PROTOCOL_LOCKDOWN = 0xE,\n"\ - + " FEATURE_HTTP_USERNAME_PASSWORD_DISABLE = 0xF,\n"\ - + " FEATURE_SAFE_BINDTOOBJECT = 0x10,\n"\ - + " FEATURE_UNC_SAVEDFILECHECK = 0x11,\n"\ - + " FEATURE_GET_URL_DOM_FILEPATH_UNENCODED = 0x12,\n"\ - + " FEATURE_TABBED_BROWSING = 0x13,\n"\ - + " FEATURE_SSLUX = 0x14,\n"\ - + " FEATURE_DISABLE_NAVIGATION_SOUNDS = 0x15,\n"\ - + " FEATURE_DISABLE_LEGACY_COMPRESSION = 0x16,\n"\ - + " FEATURE_FORCE_ADDR_AND_STATUS = 0x17,\n"\ - + " FEATURE_XMLHTTP = 0x18,\n"\ - + " FEATURE_DISABLE_TELNET_PROTOCOL = 0x19,\n"\ - + " FEATURE_FEEDS = 0x1A,\n"\ - + " FEATURE_BLOCK_INPUT_PROMPTS = 0x1B,\n"\ - + " FEATURE_ENTRY_COUNT = 0x1C,\n"\ - + "} _tagINTERNETFEATURELIST\n": - print "decl = " + decl - return -2 - - return 1 - -# ----------------------------------------------------------------------- -# various tests -def test1(stage): - # call a method that takes a string buffer and appends a dot to its end - if stage == st_ref2: - buf = a.buffer("test", 100) - vals = [378, 424, 470] - for i in xrange(0, 2+1): - n = a._ref2(buf) - if buf.value[4+i] != '.': - return -st_ref2 - if vals[i] != n: - return -stage - # call a method that takes an integer reference - elif stage == st_ref1: - v = 5 - i = a.byref(v) - a._ref1(i) - if v + 1 != i.value: - return -stage - # call a method that takes an array of integers - elif stage == st_ref3: - # create an array type - arr = a.array("int") - # create a list - L = [x for x in xrange(1, 10)] - # pack the list - p_list = arr.pack(L) - # appcall to compute the total - c_total = a._ref3(p_list, len(L)) - # internally compute the total - total = reduce(operator.add, L) - if total != c_total: - return -stage - # subst() - elif stage == st_subst: - v = a._subst(5, 1) - if v != 4: - return -stage - v = subst(5, 1) # subst() / pascal - if v != -4: - return -stage*2 - elif stage == st_make2: - x = a._str2_make(5) - s = a.cstr(x.next.str) -# print "len=%d;<%s>" % (len(s), s) - if s != "This is string 2": - return -stage - n = a._str2_print(x) - if n != 5: - return -st_make2*2 - elif stage == st_make1: - x = a._str1_make(6) - if x.val != 1 and x.next.val != 2: - return -st_make1 - n = a._str1_print(x) - if n != 6: - return -stage - # 64bit test - elif stage == st_make3: - global gr - try: - x = a._str3_make(6) - gr = x - except Exception as e: - print "Exception: ", str(e) - return -stage - print "x.val32=", x.val32 - if (x.val32 != 1) and (x.val64 != (1 << 32)): - return -stage * 2 - va = 0 - vb = 0 - r = x - i = 0 - while x != 0: - i += 1 - print "1" - va += x.val32 - print "2" - vb += x.val64.value - print "3" - x = x.next - print "i=", i, "a=", va, "b=", vb - if va != 21 and vb != 90194313216: - return -stage*3 - elif stage == st_asm: - n = asm1(5, 1) - if n != 4: - return -stage - n = asm2(5, 1, 1) - if n != 7: - return -stage*2 - elif stage == st_byvalref1: - v1 = a.obj(val=5, next=0) - v2 = a.obj(str="Hello", next=0) - n = a._byvalref1(v1, 1, v2) - if n != 78: - return -stage - # v1 is passed by ref, thus it will be changed - if n + 1 != v1.val: - return -stage * 2 - elif stage == st_altsum: - # 1 + 2 - 3 + 5 = 5 - n = altsum(1, 2, 3, 5, 0) - if n != 5: - return -stage; - elif stage == st_op64: - # invalid opcode, should return -1 - r = a._op_two64(1, 2, 6).value - print "r=", r - if r != -1: - return -stage - r = a._op_two64(6, a.int64(2), 3).value - if r != 12: - return -stage * 2 - return 1 - elif stage == st_byval3: - o = a.obj(val=6,next=a.obj(val=-1, next=0)) -# print "before: o.val=%d o.next.val=%d" % (o.val, o.next.val) - n = a._byval3(o) - if n != 5: - return -stage -# print "after: o.val=%d o.next.val=%d, n=%d" % (o.val, o.next.val, n) - #--------- - elif stage == st_ex: - def doit(): - try: - # causes a DebugBreak() - a._ex2(1) - except Exception as e: - if not "Software breakpoint" in e.message: - return -stage - try: - a._ex1(1, 2) - return -st_ex * 2 - except Exception as e: - if not "referenced memory" in e.message: - return -stage - return 1 - old = a.set_appcall_options(0) - r = doit() - a.set_appcall_options(old) - if r <= 0: - return r - #--------- - elif stage == st_ref4: - i = a.int64(5) - v = a.byref(i) - if a._ref4(v) != 1: - return -st_ref4 - # test (in case recycling failed) - if v.value.value != 6: - return -st_ref4 * 2 - # test recycling - if i.value != 6: - return -st_ref4 * 3 - # return success - return 1 - -# ----------------------------------------------------------------------- -def test2(): - fn = "pc_win32_appcall.pe" - - # Try to open an non-existing file - h = a._file_open(fn + ".1") - if h != 0: - return -1 - - n = getlasterror() - print "gle=", n - if n != c.ERROR_FILE_NOT_FOUND: - return -2 - - # Should succeed - h = a._file_open(fn) - if h == 0: - return -3 - - s = a.buffer("", 10, "!") - n = a._file_read(h, s, 2) -# print "read=%d; buf=%s" % (n, repr(s.value)) - if s.value[:2] != "MZ": - return -4 - - n = a._file_close(h) - if n != h-1: - return -5 - - return 1 - -# ----------------------------------------------------------------------- -# This test changes the appcall options and sees if the appcall -# generates an exception and if we get it properly -# An appcall can throw an exception: -# - ValueError: conversion from/to idc/py failed -# - OSError: an OSError when APPCALL_DEBEV in Appcall_Options. In that case check the exc.args[0] to get the debug event -# - Exception: in all other cases -def test_exec_throw(): - old = a.set_appcall_options(0) - print "old_opt=", old, "new=0" - try: - # causes a divide by zero exception (will be reported as an Exception) - print a._op_two64(2,0,4).value - return -1 - except Exception as e: - print "runtime error!" - - # now appcall exceptions will be reported as OSErr and other exceptions as Exception - print "old_opt=", a.set_appcall_options(a.APPCALL_DEBEV), "new=2" - try: - # causes an error: Wrong number of arguments - print a._op_two64(2).value - return -2 - except OSError, e: - return -3 - except Exception as e: - print "Got other exception:", e # good - - try: - # causes an OS error and "e" will contain the last debug_event - # in our case exception, and the code is int_divide_zero = 0xC0000094 - print a._op_two64(2, 0, 4).value - return -4 - except OSError, e: - if idaapi.as_uint32(e.args[0].code) != 0xC0000094: - return -5 - except Exception as e: - print "Got other exception:", e - return -6 - a.set_appcall_options(old) - return 1 -# ----------------------------------------------------------------------- -# all the tests that take zero parameters -tests0 = (test_gpa, test_pck_idb_raw, test_pck_bv_raw, - test_unpack_raw, test_pck_idb, test_pck_bv, test_local_types, - test_enum_files, test2, test_exec_throw, test_loaddll) -test_log = None # test log file - -# ----------------------------------------------------------------------- -def test_all(): - if test_init() <= 0: - print "test_init() failed!" - return -1 - - # tests 0 - for t in tests0: - print "testing->", t - r = t() - if r <= 0: - return r - # test 1 - for i in xrange(1, st_last): - print "test1 #", i - r = test1(i) - if r <= 0: - return r - - logprint(datetime.date.today().strftime("Python was here: %Y-%m-%d @ %I:%M:%S%p")) - - test_deinit() - - return 1 - -# ----------------------------------------------------------------------- -init() - -# reference to an integer. use i.value to dereference -i = a.byref(5) - -# object representing the str1_t type -o = a.obj(val=5,next=a.obj(val=-2, next=0)) - -# dictionary representing the str1_t type -# (dictionaries will be converted into IDC objects) -d = {'val':5, 'next': {'val':-2, 'next':0} } - -# initialize some pointers -findfirst = a["__imp__FindFirstFileA@8"] -findnext = a["__imp__FindNextFileA@8"] -findclose = a["__imp__FindClose@4"] -getlasterror = a["__imp__GetLastError@0"] -setcurdir = a["__imp__SetCurrentDirectoryA@4"] -beep = a["__imp__Beep@8"] -getwindir = a["__imp__GetWindowsDirectoryA@8"] -getprocaddr = a.proto("__imp__GetProcAddress@8", "int (__stdcall *GetProcAddress)(int hModule, LPCSTR lpProcName);") -getcurdir = a["__imp__GetCurrentDirectoryA@8"] -loadlib = a.proto("__imp__LoadLibraryA@4", "int (__stdcall *LoadLibraryA)(const char *lpLibFileName);") -freelib = a.proto("__imp__FreeLibrary@4", "int (__stdcall *FreeLibrary)(int hLibModule);") -setlasterror = a.typedobj("void __stdcall SetLastError(int dwErrCode);") -getmodulehandlew = a.proto("__imp__GetModuleHandleW@4", "int (__stdcall *GetModuleHandleW)(LPCWSTR lpModuleName);") -virtualalloc = a.typedobj("int __stdcall VirtualAlloc(int lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);") -# typed objects can become calling if an EA was provided. Thus virtualfree.ea = some_address, then we can call virtualfree(., .., ...) -virtualfree = a.typedobj("BOOL __stdcall VirtualFree(int lpAddress, SIZE_T dwSize, DWORD dwFreeType);") -asm1 = a.proto("_asm1", "int __usercall asm1(int a, int b);") -asm2 = a.proto("_asm2", "int __usercall asm2(int a, int b, int c);") -asm3 = a.proto("_asm3", "int __usercall asm3(int f, int a, int b, int c);") -asm4 = a.proto("_asm4", "unsigned __int16 __usercall asm4(unsigned __int8 a, unsigned __int8 b);") -asm5 = a.proto("_asm5", "unsigned int __usercall asm5(unsigned __int8 a, unsigned __int8 b, unsigned __int8 c
, int d);") -altsum = a.proto("_va_altsum", "int __cdecl va_altsum(int n1, ...);") -getcommandline = a.proto("__imp__GetCommandLineA@0", "LPSTR (__stdcall *GetCommandLineA)();") - -# make an appcall with a user defined prototype -subst = a.proto("_subst", "int __pascal subst(int a, int b);") - -# some test identifiers -st_ref1 = 1 -st_ref2 = 2 -st_ref3 = 3 -st_subst = 4 -st_make1 = 5 -st_make2 = 6 -st_asm = 7 -st_ex = 8 -st_byval3 = 9 -st_byvalref1 = 10 -st_altsum = 11 -st_make3 = 12 -st_op64 = 13 -st_ref4 = 14 -st_last = 15 -# some area where we can write some bytes _safely_ -WRITE_AREA = 0x400020 -gr = None -# - -# initialize the test -#test_init() diff --git a/pywraps/py_askusingform.hpp b/pywraps/py_askusingform.hpp index 0561325..f69ea58 100644 --- a/pywraps/py_askusingform.hpp +++ b/pywraps/py_askusingform.hpp @@ -1,7 +1,8 @@ #ifndef __PY_ASKUSINGFORM__ #define __PY_ASKUSINGFORM__ -// +// +static qvector py_compiled_form_vec; void free_compiled_form_instances(void) { while ( !py_compiled_form_vec.empty() ) @@ -15,10 +16,10 @@ void free_compiled_form_instances(void) newref_t unused(PyObject_CallMethod(ref.o, (char *)"Free", "()")); } } -// +// //--------------------------------------------------------------------------- -// +// #define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa; //--------------------------------------------------------------------------- @@ -26,7 +27,7 @@ static bool textctrl_info_t_assign(PyObject *self, PyObject *other) { textctrl_info_t *lhs = textctrl_info_t_get_clink(self); textctrl_info_t *rhs = textctrl_info_t_get_clink(other); - if (lhs == NULL || rhs == NULL) + if ( lhs == NULL || rhs == NULL ) return false; *lhs = *rhs; @@ -220,10 +221,10 @@ static PyObject *formchgcbfa_get_field_value( { intvec_t intvec; // Returned as 1-base - if (fa->get_chooser_value(fid, &intvec)) + if ( fa->get_chooser_value(fid, &intvec) ) { // Make 0-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it) + for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it ) (*it)--; ref_t l(PyW_IntVecToPyList(intvec)); l.incref(); @@ -347,7 +348,7 @@ static bool formchgcbfa_set_field_value( break; // Make 1-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it) + for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it ) (*it)++; return fa->set_chooser_value(fid, &intvec); @@ -381,7 +382,6 @@ static size_t py_get_OpenForm() return (size_t)OpenForm_c; } -static qvector py_compiled_form_vec; static void py_register_compiled_form(PyObject *py_form) { ref_t ref = borref_t(py_form); @@ -396,6 +396,6 @@ static void py_unregister_compiled_form(PyObject *py_form) py_compiled_form_vec.del(ref); } -// +// #endif // __PY_ASKUSINGFORM__ diff --git a/pywraps/py_askusingform.py b/pywraps/py_askusingform.py old mode 100644 new mode 100755 index e88c345..f4a8e04 --- a/pywraps/py_askusingform.py +++ b/pywraps/py_askusingform.py @@ -68,7 +68,7 @@ except Exception as e: print("Using PyWraps: %s" % pywraps_there) # -------------------------------------------------------------------------- -# +# #ICON WARNING|QUESTION|INFO|NONE #AUTOHIDE NONE|DATABASE|REGISTRY|SESSION #HIDECANCEL @@ -1394,560 +1394,4 @@ def OpenForm(*args): set_script_timeout(old) -# - -# -# -------------------------------------------------------------------------- -class TestEmbeddedChooserClass(Choose2): - """ - A simple chooser to be used as an embedded chooser - """ - def __init__(self, title, nb = 5, flags=0): - Choose2.__init__(self, - title, - [ ["Address", 10], ["Name", 30] ], - embedded=True, width=30, height=20, flags=flags) - self.n = 0 - self.items = [ self.make_item() for x in xrange(0, nb+1) ] - self.icon = 5 - self.selcount = 0 - - def make_item(self): - r = [str(self.n), "func_%04d" % self.n] - self.n += 1 - return r - - def OnClose(self): - pass - - def OnGetLine(self, n): - print("getline %d" % n) - return self.items[n] - - def OnGetSize(self): - n = len(self.items) - print("getsize -> %d" % n) - return n - -# -------------------------------------------------------------------------- -class MyForm(Form): - def __init__(self): - self.invert = False - self.EChooser = TestEmbeddedChooserClass("E1", flags=Choose2.CH_MULTI) - Form.__init__(self, r"""STARTITEM {id:rNormal} -BUTTON YES* Yeah -BUTTON NO Nope -BUTTON CANCEL Nevermind -Form Test - -{FormChangeCb} -This is a string: +{cStr1}+ -This is an address: +{cAddr1}+ - -Escape\{control} -This is a string: '{cStr2}' -This is a number: {cVal1} - -<#Hint1#Enter name:{iStr1}> -<#Hint2#Select color:{iColor1}> -Browse test -<#Select a file to open#Browse to open:{iFileOpen}> -<#Select a file to save#Browse to save:{iFileSave}> -<#Select dir#Browse for dir:{iDir}> -Type -<#Select type#Write a type:{iType}> -Numbers -<##Enter a selector value:{iSegment}> -<##Enter a raw hex:{iRawHex}> -<##Enter a character:{iChar}> -<##Enter an address:{iAddr}> -Button test -<##Button1:{iButton1}> <##Button2:{iButton2}> - -Check boxes: - - -{cGroup1}> - -Radio boxes: - - -{cGroup2}> - -The end! -""", { - 'cStr1': Form.StringLabel("Hello"), - 'cStr2': Form.StringLabel("StringTest"), - 'cAddr1': Form.NumericLabel(0x401000, Form.FT_ADDR), - 'cVal1' : Form.NumericLabel(99, Form.FT_HEX), - 'iStr1': Form.StringInput(), - 'iColor1': Form.ColorInput(), - 'iFileOpen': Form.FileInput(open=True), - 'iFileSave': Form.FileInput(save=True), - 'iDir': Form.DirInput(), - 'iType': Form.StringInput(tp=Form.FT_TYPE), - 'iSegment': Form.NumericInput(tp=Form.FT_SEG), - 'iRawHex': Form.NumericInput(tp=Form.FT_RAWHEX), - 'iAddr': Form.NumericInput(tp=Form.FT_ADDR), - 'iChar': Form.NumericInput(tp=Form.FT_CHAR), - 'iButton1': Form.ButtonInput(self.OnButton1), - 'iButton2': Form.ButtonInput(self.OnButton2), - 'cGroup1': Form.ChkGroupControl(("rNormal", "rError", "rWarnings")), - 'cGroup2': Form.RadGroupControl(("rRed", "rGreen", "rBlue")), - 'FormChangeCb': Form.FormChangeCb(self.OnFormChange), - 'cEChooser' : Form.EmbeddedChooserControl(self.EChooser) - }) - - - def OnButton1(self, code=0): - print("Button1 pressed") - - - def OnButton2(self, code=0): - print("Button2 pressed") - - - def OnFormChange(self, fid): - if fid == self.iButton1.id: - print("Button1 fchg;inv=%s" % self.invert) - self.SetFocusedField(self.rNormal) - self.EnableField(self.rError, self.invert) - self.invert = not self.invert - elif fid == self.iButton2.id: - g1 = self.GetControlValue(self.cGroup1) - g2 = self.GetControlValue(self.cGroup2) - d = self.GetControlValue(self.iDir) - f = self.GetControlValue(self.iFileOpen) - print("cGroup2:%x;Dir=%s;fopen=%s;cGroup1:%x" % (g1, d, f, g2)) - elif fid == self.cEChooser.id: - l = self.GetControlValue(self.cEChooser) - print("Chooser: %s" % l) - else: - print(">>fid:%d" % fid) - return 1 - - - -# -------------------------------------------------------------------------- -def stdalone_main(): - f = MyForm() - f, args = f.Compile() - print args[0] - print args[1:] - f.rNormal.checked = True - f.rWarnings.checked = True - print hex(f.cGroup1.value) - - f.rGreen.selected = True - print f.cGroup2.value - print "Title: '%s'" % f.title - - f.Free() - -# -------------------------------------------------------------------------- -def ida_main(): - # Create form - global f - f = MyForm() - - # Compile (in order to populate the controls) - f.Compile() - - f.iColor1.value = 0x5bffff - f.iDir.value = os.getcwd() - f.rNormal.checked = True - f.rWarnings.checked = True - f.rGreen.selected = True - f.iStr1.value = "Hello" - f.iFileSave.value = "*.*" - f.iFileOpen.value = "*.*" - # Execute the form - ok = f.Execute() - print("r=%d" % ok) - if ok == 1: - print("f.str1=%s" % f.iStr1.value) - print("f.color1=%x" % f.iColor1.value) - print("f.openfile=%s" % f.iFileOpen.value) - print("f.savefile=%s" % f.iFileSave.value) - print("f.dir=%s" % f.iDir.value) - print("f.type=%s" % f.iType.value) - print("f.seg=%s" % f.iSegment.value) - print("f.rawhex=%x" % f.iRawHex.value) - print("f.char=%x" % f.iChar.value) - 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() - if sel is None: - print("No selection") - else: - print("Selection: %s" % sel) - - # Dispose the form - f.Free() - -# -------------------------------------------------------------------------- -def ida_main_legacy(): - # Here we simply show how to use the old style form format using Python - - # Sample form from kernwin.hpp - s = """Sample dialog box - - -This is sample dialog box for %A -using address %$ - -<~E~nter value:N:32:16::> -""" - - # Use either StringArgument or NumericArgument to pass values to the function - num = Form.NumericArgument('N', value=123) - ok = idaapi.AskUsingForm(s, - Form.StringArgument("PyAskUsingForm").arg, - Form.NumericArgument('$', 0x401000).arg, - num.arg) - if ok == 1: - print("You entered: %x" % num.value) - -# -------------------------------------------------------------------------- -def test_multilinetext_legacy(): - # Here we text the multi line text control in legacy mode - - # Sample form from kernwin.hpp - s = """Sample dialog box - -This is sample dialog box - -""" - # Use either StringArgument or NumericArgument to pass values to the function - ti = textctrl_info_t("Some initial value") - ok = idaapi.AskUsingForm(s, pointer(c_void_p.from_address(ti.clink_ptr))) - if ok == 1: - print("You entered: %s" % ti.text) - - del ti - -# -------------------------------------------------------------------------- -class MyForm2(Form): - """Simple Form to test multilinetext and combo box controls""" - def __init__(self): - Form.__init__(self, r"""STARTITEM 0 -BUTTON YES* Yeah -BUTTON NO Nope -BUTTON CANCEL NONE -Form Test - -{FormChangeCb} - -""", { - 'txtMultiLineText': Form.MultiLineTextControl(text="Hello"), - 'FormChangeCb': Form.FormChangeCb(self.OnFormChange), - }) - - - def OnFormChange(self, fid): - if fid == self.txtMultiLineText.id: - pass - elif fid == -2: - ti = self.GetControlValue(self.txtMultiLineText) - print "ti.text = %s" % ti.text - else: - print(">>fid:%d" % fid) - return 1 - -# -------------------------------------------------------------------------- -def test_multilinetext(execute=True): - """Test the multilinetext and combobox controls""" - f = MyForm2() - f, args = f.Compile() - if execute: - ok = f.Execute() - else: - print args[0] - print args[1:] - ok = 0 - - if ok == 1: - assert f.txtMultiLineText.text == f.txtMultiLineText.value - print f.txtMultiLineText.text - - f.Free() - -# -------------------------------------------------------------------------- -class MyForm3(Form): - """Simple Form to test multilinetext and combo box controls""" - def __init__(self): - self.__n = 0 - Form.__init__(self, -r"""BUTTON YES* Yeah -BUTTON NO Nope -BUTTON CANCEL NONE -Dropdown list test - -{FormChangeCb} - - -""", { - 'FormChangeCb': Form.FormChangeCb(self.OnFormChange), - 'cbReadonly': Form.DropdownListControl( - items=["red", "green", "blue"], - readonly=True, - selval=1), - 'cbEditable': Form.DropdownListControl( - items=["1MB", "2MB", "3MB", "4MB"], - readonly=False, - selval="4MB"), - 'iButtonAddelement': Form.ButtonInput(self.OnButtonNop), - 'iButtonSetIndex': Form.ButtonInput(self.OnButtonNop), - 'iButtonSetString': Form.ButtonInput(self.OnButtonNop), - }) - - - def OnButtonNop(self, code=0): - """Do nothing, we will handle events in the form callback""" - pass - - def OnFormChange(self, fid): - if fid == self.iButtonSetString.id: - s = idc.AskStr("none", "Enter value") - if s: - self.SetControlValue(self.cbEditable, s) - elif fid == self.iButtonSetIndex.id: - s = idc.AskStr("1", "Enter index value:") - if s: - try: - i = int(s) - except: - i = 0 - self.SetControlValue(self.cbReadonly, i) - elif fid == self.iButtonAddelement.id: - # add a value to the string list - self.__n += 1 - self.cbReadonly.add("some text #%d" % self.__n) - # Refresh the control - self.RefreshField(self.cbReadonly) - elif fid == -2: - s = self.GetControlValue(self.cbEditable) - print "user entered: %s" % s - sel_idx = self.GetControlValue(self.cbReadonly) - - return 1 - -# -------------------------------------------------------------------------- -def test_dropdown(execute=True): - """Test the combobox controls, in a modal dialog""" - f = MyForm3() - f, args = f.Compile() - if execute: - ok = f.Execute() - else: - print args[0] - print args[1:] - ok = 0 - - if ok == 1: - print "Editable: %s" % f.cbEditable.value - print "Readonly: %s" % f.cbReadonly.value - - f.Free() - -# -------------------------------------------------------------------------- -tdn_form = None -def test_dropdown_nomodal(): - """Test the combobox controls, in a non-modal form""" - global tdn_form - if tdn_form is None: - tdn_form = MyForm3() - tdn_form.modal = False - tdn_form.openform_flags = idaapi.PluginForm.FORM_TAB - tdn_form, _ = tdn_form.Compile() - tdn_form.Open() - -# -# -------------------------------------------------------------------------- - -# -# -------------------------------------------------------------------------- -class MainChooserClass(Choose2): - def __init__(self, title, icon): - Choose2.__init__(self, - title, - [ ["Item", 10] ], - icon=icon, - flags=Choose2.CH_NOIDB, - embedded=True, width=30, height=20) - - def OnClose(self): - pass - - def OnGetLine(self, n): - return ["Option %d" % n] - - def OnGetSize(self): - return 10 - - def OnCommand(self, n, cmd_id): - if cmd_id == self.cmd_id1: - print("Context menu on: %d" % n) - - return 0 - - -# -------------------------------------------------------------------------- -class AuxChooserClass(Choose2): - def __init__(self, title, icon): - Choose2.__init__(self, - title, - [ ["Item", 10] ], - icon=icon, - flags=Choose2.CH_NOIDB | Choose2.CH_MULTI, - embedded=True, width=30, height=20) - - def OnClose(self): - pass - - def OnGetLine(self, n): - return ["Item %d" % n] - - def OnGetSize(self): - t = self.form.main_current_index - return 0 if t < 0 else t+1 - - -# -------------------------------------------------------------------------- -class MyChooserForm(Form): - - # Custom icon data - icon_data = ( - "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" - "\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1F\xF3\xFF" - "\x61\x00\x00\x00\x7D\x49\x44\x41\x54\x78\xDA\x63\x64\xC0\x0E\xFE" - "\xE3\x10\x67\x24\x28\x00\xD2\xFC\xF3\xAF\x36\x56\xDD\xEC\xCC\x57" - "\x31\xF4\x20\x73\xC0\xB6\xE2\xD2\x8C\x66\x08\x5C\x2F\x8A\x01\x84" - "\x34\x63\x73\x09\x23\xA9\x9A\xD1\x0D\x61\x44\xD7\xCC\xCF\x02\x71" - "\xE2\xC7\x3F\xA8\x06\x62\x13\x07\x19\x42\x7D\x03\x48\xF5\xC6\x20" - "\x34\x00\xE4\x57\x74\xFF\xE3\x92\x83\x19\xC0\x40\x8C\x21\xD8\x34" - "\x33\x40\xA3\x91\x01\x97\x21\xC8\x00\x9B\x66\x38\x01\x33\x00\x44" - "\x50\x92\x94\xB1\xBA\x04\x8B\x66\x9C\x99\x09\xC5\x10\x1C\xE2\x18" - "\xEA\x01\xA3\x65\x55\x0B\x33\x14\x07\x63\x00\x00\x00\x00\x49\x45" - "\x4E\x44\xAE\x42\x60\x82") - - - def Free(self): - # Call the base - Form.Free(self) - - # Free icon - if self.icon_id != 0: - idaapi.free_custom_icon(self.icon_id) - self.icon_id = 0 - - - def __init__(self): - # Load custom icon - self.icon_id = idaapi.load_custom_icon(data=MyChooserForm.icon_data) - if self.icon_id == 0: - raise RuntimeError("Failed to load icon data!") - - self.main_current_index = -1 - self.EChMain = MainChooserClass("MainChooser", self.icon_id) - self.EChAux = AuxChooserClass("AuxChooser", self.icon_id) - - # Link the form to the EChooser - self.EChMain.form = self - self.EChAux.form = self - - Form.__init__(self, r"""STARTITEM 0 -Form with choosers - - {FormChangeCb} - Select an item in the main chooser: - -
- - - - -""", { - 'ctrlSelectionEdit' : Form.StringInput(), - 'FormChangeCb' : Form.FormChangeCb(self.OnFormChange), - 'ctrlMainChooser' : Form.EmbeddedChooserControl(self.EChMain), - 'ctrlAuxChooser' : Form.EmbeddedChooserControl(self.EChAux), - }) - - - def refresh_selection_edit(self): - if self.main_current_index < 0: - s = "No selection in the main chooser" - else: - s = "Main %d" % self.main_current_index - - # Get selection in the aux chooser - sel = self.GetControlValue(self.ctrlAuxChooser) - if sel: - s = "%s - Aux item(s): %s" % (s, ",".join(str(x) for x in sel)) - - # Update string input - self.SetControlValue(self.ctrlSelectionEdit, s) - - - def OnFormChange(self, fid): - if fid == -1: - print("Initialization") - self.refresh_selection_edit() - - # Add an item to the context menu of the main chooser - id = self.ctrlMainChooser.AddCommand("Test", icon=self.icon_id) - print "id=%d" % id - if id < 0: - print("Failed to install menu for main embedded chooser") - else: - self.EChMain.cmd_id1 = id - - elif fid == -2: - print("Terminating"); - - elif fid == self.ctrlMainChooser.id: - print("main chooser selection change"); - l = self.GetControlValue(self.ctrlMainChooser); - if not l: - self.main_current_index = -1 - else: - self.main_current_index = l[0] - - # Refresh auxiliar chooser - self.RefreshField(self.ctrlAuxChooser) - self.refresh_selection_edit() - - elif fid == self.ctrlAuxChooser.id: - self.refresh_selection_edit() - - elif fid == self.ctrlSelectionEdit.id: - pass - else: - print("unknown id %d" % fid) - - return 1 - -# - -# -------------------------------------------------------------------------- -def main_formchooser(): - global f - f = MyChooserForm() - try: - f.Compile() - r = f.Execute() - print("Execute returned: %d" % r) - f.Free() - except Exception as e: - print("Failed to show form: %s" % str(e)) - -# -------------------------------------------------------------------------- -if __name__=='__main__': - #stdalone_main() if stdalone else main_formchooser() - #stdalone_main() if stdalone else test_multilinetext() - test_dropdown() - #test_multilinetext(False) - +# diff --git a/pywraps/py_choose.hpp b/pywraps/py_choose.hpp index b7723b1..8e4995f 100644 --- a/pywraps/py_choose.hpp +++ b/pywraps/py_choose.hpp @@ -2,7 +2,7 @@ #define __PY_CHOOSE__ //--------------------------------------------------------------------------- -// +// //--------------------------------------------------------------------------- uint32 idaapi choose_sizer(void *self) { @@ -23,7 +23,7 @@ char *idaapi choose_getl(void *self, uint32 n, char *buf) n)); const char *res; - if (pyres == NULL || (res = PyString_AsString(pyres.o)) == NULL ) + if ( pyres == NULL || (res = PyString_AsString(pyres.o)) == NULL ) qstrncpy(buf, "", MAXSTR); else qstrncpy(buf, res, MAXSTR); @@ -73,6 +73,6 @@ uint32 choose_choose( return r; } -// +// #endif // __PY_CHOOSE__ diff --git a/pywraps/py_choose.py b/pywraps/py_choose.py new file mode 100644 index 0000000..2cde81a --- /dev/null +++ b/pywraps/py_choose.py @@ -0,0 +1,86 @@ + +# +class Choose: + """ + Choose - class for choose() with callbacks + """ + def __init__(self, list, title, flags=0, deflt=1, icon=37): + self.list = list + self.title = title + + self.flags = flags + self.x0 = -1 + self.x1 = -1 + self.y0 = -1 + self.y1 = -1 + + self.width = -1 + self.deflt = deflt + self.icon = icon + + # HACK: Add a circular reference for non-modal choosers. This prevents the GC + # from collecting the class object the callbacks need. Unfortunately this means + # that the class will never be collected, unless refhack is set to None explicitly. + if (flags & Choose2.CH_MODAL) == 0: + self.refhack = self + + def sizer(self): + """ + Callback: sizer - returns the length of the list + """ + return len(self.list) + + def getl(self, n): + """ + Callback: getl - get one item from the list + """ + if n == 0: + return self.title + if n <= self.sizer(): + return str(self.list[n-1]) + else: + return "" + + + def ins(self): + pass + + + def update(self, n): + pass + + + def edit(self, n): + pass + + + def enter(self, n): + print "enter(%d) called" % n + + + def destroy(self): + pass + + + def get_icon(self, n): + pass + + + def choose(self): + """ + choose - Display the choose dialogue + """ + old = set_script_timeout(0) + n = _idaapi.choose_choose( + self, + self.flags, + self.x0, + self.y0, + self.x1, + self.y1, + self.width, + self.deflt, + self.icon) + set_script_timeout(old) + return n +# diff --git a/pywraps/py_choose2.hpp b/pywraps/py_choose2.hpp index e536645..6b6693b 100644 --- a/pywraps/py_choose2.hpp +++ b/pywraps/py_choose2.hpp @@ -1,7 +1,7 @@ #ifndef __PY_CHOOSE2__ #define __PY_CHOOSE2__ -// +// //------------------------------------------------------------------------ // Some defines @@ -133,7 +133,7 @@ private: return (uint32)thisobj->on_get_size(); } - static void idaapi s_getl(void *obj, uint32 n, char * const *arrptr) + static void idaapi s_getl(void *obj, uint32 n, char *const *arrptr) { thisobj->on_get_line(int(n), arrptr); } @@ -210,7 +210,7 @@ private: } } - void on_get_line(int lineno, char * const *line_arr) + void on_get_line(int lineno, char *const *line_arr) { // Called from s_getl, which itself can be called from the kernel. Ensure GIL PYW_GIL_GET; @@ -355,7 +355,7 @@ private: (char *)S_ON_GET_ICON, "i", lineno - 1)); - return PyInt_AsLong(pyres.result.o); + return pyres.result == NULL ? -1 : PyInt_AsLong(pyres.result.o); } void on_get_line_attr(int lineno, chooser_item_attrs_t *attr) @@ -460,8 +460,8 @@ private: // Fill callbacks that are only present in idaq if ( is_idaq() ) { - out->select = (cb_flags & CHOOSE2_HAVE_SELECT) != 0 ? s_select : NULL; - out->refresh = (cb_flags & CHOOSE2_HAVE_REFRESHED)!= 0 ? s_refreshed : NULL; + out->select = (cb_flags & CHOOSE2_HAVE_SELECT) != 0 ? s_select : NULL; + out->refresh = (cb_flags & CHOOSE2_HAVE_REFRESHED) != 0 ? s_refreshed : NULL; } else { @@ -599,7 +599,7 @@ public: // Get *x1,y1,x2,y2 int pts[4]; - static const char *pt_attrs[qnumber(pts)] = {"x1", "y1", "x2", "y2"}; + static const char *pt_attrs[qnumber(pts)] = { "x1", "y1", "x2", "y2" }; for ( size_t i=0; i < qnumber(pts); i++ ) { ref_t pt_attr(PyW_TryGetAttrString(self, pt_attrs[i])); @@ -616,19 +616,19 @@ public: unsigned int have; // 0 = mandatory callback } callbacks[] = { - {S_ON_GET_SIZE, 0}, - {S_ON_GET_LINE, 0}, - {S_ON_CLOSE, 0}, - {S_ON_EDIT_LINE, CHOOSE2_HAVE_EDIT}, - {S_ON_INSERT_LINE, CHOOSE2_HAVE_INS}, - {S_ON_DELETE_LINE, CHOOSE2_HAVE_DEL}, - {S_ON_REFRESH, CHOOSE2_HAVE_UPDATE}, // update() - {S_ON_SELECT_LINE, CHOOSE2_HAVE_ENTER}, // enter() - {S_ON_COMMAND, CHOOSE2_HAVE_COMMAND}, - {S_ON_GET_LINE_ATTR, CHOOSE2_HAVE_GETATTR}, - {S_ON_GET_ICON, CHOOSE2_HAVE_GETICON}, - {S_ON_SELECTION_CHANGE, CHOOSE2_HAVE_SELECT}, - {S_ON_REFRESHED, CHOOSE2_HAVE_REFRESHED}, + { S_ON_GET_SIZE, 0 }, + { S_ON_GET_LINE, 0 }, + { S_ON_CLOSE, 0 }, + { S_ON_EDIT_LINE, CHOOSE2_HAVE_EDIT }, + { S_ON_INSERT_LINE, CHOOSE2_HAVE_INS }, + { S_ON_DELETE_LINE, CHOOSE2_HAVE_DEL }, + { S_ON_REFRESH, CHOOSE2_HAVE_UPDATE }, // update() + { S_ON_SELECT_LINE, CHOOSE2_HAVE_ENTER }, // enter() + { S_ON_COMMAND, CHOOSE2_HAVE_COMMAND }, + { S_ON_GET_LINE_ATTR, CHOOSE2_HAVE_GETATTR }, + { S_ON_GET_ICON, CHOOSE2_HAVE_GETICON }, + { S_ON_SELECTION_CHANGE, CHOOSE2_HAVE_SELECT }, + { S_ON_REFRESHED, CHOOSE2_HAVE_REFRESHED }, }; cb_flags = 0; for ( int i=0; iget_sel_vec(); // Make 0-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it) + for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it ) (*it)--; ref_t ret(PyW_IntVecToPyList(intvec)); @@ -843,14 +843,14 @@ PyObject *choose2_get_embedded(PyObject *self) PYW_GIL_CHECK_LOCKED_SCOPE(); py_choose2_t *c2 = choose2_find_instance(self); - chooser_info_t *embedded; - - if ( c2 == NULL || (embedded = c2->get_embedded()) == NULL ) + if ( c2 == NULL ) Py_RETURN_NONE; - else - return Py_BuildValue("(KK)", - PY_ULONG_LONG(embedded), - PY_ULONG_LONG(c2->get_sel_vec())); + + chooser_info_t *embedded = c2->get_embedded(); + if ( embedded == NULL ) + Py_RETURN_NONE; + + return Py_BuildValue("(KK)", PTR2U64(embedded), PTR2U64(c2->get_sel_vec())); } //------------------------------------------------------------------------ @@ -871,10 +871,10 @@ PyObject *choose2_find(const char *title) py_choose2_t *c2 = py_choose2_t::find_chooser(title); return c2 == NULL ? NULL : c2->get_self(); } -// +// //--------------------------------------------------------------------------- -// +// PyObject *choose2_find(const char *title); int choose2_add_command(PyObject *self, const char *caption, int flags, int menu_index, int icon); void choose2_refresh(PyObject *self); @@ -883,7 +883,7 @@ int choose2_create(PyObject *self, bool embedded); void choose2_activate(PyObject *self); PyObject *choose2_get_embedded(PyObject *self); PyObject *choose2_get_embedded_selection(PyObject *self); -// +// //--------------------------------------------------------------------------- // Testing functions. They belong to PyWraps and won't be copied to IDAPython diff --git a/pywraps/py_choose2.py b/pywraps/py_choose2.py old mode 100644 new mode 100755 index f809f09..ceb3745 --- a/pywraps/py_choose2.py +++ b/pywraps/py_choose2.py @@ -35,7 +35,7 @@ except Exception as e: print("Choose2: Not using pywraps: %s" % str(e)) # ----------------------------------------------------------------------- -# +# class Choose2(object): """ Choose2 wrapper class. @@ -273,136 +273,4 @@ class Choose2(object): # """ # return [0x0, CHITEM_BOLD] # -# - -# ----------------------------------------------------------------------- -# - - -class chooser_handler_t(idaapi.action_handler_t): - def __init__(self, thing): - idaapi.action_handler_t.__init__(self) - self.thing = thing - - def activate(self, ctx): - sel = [] - for i in xrange(len(ctx.chooser_selection)): - sel.append(str(ctx.chooser_selection.at(i))) - print "command %s selected @ %s" % (self.thing, ", ".join(sel)) - - def update(self, ctx): - return idaapi.AST_ENABLE_FOR_FORM if idaapi.is_chooser_tform(ctx.form_type) else idaapi.AST_DISABLE_FOR_FORM - - -class MyChoose2(Choose2): - - def __init__(self, title, nb = 5, flags=0, width=None, height=None, embedded=False, modal=False): - Choose2.__init__( - self, - title, - [ ["Address", 10], ["Name", 30] ], - flags = flags, - width = width, - height = height, - embedded = embedded) - self.n = 0 - self.items = [ self.make_item() for x in xrange(0, nb+1) ] - self.icon = 5 - self.selcount = 0 - self.modal = modal - self.popup_names = ["Inzert", "Del leet", "Ehdeet", "Ree frech"] - - print("created %s" % str(self)) - - def OnClose(self): - print "closed", str(self) - - def OnEditLine(self, n): - self.items[n][1] = self.items[n][1] + "*" - print("editing %d" % n) - - def OnInsertLine(self): - self.items.append(self.make_item()) - print("insert line") - - def OnSelectLine(self, n): - self.selcount += 1 - Warning("[%02d] selectline '%s'" % (self.selcount, n)) - - def OnGetLine(self, n): - print("getline %d" % n) - return self.items[n] - - def OnGetSize(self): - n = len(self.items) - print("getsize -> %d" % n) - return n - - def OnDeleteLine(self, n): - print("del %d " % n) - del self.items[n] - return n - - def OnRefresh(self, n): - print("refresh %d" % n) - return n - - def OnGetIcon(self, n): - r = self.items[n] - t = self.icon + r[1].count("*") - print "geticon", n, t - return t - - def show(self): - return self.Show(self.modal) >= 0 - - def make_item(self): - r = [str(self.n), "func_%04d" % self.n] - self.n += 1 - return r - - def OnGetLineAttr(self, n): - print("getlineattr %d" % n) - if n == 1: - return [0xFF0000, 0] - - -# ----------------------------------------------------------------------- -def test_choose2(modal=False): - global c - c = MyChoose2("Choose2 - sample 1", nb=10, modal=modal) - r = c.show() - form = idaapi.get_current_tform() - for thing in ["A", "B"]: - idaapi.attach_action_to_popup(form, None, "choose2:act%s" % thing) - -# ----------------------------------------------------------------------- -def test_choose2_embedded(): - global c - c = MyChoose2("Choose2 - embedded", nb=12, embedded = True, width=123, height=222) - r = c.Embedded() - if r == 1: - try: - if test_embedded: - o, sel = _idaapi.choose2_get_embedded(c) - print("o=%s, type(o)=%s" % (str(o), type(o))) - test_embedded(o) - finally: - c.Close() - -# ----------------------------------------------------------------------- -if __name__ == '__main__': - - # Register actions - for thing in ["A", "B"]: - actname = "choose2:act%s" % thing - idaapi.register_action( - idaapi.action_desc_t( - actname, - "command %s" % thing, - chooser_handler_t(thing))) - - #test_choose2_embedded() - test_choose2(False) - -# +# diff --git a/pywraps/py_cli.hpp b/pywraps/py_cli.hpp index 7cc3a56..16b4650 100644 --- a/pywraps/py_cli.hpp +++ b/pywraps/py_cli.hpp @@ -267,7 +267,7 @@ public: return; } }; -py_cli_t *py_cli_t::py_clis[MAX_PY_CLI] = {NULL}; +py_cli_t *py_cli_t::py_clis[MAX_PY_CLI] = { NULL }; #define DECL_PY_CLI_CB(CBN) { s_execute_line##CBN, s_complete_line##CBN, s_keydown##CBN } const py_cli_cbs_t py_cli_t::py_cli_cbs[MAX_PY_CLI] = { diff --git a/pywraps/py_cli.py b/pywraps/py_cli.py old mode 100644 new mode 100755 index 2f6f4cd..085874c --- a/pywraps/py_cli.py +++ b/pywraps/py_cli.py @@ -126,62 +126,3 @@ class cli_t(pyidc_opaque_object_t): # # - -# ----------------------------------------------------------------------- -# -class mycli_t(cli_t): - flags = 0 - sname = "pycli" - lname = "Python CLI" - hint = "pycli hint" - - def OnExecuteLine(self, line): - """ - The user pressed Enter. The CLI is free to execute the line immediately or ask for more lines. - - This callback is mandatory. - - @param line: typed line(s) - @return Boolean: True-executed line, False-ask for more lines - """ - print "OnExecute:", line - return True - - def OnKeydown(self, line, x, sellen, vkey, shift): - """ - A keyboard key has been pressed - This is a generic callback and the CLI is free to do whatever it wants. - - This callback is optional. - - @param line: current input line - @param x: current x coordinate of the cursor - @param sellen: current selection length (usually 0) - @param vkey: virtual key code. if the key has been handled, it should be returned as zero - @param shift: shift state - - @return: - None - Nothing was changed - tuple(line, x, sellen, vkey): if either of the input line or the x coordinate or the selection length has been modified. - It is possible to return a tuple with None elements to preserve old values. Example: tuple(new_line, None, None, None) or tuple(new_line) - """ - print "Onkeydown: line=%s x=%d sellen=%d vkey=%d shift=%d" % (line, x, sellen, vkey, shift) - return None - - def OnCompleteLine(self, prefix, n, line, prefix_start): - """ - The user pressed Tab. Find a completion number N for prefix PREFIX - - This callback is optional. - - @param prefix: Line prefix at prefix_start (string) - @param n: completion number (int) - @param line: the current line (string) - @param prefix_start: the index where PREFIX starts in LINE (int) - - @return: None if no completion could be generated otherwise a String with the completion suggestion - """ - print "OnCompleteLine: prefix=%s n=%d line=%s prefix_start=%d" % (prefix, n, line, prefix_start) - return None -# -# ----------------------------------------------------------------------- diff --git a/pywraps/py_custdata.hpp b/pywraps/py_custdata.hpp index f578b48..edc4bc0 100644 --- a/pywraps/py_custdata.hpp +++ b/pywraps/py_custdata.hpp @@ -1,9 +1,7 @@ #ifndef __PY_IDA_CUSTDATA__ #define __PY_IDA_CUSTDATA__ -// - -//------------------------------------------------------------------------ +// class py_custom_data_type_t { data_type_t dt; @@ -247,7 +245,7 @@ private: operand_num)); // Error while calling the function? - if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL) + if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL ) return false; bool ok = false; @@ -494,10 +492,10 @@ static PyObject *py_data_format_to_py_dict(const data_format_t *df) S_MENU_NAME, df->menu_name == NULL ? "" : df->menu_name, S_HOTKEY, df->hotkey == NULL ? "" : df->hotkey); } -// +// //------------------------------------------------------------------------ -// +// //------------------------------------------------------------------------ /* @@ -678,6 +676,6 @@ static PyObject *py_get_custom_data_type(int dtid) return py_data_type_to_py_dict(dt); } -// +// #endif diff --git a/pywraps/py_custdata.py b/pywraps/py_custdata.py old mode 100644 new mode 100755 index b996097..a0405d4 --- a/pywraps/py_custdata.py +++ b/pywraps/py_custdata.py @@ -26,7 +26,7 @@ if pywraps_there: _idaapi.get_custom_data_type = pywraps.get_custom_data_type # ----------------------------------------------------------------------- -# +# DTP_NODUP = 0x0001 class data_type_t(object): @@ -243,5 +243,5 @@ def unregister_data_types_and_formats(formats): ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format, False) return 1 if ok else -1 -# +# # ----------------------------------------------------------------------- diff --git a/pywraps/py_custview.hpp b/pywraps/py_custview.hpp index 2fe185b..0a7b83c 100644 --- a/pywraps/py_custview.hpp +++ b/pywraps/py_custview.hpp @@ -1,6 +1,6 @@ #ifndef __PYWRAPS_CUSTVIEWER__ #define __PYWRAPS_CUSTVIEWER__ -// +// //--------------------------------------------------------------------------- // Base class for all custviewer place_t providers class custviewer_data_t @@ -145,6 +145,8 @@ protected: TCustomControl *_cv; custviewer_data_t *_data; int _features; + custom_viewer_handlers_t handlers; + enum { HAVE_HINT = 0x0001, @@ -160,8 +162,8 @@ private: { size_t menu_id; customviewer_t *cv; - cvw_popupctx_t(): menu_id(0), cv(NULL) { } - cvw_popupctx_t(size_t mid, customviewer_t *v): menu_id(mid), cv(v) { } + cvw_popupctx_t(): menu_id(0), cv(NULL) {} + cvw_popupctx_t(size_t mid, customviewer_t *v): menu_id(mid), cv(v) {} }; typedef std::map cvw_popupmap_t; static cvw_popupmap_t _global_popup_map; @@ -282,10 +284,10 @@ public: virtual bool on_dblclick(int /*shift*/) { return false; } // OnCurorPositionChanged - virtual void on_curpos_changed() { } + virtual void on_curpos_changed() {} // OnHostFormClose - virtual void on_close() { } + virtual void on_close() {} // OnKeyDown virtual bool on_keydown(int /*vk_key*/, int /*shift*/) { return false; } @@ -434,9 +436,10 @@ public: if ( _cv != NULL ) set_custom_viewer_popup_menu(_cv, NULL); - for (intvec_t::iterator it=_installed_popups.begin(), it_end=_installed_popups.end(); - it != it_end; - ++it) + intvec_t::iterator it, it_end; + for ( it=_installed_popups.begin(), it_end=_installed_popups.end(); + it != it_end; + ++it ) { _global_popup_map.erase(*it); } @@ -451,11 +454,9 @@ public: size_t menu_id = _global_popup_id + 1; // Overlap / already exists? - if (_cv == NULL || // No custviewer? - // Overlap? - menu_id == 0 || - // Already exists? - _global_popup_map.find(menu_id) != _global_popup_map.end()) + if ( _cv == NULL // No custviewer? + || menu_id == 0 // Overlap? + || _global_popup_map.find(menu_id) != _global_popup_map.end() ) // Already exists? { return 0; } @@ -488,6 +489,24 @@ public: _form = form; _features = features; + // + // Prepare handlers + // + 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; + + if ( (features & HAVE_DBLCLICK) != 0 ) + handlers.dblclick = s_cv_dblclick; + + if ( (features & HAVE_CURPOS) != 0 ) + handlers.curpos = s_cv_curpos; + // Create the viewer _cv = create_custom_viewer( title, @@ -495,29 +514,10 @@ public: _data->get_min(), _data->get_max(), _data->get_min(), - 0, - _data->get_ud()); - - // Set user-data - set_custom_viewer_handler(_cv, CVH_USERDATA, (void *)this); - - // - // Set other optional callbacks - // - if ( (features & HAVE_KEYDOWN) != 0 ) - set_custom_viewer_handler(_cv, CVH_KEYDOWN, (void *)s_cv_keydown); - - if ( (features & HAVE_POPUP) != 0 ) - set_custom_viewer_handler(_cv, CVH_POPUP, (void *)s_cv_popup); - - if ( (features & HAVE_DBLCLICK) != 0 ) - set_custom_viewer_handler(_cv, CVH_DBLCLICK, (void *)s_cv_dblclick); - - if ( (features & HAVE_CURPOS) != 0 ) - set_custom_viewer_handler(_cv, CVH_CURPOS, (void *)s_cv_curpos); - - if ( (features & HAVE_CLICK) != 0 ) - set_custom_viewer_handler(_cv, CVH_CLICK, (void *)s_cv_click); + (const renderer_info_t *) NULL, + _data->get_ud(), + &handlers, + this); // Hook to UI notifications (for TForm close event) hook_to_notification_point(HT_UI, s_ui_cb, this); @@ -568,10 +568,10 @@ private: sl.line = PyString_AsString(py_val); - if ( (sz > 1) && (py_val = PyTuple_GetItem(py, 1)) && PyLong_Check(py_val) ) + if ( (sz > 1) && (py_val = PyTuple_GetItem(py, 1)) && PyLong_Check(py_val) ) sl.color = color_t(PyLong_AsUnsignedLong(py_val)); - if ( (sz > 2) && (py_val = PyTuple_GetItem(py, 2)) && PyLong_Check(py_val) ) + if ( (sz > 2) && (py_val = PyTuple_GetItem(py, 2)) && PyLong_Check(py_val) ) sl.bgcolor = PyLong_AsUnsignedLong(py_val); return true; @@ -816,13 +816,13 @@ public: int feature; } const cbtable[] = { - {S_ON_CLICK, HAVE_CLICK}, - {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} + { S_ON_CLICK, HAVE_CLICK }, + { 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 } }; PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -901,13 +901,13 @@ public: } }; -// +// //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -// +// // // Pywraps Simple Custom Viewer functions // @@ -1128,6 +1128,6 @@ TCustomControl *pyscv_get_tcustom_control(PyObject *py_this) #undef DECL_THIS -// +// //--------------------------------------------------------------------------- #endif // __PYWRAPS_CUSTVIEWER__ diff --git a/pywraps/py_custview.py b/pywraps/py_custview.py old mode 100644 new mode 100755 index 4d7d790..c97c70f --- a/pywraps/py_custview.py +++ b/pywraps/py_custview.py @@ -40,7 +40,7 @@ except: print "Not using pywraps" # ----------------------------------------------------------------------- -# +# class simplecustviewer_t(object): """The base class for implementing simple custom viewers""" def __init__(self): @@ -292,181 +292,4 @@ class simplecustviewer_t(object): # print "OnPopupMenu, menu_id=" % menu_id # return True # -# - -# - -class say_something_handler_t(idaapi.action_handler_t): - def __init__(self, thing): - idaapi.action_handler_t.__init__(self) - self.thing = thing - - def activate(self, ctx): - print self.thing - - def update(self, ctx): - return idaapi.AST_ENABLE_ALWAYS - - -# ----------------------------------------------------------------------- -class mycv_t(simplecustviewer_t): - def Create(self, sn=None): - # Form the title - title = "Simple custom view test" - if sn: - title += " %d" % sn - - # Create the customviewer - if not simplecustviewer_t.Create(self, title): - return False - - for i in xrange(0, 100): - self.AddLine("Line %d" % i) - -# self.Jump(0) - - return True - - def OnClick(self, shift): - """ - User clicked in the view - @param shift: Shift flag - @return: Boolean. True if you handled the event - """ - print "OnClick, shift=%d" % shift - return True - - def OnDblClick(self, shift): - """ - User dbl-clicked in the view - @param shift: Shift flag - @return: Boolean. True if you handled the event - """ - word = self.GetCurrentWord() - if not word: word = "" - print "OnDblClick, shift=%d, current word=%s" % (shift, word) - return True - - def OnCursorPosChanged(self): - """ - Cursor position changed. - @return: Nothing - """ - print "OnCurposChanged" - - def OnClose(self): - """ - The view is closing. Use this event to cleanup. - @return: Nothing - """ - print "OnClose " + self.title - - def OnKeydown(self, vkey, shift): - """ - User pressed a key - @param vkey: Virtual key code - @param shift: Shift flag - @return: Boolean. True if you handled the event - """ - print "OnKeydown, vk=%d shift=%d" % (vkey, shift) - # ESCAPE? - if vkey == 27: - self.Close() - # VK_DELETE - elif vkey == 46: - n = self.GetLineNo() - if n is not None: - self.DelLine(n) - self.Refresh() - print "Deleted line %d" % n - # Goto? - elif vkey == ord('G'): - n = self.GetLineNo() - if n is not None: - v = idc.AskLong(self.GetLineNo(), "Where to go?") - if v: - self.Jump(v, 0, 5) - elif vkey == ord('R'): - print "refreshing...." - self.Refresh() - elif vkey == ord('C'): - print "refreshing current line..." - self.RefreshCurrent() - elif vkey == ord('A'): - s = idc.AskStr("NewLine%d" % self.Count(), "Append new line") - self.AddLine(s) - self.Refresh() - elif vkey == ord('X'): - print "Clearing all lines" - self.ClearLines() - self.Refresh() - elif vkey == ord('I'): - n = self.GetLineNo() - s = idc.AskStr("InsertedLine%d" % n, "Insert new line") - self.InsertLine(n, s) - self.Refresh() - elif vkey == ord('E'): - l = self.GetCurrentLine(notags=1) - if not l: - return False - n = self.GetLineNo() - print "curline=<%s>" % l - l = l + idaapi.COLSTR("*", idaapi.SCOLOR_VOIDOP) - self.EditLine(n, l) - self.RefreshCurrent() - print "Edited line %d" % n - else: - return False - return True - - def OnHint(self, lineno): - """ - Hint requested for the given line number. - @param lineno: The line number (zero based) - @return: - - tuple(number of important lines, hint string) - - None: if no hint available - """ - return (1, "OnHint, line=%d" % lineno) - -# ----------------------------------------------------------------------- -try: - # created already? - mycv - print "Already created, will close it..." - mycv.Close() - del mycv -except: - pass - -def show_win(): - x = mycv_t() - if not x.Create(): - print "Failed to create!" - return None - x.Show() - tcc = x.GetTCustomControl() - - # 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() -if not mycv: - del mycv - -def make_many(n): - L = [] - for i in xrange(1, n+1): - v = mycv_t() - if not v.Create(i): - break - v.Show() - L.append(v) - return L - -# +# diff --git a/pywraps/py_cvt.hpp b/pywraps/py_cvt.hpp deleted file mode 100644 index 2d465f7..0000000 --- a/pywraps/py_cvt.hpp +++ /dev/null @@ -1,757 +0,0 @@ -#ifndef __PYCVT__ -#define __PYCVT__ - -// - -//------------------------------------------------------------------------ -// String constants used -static const char S_PY_IDCCVT_VALUE_ATTR[] = "__idc_cvt_value__"; -static const char S_PY_IDCCVT_ID_ATTR[] = "__idc_cvt_id__"; -static const char S_PY_IDC_OPAQUE_T[] = "py_idc_cvt_helper_t"; -static const char S_PY_IDC_GLOBAL_VAR_FMT[] = "__py_cvt_gvar_%d"; - -// Constants used by get_idaapi_class_reference() -#define PY_CLSID_CVT_INT64 0 -#define PY_CLSID_APPCALL_SKEL_OBJ 1 -#define PY_CLSID_CVT_BYREF 2 -#define PY_CLSID_LAST 3 - -//--------------------------------------------------------------------------- -// Use these macros to define script<->C fields -#define DEFINE_SCFIELDX(name, type, is_opt) { #name, type, qoffsetof(CUR_STRUC, name), is_opt } -#define DEFINE_SCFIELD(name, type) DEFINE_SCFIELDX(name, type, 0) -#define DEFINE_SCFIELD_OPT(name, type) DEFINE_SCFIELDX(name, type, 1) - -//--------------------------------------------------------------------------- -enum scfield_types_t -{ - // Numeric fields - FT_FIRST_NUM, - FT_INT, - FT_SIZET, - FT_SSIZET, - FT_NUM16, - FT_NUM32, - FT_LAST_NUM, - // String field - FT_STR, - FT_CHAR, - // Object fields - FT_ARR, - // Allocated array of strings - FT_STRARR, - // Allocated array of 16bit numbers - FT_NUM16ARR, - // Fixed size character array. The size must be passed in the definition - FT_CHRARR_STATIC, -}; - -//--------------------------------------------------------------------------- -struct scfld_t -{ - const char *field_name; - uint32 field_type; - size_t field_offs; - bool is_optional; -}; - -#define FT_VALUE_MASK 0xFFFF0000 -// Possible return values of conversion functions -#define FT_NOT_FOUND -1 -#define FT_BAD_TYPE -2 -#define FT_OK 1 - -//------------------------------------------------------------------------- -Py_ssize_t pyvar_walk_list( - const ref_t &py_list, - int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud), - void *ud) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - Py_ssize_t size = CIP_FAILED; - do - { - PyObject *o = py_list.o; - if ( !PyList_CheckExact(o) && !PyW_IsSequenceType(o) ) - break; - - bool is_seq = !PyList_CheckExact(o); - size = is_seq ? PySequence_Size(o) : PyList_Size(o); - if ( cb == NULL ) - break; - - Py_ssize_t i; - for ( i=0; i= CIP_OK; - if ( !ok ) - PyErr_SetString(PyExc_ValueError, "Could not convert Python object to IDC object!"); - return ok; -} - -//------------------------------------------------------------------------ -static idc_class_t *get_py_idc_cvt_opaque() -{ - return find_idc_class(S_PY_IDC_OPAQUE_T); -} - -//------------------------------------------------------------------------- -// Utility function to create opaque / convertible Python <-> IDC variables -// The referred Python variable will have its reference increased -static bool wrap_PyObject_ptr(const ref_t &py_var, idc_value_t *idc_var) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Create an IDC object of this special helper class - if ( VarObject(idc_var, get_py_idc_cvt_opaque()) != eOk ) - return false; - - // Store the CVT id - idc_value_t idc_val; - idc_val.set_long(PY_ICID_OPAQUE); - VarSetAttr(idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val); - - // Store the value as a PVOID referencing the given Python object - py_var.incref(); - idc_val.set_pvoid(py_var.o); - VarSetAttr(idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val); - - return true; -} - -//------------------------------------------------------------------------ -// IDC Opaque object destructor: when the IDC object dies we kill the -// opaque Python object along with it -static const char py_idc_cvt_helper_dtor_args[] = { VT_OBJ, 0 }; -static error_t idaapi py_idc_opaque_dtor( - idc_value_t *argv, - idc_value_t * /*res*/) -{ - // This can be called at plugin registration time, when a - // 'script_plugin_t' instance is ::free()'d. It is - // not guaranteed that we have the GIL at that point. - PYW_GIL_GET; - - // Get the value from the object - idc_value_t idc_val; - VarGetAttr(&argv[0], S_PY_IDCCVT_VALUE_ATTR, &idc_val); - - // Extract the Python object reference - PyObject *py_obj = (PyObject *)idc_val.pvoid; - - // Decrease its reference (and eventually destroy it) - Py_DECREF(py_obj); - - return eOk; -} - -//------------------------------------------------------------------------- -// Converts a Python variable into an IDC variable -// This function returns on one CIP_XXXX -int pyvar_to_idcvar( - const ref_t &py_var, - idc_value_t *idc_var, - int *gvar_sn) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // None / NULL - if ( py_var == NULL || py_var.o == Py_None ) - { - idc_var->set_long(0); - } - // Numbers? - else if ( PyW_GetNumberAsIDC(py_var.o, idc_var) ) - { - return CIP_OK; - } - // String - else if ( PyString_Check(py_var.o) ) - { - idc_var->_set_string(PyString_AsString(py_var.o), PyString_Size(py_var.o)); - } - // Boolean - else if ( PyBool_Check(py_var.o) ) - { - idc_var->set_long(py_var.o == Py_True ? 1 : 0); - } - // Float - else if ( PyFloat_Check(py_var.o) ) - { - double dresult = PyFloat_AsDouble(py_var.o); - ieee_realcvt((void *)&dresult, idc_var->e, 3); - idc_var->vtype = VT_FLOAT; - } - // void* - else if ( PyCObject_Check(py_var.o) ) - { - idc_var->set_pvoid(PyCObject_AsVoidPtr(py_var.o)); - } - // Python list? - else if ( PyList_CheckExact(py_var.o) || PyW_IsSequenceType(py_var.o) ) - { - // Create the object - VarObject(idc_var); - - // Determine list size and type - bool is_seq = !PyList_CheckExact(py_var.o); - Py_ssize_t size = is_seq ? PySequence_Size(py_var.o) : PyList_Size(py_var.o); - bool ok = true; - qstring attr_name; - - // Convert each item - for ( Py_ssize_t i=0; i= CIP_OK; - if ( ok ) - { - // Form the attribute name - newref_t py_int(PyInt_FromSsize_t(i)); - ok = PyW_ObjectToString(py_int.o, &attr_name); - if ( !ok ) - break; - // Store the attribute - VarSetAttr(idc_var, attr_name.c_str(), &v); - } - if ( !ok ) - break; - } - return ok ? CIP_OK : CIP_FAILED; - } - // Dictionary: we convert to an IDC object - else if ( PyDict_Check(py_var.o) ) - { - // Create an empty IDC object - VarObject(idc_var); - - // Get the dict.items() list - newref_t py_items(PyDict_Items(py_var.o)); - - // Get the size of the list - qstring key_name; - bool ok = true; - Py_ssize_t size = PySequence_Size(py_items.o); - for ( Py_ssize_t i=0; i (key, value) - PyObject *py_item = PyList_GetItem(py_items.o, i); - - // Extract key/value - newref_t key(PySequence_GetItem(py_item, 0)); - newref_t val(PySequence_GetItem(py_item, 1)); - - // Get key's string representation - PyW_ObjectToString(key.o, &key_name); - - // Convert the attribute into an IDC value - idc_value_t v; - ok = pyvar_to_idcvar(val, &v, gvar_sn) >= CIP_OK; - if ( ok ) - { - // Store the attribute - VarSetAttr(idc_var, key_name.c_str(), &v); - } - if ( !ok ) - break; - } - return ok ? CIP_OK : CIP_FAILED; - } - // Possible function? - else if ( PyCallable_Check(py_var.o) ) - { - idc_var->clear(); - idc_var->vtype = VT_FUNC; - idc_var->funcidx = -1; // Does not apply - return CIP_OK; - } - // Objects: - // - pyidc_cvt objects: int64, byref, opaque - // - other python objects - else - { - // Get the type - int cvt_id = get_pyidc_cvt_type(py_var.o); - switch ( cvt_id ) - { - // - // 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; - } - // - // 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 ) - { - (*gvar_sn)++; - // Create a reference to this global variable - VarRef(idc_var, gvar); - } - return ok ? CIP_OK : CIP_FAILED; - } - // - // 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 - VarObject(idc_var); - for ( Py_ssize_t i=0; i 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 - VarSetAttr(idc_var, field_name, &v); - } - } - } - return CIP_OK; -} - -//------------------------------------------------------------------------- -inline PyObject *cvt_to_pylong(int32 v) -{ - return PyLong_FromLong(v); -} - -inline PyObject *cvt_to_pylong(int64 v) -{ - return PyLong_FromLongLong(v); -} - -//------------------------------------------------------------------------- -// Converts an IDC variable to a Python variable -// If py_var points to an existing object then the object will be updated -// If py_var points to an existing immutable object then ZERO is returned -// Returns one of CIP_xxxx. Check pywraps.hpp -int idcvar_to_pyvar( - const idc_value_t &idc_var, - ref_t *py_var) -{ - 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: - { - // 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; - } - -#if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC) - case VT_STR: - *py_var = newref_t(PyString_FromString(idc_var.str)); - break; - -#endif - case VT_STR2: - 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) != 0 ) - 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 = VarDeref(const_cast(&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 ( VarGetAttr(&idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val) == eOk - && VarGetAttr(&idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val) == 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 = VarFirstAttr(&idc_var); - attr_name != NULL; - attr_name = VarNextAttr(&idc_var, attr_name) ) - { - // Get the attribute - idc_value_t v; - VarGetAttr(&idc_var, attr_name, &v, 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; -} - -//------------------------------------------------------------------------- -// Converts IDC arguments to Python argument list or just one tuple -// If 'decref' is NULL then 'pargs' will contain one element which is the tuple -bool pyw_convert_idc_args( - const idc_value_t args[], - int nargs, - ref_vec_t &pargs, - bool as_tupple, - char *errbuf, - size_t errbufsize) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - ref_t py_tuple; - - pargs.qclear(); - - if ( as_tupple ) - { - py_tuple = newref_t(PyTuple_New(nargs)); - if ( py_tuple == NULL ) - { - if ( errbuf != 0 && errbufsize > 0 ) - qstrncpy(errbuf, "Failed to create a new tuple to store arguments!", errbufsize); - return false; - } - } - - for ( int i=0; i 0 ) - qsnprintf(errbuf, errbufsize, "arg#%d has wrong type %d", i, args[i].vtype); - return false; - } - - if ( as_tupple ) - { - // PyTuple_SetItem() steals the reference. - py_obj.incref(); - QASSERT(30412, PyTuple_SetItem(py_tuple.o, i, py_obj.o) == 0); - } - else - { - pargs.push_back(py_obj); - } - } - - // Add the tuple to the list of args only now. Doing so earlier will - // cause the py_tuple.o->ob_refcnt to be 2 and not 1, and that will - // cause 'PyTuple_SetItem()' to fail. - if ( as_tupple ) - pargs.push_back(py_tuple); - - return true; -} - -// - -#endif diff --git a/pywraps/py_dbg.hpp b/pywraps/py_dbg.hpp index 12a675b..b0592c5 100644 --- a/pywraps/py_dbg.hpp +++ b/pywraps/py_dbg.hpp @@ -1,424 +1,6 @@ #ifndef __PYDBG__ #define __PYDBG__ -// - -//------------------------------------------------------------------------- -static bool dbg_can_query() -{ - // Reject the request only if no debugger is set - // or the debugger cannot be queried while not in suspended state - return dbg != NULL && (dbg->may_disturb() || get_process_state() < DSTATE_NOTASK); -} - -//------------------------------------------------------------------------- -static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - PyObject *py_list = PyList_New(areas.size()); - meminfo_vec_t::const_iterator it, it_end(areas.end()); - Py_ssize_t i = 0; - for ( it=areas.begin(); it!=it_end; ++it, ++i ) - { - const memory_info_t &mi = *it; - // startEA endEA name sclass sbase bitness perm - PyList_SetItem(py_list, i, - Py_BuildValue("("PY_FMT64 PY_FMT64 "ss" PY_FMT64 "II)", - pyul_t(mi.startEA), - pyul_t(mi.endEA), - mi.name.c_str(), - mi.sclass.c_str(), - pyul_t(mi.sbase), - (unsigned int)(mi.bitness), - (unsigned int)mi.perm)); - } - return py_list; -} - -//------------------------------------------------------------------------- -PyObject *py_appcall( - ea_t func_ea, - thid_t tid, - PyObject *py_type, - PyObject *py_fields, - PyObject *arg_list) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !PyList_Check(arg_list) ) - return NULL; - - const char *type = py_type == Py_None ? NULL : PyString_AS_STRING(py_type); - const char *fields = py_fields == Py_None ? NULL : PyString_AS_STRING(py_fields); - - // Convert Python arguments into IDC values - qvector idc_args; - int sn = 0; - Py_ssize_t nargs = PyList_Size(arg_list); - idc_args.resize(nargs); - bool ok = true; - for ( Py_ssize_t i=0; i%s\n", int(i), s.c_str()); - } - // Convert it - if ( pyvar_to_idcvar(py_item, &idc_args[i], &sn) < CIP_OK ) - { - ok = false; - break; - } - } - - // Set exception message - if ( !ok ) - { - PyErr_SetString( - PyExc_ValueError, - "PyAppCall: Failed to convert Python values to IDC values"); - return NULL; - } - - error_t ret; - idc_value_t idc_result; - Py_BEGIN_ALLOW_THREADS; - - if ( (debug & IDA_DEBUG_APPCALL) != 0 ) - { - msg("input variables:\n" - "----------------\n"); - - qstring s; - for ( Py_ssize_t i=0; iob_refcnt == 1); - if ( (debug & IDA_DEBUG_APPCALL) != 0 ) - { - msg("return var:\n" - "-----------\n"); - qstring s; - VarPrint(&s, &idc_result); - msg("%s\n-----------\n", s.c_str()); - } - py_result.incref(); - return py_result.o; -} -// - -// - -//------------------------------------------------------------------------- -/* -# -def dbg_get_registers(): - """ - This function returns the register definition from the currently loaded debugger. - Basically, it returns an array of structure similar to to idd.hpp / register_info_t - @return: - None if no debugger is loaded - tuple(name, flags, class, dtyp, bit_strings, default_bit_strings_mask) - The bit_strings can be a tuple of strings or None (if the register does not have bit_strings) - """ - pass -# -*/ -static PyObject *dbg_get_registers() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( dbg == NULL ) - Py_RETURN_NONE; - - PyObject *py_list = PyList_New(dbg->registers_size); - - for ( int i=0; iregisters_size; i++ ) - { - register_info_t &ri = dbg->registers(i); - PyObject *py_bits; - - // Does this register have bit strings? - // (Make sure it does not use custom formats because bit_string would be the format name) - if ( ri.bit_strings != NULL && (ri.flags & REGISTER_CUSTFMT) == 0 ) - { - int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4; - py_bits = PyList_New(nbits); - for ( int i=0; i -def dbg_get_thread_sreg_base(tid, sreg_value): - """ - Returns the segment register base value - @param tid: thread id - @param sreg_value: segment register (selector) value - @return: - - The base as an 'ea' - - Or None on failure - """ - pass -# -*/ -static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) ) - Py_RETURN_NONE; - ea_t answer; - thid_t tid = PyInt_AsLong(py_tid); - int sreg_value = PyInt_AsLong(py_sreg_value); - if ( internal_get_sreg_base(tid, sreg_value, &answer) != 1 ) - Py_RETURN_NONE; - - return Py_BuildValue(PY_FMT64, pyul_t(answer)); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_read_memory(ea, sz): - """ - Reads from the debugee's memory at the specified ea - @return: - - The read buffer (as a string) - - Or None on failure - """ - pass -# -*/ -static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - uint64 ea, sz; - if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) ) - Py_RETURN_NONE; - - // Create a Python string - PyObject *ret = PyString_FromStringAndSize(NULL, Py_ssize_t(sz)); - if ( ret == NULL ) - Py_RETURN_NONE; - - // Get the internal buffer - Py_ssize_t len; - char *buf; - PyString_AsStringAndSize(ret, &buf, &len); - - if ( (size_t)read_dbg_memory(ea_t(ea), buf, size_t(sz)) != sz ) - { - // Release the string on failure - Py_DECREF(ret); - // Return None on failure - Py_RETURN_NONE; - } - return ret; -} - -//------------------------------------------------------------------------- -/* -# -def dbg_write_memory(ea, buffer): - """ - Writes a buffer to the debugee's memory - @return: Boolean - """ - pass -# -*/ -static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - uint64 ea; - if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) ) - Py_RETURN_NONE; - - size_t sz = PyString_GET_SIZE(py_buf); - void *buf = (void *)PyString_AS_STRING(py_buf); - if ( write_dbg_memory(ea_t(ea), buf, sz) != sz ) - Py_RETURN_FALSE; - Py_RETURN_TRUE; -} - -//------------------------------------------------------------------------- -/* -# -def dbg_get_name(): - """ - This function returns the current debugger's name. - @return: Debugger name or None if no debugger is active - """ - pass -# -*/ -static PyObject *dbg_get_name() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( dbg == NULL ) - Py_RETURN_NONE; - else - return PyString_FromString(dbg->name); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_get_memory_info(): - """ - This function returns the memory configuration of a debugged process. - @return: - None if no debugger is active - tuple(startEA, endEA, name, sclass, sbase, bitness, perm) - """ - pass -# -*/ -static PyObject *dbg_get_memory_info() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !dbg_can_query() ) - Py_RETURN_NONE; - - // Invalidate memory - meminfo_vec_t areas; - Py_BEGIN_ALLOW_THREADS; - invalidate_dbgmem_config(); - invalidate_dbgmem_contents(BADADDR, BADADDR); - - get_dbg_memory_info(&areas); - Py_END_ALLOW_THREADS; - return meminfo_vec_t_to_py(areas); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_can_query(): - """ - This function can be used to check if the debugger can be queried: - - debugger is loaded - - process is suspended - - process is not suspended but can take requests. In this case some requests like - memory read/write, bpt management succeed and register querying will fail. - Check if idaapi.get_process_state() < 0 to tell if the process is suspended - @return: Boolean - """ - pass -# -*/ -static bool dbg_can_query(); -PyObject *py_appcall( - ea_t func_ea, - thid_t tid, - PyObject *py_type, - PyObject *py_fields, - PyObject *arg_list); -// - // static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas); // @@ -494,63 +76,39 @@ public: bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); } bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); } - /* Hook functions to be overridden in Python */ - virtual void dbg_process_start(pid_t pid, - thid_t tid, - ea_t ea, - char *name, - ea_t base, - asize_t size) {} - virtual void dbg_process_exit(pid_t pid, - thid_t tid, - ea_t ea, - int exit_code) {} - virtual void dbg_process_attach(pid_t pid, - thid_t tid, - ea_t ea, - char *name, - ea_t base, - asize_t size) {} - virtual void dbg_process_detach(pid_t pid, - thid_t tid, - ea_t ea) {} - virtual void dbg_thread_start(pid_t pid, - thid_t tid, - ea_t ea) {} - virtual void dbg_thread_exit(pid_t pid, - thid_t tid, - ea_t ea, - int exit_code) {} - virtual void dbg_library_load(pid_t pid, - thid_t tid, - ea_t ea, - char *name, - ea_t base, - asize_t size) {} - virtual void dbg_library_unload(pid_t pid, - thid_t tid, - ea_t ea, - char *libname) {} - virtual void dbg_information(pid_t pid, - thid_t tid, - ea_t ea, - char *info) {} - virtual int dbg_exception(pid_t pid, - thid_t tid, - ea_t ea, - int code, - bool can_cont, - ea_t exc_ea, - char *info) { return 0; } - virtual void dbg_suspend_process(void) {} - virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; } - virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; } - virtual void dbg_request_error(int failed_command, - int failed_dbg_notification) {} - virtual void dbg_step_into(void) {} - virtual void dbg_step_over(void) {} - virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) {} - virtual void dbg_step_until_ret(void) {} + + static int 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) + { + *warn = rc; + return 0; + } + + // hookgenDBG:methods +virtual void dbg_process_start(pid_t pid, thid_t tid, ea_t ea, const char * modinfo_name, ea_t modinfo_base, asize_t modinfo_size) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(modinfo_name); qnotused(modinfo_base); qnotused(modinfo_size); } +virtual void dbg_process_exit(pid_t pid, thid_t tid, ea_t ea, int exit_code) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(exit_code); } +virtual void dbg_process_attach(pid_t pid, thid_t tid, ea_t ea, const char * modinfo_name, ea_t modinfo_base, asize_t modinfo_size) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(modinfo_name); qnotused(modinfo_base); qnotused(modinfo_size); } +virtual void dbg_process_detach(pid_t pid, thid_t tid, ea_t ea) {qnotused(pid); qnotused(tid); qnotused(ea); } +virtual void dbg_thread_start(pid_t pid, thid_t tid, ea_t ea) {qnotused(pid); qnotused(tid); qnotused(ea); } +virtual void dbg_thread_exit(pid_t pid, thid_t tid, ea_t ea, int exit_code) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(exit_code); } +virtual void dbg_library_load(pid_t pid, thid_t tid, ea_t ea, const char * modinfo_name, ea_t modinfo_base, asize_t modinfo_size) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(modinfo_name); qnotused(modinfo_base); qnotused(modinfo_size); } +virtual void dbg_library_unload(pid_t pid, thid_t tid, ea_t ea, const char * info) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(info); } +virtual void dbg_information(pid_t pid, thid_t tid, ea_t ea, const char * info) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(info); } +virtual int dbg_exception(pid_t pid, thid_t tid, ea_t ea, int exc_code, bool exc_can_cont, ea_t exc_ea, const char * exc_info) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(exc_code); qnotused(exc_can_cont); qnotused(exc_ea); qnotused(exc_info); return 0;} +virtual void dbg_suspend_process() {} +virtual int dbg_bpt(thid_t tid, ea_t bptea) {qnotused(tid); qnotused(bptea); return 0;} +virtual int dbg_trace(thid_t tid, ea_t ip) {qnotused(tid); qnotused(ip); return 0;} +virtual void dbg_request_error(int failed_command, int failed_dbg_notification) {qnotused(failed_command); qnotused(failed_dbg_notification); } +virtual void dbg_step_into() {} +virtual void dbg_step_over() {} +virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) {qnotused(pid); qnotused(tid); qnotused(ea); } +virtual void dbg_step_until_ret() {} +virtual void dbg_bpt_changed(int bptev_code, bpt_t * bpt) {qnotused(bptev_code); qnotused(bpt); } }; int idaapi DBG_Callback(void *ud, int notification_code, va_list va) @@ -560,168 +118,167 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va) class DBG_Hooks *proxy = (class DBG_Hooks *)ud; debug_event_t *event; - int code = 0; + int ret = 0; try { - switch (notification_code) + switch ( notification_code ) { - case dbg_process_start: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_start(event->pid, - event->tid, - event->ea, - event->modinfo.name, - event->modinfo.base, - event->modinfo.size); - break; + // hookgenDBG:notifications +case dbg_process_start: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_process_start(event->pid, event->tid, event->ea, event->modinfo.name, event->modinfo.base, event->modinfo.size); +} +break; - case dbg_process_exit: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_exit( - event->pid, - event->tid, - event->ea, - event->exit_code); - break; +case dbg_process_exit: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_process_exit(event->pid, event->tid, event->ea, event->exit_code); +} +break; - case dbg_process_attach: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_attach( - event->pid, - event->tid, - event->ea, - event->modinfo.name, - event->modinfo.base, - event->modinfo.size); - break; +case dbg_process_attach: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_process_attach(event->pid, event->tid, event->ea, event->modinfo.name, event->modinfo.base, event->modinfo.size); +} +break; - case dbg_process_detach: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_detach( - event->pid, - event->tid, - event->ea); - break; +case dbg_process_detach: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_process_detach(event->pid, event->tid, event->ea); +} +break; - case dbg_thread_start: - event = va_arg(va, debug_event_t *); - proxy->dbg_thread_start( - event->pid, - event->tid, - event->ea); - break; +case dbg_thread_start: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_thread_start(event->pid, event->tid, event->ea); +} +break; - case dbg_thread_exit: - event = va_arg(va, debug_event_t *); - proxy->dbg_thread_exit( - event->pid, - event->tid, - event->ea, - event->exit_code); - break; +case dbg_thread_exit: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_thread_exit(event->pid, event->tid, event->ea, event->exit_code); +} +break; - case dbg_library_load: - event = va_arg(va, debug_event_t *); - proxy->dbg_library_load( - event->pid, - event->tid, - event->ea, - event->modinfo.name, - event->modinfo.base, - event->modinfo.size); - break; +case dbg_library_load: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_library_load(event->pid, event->tid, event->ea, event->modinfo.name, event->modinfo.base, event->modinfo.size); +} +break; - case dbg_library_unload: - event = va_arg(va, debug_event_t *); - proxy->dbg_library_unload( - event->pid, - event->tid, - event->ea, - event->info); - break; +case dbg_library_unload: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_library_unload(event->pid, event->tid, event->ea, event->info); +} +break; - case dbg_information: - event = va_arg(va, debug_event_t *); - proxy->dbg_information( - event->pid, - event->tid, - event->ea, - event->info); - break; +case dbg_information: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_information(event->pid, event->tid, event->ea, event->info); +} +break; - case dbg_exception: - { - event = va_arg(va, debug_event_t *); - int *warn = va_arg(va, int *); - *warn = proxy->dbg_exception( - event->pid, - event->tid, - event->ea, - event->exc.code, - event->exc.can_cont, - event->exc.ea, - event->exc.info); - break; - } +case dbg_exception: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + int * warn = va_arg(va, int *); + int _tmp = proxy->dbg_exception(event->pid, event->tid, event->ea, event->exc.code, event->exc.can_cont, event->exc.ea, event->exc.info); + ret = DBG_Hooks::store_int(_tmp, event, warn); +} +break; - case dbg_suspend_process: - proxy->dbg_suspend_process(); - break; +case dbg_suspend_process: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + qnotused(event); + proxy->dbg_suspend_process(); +} +break; - case dbg_bpt: - { - thid_t tid = va_arg(va, thid_t); - ea_t breakpoint_ea = va_arg(va, ea_t); - int *warn = va_arg(va, int *); - *warn = proxy->dbg_bpt(tid, breakpoint_ea); - break; - } +case dbg_bpt: +{ + thid_t tid = va_arg(va, thid_t); + ea_t bptea = va_arg(va, ea_t); + int * warn = va_arg(va, int *); + int _tmp = proxy->dbg_bpt(tid, bptea); + ret = DBG_Hooks::store_int(_tmp, tid, bptea, warn); +} +break; - case dbg_trace: - { - thid_t tid = va_arg(va, thid_t); - ea_t ip = va_arg(va, ea_t); - code = proxy->dbg_trace(tid, ip); - break; - } +case dbg_trace: +{ + thid_t tid = va_arg(va, thid_t); + ea_t ip = va_arg(va, ea_t); + ret = proxy->dbg_trace(tid, ip); +} +break; - case dbg_request_error: - { - int failed_command = (int)va_argi(va, ui_notification_t); - int failed_dbg_notification = (int)va_argi(va, dbg_notification_t); - proxy->dbg_request_error(failed_command, failed_dbg_notification); - break; - } +case dbg_request_error: +{ + ui_notification_t failed_command = ui_notification_t(va_arg(va, int)); + dbg_notification_t failed_dbg_notification = dbg_notification_t(va_arg(va, int)); + proxy->dbg_request_error((int) failed_command, (int) failed_dbg_notification); +} +break; - case dbg_step_into: - proxy->dbg_step_into(); - break; +case dbg_step_into: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + qnotused(event); + proxy->dbg_step_into(); +} +break; - case dbg_step_over: - proxy->dbg_step_over(); - break; +case dbg_step_over: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + qnotused(event); + proxy->dbg_step_over(); +} +break; - case dbg_run_to: - event = va_arg(va, debug_event_t *); - proxy->dbg_run_to( - event->pid, - event->tid, - event->ea); - break; +case dbg_run_to: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + proxy->dbg_run_to(event->pid, event->tid, event->ea); +} +break; + +case dbg_step_until_ret: +{ + const debug_event_t * event = va_arg(va, const debug_event_t *); + qnotused(event); + proxy->dbg_step_until_ret(); +} +break; + +case dbg_bpt_changed: +{ + int bptev_code = va_arg(va, int); + bpt_t * bpt = va_arg(va, bpt_t *); + proxy->dbg_bpt_changed(bptev_code, bpt); +} +break; - case dbg_step_until_ret: - proxy->dbg_step_until_ret(); - break; } } catch (Swig::DirectorException &e) { msg("Exception in DBG Hook function: %s\n", e.getMessage()); - if (PyErr_Occurred()) + if ( PyErr_Occurred() ) PyErr_Print(); } - return code; + return ret; } //------------------------------------------------------------------------ @@ -777,8 +334,8 @@ static ea_t py_internal_get_sreg_base(thid_t tid, int sreg_value) PYW_GIL_CHECK_LOCKED_SCOPE(); ea_t answer; return internal_get_sreg_base(tid, sreg_value, &answer) < 1 - ? BADADDR - : answer; + ? BADADDR + : answer; } // diff --git a/pywraps/py_dbg.py b/pywraps/py_dbg.py deleted file mode 100644 index 0a033aa..0000000 --- a/pywraps/py_dbg.py +++ /dev/null @@ -1,7 +0,0 @@ - -# -NO_PROCESS = 0xFFFFFFFF -NO_THREAD = 0 -# - - diff --git a/pywraps/py_diskio.py b/pywraps/py_diskio.py old mode 100644 new mode 100755 diff --git a/pywraps/py_expr.hpp b/pywraps/py_expr.hpp index b6f18ae..71d64d9 100644 --- a/pywraps/py_expr.hpp +++ b/pywraps/py_expr.hpp @@ -92,7 +92,7 @@ static bool pyw_unregister_idc_func(size_t ctxptr) // Unregister the function py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)ctxptr; bool ok = set_idc_func_ex(ctx->name.c_str(), NULL, NULL, 0); - + // Delete the context delete ctx; @@ -113,7 +113,7 @@ static bool py_set_idc_func_ex( // Compile* functions return false when error so the return // value must be negated for the error string to be returned bool CompileEx_wrap( - const char *file, + const char *file, bool del_macros, char *errbuf, size_t errbufsize) { diff --git a/pywraps/py_expr.py b/pywraps/py_expr.py index e14aec7..aefdd13 100644 --- a/pywraps/py_expr.py +++ b/pywraps/py_expr.py @@ -136,34 +136,3 @@ def set_idc_func_ex(name, fp=None, args=(), flags=0): flags) # - -# -------------------------------------------------------------------------- -def test1(): - global MY_IDC_FUNC - try: - # Already registered? - MY_IDC_FUNC - # Unregister - print("Unregistering function") - set_idc_func_ex(MY_IDC_FUNC) - except: - MY_IDC_FUNC = "pysum" - - ok = set_idc_func_ex(MY_IDC_FUNC, my_idc_sum, (idaapi.VT_LONG, idaapi.VT_LONG), 0) - if not ok: - del MY_IDC_FUNC - - -# - -# -------------------------------------------------------------------------- -# -def py_power(n, e): - return n ** e - -ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0) -if ok: - print("Now the pow() will be present IDC!") -else: - print("Failed to register pow() IDC function") -# diff --git a/pywraps/py_qfile.hpp b/pywraps/py_fpro.hpp similarity index 99% rename from pywraps/py_qfile.hpp rename to pywraps/py_fpro.hpp index bbd6864..7eed9f1 100644 --- a/pywraps/py_qfile.hpp +++ b/pywraps/py_fpro.hpp @@ -1,7 +1,7 @@ -#ifndef __PY_IDA_QFILE__ -#define __PY_IDA_QFILE__ +#ifndef __PY_IDA_FPRO__ +#define __PY_IDA_FPRO__ -// +// /* # class qfile_t(pyidc_opaque_object_t): @@ -402,6 +402,6 @@ public: return rc; } }; -// +// #endif diff --git a/pywraps/py_funcs.hpp b/pywraps/py_funcs.hpp new file mode 100644 index 0000000..8c60b46 --- /dev/null +++ b/pywraps/py_funcs.hpp @@ -0,0 +1,106 @@ + +// + +#ifndef FUNC_STATICDEF +#define FUNC_STATICDEF 0x00000008 +#endif + +//----------------------------------------------------------------------- +/* +# +def get_fchunk_referer(ea, idx): + pass +# +*/ +static ea_t get_fchunk_referer(ea_t ea, size_t idx) +{ + func_t *pfn = get_fchunk(ea); + func_parent_iterator_t dummy(pfn); // read referer info + if ( idx >= pfn->refqty || pfn->referers == NULL ) + return BADADDR; + else + return pfn->referers[idx]; +} + +//----------------------------------------------------------------------- +/* +# +def get_idasgn_desc(n): + """ + Get information about a signature in the list. + It returns: (name of signature, names of optional libraries) + + See also: get_idasgn_desc_with_matches + + @param n: number of signature in the list (0..get_idasgn_qty()-1) + @return: None on failure or tuple(signame, optlibs) + """ + pass +# +*/ +static PyObject *py_get_idasgn_desc(int n) +{ + char signame[MAXSTR]; + char optlibs[MAXSTR]; + + if ( get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)) < 0 ) + Py_RETURN_NONE; + else + return Py_BuildValue("(ss)", signame, optlibs); +} + +//----------------------------------------------------------------------- +/* +# +def get_idasgn_desc_with_matches(n): + """ + Get information about a signature in the list. + It returns: (name of signature, names of optional libraries, number of matches) + + @param n: number of signature in the list (0..get_idasgn_qty()-1) + @return: None on failure or tuple(signame, optlibs, nmatches) + """ + pass +# +*/ +static PyObject *py_get_idasgn_desc_with_matches(int n) +{ + char signame[MAXSTR]; + char optlibs[MAXSTR]; + + int32 matches = get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)); + if ( matches < 0 ) + Py_RETURN_NONE; + else + return Py_BuildValue("(ssi)", signame, optlibs, matches); +} + +//----------------------------------------------------------------------- +/* +# +def get_func_cmt(fn, repeatable): + """ + Retrieve function comment + @param fn: function instance + @param repeatable: retrieve repeatable or non-repeatable comments + @return: None on failure or the comment + """ + pass +# +*/ +static PyObject *py_get_func_cmt(func_t *fn, bool repeatable) +{ + char *s = get_func_cmt(fn, repeatable); + if ( s == NULL ) + { + Py_RETURN_NONE; + } + else + { + PyObject *py_s = PyString_FromString(s); + qfree(s); + return py_s; + } +} + +// diff --git a/pywraps/py_gdl.py b/pywraps/py_gdl.py old mode 100644 new mode 100755 index 0de5dcb..32604ec --- a/pywraps/py_gdl.py +++ b/pywraps/py_gdl.py @@ -17,7 +17,7 @@ class BasicBlock(object): self.type = self._fc._q.calc_block_type(self.id) """Block type (check fc_block_type_t enum)""" - + def preds(self): """ Iterates the predecessors list @@ -26,7 +26,7 @@ class BasicBlock(object): for i in xrange(0, self._fc._q.npred(self.id)): yield self._fc[q.pred(self.id, i)] - + def succs(self): """ Iterates the successors list @@ -50,16 +50,16 @@ class FlowChart(object): """ if (f is None) and (bounds is None or type(bounds) != types.TupleType): raise Exception("Please specifiy either a function or start/end pair") - + if bounds is None: bounds = (BADADDR, BADADDR) - + # Create the flowchart self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags) - + size = property(lambda self: self._q.size()) """Number of blocks in the flow chart""" - + def refresh(): """Refreshes the flow chart""" @@ -67,13 +67,13 @@ class FlowChart(object): def _getitem(self, index): - return BasicBlock(index, self._q[index], self) - - + return BasicBlock(index, self._q[index], self) + + def __iter__(self): return (self._getitem(index) for index in xrange(0, self.size)) - - + + def __getitem__(self, index): """ Returns a basic block @@ -82,7 +82,7 @@ class FlowChart(object): """ if index >= self.size: raise KeyError - else: + else: return self._getitem(index) # diff --git a/pywraps/py_graph.hpp b/pywraps/py_graph.hpp index 89d3d9b..c608bc3 100644 --- a/pywraps/py_graph.hpp +++ b/pywraps/py_graph.hpp @@ -7,26 +7,6 @@ class py_graph_t : public py_customidamemo_t typedef py_customidamemo_t inherited; protected: - - virtual void node_info_modified(int n, const node_info_t *ni, uint32 flags) - { - if ( ni == NULL ) - { - node_cache.erase(n); - } - else - { - nodetext_cache_t *c = node_cache.get(n); - if ( c != NULL ) - { - if ( (flags & NIF_TEXT) == NIF_TEXT ) - c->text = ni->text; - if ( (flags & NIF_BG_COLOR) == NIF_BG_COLOR ) - c->bgcolor = ni->bg_color; - } - } - } - void collect_class_callbacks_ids(callbacks_ids_t *out); private: @@ -47,9 +27,9 @@ private: { qstring text; bgcolor_t bgcolor; - nodetext_cache_t(const nodetext_cache_t &rhs): text(rhs.text), bgcolor(rhs.bgcolor) { } - nodetext_cache_t(const char *t, bgcolor_t c): text(t), bgcolor(c) { } - nodetext_cache_t() { } + nodetext_cache_t(const nodetext_cache_t &rhs): text(rhs.text), bgcolor(rhs.bgcolor) {} + nodetext_cache_t(const char *t, bgcolor_t c): text(t), bgcolor(c) {} + nodetext_cache_t() {} }; class nodetext_cache_map_t: public std::map @@ -94,7 +74,7 @@ private: void clear(py_graph_t *pyg) { iterator e = end(); - for (iterator it=begin();it!=end();) + for ( iterator it=begin(); it!=end(); ) { if ( it->second == pyg ) { @@ -356,13 +336,15 @@ private: char grnode[MAXSTR]; qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title); id.create(grnode); + // pre-bind 'self', so that 'on_user_refresh()' can complete + this->self = borref_t(self); graph_viewer_t *pview = create_graph_viewer(form, id, s_callback, this, 0); + this->self = ref_t(); open_tform(form, FORM_TAB | FORM_MENU | FORM_QWIDGET); if ( pview != NULL ) viewer_fit_window(pview); bind(self, pview); install_custom_viewer_handlers(); - refresh(); lookup_info.commit(e, form, view); } else @@ -376,7 +358,7 @@ private: Py_ssize_t add_command(const char *title, const char *hotkey) { - if ( !has_callback(GRCODE_HAVE_COMMAND) || view == NULL) + if ( !has_callback(GRCODE_HAVE_COMMAND) || view == NULL ) return 0; Py_ssize_t cmd_id = cmdid_pyg.id(); bool ok = viewer_add_menu_item(view, title, s_menucb, (void *)cmd_id, hotkey, 0); @@ -496,7 +478,7 @@ void py_graph_t::collect_class_callbacks_ids(callbacks_ids_t *out) //------------------------------------------------------------------------- void py_graph_t::on_user_refresh(mutable_graph_t *g) { - if ( !refresh_needed || self == NULL /* Happens at creation-time */ ) + if ( !refresh_needed ) return; // Check return value to OnRefresh() call @@ -658,7 +640,7 @@ int py_graph_t::gr_callback(int code, va_list va) { graph_viewer_t *view = va_arg(va, graph_viewer_t *); selection_item_t *item = va_arg(va, selection_item_t *); - graph_item_t *gitem = va_arg(va, graph_item_t *); + graph_item_t *gitem = va_arg(va, graph_item_t *); ret = on_clicked(view, item, gitem); } else diff --git a/pywraps/py_graph.py b/pywraps/py_graph.py old mode 100644 new mode 100755 diff --git a/pywraps/py_idaapi.hpp b/pywraps/py_idaapi.hpp index a87ca7d..633e283 100644 --- a/pywraps/py_idaapi.hpp +++ b/pywraps/py_idaapi.hpp @@ -3,6 +3,755 @@ // +//------------------------------------------------------------------------ +// String constants used +static const char S_PY_IDCCVT_VALUE_ATTR[] = "__idc_cvt_value__"; +static const char S_PY_IDCCVT_ID_ATTR[] = "__idc_cvt_id__"; +static const char S_PY_IDC_OPAQUE_T[] = "py_idc_cvt_helper_t"; +static const char S_PY_IDC_GLOBAL_VAR_FMT[] = "__py_cvt_gvar_%d"; + +// Constants used by get_idaapi_class_reference() +#define PY_CLSID_CVT_INT64 0 +#define PY_CLSID_APPCALL_SKEL_OBJ 1 +#define PY_CLSID_CVT_BYREF 2 +#define PY_CLSID_LAST 3 + +//--------------------------------------------------------------------------- +// Use these macros to define script<->C fields +#define DEFINE_SCFIELDX(name, type, is_opt) { #name, type, qoffsetof(CUR_STRUC, name), is_opt } +#define DEFINE_SCFIELD(name, type) DEFINE_SCFIELDX(name, type, 0) +#define DEFINE_SCFIELD_OPT(name, type) DEFINE_SCFIELDX(name, type, 1) + +//--------------------------------------------------------------------------- +enum scfield_types_t +{ + // Numeric fields + FT_FIRST_NUM, + FT_INT, + FT_SIZET, + FT_SSIZET, + FT_NUM16, + FT_NUM32, + FT_LAST_NUM, + // String field + FT_STR, + FT_CHAR, + // Object fields + FT_ARR, + // Allocated array of strings + FT_STRARR, + // Allocated array of 16bit numbers + FT_NUM16ARR, + // Fixed size character array. The size must be passed in the definition + FT_CHRARR_STATIC, +}; + +//--------------------------------------------------------------------------- +struct scfld_t +{ + const char *field_name; + uint32 field_type; + size_t field_offs; + bool is_optional; +}; + +#define FT_VALUE_MASK 0xFFFF0000 +// Possible return values of conversion functions +#define FT_NOT_FOUND -1 +#define FT_BAD_TYPE -2 +#define FT_OK 1 + +//------------------------------------------------------------------------- +Py_ssize_t pyvar_walk_list( + const ref_t &py_list, + int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud), + void *ud) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + Py_ssize_t size = CIP_FAILED; + do + { + PyObject *o = py_list.o; + if ( !PyList_CheckExact(o) && !PyW_IsSequenceType(o) ) + break; + + bool is_seq = !PyList_CheckExact(o); + size = is_seq ? PySequence_Size(o) : PyList_Size(o); + if ( cb == NULL ) + break; + + Py_ssize_t i; + for ( i=0; i= CIP_OK; + if ( !ok ) + PyErr_SetString(PyExc_ValueError, "Could not convert Python object to IDC object!"); + return ok; +} + +//------------------------------------------------------------------------ +static idc_class_t *get_py_idc_cvt_opaque() +{ + return find_idc_class(S_PY_IDC_OPAQUE_T); +} + +//------------------------------------------------------------------------- +// Utility function to create opaque / convertible Python <-> IDC variables +// The referred Python variable will have its reference increased +static bool wrap_PyObject_ptr(const ref_t &py_var, idc_value_t *idc_var) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + // Create an IDC object of this special helper class + if ( VarObject(idc_var, get_py_idc_cvt_opaque()) != eOk ) + return false; + + // Store the CVT id + idc_value_t idc_val; + idc_val.set_long(PY_ICID_OPAQUE); + VarSetAttr(idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val); + + // Store the value as a PVOID referencing the given Python object + py_var.incref(); + idc_val.set_pvoid(py_var.o); + VarSetAttr(idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val); + + return true; +} + +//------------------------------------------------------------------------ +// IDC Opaque object destructor: when the IDC object dies we kill the +// opaque Python object along with it +static const char py_idc_cvt_helper_dtor_args[] = { VT_OBJ, 0 }; +static error_t idaapi py_idc_opaque_dtor( + idc_value_t *argv, + idc_value_t * /*res*/) +{ + // This can be called at plugin registration time, when a + // 'script_plugin_t' instance is ::free()'d. It is + // not guaranteed that we have the GIL at that point. + PYW_GIL_GET; + + // Get the value from the object + idc_value_t idc_val; + VarGetAttr(&argv[0], S_PY_IDCCVT_VALUE_ATTR, &idc_val); + + // Extract the Python object reference + PyObject *py_obj = (PyObject *)idc_val.pvoid; + + // Decrease its reference (and eventually destroy it) + Py_DECREF(py_obj); + + return eOk; +} + +//------------------------------------------------------------------------- +// Converts a Python variable into an IDC variable +// This function returns on one CIP_XXXX +int pyvar_to_idcvar( + const ref_t &py_var, + idc_value_t *idc_var, + int *gvar_sn) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + // None / NULL + if ( py_var == NULL || py_var.o == Py_None ) + { + idc_var->set_long(0); + } + // Numbers? + else if ( PyW_GetNumberAsIDC(py_var.o, idc_var) ) + { + return CIP_OK; + } + // String + else if ( PyString_Check(py_var.o) ) + { + idc_var->_set_string(PyString_AsString(py_var.o), PyString_Size(py_var.o)); + } + // Boolean + else if ( PyBool_Check(py_var.o) ) + { + idc_var->set_long(py_var.o == Py_True ? 1 : 0); + } + // Float + else if ( PyFloat_Check(py_var.o) ) + { + double dresult = PyFloat_AsDouble(py_var.o); + ieee_realcvt((void *)&dresult, idc_var->e, 3); + idc_var->vtype = VT_FLOAT; + } + // void* + else if ( PyCObject_Check(py_var.o) ) + { + idc_var->set_pvoid(PyCObject_AsVoidPtr(py_var.o)); + } + // Python list? + else if ( PyList_CheckExact(py_var.o) || PyW_IsSequenceType(py_var.o) ) + { + // Create the object + VarObject(idc_var); + + // Determine list size and type + bool is_seq = !PyList_CheckExact(py_var.o); + Py_ssize_t size = is_seq ? PySequence_Size(py_var.o) : PyList_Size(py_var.o); + bool ok = true; + qstring attr_name; + + // Convert each item + for ( Py_ssize_t i=0; i= CIP_OK; + if ( ok ) + { + // Form the attribute name + newref_t py_int(PyInt_FromSsize_t(i)); + ok = PyW_ObjectToString(py_int.o, &attr_name); + if ( !ok ) + break; + // Store the attribute + VarSetAttr(idc_var, attr_name.c_str(), &v); + } + if ( !ok ) + break; + } + return ok ? CIP_OK : CIP_FAILED; + } + // Dictionary: we convert to an IDC object + else if ( PyDict_Check(py_var.o) ) + { + // Create an empty IDC object + VarObject(idc_var); + + // Get the dict.items() list + newref_t py_items(PyDict_Items(py_var.o)); + + // Get the size of the list + qstring key_name; + bool ok = true; + Py_ssize_t size = PySequence_Size(py_items.o); + for ( Py_ssize_t i=0; i (key, value) + PyObject *py_item = PyList_GetItem(py_items.o, i); + + // Extract key/value + newref_t key(PySequence_GetItem(py_item, 0)); + newref_t val(PySequence_GetItem(py_item, 1)); + + // Get key's string representation + PyW_ObjectToString(key.o, &key_name); + + // Convert the attribute into an IDC value + idc_value_t v; + ok = pyvar_to_idcvar(val, &v, gvar_sn) >= CIP_OK; + if ( ok ) + { + // Store the attribute + VarSetAttr(idc_var, key_name.c_str(), &v); + } + if ( !ok ) + break; + } + return ok ? CIP_OK : CIP_FAILED; + } + // Possible function? + else if ( PyCallable_Check(py_var.o) ) + { + idc_var->clear(); + idc_var->vtype = VT_FUNC; + idc_var->funcidx = -1; // Does not apply + return CIP_OK; + } + // Objects: + // - pyidc_cvt objects: int64, byref, opaque + // - other python objects + else + { + // Get the type + int cvt_id = get_pyidc_cvt_type(py_var.o); + switch ( cvt_id ) + { + // + // 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; + } + // + // 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 ) + { + (*gvar_sn)++; + // Create a reference to this global variable + VarRef(idc_var, gvar); + } + return ok ? CIP_OK : CIP_FAILED; + } + // + // 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 + VarObject(idc_var); + for ( Py_ssize_t i=0; i 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 + VarSetAttr(idc_var, field_name, &v); + } + } + } + return CIP_OK; +} + +//------------------------------------------------------------------------- +inline PyObject *cvt_to_pylong(int32 v) +{ + return PyLong_FromLong(v); +} + +inline PyObject *cvt_to_pylong(int64 v) +{ + return PyLong_FromLongLong(v); +} + +//------------------------------------------------------------------------- +// Converts an IDC variable to a Python variable +// If py_var points to an existing object then the object will be updated +// If py_var points to an existing immutable object then ZERO is returned +// Returns one of CIP_xxxx. Check pywraps.hpp +int idcvar_to_pyvar( + const idc_value_t &idc_var, + ref_t *py_var) +{ + 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: + { + // 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; + } + +#if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC) + case VT_STR: + *py_var = newref_t(PyString_FromString(idc_var.str)); + break; + +#endif + case VT_STR2: + 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) != 0 ) + 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 = VarDeref(const_cast(&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 ( VarGetAttr(&idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val) == eOk + && VarGetAttr(&idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val) == 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 = VarFirstAttr(&idc_var); + attr_name != NULL; + attr_name = VarNextAttr(&idc_var, attr_name) ) + { + // Get the attribute + idc_value_t v; + VarGetAttr(&idc_var, attr_name, &v, 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; +} + +//------------------------------------------------------------------------- +// Converts IDC arguments to Python argument list or just one tuple +// If 'decref' is NULL then 'pargs' will contain one element which is the tuple +bool pyw_convert_idc_args( + const idc_value_t args[], + int nargs, + ref_vec_t &pargs, + bool as_tupple, + char *errbuf, + size_t errbufsize) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + ref_t py_tuple; + + pargs.qclear(); + + if ( as_tupple ) + { + py_tuple = newref_t(PyTuple_New(nargs)); + if ( py_tuple == NULL ) + { + if ( errbuf != 0 && errbufsize > 0 ) + qstrncpy(errbuf, "Failed to create a new tuple to store arguments!", errbufsize); + return false; + } + } + + for ( int i=0; i 0 ) + qsnprintf(errbuf, errbufsize, "arg#%d has wrong type %d", i, args[i].vtype); + return false; + } + + if ( as_tupple ) + { + // PyTuple_SetItem() steals the reference. + py_obj.incref(); + QASSERT(30412, PyTuple_SetItem(py_tuple.o, i, py_obj.o) == 0); + } + else + { + pargs.push_back(py_obj); + } + } + + // Add the tuple to the list of args only now. Doing so earlier will + // cause the py_tuple.o->ob_refcnt to be 2 and not 1, and that will + // cause 'PyTuple_SetItem()' to fail. + if ( as_tupple ) + pargs.push_back(py_tuple); + + return true; +} + //------------------------------------------------------------------------ // String constants used static const char S_PYINVOKE0[] = "_py_invoke0"; @@ -243,21 +992,6 @@ void deinit_pywraps() set_idc_func_ex(S_PYINVOKE0, NULL, idc_py_invoke0_args, 0); } -//------------------------------------------------------------------------ -// Utility function to create a class instance whose constructor takes zero arguments -ref_t create_idaapi_class_instance0(const char *clsname) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t py_cls(get_idaapi_attr(clsname)); - if ( py_cls == NULL ) - return ref_t(); - - ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL)); - if ( PyW_GetError() || py_obj == NULL ) - py_obj = ref_t(); - return py_obj; -} - //------------------------------------------------------------------------ // Utility function to create linked class instances ref_t create_idaapi_linked_class_instance( @@ -302,8 +1036,8 @@ ref_t get_idaapi_attr(const char *attrname) { PYW_GIL_CHECK_LOCKED_SCOPE(); return py_cvt_helper_module == NULL - ? ref_t() - : PyW_TryGetAttrString(py_cvt_helper_module.o, attrname); + ? ref_t() + : PyW_TryGetAttrString(py_cvt_helper_module.o, attrname); } //------------------------------------------------------------------------ @@ -608,7 +1342,7 @@ bool PyW_ShowCbErr(const char *cb_name) if ( !PyW_GetError(&err_str) ) return false; - warning("IDAPython: Error while calling Python callback <%s>:\n%s", cb_name, err_str.c_str()); + msg("IDAPython: Error while calling Python callback <%s>:\n%s", cb_name, err_str.c_str()); return true; } @@ -623,8 +1357,290 @@ void *pyobj_get_clink(PyObject *pyobj) return t; } +//------------------------------------------------------------------------ +class pywraps_notify_when_t +{ + ref_vec_t table[NW_EVENTSCNT]; + qstring err; + bool in_notify; + struct notify_when_args_t + { + int when; + PyObject *py_callable; + }; + typedef qvector notify_when_args_vec_t; + notify_when_args_vec_t delayed_notify_when_list; + + //------------------------------------------------------------------------ + static int idaapi idp_callback(void *ud, int event_id, va_list va) + { + pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud; + switch ( event_id ) + { + case processor_t::newfile: + case processor_t::oldfile: + { + // This hook gets called from the kernel. Ensure we hold the GIL. + // Note that PYW_GIL_GET appears in each case of the switch, which is to + // ensure that the GIL is retrieved ONLY when we need it. If PYW_GIL_GET + // appears outside the switch, it will be executed each time this callback + // is called, which results in a huge slowdown (at least on mac). + PYW_GIL_GET; + int old = event_id == processor_t::oldfile ? 1 : 0; + char *dbname = va_arg(va, char *); + _this->notify(NW_OPENIDB_SLOT, old); + } + break; + case processor_t::closebase: + { + PYW_GIL_GET; + _this->notify(NW_CLOSEIDB_SLOT); + } + break; + } + // event not processed, let other plugins or the processor module handle it + return 0; + } + + //------------------------------------------------------------------------ + bool unnotify_when(int when, PyObject *py_callable) + { + int cnt = 0; + for ( int slot=0; slot 0; + } + + //------------------------------------------------------------------------ + void register_callback(int slot, PyObject *py_callable) + { + borref_t callable_ref(py_callable); + ref_vec_t &tbl = table[slot]; + ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref); + + // Already added + if ( it != it_end ) + return; + + // Insert the element + tbl.push_back(callable_ref); + } + + //------------------------------------------------------------------------ + void unregister_callback(int slot, PyObject *py_callable) + { + borref_t callable_ref(py_callable); + ref_vec_t &tbl = table[slot]; + ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref); + + // Not found? + if ( it == it_end ) + return; + + // Delete the element + tbl.erase(it); + } + +public: + //------------------------------------------------------------------------ + bool init() + { + return hook_to_notification_point(HT_IDP, idp_callback, this); + } + + //------------------------------------------------------------------------ + bool deinit() + { + // Uninstall all objects + ref_vec_t::iterator it, it_end; + for ( int slot=0; sloto); + } + // ...and remove the notification + return unhook_from_notification_point(HT_IDP, idp_callback, this); + } + + //------------------------------------------------------------------------ + bool notify_when(int when, PyObject *py_callable) + { + // While in notify() do not allow insertion or deletion to happen on the spot + // Instead we will queue them so that notify() will carry the action when it finishes + // dispatching the notification handlers + if ( in_notify ) + { + notify_when_args_t &args = delayed_notify_when_list.push_back(); + args.when = when; + args.py_callable = py_callable; + return true; + } + // Uninstalling the notification? + if ( (when & NW_REMOVE) != 0 ) + return unnotify_when(when & ~NW_REMOVE, py_callable); + + int cnt = 0; + for ( int slot=0; slot 0; + } + + //------------------------------------------------------------------------ + bool notify(int slot, ...) + { + va_list va; + va_start(va, slot); + bool ok = notify_va(slot, va); + va_end(va); + return ok; + } + + //------------------------------------------------------------------------ + bool notify_va(int slot, va_list va) + { + PYW_GIL_CHECK_LOCKED_SCOPE(); + + // Sanity bounds check! + if ( slot < 0 || slot >= NW_EVENTSCNT ) + return false; + + bool ok = true; + in_notify = true; + int old = slot == NW_OPENIDB_SLOT ? va_arg(va, int) : 0; + + { + for ( ref_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end(); + it != it_end; + ++it ) + { + // Form the notification code + newref_t py_code(PyInt_FromLong(1 << slot)); + ref_t py_result; + switch ( slot ) + { + case NW_CLOSEIDB_SLOT: + case NW_INITIDA_SLOT: + case NW_TERMIDA_SLOT: + { + py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, NULL)); + break; + } + case NW_OPENIDB_SLOT: + { + newref_t py_old(PyInt_FromLong(old)); + py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, py_old.o, NULL)); + } + break; + } + if ( PyW_GetError(&err) || py_result == NULL ) + { + PyErr_Clear(); + warning("notify_when(): Error occured while notifying object.\n%s", err.c_str()); + ok = false; + } + } + } + in_notify = false; + + // Process any delayed notify_when() calls that + if ( !delayed_notify_when_list.empty() ) + { + notify_when_args_vec_t::iterator it, it_end; + for ( it = delayed_notify_when_list.begin(), it_end=delayed_notify_when_list.end(); + it != it_end; + ++it ) + { + notify_when(it->when, it->py_callable); + } + delayed_notify_when_list.qclear(); + } + + return ok; + } + + //------------------------------------------------------------------------ + pywraps_notify_when_t() + { + in_notify = false; + } +}; + +static pywraps_notify_when_t *g_nw = NULL; + +//------------------------------------------------------------------------ +// Initializes the notify_when mechanism +// (Normally called by IDAPython plugin.init()) +bool pywraps_nw_init() +{ + if ( g_nw != NULL ) + return true; + + g_nw = new pywraps_notify_when_t(); + if ( g_nw->init() ) + return true; + + // Things went bad, undo! + delete g_nw; + g_nw = NULL; + return false; +} + +//------------------------------------------------------------------------ +bool pywraps_nw_notify(int slot, ...) +{ + if ( g_nw == NULL ) + return false; + + // Appears to be called from 'driver_notifywhen.cpp', which + // itself is called from possibly non-python code. + // I.e., we must acquire the GIL. + PYW_GIL_GET; + va_list va; + va_start(va, slot); + bool ok = g_nw->notify_va(slot, va); + va_end(va); + + return ok; +} + +//------------------------------------------------------------------------ +// Deinitializes the notify_when mechanism +bool pywraps_nw_term() +{ + if ( g_nw == NULL ) + return true; + + // If could not deinitialize then return w/o stopping nw + if ( !g_nw->deinit() ) + return false; + + // Cleanup + delete g_nw; + g_nw = NULL; + return true; +} + + // + + // + + //------------------------------------------------------------------------ /* # @@ -728,7 +1744,7 @@ static bool qstrvec_t_assign(PyObject *self, PyObject *other) { qstrvec_t *lhs = qstrvec_t_get_clink(self); qstrvec_t *rhs = qstrvec_t_get_clink(other); - if (lhs == NULL || rhs == NULL) + if ( lhs == NULL || rhs == NULL ) return false; *lhs = *rhs; return true; @@ -826,7 +1842,30 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx) return true; } -//--------------------------------------------------------------------------- +//------------------------------------------------------------------------ +/* +# +def notify_when(when, callback): + """ + Register a callback that will be called when an event happens. + @param when: one of NW_XXXX constants + @param callback: This callback prototype varies depending on the 'when' parameter: + The general callback format: + def notify_when_callback(nw_code) + In the case of NW_OPENIDB: + def notify_when_callback(nw_code, is_old_database) + @return: Boolean + """ + pass +# +*/ +static bool notify_when(int when, PyObject *py_callable) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + if ( g_nw == NULL || !PyCallable_Check(py_callable) ) + return false; + return g_nw->notify_when(when, py_callable); +} // #endif diff --git a/pywraps/py_idaapi.py b/pywraps/py_idaapi.py old mode 100644 new mode 100755 index c7204dd..a500a04 --- a/pywraps/py_idaapi.py +++ b/pywraps/py_idaapi.py @@ -435,7 +435,7 @@ def IDAPython_FormatExc(etype, value, tb, limit=None): # ------------------------------------------------------------ -def IDAPython_ExecScript(script, g): +def IDAPython_ExecScript(script, g, print_error=True): """ Run the specified script. It also addresses http://code.google.com/p/idapython/issues/detail?id=42 @@ -458,7 +458,8 @@ def IDAPython_ExecScript(script, g): PY_COMPILE_ERR = None except Exception as e: PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc()) - print(PY_COMPILE_ERR) + if print_error: + print(PY_COMPILE_ERR) finally: # Restore state g['__file__'] = old__file__ @@ -467,7 +468,7 @@ def IDAPython_ExecScript(script, g): return PY_COMPILE_ERR # ------------------------------------------------------------ -def IDAPython_LoadProcMod(script, g): +def IDAPython_LoadProcMod(script, g, print_error=True): """ Load processor module. """ @@ -497,7 +498,8 @@ def IDAPython_LoadProcMod(script, g): PY_COMPILE_ERR = None except Exception as e: PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc()) - print(PY_COMPILE_ERR) + if print_error: + print(PY_COMPILE_ERR) finally: if fp: fp.close() @@ -506,7 +508,7 @@ def IDAPython_LoadProcMod(script, g): return (PY_COMPILE_ERR, procobj) # ------------------------------------------------------------ -def IDAPython_UnLoadProcMod(script, g): +def IDAPython_UnLoadProcMod(script, g, print_error=True): """ Unload processor module. """ @@ -598,8 +600,23 @@ IDAPython_Completion = __IDAPython_Completion_Util() def _listify_types(*classes): for cls in classes: - cls.__getitem__ = cls.at + cls.at = cls.__getitem__ # '__getitem__' has bounds checkings cls.__len__ = cls.size cls.__iter__ = _bounded_getitem_iterator +# The general callback format of notify_when() is: +# def notify_when_callback(nw_code) +# In the case of NW_OPENIDB, the callback is: +# def notify_when_callback(nw_code, is_old_database) +NW_OPENIDB = 0x0001 +"""Notify when the database is opened. Its callback is of the form: def notify_when_callback(nw_code, is_old_database)""" +NW_CLOSEIDB = 0x0002 +"""Notify when the database is closed. Its callback is of the form: def notify_when_callback(nw_code)""" +NW_INITIDA = 0x0004 +"""Notify when the IDA starts. Its callback is of the form: def notify_when_callback(nw_code)""" +NW_TERMIDA = 0x0008 +"""Notify when the IDA terminates. Its callback is of the form: def notify_when_callback(nw_code)""" +NW_REMOVE = 0x0010 +"""Use this flag with other flags to uninstall a notifywhen callback""" + # diff --git a/pywraps/py_idaview.hpp b/pywraps/py_idaview.hpp deleted file mode 100644 index 2c6c251..0000000 --- a/pywraps/py_idaview.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __PY_IDA_VIEW__ -#define __PY_IDA_VIEW__ - -// -class py_idaview_t : public py_customidamemo_t -{ - typedef py_customidamemo_t inherited; - -public: - static bool Bind(PyObject *self); - static bool Unbind(PyObject *self); -}; - -//------------------------------------------------------------------------- -bool py_idaview_t::Bind(PyObject *self) -{ - // Already a py_idaview_t associated to this object? - py_idaview_t *_this = view_extract_this(self); - if ( _this != NULL ) - return false; - - qstring title; - if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) ) - return false; - - // Get the IDAView associated to this TForm - TForm *tform = find_tform(title.c_str()); - if ( tform == NULL ) - return false; - TCustomControl *v = get_tform_idaview(tform); - if ( v == NULL ) - return false; - - // Get unique py_idaview_t associated to that tform - py_idaview_t *py_view; - TCustomControl *found_view; - if ( lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) ) - { - // If we have a py_idaview_t for that form, ensure it has - // the expected view. - QASSERT(30451, found_view == v); - } - else - { - py_view = new py_idaview_t(); - lookup_info_t::entry_t &e = lookup_info.new_entry(py_view); - lookup_info.commit(e, tform, v); - } - - // Finally, bind: - // py_idaview_t <=> IDAViewWrapper - // py_idaview_t => TCustomControl - bool ok = py_view->bind(self, v); - if ( ok ) - { - ok = py_view->collect_pyobject_callbacks(self); - if ( ok ) - py_view->install_custom_viewer_handlers(); - else - delete py_view; - } - return ok; -} - -//------------------------------------------------------------------------- -bool py_idaview_t::Unbind(PyObject *self) -{ - py_idaview_t *_this = view_extract_this(self); - if ( _this == NULL ) - return false; - _this->unbind(true); - return true; -} - -//------------------------------------------------------------------------- -bool pyidag_bind(PyObject *self) -{ - return py_idaview_t::Bind(self); -} - -//------------------------------------------------------------------------- -bool pyidag_unbind(PyObject *self) -{ - return py_idaview_t::Unbind(self); -} - -// - -//-------------------------------------------------------------------------- - -// -bool pyidag_bind(PyObject *self); -bool pyidag_unbind(PyObject *self); -// - -#endif // __PY_IDA_VIEW__ diff --git a/pywraps/py_idaview.py b/pywraps/py_idaview.py deleted file mode 100644 index 3d3783e..0000000 --- a/pywraps/py_idaview.py +++ /dev/null @@ -1,20 +0,0 @@ - -# -class IDAViewWrapper(CustomIDAMemo): - """This class wraps access to native IDA views. See kernwin.hpp file""" - def __init__(self, title): - """ - Constructs the IDAViewWrapper object around the view - whose title is 'title'. - - @param title: The title of the existing IDA view. E.g., 'IDA View-A' - """ - self._title = title - - def Bind(self): - return _idaapi.pyidag_bind(self) - - def Unbind(self): - return _idaapi.pyidag_unbind(self) - -# diff --git a/pywraps/py_idbhooks.hpp b/pywraps/py_idbhooks.hpp new file mode 100644 index 0000000..8ae422b --- /dev/null +++ b/pywraps/py_idbhooks.hpp @@ -0,0 +1,640 @@ + + +// + +//--------------------------------------------------------------------------- +// IDB hooks +//--------------------------------------------------------------------------- +int idaapi IDB_Callback(void *ud, int notification_code, va_list va); +class IDB_Hooks +{ +public: + virtual ~IDB_Hooks() { unhook(); } + + bool hook() + { + return hook_to_notification_point(HT_IDB, IDB_Callback, this); + } + bool unhook() + { + return unhook_from_notification_point(HT_IDB, IDB_Callback, this); + } + + // hookgenIDB:methods +virtual int byte_patched(ea_t ea, uint32 old_value) {qnotused(ea); qnotused(old_value); return 0;} +virtual int cmt_changed(ea_t ea, bool repeatable_cmt) {qnotused(ea); qnotused(repeatable_cmt); return 0;} +virtual int ti_changed(ea_t ea, const type_t * type, const p_list * fnames) {qnotused(ea); qnotused(type); qnotused(fnames); return 0;} +virtual int op_ti_changed(ea_t ea, int n, const type_t * type, const p_list * fnames) {qnotused(ea); qnotused(n); qnotused(type); qnotused(fnames); return 0;} +virtual int op_type_changed(ea_t ea, int n) {qnotused(ea); qnotused(n); return 0;} +virtual int enum_created(enum_t id) {qnotused(id); return 0;} +virtual int enum_deleted(enum_t id) {qnotused(id); return 0;} +virtual int enum_bf_changed(enum_t id) {qnotused(id); return 0;} +virtual int enum_renamed(tid_t id) {qnotused(id); return 0;} +virtual int enum_cmt_changed(tid_t id, bool repeatable) {qnotused(id); qnotused(repeatable); return 0;} +virtual int enum_member_created(enum_t id, const_t cid) {qnotused(id); qnotused(cid); return 0;} +virtual int enum_member_deleted(enum_t id, const_t cid) {qnotused(id); qnotused(cid); return 0;} +virtual int struc_created(tid_t struc_id) {qnotused(struc_id); return 0;} +virtual int struc_deleted(tid_t struc_id) {qnotused(struc_id); return 0;} +virtual int struc_renamed(struc_t * sptr) {qnotused(sptr); return 0;} +virtual int struc_expanded(struc_t * sptr) {qnotused(sptr); return 0;} +virtual int struc_cmt_changed(tid_t struc_id, bool repeatable_cmt) {qnotused(struc_id); qnotused(repeatable_cmt); return 0;} +virtual int struc_member_created(struc_t * sptr, member_t * mptr) {qnotused(sptr); qnotused(mptr); return 0;} +virtual int struc_member_deleted(struc_t * sptr, tid_t member_id, ea_t offset) {qnotused(sptr); qnotused(member_id); qnotused(offset); return 0;} +virtual int struc_member_renamed(struc_t * sptr, member_t * mptr) {qnotused(sptr); qnotused(mptr); return 0;} +virtual int struc_member_changed(struc_t * sptr, member_t * mptr) {qnotused(sptr); qnotused(mptr); return 0;} +virtual int thunk_func_created(func_t * pfn) {qnotused(pfn); return 0;} +virtual int func_tail_appended(func_t * pfn, func_t * tail) {qnotused(pfn); qnotused(tail); return 0;} +virtual int func_tail_removed(func_t * pfn, ea_t tail_ea) {qnotused(pfn); qnotused(tail_ea); return 0;} +virtual int tail_owner_changed(func_t * tail, ea_t owner_func, ea_t old_owner) {qnotused(tail); qnotused(owner_func); qnotused(old_owner); return 0;} +virtual int func_noret_changed(func_t * pfn) {qnotused(pfn); return 0;} +virtual int segm_added(segment_t * s) {qnotused(s); return 0;} +virtual int segm_deleted(ea_t startEA, ea_t endEA) {qnotused(startEA); qnotused(endEA); return 0;} +virtual int segm_start_changed(segment_t * s, ea_t oldstart) {qnotused(s); qnotused(oldstart); return 0;} +virtual int segm_end_changed(segment_t * s, ea_t oldend) {qnotused(s); qnotused(oldend); return 0;} +virtual int segm_moved(ea_t from, ea_t to, asize_t size) {qnotused(from); qnotused(to); qnotused(size); return 0;} +virtual int area_cmt_changed(areacb_t * cb, const area_t * a, const char * cmt, bool repeatable) {qnotused(cb); qnotused(a); qnotused(cmt); qnotused(repeatable); return 0;} +virtual int changing_cmt(ea_t ea, bool repeatable_cmt, const char * newcmt) {qnotused(ea); qnotused(repeatable_cmt); qnotused(newcmt); return 0;} +virtual int changing_ti(ea_t ea, const type_t * new_type, const p_list * new_fnames) {qnotused(ea); qnotused(new_type); qnotused(new_fnames); return 0;} +virtual int changing_op_ti(ea_t ea, int n, const type_t * new_type, const p_list * new_fnames) {qnotused(ea); qnotused(n); qnotused(new_type); qnotused(new_fnames); return 0;} +virtual int changing_op_type(ea_t ea, int n) {qnotused(ea); qnotused(n); return 0;} +virtual int deleting_enum(enum_t id) {qnotused(id); return 0;} +virtual int changing_enum_bf(enum_t id, bool new_bf) {qnotused(id); qnotused(new_bf); return 0;} +virtual int renaming_enum(tid_t id, bool is_enum, const char * newname) {qnotused(id); qnotused(is_enum); qnotused(newname); return 0;} +virtual int changing_enum_cmt(tid_t id, bool repeatable, const char * newcmt) {qnotused(id); qnotused(repeatable); qnotused(newcmt); return 0;} +virtual int deleting_enum_const() {return 0;} +virtual int deleting_struc(struc_t * sptr) {qnotused(sptr); return 0;} +virtual int renaming_struc(tid_t id, const char * oldname, const char * newname) {qnotused(id); qnotused(oldname); qnotused(newname); return 0;} +virtual int expanding_struc(struc_t * sptr, ea_t offset, adiff_t delta) {qnotused(sptr); qnotused(offset); qnotused(delta); return 0;} +virtual int changing_struc_cmt(tid_t struc_id, bool repeatable, const char * newcmt) {qnotused(struc_id); qnotused(repeatable); qnotused(newcmt); return 0;} +virtual int deleting_struc_member(struc_t * sptr, member_t * mptr) {qnotused(sptr); qnotused(mptr); return 0;} +virtual int renaming_struc_member(struc_t * sptr, member_t * mptr, const char * newname) {qnotused(sptr); qnotused(mptr); qnotused(newname); return 0;} +virtual int changing_struc_member(struc_t * sptr, member_t * mptr, flags_t flag, const opinfo_t * ti, asize_t nbytes) {qnotused(sptr); qnotused(mptr); qnotused(flag); qnotused(ti); qnotused(nbytes); return 0;} +virtual int removing_func_tail(func_t * pfn, const area_t * tail) {qnotused(pfn); qnotused(tail); return 0;} +virtual int deleting_segm(ea_t startEA) {qnotused(startEA); return 0;} +virtual int changing_segm_start(segment_t * s, ea_t new_start, int segmod_flags) {qnotused(s); qnotused(new_start); qnotused(segmod_flags); return 0;} +virtual int changing_segm_end(segment_t * s, ea_t new_end, int segmod_flags) {qnotused(s); qnotused(new_end); qnotused(segmod_flags); return 0;} +virtual int changing_area_cmt(areacb_t * cb, const area_t * a, const char * cmt, bool repeatable) {qnotused(cb); qnotused(a); qnotused(cmt); qnotused(repeatable); return 0;} +virtual int changing_segm_name(segment_t * s, const char * oldname) {qnotused(s); qnotused(oldname); return 0;} +virtual int changing_segm_class(segment_t * s) {qnotused(s); return 0;} +virtual int segm_name_changed(segment_t * s, const char * name) {qnotused(s); qnotused(name); return 0;} +virtual int segm_class_changed(segment_t * s, const char * sclass) {qnotused(s); qnotused(sclass); return 0;} +virtual int destroyed_items(ea_t ea1, ea_t ea2, bool will_disable_range) {qnotused(ea1); qnotused(ea2); qnotused(will_disable_range); return 0;} +virtual int changed_stkpnts(func_t * pfn) {qnotused(pfn); return 0;} +virtual int extra_cmt_changed(ea_t ea, int line_idx, const char * cmt) {qnotused(ea); qnotused(line_idx); qnotused(cmt); return 0;} +virtual int changing_struc(struc_t * sptr) {qnotused(sptr); return 0;} +virtual int changed_struc(struc_t * sptr) {qnotused(sptr); return 0;} +virtual int local_types_changed() {return 0;} +virtual int segm_attrs_changed(segment_t * s) {qnotused(s); return 0;} +virtual int allsegs_moved(segm_move_infos_t * info) {qnotused(info); return 0;} +}; +// + + +// +//--------------------------------------------------------------------------- +int 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; + try + { + switch ( notification_code ) + { + // hookgenIDB:notifications +case idb_event::byte_patched: +{ + ea_t ea = va_arg(va, ea_t); + uint32 old_value = va_arg(va, uint32); + ret = proxy->byte_patched(ea, old_value); +} +break; + +case idb_event::cmt_changed: +{ + ea_t ea = va_arg(va, ea_t); + bool repeatable_cmt = bool(va_arg(va, int)); + ret = proxy->cmt_changed(ea, repeatable_cmt); +} +break; + +case idb_event::ti_changed: +{ + ea_t ea = va_arg(va, ea_t); + const type_t * type = va_arg(va, const type_t *); + const p_list * fnames = va_arg(va, const p_list *); + ret = proxy->ti_changed(ea, type, fnames); +} +break; + +case idb_event::op_ti_changed: +{ + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + const type_t * type = va_arg(va, const type_t *); + const p_list * fnames = va_arg(va, const p_list *); + ret = proxy->op_ti_changed(ea, n, type, fnames); +} +break; + +case idb_event::op_type_changed: +{ + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + ret = proxy->op_type_changed(ea, n); +} +break; + +case idb_event::enum_created: +{ + enum_t id = va_arg(va, enum_t); + ret = proxy->enum_created(id); +} +break; + +case idb_event::enum_deleted: +{ + enum_t id = va_arg(va, enum_t); + ret = proxy->enum_deleted(id); +} +break; + +case idb_event::enum_bf_changed: +{ + enum_t id = va_arg(va, enum_t); + ret = proxy->enum_bf_changed(id); +} +break; + +case idb_event::enum_renamed: +{ + tid_t id = va_arg(va, tid_t); + ret = proxy->enum_renamed(id); +} +break; + +case idb_event::enum_cmt_changed: +{ + tid_t id = va_arg(va, tid_t); + bool repeatable = bool(va_arg(va, int)); + ret = proxy->enum_cmt_changed(id, repeatable); +} +break; + +case idb_event::enum_const_created: +{ + enum_t id = va_arg(va, enum_t); + const_t cid = va_arg(va, const_t); + ret = proxy->enum_member_created(id, cid); +} +break; + +case idb_event::enum_const_deleted: +{ + enum_t id = va_arg(va, enum_t); + const_t cid = va_arg(va, const_t); + ret = proxy->enum_member_deleted(id, cid); +} +break; + +case idb_event::struc_created: +{ + tid_t struc_id = va_arg(va, tid_t); + ret = proxy->struc_created(struc_id); +} +break; + +case idb_event::struc_deleted: +{ + tid_t struc_id = va_arg(va, tid_t); + ret = proxy->struc_deleted(struc_id); +} +break; + +case idb_event::struc_renamed: +{ + struc_t * sptr = va_arg(va, struc_t *); + ret = proxy->struc_renamed(sptr); +} +break; + +case idb_event::struc_expanded: +{ + struc_t * sptr = va_arg(va, struc_t *); + ret = proxy->struc_expanded(sptr); +} +break; + +case idb_event::struc_cmt_changed: +{ + tid_t struc_id = va_arg(va, tid_t); + bool repeatable_cmt = bool(va_arg(va, int)); + ret = proxy->struc_cmt_changed(struc_id, repeatable_cmt); +} +break; + +case idb_event::struc_member_created: +{ + struc_t * sptr = va_arg(va, struc_t *); + member_t * mptr = va_arg(va, member_t *); + ret = proxy->struc_member_created(sptr, mptr); +} +break; + +case idb_event::struc_member_deleted: +{ + struc_t * sptr = va_arg(va, struc_t *); + tid_t member_id = va_arg(va, tid_t); + ea_t offset = va_arg(va, ea_t); + ret = proxy->struc_member_deleted(sptr, member_id, offset); +} +break; + +case idb_event::struc_member_renamed: +{ + struc_t * sptr = va_arg(va, struc_t *); + member_t * mptr = va_arg(va, member_t *); + ret = proxy->struc_member_renamed(sptr, mptr); +} +break; + +case idb_event::struc_member_changed: +{ + struc_t * sptr = va_arg(va, struc_t *); + member_t * mptr = va_arg(va, member_t *); + ret = proxy->struc_member_changed(sptr, mptr); +} +break; + +case idb_event::thunk_func_created: +{ + func_t * pfn = va_arg(va, func_t *); + ret = proxy->thunk_func_created(pfn); +} +break; + +case idb_event::func_tail_appended: +{ + func_t * pfn = va_arg(va, func_t *); + func_t * tail = va_arg(va, func_t *); + ret = proxy->func_tail_appended(pfn, tail); +} +break; + +case idb_event::func_tail_removed: +{ + func_t * pfn = va_arg(va, func_t *); + ea_t tail_ea = va_arg(va, ea_t); + ret = proxy->func_tail_removed(pfn, tail_ea); +} +break; + +case idb_event::tail_owner_changed: +{ + func_t * tail = va_arg(va, func_t *); + ea_t owner_func = va_arg(va, ea_t); + ea_t old_owner = va_arg(va, ea_t); + ret = proxy->tail_owner_changed(tail, owner_func, old_owner); +} +break; + +case idb_event::func_noret_changed: +{ + func_t * pfn = va_arg(va, func_t *); + ret = proxy->func_noret_changed(pfn); +} +break; + +case idb_event::segm_added: +{ + segment_t * s = va_arg(va, segment_t *); + ret = proxy->segm_added(s); +} +break; + +case idb_event::segm_deleted: +{ + ea_t startEA = va_arg(va, ea_t); + ea_t endEA = va_arg(va, ea_t); + ret = proxy->segm_deleted(startEA, endEA); +} +break; + +case idb_event::segm_start_changed: +{ + segment_t * s = va_arg(va, segment_t *); + ea_t oldstart = va_arg(va, ea_t); + ret = proxy->segm_start_changed(s, oldstart); +} +break; + +case idb_event::segm_end_changed: +{ + segment_t * s = va_arg(va, segment_t *); + ea_t oldend = va_arg(va, ea_t); + ret = proxy->segm_end_changed(s, oldend); +} +break; + +case idb_event::segm_moved: +{ + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + asize_t size = va_arg(va, asize_t); + ret = proxy->segm_moved(from, to, size); +} +break; + +case idb_event::area_cmt_changed: +{ + areacb_t * cb = va_arg(va, areacb_t *); + const area_t * a = va_arg(va, const area_t *); + const char * cmt = va_arg(va, const char *); + bool repeatable = bool(va_arg(va, int)); + ret = proxy->area_cmt_changed(cb, a, cmt, repeatable); +} +break; + +case idb_event::changing_cmt: +{ + ea_t ea = va_arg(va, ea_t); + bool repeatable_cmt = bool(va_arg(va, int)); + const char * newcmt = va_arg(va, const char *); + ret = proxy->changing_cmt(ea, repeatable_cmt, newcmt); +} +break; + +case idb_event::changing_ti: +{ + ea_t ea = va_arg(va, ea_t); + const type_t * new_type = va_arg(va, const type_t *); + const p_list * new_fnames = va_arg(va, const p_list *); + ret = proxy->changing_ti(ea, new_type, new_fnames); +} +break; + +case idb_event::changing_op_ti: +{ + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + const type_t * new_type = va_arg(va, const type_t *); + const p_list * new_fnames = va_arg(va, const p_list *); + ret = proxy->changing_op_ti(ea, n, new_type, new_fnames); +} +break; + +case idb_event::changing_op_type: +{ + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + ret = proxy->changing_op_type(ea, n); +} +break; + +case idb_event::deleting_enum: +{ + enum_t id = va_arg(va, enum_t); + ret = proxy->deleting_enum(id); +} +break; + +case idb_event::changing_enum_bf: +{ + enum_t id = va_arg(va, enum_t); + bool new_bf = bool(va_arg(va, int)); + ret = proxy->changing_enum_bf(id, new_bf); +} +break; + +case idb_event::renaming_enum: +{ + tid_t id = va_arg(va, tid_t); + bool is_enum = bool(va_arg(va, int)); + const char * newname = va_arg(va, const char *); + ret = proxy->renaming_enum(id, is_enum, newname); +} +break; + +case idb_event::changing_enum_cmt: +{ + tid_t id = va_arg(va, tid_t); + bool repeatable = bool(va_arg(va, int)); + const char * newcmt = va_arg(va, const char *); + ret = proxy->changing_enum_cmt(id, repeatable, newcmt); +} +break; + +case idb_event::deleting_enum_const: +{ + ret = proxy->deleting_enum_const(); +} +break; + +case idb_event::deleting_struc: +{ + struc_t * sptr = va_arg(va, struc_t *); + ret = proxy->deleting_struc(sptr); +} +break; + +case idb_event::renaming_struc: +{ + tid_t id = va_arg(va, tid_t); + const char * oldname = va_arg(va, const char *); + const char * newname = va_arg(va, const char *); + ret = proxy->renaming_struc(id, oldname, newname); +} +break; + +case idb_event::expanding_struc: +{ + struc_t * sptr = va_arg(va, struc_t *); + ea_t offset = va_arg(va, ea_t); + adiff_t delta = va_arg(va, adiff_t); + ret = proxy->expanding_struc(sptr, offset, delta); +} +break; + +case idb_event::changing_struc_cmt: +{ + tid_t struc_id = va_arg(va, tid_t); + bool repeatable = bool(va_arg(va, int)); + const char * newcmt = va_arg(va, const char *); + ret = proxy->changing_struc_cmt(struc_id, repeatable, newcmt); +} +break; + +case idb_event::deleting_struc_member: +{ + struc_t * sptr = va_arg(va, struc_t *); + member_t * mptr = va_arg(va, member_t *); + ret = proxy->deleting_struc_member(sptr, mptr); +} +break; + +case idb_event::renaming_struc_member: +{ + struc_t * sptr = va_arg(va, struc_t *); + member_t * mptr = va_arg(va, member_t *); + const char * newname = va_arg(va, const char *); + ret = proxy->renaming_struc_member(sptr, mptr, newname); +} +break; + +case idb_event::changing_struc_member: +{ + struc_t * sptr = va_arg(va, struc_t *); + member_t * mptr = va_arg(va, member_t *); + flags_t flag = va_arg(va, flags_t); + const opinfo_t * ti = va_arg(va, const opinfo_t *); + asize_t nbytes = va_arg(va, asize_t); + ret = proxy->changing_struc_member(sptr, mptr, flag, ti, nbytes); +} +break; + +case idb_event::removing_func_tail: +{ + func_t * pfn = va_arg(va, func_t *); + const area_t * tail = va_arg(va, const area_t *); + ret = proxy->removing_func_tail(pfn, tail); +} +break; + +case idb_event::deleting_segm: +{ + ea_t startEA = va_arg(va, ea_t); + ret = proxy->deleting_segm(startEA); +} +break; + +case idb_event::changing_segm_start: +{ + segment_t * s = va_arg(va, segment_t *); + ea_t new_start = va_arg(va, ea_t); + int segmod_flags = va_arg(va, int); + ret = proxy->changing_segm_start(s, new_start, segmod_flags); +} +break; + +case idb_event::changing_segm_end: +{ + segment_t * s = va_arg(va, segment_t *); + ea_t new_end = va_arg(va, ea_t); + int segmod_flags = va_arg(va, int); + ret = proxy->changing_segm_end(s, new_end, segmod_flags); +} +break; + +case idb_event::changing_area_cmt: +{ + areacb_t * cb = va_arg(va, areacb_t *); + const area_t * a = va_arg(va, const area_t *); + const char * cmt = va_arg(va, const char *); + bool repeatable = bool(va_arg(va, int)); + ret = proxy->changing_area_cmt(cb, a, cmt, repeatable); +} +break; + +case idb_event::changing_segm_name: +{ + segment_t * s = va_arg(va, segment_t *); + const char * oldname = va_arg(va, const char *); + ret = proxy->changing_segm_name(s, oldname); +} +break; + +case idb_event::changing_segm_class: +{ + segment_t * s = va_arg(va, segment_t *); + ret = proxy->changing_segm_class(s); +} +break; + +case idb_event::segm_name_changed: +{ + segment_t * s = va_arg(va, segment_t *); + const char * name = va_arg(va, const char *); + ret = proxy->segm_name_changed(s, name); +} +break; + +case idb_event::segm_class_changed: +{ + segment_t * s = va_arg(va, segment_t *); + const char * sclass = va_arg(va, const char *); + ret = proxy->segm_class_changed(s, sclass); +} +break; + +case idb_event::destroyed_items: +{ + ea_t ea1 = va_arg(va, ea_t); + ea_t ea2 = va_arg(va, ea_t); + bool will_disable_range = bool(va_arg(va, int)); + ret = proxy->destroyed_items(ea1, ea2, will_disable_range); +} +break; + +case idb_event::changed_stkpnts: +{ + func_t * pfn = va_arg(va, func_t *); + ret = proxy->changed_stkpnts(pfn); +} +break; + +case idb_event::extra_cmt_changed: +{ + ea_t ea = va_arg(va, ea_t); + int line_idx = va_arg(va, int); + const char * cmt = va_arg(va, const char *); + ret = proxy->extra_cmt_changed(ea, line_idx, cmt); +} +break; + +case idb_event::changing_struc: +{ + struc_t * sptr = va_arg(va, struc_t *); + ret = proxy->changing_struc(sptr); +} +break; + +case idb_event::changed_struc: +{ + struc_t * sptr = va_arg(va, struc_t *); + ret = proxy->changed_struc(sptr); +} +break; + +case idb_event::local_types_changed: +{ + ret = proxy->local_types_changed(); +} +break; + +case idb_event::segm_attrs_changed: +{ + segment_t * s = va_arg(va, segment_t *); + ret = proxy->segm_attrs_changed(s); +} +break; + +case idb_event::allsegs_moved: +{ + segm_move_infos_t * info = va_arg(va, segm_move_infos_t *); + ret = proxy->allsegs_moved(info); +} +break; + + } + } + catch (Swig::DirectorException &e) + { + msg("Exception in IDB Hook function: %s\n", e.getMessage()); + PYW_GIL_CHECK_LOCKED_SCOPE(); + if ( PyErr_Occurred() ) + PyErr_Print(); + } + return 0; +} +// diff --git a/pywraps/py_idd.hpp b/pywraps/py_idd.hpp new file mode 100644 index 0000000..7ed17c5 --- /dev/null +++ b/pywraps/py_idd.hpp @@ -0,0 +1,467 @@ + +// + +//------------------------------------------------------------------------- +static bool dbg_can_query() +{ + // Reject the request only if no debugger is set + // or the debugger cannot be queried while not in suspended state + return dbg != NULL && (dbg->may_disturb() || get_process_state() < DSTATE_NOTASK); +} + +//------------------------------------------------------------------------- +static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + PyObject *py_list = PyList_New(areas.size()); + meminfo_vec_t::const_iterator it, it_end(areas.end()); + Py_ssize_t i = 0; + for ( it=areas.begin(); it!=it_end; ++it, ++i ) + { + const memory_info_t &mi = *it; + // startEA endEA name sclass sbase bitness perm + PyList_SetItem(py_list, i, + Py_BuildValue("(" PY_FMT64 PY_FMT64 "ss" PY_FMT64 "II)", + pyul_t(mi.startEA), + pyul_t(mi.endEA), + mi.name.c_str(), + mi.sclass.c_str(), + pyul_t(mi.sbase), + (unsigned int)(mi.bitness), + (unsigned int)mi.perm)); + } + return py_list; +} + +//------------------------------------------------------------------------- +PyObject *py_appcall( + ea_t func_ea, + thid_t tid, + PyObject *py_type, + PyObject *py_fields, + PyObject *arg_list) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + if ( !PyList_Check(arg_list) ) + return NULL; + + const char *type = py_type == Py_None ? NULL : PyString_AS_STRING(py_type); + const char *fields = py_fields == Py_None ? NULL : PyString_AS_STRING(py_fields); + + // Convert Python arguments into IDC values + qvector idc_args; + int sn = 0; + Py_ssize_t nargs = PyList_Size(arg_list); + idc_args.resize(nargs); + bool ok = true; + for ( Py_ssize_t i=0; i%s\n", int(i), s.c_str()); + } + // Convert it + if ( pyvar_to_idcvar(py_item, &idc_args[i], &sn) < CIP_OK ) + { + ok = false; + break; + } + } + + // Set exception message + if ( !ok ) + { + PyErr_SetString( + PyExc_ValueError, + "PyAppCall: Failed to convert Python values to IDC values"); + return NULL; + } + + error_t ret; + idc_value_t idc_result; + Py_BEGIN_ALLOW_THREADS; + + if ( (debug & IDA_DEBUG_APPCALL) != 0 ) + { + msg("input variables:\n" + "----------------\n"); + + qstring s; + for ( Py_ssize_t i=0; iob_refcnt == 1); + if ( (debug & IDA_DEBUG_APPCALL) != 0 ) + { + msg("return var:\n" + "-----------\n"); + qstring s; + VarPrint(&s, &idc_result); + msg("%s\n-----------\n", s.c_str()); + } + py_result.incref(); + return py_result.o; +} +// + + +//------------------------------------------------------------------------- +// +/* +# +def dbg_get_registers(): + """ + This function returns the register definition from the currently loaded debugger. + Basically, it returns an array of structure similar to to idd.hpp / register_info_t + @return: + None if no debugger is loaded + tuple(name, flags, class, dtyp, bit_strings, default_bit_strings_mask) + The bit_strings can be a tuple of strings or None (if the register does not have bit_strings) + """ + pass +# +*/ +static PyObject *dbg_get_registers() +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + if ( dbg == NULL ) + Py_RETURN_NONE; + + PyObject *py_list = PyList_New(dbg->registers_size); + + for ( int i=0; iregisters_size; i++ ) + { + register_info_t &ri = dbg->registers(i); + PyObject *py_bits; + + // Does this register have bit strings? + // (Make sure it does not use custom formats because bit_string would be the format name) + if ( ri.bit_strings != NULL && (ri.flags & REGISTER_CUSTFMT) == 0 ) + { + int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4; + py_bits = PyList_New(nbits); + for ( int i=0; i +def dbg_get_thread_sreg_base(tid, sreg_value): + """ + Returns the segment register base value + @param tid: thread id + @param sreg_value: segment register (selector) value + @return: + - The base as an 'ea' + - Or None on failure + """ + pass +# +*/ +static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) ) + Py_RETURN_NONE; + ea_t answer; + thid_t tid = PyInt_AsLong(py_tid); + int sreg_value = PyInt_AsLong(py_sreg_value); + if ( internal_get_sreg_base(tid, sreg_value, &answer) != 1 ) + Py_RETURN_NONE; + + return Py_BuildValue(PY_FMT64, pyul_t(answer)); +} + +//------------------------------------------------------------------------- +/* +# +def dbg_read_memory(ea, sz): + """ + Reads from the debugee's memory at the specified ea + @return: + - The read buffer (as a string) + - Or None on failure + """ + pass +# +*/ +static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + uint64 ea, sz; + if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) ) + Py_RETURN_NONE; + + // Create a Python string + PyObject *ret = PyString_FromStringAndSize(NULL, Py_ssize_t(sz)); + if ( ret == NULL ) + Py_RETURN_NONE; + + // Get the internal buffer + Py_ssize_t len; + char *buf; + PyString_AsStringAndSize(ret, &buf, &len); + + if ( (size_t)read_dbg_memory(ea_t(ea), buf, size_t(sz)) != sz ) + { + // Release the string on failure + Py_DECREF(ret); + // Return None on failure + Py_RETURN_NONE; + } + return ret; +} + +//------------------------------------------------------------------------- +/* +# +def dbg_write_memory(ea, buffer): + """ + Writes a buffer to the debugee's memory + @return: Boolean + """ + pass +# +*/ +static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + uint64 ea; + if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) ) + Py_RETURN_NONE; + + size_t sz = PyString_GET_SIZE(py_buf); + void *buf = (void *)PyString_AS_STRING(py_buf); + if ( write_dbg_memory(ea_t(ea), buf, sz) != sz ) + Py_RETURN_FALSE; + Py_RETURN_TRUE; +} + +//------------------------------------------------------------------------- +/* +# +def dbg_get_name(): + """ + This function returns the current debugger's name. + @return: Debugger name or None if no debugger is active + """ + pass +# +*/ +static PyObject *dbg_get_name() +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + if ( dbg == NULL ) + Py_RETURN_NONE; + else + return PyString_FromString(dbg->name); +} + +//------------------------------------------------------------------------- +/* +# +def dbg_get_memory_info(): + """ + This function returns the memory configuration of a debugged process. + @return: + None if no debugger is active + tuple(startEA, endEA, name, sclass, sbase, bitness, perm) + """ + pass +# +*/ +static PyObject *dbg_get_memory_info() +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + if ( !dbg_can_query() ) + Py_RETURN_NONE; + + // Invalidate memory + meminfo_vec_t areas; + Py_BEGIN_ALLOW_THREADS; + invalidate_dbgmem_config(); + invalidate_dbgmem_contents(BADADDR, BADADDR); + + get_dbg_memory_info(&areas); + Py_END_ALLOW_THREADS; + return meminfo_vec_t_to_py(areas); +} + +//------------------------------------------------------------------------- +/* +# +def dbg_can_query(): + """ + This function can be used to check if the debugger can be queried: + - debugger is loaded + - process is suspended + - process is not suspended but can take requests. In this case some requests like + memory read/write, bpt management succeed and register querying will fail. + Check if idaapi.get_process_state() < 0 to tell if the process is suspended + @return: Boolean + """ + pass +# +*/ +static bool dbg_can_query(); +PyObject *py_appcall( + ea_t func_ea, + thid_t tid, + PyObject *py_type, + PyObject *py_fields, + PyObject *arg_list); + +char get_event_module_name(const debug_event_t *ev, char *buf, size_t bufsize) +{ + qstrncpy(buf, ev->modinfo.name, bufsize); + return true; +} + +ea_t get_event_module_base(const debug_event_t *ev) +{ + return ev->modinfo.base; +} + +asize_t get_event_module_size(const debug_event_t *ev) +{ + return ev->modinfo.size; +} + +char get_event_exc_info(const debug_event_t *ev, char *buf, size_t bufsize) +{ + qstrncpy(buf, ev->exc.info, bufsize); + return true; +} + +char get_event_info(const debug_event_t *ev, char *buf, size_t bufsize) +{ + qstrncpy(buf, ev->info, bufsize); + return true; +} + +ea_t get_event_bpt_hea(const debug_event_t *ev) +{ + return ev->bpt.hea; +} + +uint get_event_exc_code(const debug_event_t *ev) +{ + return ev->exc.code; +} + +ea_t get_event_exc_ea(const debug_event_t *ev) +{ + return ev->exc.ea; +} + +bool can_exc_continue(const debug_event_t *ev) +{ + return ev->exc.can_cont; +} + +// diff --git a/pywraps/py_idd.py b/pywraps/py_idd.py new file mode 100644 index 0000000..f1a2150 --- /dev/null +++ b/pywraps/py_idd.py @@ -0,0 +1,409 @@ + +# +NO_PROCESS = 0xFFFFFFFF +NO_THREAD = 0 + +import types + +# ----------------------------------------------------------------------- +class Appcall_array__(object): + """This class is used with Appcall.array() method""" + def __init__(self, tp): + self.__type = tp + + def pack(self, L): + """Packs a list or tuple into a byref buffer""" + t = type(L) + if not (t == types.ListType or t == types.TupleType): + raise ValueError, "Either a list or a tuple must be passed" + self.__size = len(L) + if self.__size == 1: + self.__typedobj = Appcall__.typedobj(self.__type + ";") + else: + self.__typedobj = Appcall__.typedobj("%s x[%d];" % (self.__type, self.__size)) + # Now store the object in a string buffer + ok, buf = self.__typedobj.store(L) + if ok: + return Appcall__.byref(buf) + else: + return None + + def try_to_convert_to_list(self, obj): + """Is this object a list? We check for the existance of attribute zero and attribute self.size-1""" + if not (hasattr(obj, "0") and hasattr(obj, str(self.__size-1))): + return obj + # at this point, we are sure we have an "idc list" + # let us convert to a Python list + return [getattr(obj, str(x)) for x in xrange(0, self.__size)] + + def unpack(self, buf, as_list=True): + """Unpacks an array back into a list or an object""" + # take the value from the special ref object + if isinstance(buf, PyIdc_cvt_refclass__): + buf = buf.value + + # we can only unpack from strings + if type(buf) != types.StringType: + raise ValueError, "Cannot unpack this type!" + # now unpack + ok, obj = self.__typedobj.retrieve(buf) + if not ok: + raise ValueError, "Failed while unpacking!" + if not as_list: + return obj + return self.try_to_convert_to_list(obj) + + +# ----------------------------------------------------------------------- +# Wrapper class for the appcall() +class Appcall_callable__(object): + """ + Helper class to issue appcalls using a natural syntax: + appcall.FunctionNameInTheDatabase(arguments, ....) + or + appcall["Function@8"](arguments, ...) + or + f8 = appcall["Function@8"] + f8(arg1, arg2, ...) + or + o = appcall.obj() + i = byref(5) + appcall.funcname(arg1, i, "hello", o) + """ + def __init__(self, ea, tp = None, fld = None): + """Initializes an appcall with a given function ea""" + self.__ea = ea + self.__type = tp + self.__fields = fld + self.__options = None # Appcall options + self.__timeout = None # Appcall timeout + + def __get_timeout(self): + return self.__timeout + + def __set_timeout(self, v): + self.__timeout = v + + timeout = property(__get_timeout, __set_timeout) + """An Appcall instance can change its timeout value with this attribute""" + + def __get_options(self): + return self.__options if self.__options != None else Appcall__.get_appcall_options() + + def __set_options(self, v): + if self.timeout: + # If timeout value is set, then put the timeout flag and encode the timeout value + v |= Appcall__.APPCALL_TIMEOUT | (self.timeout << 16) + else: + # Timeout is not set, then clear the timeout flag + v &= ~Appcall__.APPCALL_TIMEOUT + + self.__options = v + + options = property(__get_options, __set_options) + """Sets the Appcall options locally to this Appcall instance""" + + def __call__(self, *args): + """Make object callable. We redirect execution to idaapi.appcall()""" + if self.ea is None: + raise ValueError, "Object not callable!" + + # convert arguments to a list + arg_list = list(args) + + # Save appcall options and set new global options + old_opt = Appcall__.get_appcall_options() + Appcall__.set_appcall_options(self.options) + + # Do the Appcall (use the wrapped version) + e_obj = None + try: + r = _idaapi.appcall( + self.ea, + _idaapi.get_current_thread(), + self.type, + self.fields, + arg_list) + except Exception as e: + e_obj = e + + # Restore appcall options + Appcall__.set_appcall_options(old_opt) + + # Return or re-raise exception + if e_obj: + raise Exception, e_obj + + return r + + def __get_ea(self): + return self.__ea + + def __set_ea(self, val): + self.__ea = val + + ea = property(__get_ea, __set_ea) + """Returns or sets the EA associated with this object""" + + def __get_size(self): + if self.__type == None: + return -1 + r = _idaapi.calc_type_size(_idaapi.cvar.idati, self.__type) + if not r: + return -1 + return r + + size = property(__get_size) + """Returns the size of the type""" + + def __get_type(self): + return self.__type + + type = property(__get_type) + """Returns the typestring""" + + def __get_fields(self): + return self.__fields + + fields = property(__get_fields) + """Returns the field names""" + + + def retrieve(self, src=None, flags=0): + """ + Unpacks a typed object from the database if an ea is given or from a string if a string was passed + @param src: the address of the object or a string + @return: Returns a tuple of boolean and object or error number (Bool, Error | Object). + """ + + # Nothing passed? Take the address and unpack from the database + if src is None: + src = self.ea + + if type(src) == types.StringType: + return _idaapi.unpack_object_from_bv(_idaapi.cvar.idati, self.type, self.fields, src, flags) + else: + return _idaapi.unpack_object_from_idb(_idaapi.cvar.idati, self.type, self.fields, src, flags) + + def store(self, obj, dest_ea=None, base_ea=0, flags=0): + """ + Packs an object into a given ea if provided or into a string if no address was passed. + @param obj: The object to pack + @param dest_ea: If packing to idb this will be the store location + @param base_ea: If packing to a buffer, this will be the base that will be used to relocate the pointers + + @return: + - If packing to a string then a Tuple(Boolean, packed_string or error code) + - If packing to the database then a return code is returned (0 is success) + """ + + # no ea passed? thus pack to a string + if dest_ea is None: + return _idaapi.pack_object_to_bv(obj, + _idaapi.cvar.idati, + self.type, + self.fields, + base_ea, + flags) + else: + return _idaapi.pack_object_to_idb(obj, + _idaapi.cvar.idati, + self.type, + self.fields, + dest_ea, + flags) + +# ----------------------------------------------------------------------- +class Appcall_consts__(object): + """Helper class used by Appcall.Consts attribute + It is used to retrieve constants via attribute access""" + def __init__(self, default=0): + self.__default = default + + def __getattr__(self, attr): + return Appcall__.valueof(attr, self.__default) + +# ----------------------------------------------------------------------- +class Appcall__(object): + APPCALL_MANUAL = 0x1 + """ + Only set up the appcall, do not run it. + you should call CleanupAppcall() when finished + """ + + APPCALL_DEBEV = 0x2 + """ + Return debug event information + If this bit is set, exceptions during appcall + will generate idc exceptions with full + information about the exception + """ + + APPCALL_TIMEOUT = 0x4 + """ + Appcall with timeout + The timeout value in milliseconds is specified + in the high 2 bytes of the 'options' argument: + If timed out, errbuf will contain "timeout". + """ + + def __init__(self): + self.__consts = Appcall_consts__() + def __get_consts(self): + return self.__consts + Consts = property(__get_consts) + """Use Appcall.Consts.CONST_NAME to access constants""" + + @staticmethod + def __name_or_ea(name_or_ea): + """ + Function that accepts a name or an ea and checks if the address is enabled. + If a name is passed then idaapi.get_name_ea() is applied to retrieve the name + @return: + - Returns the resolved EA or + - Raises an exception if the address is not enabled + """ + + # a string? try to resolve it + if type(name_or_ea) == types.StringType: + ea = _idaapi.get_name_ea(_idaapi.BADADDR, name_or_ea) + else: + ea = name_or_ea + # could not resolve name or invalid address? + if ea == _idaapi.BADADDR or not _idaapi.isEnabled(ea): + raise ValueError, "Undefined function " + name_or_ea + return ea + + @staticmethod + def proto(name_or_ea, prototype, flags = None): + """ + Allows you to instantiate an appcall (callable object) with the desired prototype + @param name_or_ea: The name of the function (will be resolved with LocByName()) + @param prototype: + @return: + - On failure it raises an exception if the prototype could not be parsed + or the address is not resolvable + - Returns a callbable Appcall instance with the given prototypes and flags + """ + + # resolve and raise exception on error + ea = Appcall__.__name_or_ea(name_or_ea) + # parse the type + if flags is None: + flags = 1 | 2 | 4 # PT_SIL | PT_NDC | PT_TYP + + result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, prototype, flags) + if result is None: + raise ValueError, "Could not parse type: " + prototype + + # Return the callable method with type info + return Appcall_callable__(ea, result[1], result[2]) + + def __getattr__(self, name_or_ea): + """Allows you to call functions as if they were member functions (by returning a callable object)""" + # resolve and raise exception on error + ea = self.__name_or_ea(name_or_ea) + if ea == _idaapi.BADADDR: + raise ValueError, "Undefined function " + name + # Return the callable method + return Appcall_callable__(ea) + + def __getitem__(self, idx): + """ + Use self[func_name] syntax if the function name contains invalid characters for an attribute name + See __getattr___ + """ + return self.__getattr__(idx) + + @staticmethod + def valueof(name, default=0): + """ + Returns the numeric value of a given name string. + If the name could not be resolved then the default value will be returned + """ + t, v = _idaapi.get_name_value(_idaapi.BADADDR, name) + if t == 0: # NT_NONE + v = default + return v + + @staticmethod + def int64(v): + """Whenever a 64bit number is needed use this method to construct an object""" + return PyIdc_cvt_int64__(v) + + @staticmethod + def byref(val): + """ + Method to create references to immutable objects + Currently we support references to int/strings + Objects need not be passed by reference (this will be done automatically) + """ + return PyIdc_cvt_refclass__(val) + + @staticmethod + def buffer(str = None, size = 0, fill="\x00"): + """ + Creates a string buffer. The returned value (r) will be a byref object. + Use r.value to get the contents and r.size to get the buffer's size + """ + if str is None: + str = "" + left = size - len(str) + if left > 0: + str = str + (fill * left) + r = Appcall__.byref(str) + r.size = size + return r + + @staticmethod + def obj(**kwds): + """Returns an empty object or objects with attributes as passed via its keywords arguments""" + return object_t(**kwds) + + @staticmethod + def cstr(val): + return as_cstr(val) + + @staticmethod + def unicode(s): + return as_unicode(s) + + @staticmethod + def array(type_name): + """Defines an array type. Later you need to pack() / unpack()""" + return Appcall_array__(type_name) + + @staticmethod + def typedobj(typestr, ea=None): + """ + Parses a type string and returns an appcall object. + One can then use retrieve() member method + @param ea: Optional parameter that later can be used to retrieve the type + @return: Appcall object or raises ValueError exception + """ + # parse the type + result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, typestr, 1 | 2 | 4) # PT_SIL | PT_NDC | PT_TYP + if result is None: + raise ValueError, "Could not parse type: " + typestr + # Return the callable method with type info + return Appcall_callable__(ea, result[1], result[2]) + + @staticmethod + def set_appcall_options(opt): + """Method to change the Appcall options globally (not per Appcall)""" + old_opt = Appcall__.get_appcall_options() + _idaapi.cvar.inf.appcall_options = opt + return old_opt + + @staticmethod + def get_appcall_options(): + """Return the global Appcall options""" + return _idaapi.cvar.inf.appcall_options + + @staticmethod + def cleanup_appcall(tid = 0): + """Equivalent to IDC's CleanupAppcall()""" + return _idaapi.cleanup_appcall(tid) + +Appcall = Appcall__() +# diff --git a/pywraps/py_idp.hpp b/pywraps/py_idp.hpp index 7177fa2..3cd639b 100644 --- a/pywraps/py_idp.hpp +++ b/pywraps/py_idp.hpp @@ -34,8 +34,8 @@ static PyObject *AssembleLine( int inslen; char buf[MAXSTR]; bool ok = false; - if (ph.notify != NULL && - (inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0) + if ( ph.notify != NULL + && (inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0 ) { ok = true; } @@ -74,10 +74,10 @@ bool assemble( PYW_GIL_CHECK_LOCKED_SCOPE(); bool rc = false; Py_BEGIN_ALLOW_THREADS; - if (ph.notify != NULL) + if ( ph.notify != NULL ) { inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf); - if (inslen > 0) + if ( inslen > 0 ) { patch_many_bytes(ea, buf, inslen); rc = true; @@ -685,6 +685,13 @@ class IDP_Hooks(object): //--------------------------------------------------------------------------- // IDP hooks //--------------------------------------------------------------------------- + +// Necessary forward declarations; idp.hpp itself doesn't need them. +struct mblock_t; +struct proc_def; +struct set_elf_reloc_t; +struct libfunc_t; + int idaapi IDP_Callback(void *ud, int notification_code, va_list va); class IDP_Hooks { @@ -704,120 +711,157 @@ public: return unhook_from_notification_point(HT_IDP, IDP_Callback, this); } - virtual bool custom_ana() + static int bool_to_cmdsize(bool in) { return in ? (1 + cmd.size) : 0; } + static int bool_to_2or0(bool in) { return in ? 2 : 0; } + static int cm_t_to_int(cm_t cm) { return int(cm); } + static int handle_custom_mnem_output(PyObject *o, char *buf, size_t bufsize) { - return false; + int rc = 0; + if ( o != NULL && PyString_Check(o) ) + { + qstrncpy(buf, PyString_AS_STRING(o), bufsize); + rc = 2; + } + Py_XDECREF(o); + return rc; + } + static int handle_assemble_output(PyObject *o, ea_t /*ea*/, ea_t /*cs*/, ea_t /*ip*/, bool /*use32*/, const char */*line*/, uchar *bin) + { + int rc = 0; + if ( o != NULL && PyString_Check(o) ) + { + char *s; + Py_ssize_t len = 0; + if ( PyString_AsStringAndSize(o, &s, &len) != -1 ) + { + if ( len > MAXSTR ) + len = MAXSTR; + memcpy(bin, s, len); + } + rc = int(len); + } + Py_XDECREF(o); + return rc; } - virtual bool custom_out() - { - return false; - } - - virtual bool custom_emu() - { - return false; - } - - virtual bool custom_outop(PyObject *py_op) - { - return false; - } - - virtual PyObject *custom_mnem() - { - Py_RETURN_NONE; - } - - virtual int is_sane_insn(int no_crefs) - { - return 0; - } - - virtual int may_be_func(int state) - { - return 0; - } - - virtual int closebase() - { - return 0; - } - - virtual void savebase() - { - } - - virtual void auto_empty_finally() - { - } - - virtual int rename(ea_t ea, const char *new_name) - { - return 0; - } - - virtual void renamed(ea_t ea, const char *new_name, bool local_name) - { - } - - virtual int undefine(ea_t ea) - { - return 0; - } - - virtual int make_code(ea_t ea, asize_t size) - { - return 0; - } - - virtual int make_data(ea_t ea, flags_t flags, tid_t tid, asize_t len) - { - return 0; - } - - virtual void load_idasgn(const char *short_sig_name) - { - } - - virtual void auto_empty() - { - } - - virtual int auto_queue_empty(atype_t type) - { - return 1; // Keep the queue empty. - } - - virtual void add_func(func_t *func) - { - } - - virtual int del_func(func_t *func) - { - return 0; - } - - virtual int is_call_insn(ea_t /*ea*/) - { - return 0; - } - - virtual int is_ret_insn(ea_t /*ea*/, bool /*strict*/) - { - return 0; - } - - virtual PyObject *assemble( - ea_t /*ea*/, - ea_t /*cs*/, - ea_t /*ip*/, - bool /*use32*/, - const char * /*line*/) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - } + // hookgenIDP:methods +virtual int init(const char * idp_modname) {qnotused(idp_modname); return 0;} +virtual int term() {return 0;} +virtual int newprc(int pnum) {qnotused(pnum); return 0;} +virtual int newasm(int asmnum) {qnotused(asmnum); return 0;} +virtual int newfile(char * fname) {qnotused(fname); return 0;} +virtual int oldfile(char * fname) {qnotused(fname); return 0;} +virtual int newbinary(char * filename, uint32 fileoff, ea_t basepara, ea_t binoff, uint32 nbytes) {qnotused(filename); qnotused(fileoff); qnotused(basepara); qnotused(binoff); qnotused(nbytes); return 0;} +virtual int endbinary(bool ok) {qnotused(ok); return 0;} +virtual int newseg(segment_t * seg) {qnotused(seg); return 0;} +virtual PyObject * assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char * line) {qnotused(ea); qnotused(cs); qnotused(ip); qnotused(use32); qnotused(line); Py_RETURN_NONE;} +virtual int obsolete_makemicro(mblock_t * block) {qnotused(block); return 0;} +virtual int outlabel(ea_t ea, const char * colored_name) {qnotused(ea); qnotused(colored_name); return 0;} +virtual int rename(ea_t ea, const char * new_name) {qnotused(ea); qnotused(new_name); return 0;} +virtual int may_show_sreg(ea_t current_ea) {qnotused(current_ea); return 0;} +virtual int closebase() {return 0;} +virtual void load_idasgn(const char * short_sig_name) {qnotused(short_sig_name); } +virtual int coagulate(ea_t start_ea) {qnotused(start_ea); return 0;} +virtual void auto_empty() {} +virtual int auto_queue_empty(atype_t type) {qnotused(type); return 0;} +virtual void func_bounds(int * possible_return_code, func_t * pfn, ea_t max_func_end_ea) {qnotused(possible_return_code); qnotused(pfn); qnotused(max_func_end_ea); } +virtual int may_be_func(int state) {qnotused(state); return 0;} +virtual int is_sane_insn(int no_crefs) {qnotused(no_crefs); return 0;} +virtual int is_jump_func(func_t * pfn, ea_t * jump_target, ea_t * func_pointer) {qnotused(pfn); qnotused(jump_target); qnotused(func_pointer); return 0;} +virtual int gen_regvar_def(regvar_t * v) {qnotused(v); return 0;} +virtual int setsgr(ea_t startEA, ea_t endEA, int regnum, sel_t value, sel_t old_value, uchar tag) {qnotused(startEA); qnotused(endEA); qnotused(regnum); qnotused(value); qnotused(old_value); qnotused(tag); return 0;} +virtual int set_compiler() {return 0;} +virtual int is_basic_block_end(bool call_insn_stops_block) {qnotused(call_insn_stops_block); return 0;} +virtual int reglink() {return 0;} +virtual void get_vxd_name(int vxdnum, int funcnum, char * outbuf) {qnotused(vxdnum); qnotused(funcnum); qnotused(outbuf); } +virtual bool custom_ana() {return false;} +virtual bool custom_out() {return false;} +virtual bool custom_emu() {return false;} +virtual bool custom_outop(PyObject * op) {qnotused(op); return false;} +virtual PyObject * custom_mnem() {Py_RETURN_NONE;} +virtual int undefine(ea_t ea) {qnotused(ea); return 0;} +virtual int make_code(ea_t ea, asize_t size) {qnotused(ea); qnotused(size); return 0;} +virtual int make_data(ea_t ea, flags_t flags, tid_t tid, asize_t len) {qnotused(ea); qnotused(flags); qnotused(tid); qnotused(len); return 0;} +virtual int moving_segm(segment_t * seg, ea_t to, int flags) {qnotused(seg); qnotused(to); qnotused(flags); return 0;} +virtual void move_segm(ea_t from, segment_t * seg) {qnotused(from); qnotused(seg); } +virtual int is_call_insn(ea_t ea) {qnotused(ea); return 0;} +virtual int is_ret_insn(ea_t ea, bool strict) {qnotused(ea); qnotused(strict); return 0;} +virtual int get_stkvar_scale_factor() {return 0;} +virtual int create_flat_group(ea_t image_base, int bitness, sel_t dataseg_sel) {qnotused(image_base); qnotused(bitness); qnotused(dataseg_sel); return 0;} +virtual void kernel_config_loaded() {} +virtual int might_change_sp(ea_t ea) {qnotused(ea); return 0;} +virtual int is_alloca_probe(ea_t ea) {qnotused(ea); return 0;} +virtual int out_3byte(ea_t dataea, uint32 value, bool analyze_only) {qnotused(dataea); qnotused(value); qnotused(analyze_only); return 0;} +virtual int get_reg_name(int reg, size_t width, char * buf, size_t bufsize, int reghi) {qnotused(reg); qnotused(width); qnotused(buf); qnotused(bufsize); qnotused(reghi); return 0;} +virtual void savebase() {} +virtual void gen_asm_or_lst(bool starting, FILE * fp, bool is_asm, int flags, gen_outline_t ** outline) {qnotused(starting); qnotused(fp); qnotused(is_asm); qnotused(flags); qnotused(outline); } +virtual int out_src_file_lnnum() {return 0;} +virtual int get_autocmt(char * buf, size_t bufsize) {qnotused(buf); qnotused(bufsize); return 0;} +virtual int is_insn_table_jump() {return 0;} +virtual void auto_empty_finally() {} +virtual int loader_finished(linput_t * li, uint16 neflags, const char * filetypename) {qnotused(li); qnotused(neflags); qnotused(filetypename); return 0;} +virtual int loader_elf_machine(linput_t * li, int machine_type, const char ** p_procname, proc_def ** p_pd, set_elf_reloc_t * set_reloc) {qnotused(li); qnotused(machine_type); qnotused(p_procname); qnotused(p_pd); qnotused(set_reloc); return 0;} +virtual int is_indirect_jump() {return 0;} +virtual int verify_noreturn(func_t * pfn) {qnotused(pfn); return 0;} +virtual int verify_sp(func_t * pfn) {qnotused(pfn); return 0;} +virtual void renamed(ea_t ea, const char * new_name, bool local_name) {qnotused(ea); qnotused(new_name); qnotused(local_name); } +virtual void add_func(func_t * pfn) {qnotused(pfn); } +virtual int del_func(func_t * pfn) {qnotused(pfn); return 0;} +virtual int set_func_start(func_t * pfn, ea_t new_start) {qnotused(pfn); qnotused(new_start); return 0;} +virtual int set_func_end(func_t * pfn, ea_t new_end) {qnotused(pfn); qnotused(new_end); return 0;} +virtual int treat_hindering_item(ea_t hindering_item_ea, flags_t new_item_flags, ea_t new_item_ea, asize_t new_item_length) {qnotused(hindering_item_ea); qnotused(new_item_flags); qnotused(new_item_ea); qnotused(new_item_length); return 0;} +virtual int str2reg(const char * regname) {qnotused(regname); return 0;} +virtual int create_switch_xrefs(ea_t jumpea, switch_info_ex_t * si) {qnotused(jumpea); qnotused(si); return 0;} +virtual int calc_switch_cases(ea_t insn_ea, switch_info_ex_t * si, casevec_t * casevec, eavec_t * targets) {qnotused(insn_ea); qnotused(si); qnotused(casevec); qnotused(targets); return 0;} +virtual void determined_main(ea_t main) {qnotused(main); } +virtual void preprocess_chart(qflow_chart_t * fc) {qnotused(fc); } +virtual int get_bg_color(ea_t ea, bgcolor_t color) {qnotused(ea); qnotused(color); return 0;} +virtual int validate_flirt_func(ea_t start_ea, const char * funcname) {qnotused(start_ea); qnotused(funcname); return 0;} +virtual int get_operand_string(int opnum, char * buf, size_t buflen) {qnotused(opnum); qnotused(buf); qnotused(buflen); return 0;} +virtual int add_cref(ea_t from, ea_t to, cref_t type) {qnotused(from); qnotused(to); qnotused(type); return 0;} +virtual int add_dref(ea_t from, ea_t to, dref_t type) {qnotused(from); qnotused(to); qnotused(type); return 0;} +virtual int del_cref(ea_t from, ea_t to, bool expand) {qnotused(from); qnotused(to); qnotused(expand); return 0;} +virtual int del_dref(ea_t from, ea_t to) {qnotused(from); qnotused(to); return 0;} +virtual int coagulate_dref(ea_t from, ea_t to, bool may_define, ea_t * code_ea) {qnotused(from); qnotused(to); qnotused(may_define); qnotused(code_ea); return 0;} +virtual int register_custom_fixup(const char * name) {qnotused(name); return 0;} +virtual int custom_refinfo(ea_t ea, int numop, ea_t * opval, const refinfo_t* ri, char * buf, size_t bufsize, ea_t * target, ea_t * fullvalue, ea_t from, int getn_flags) {qnotused(ea); qnotused(numop); qnotused(opval); qnotused(ri); qnotused(buf); qnotused(bufsize); qnotused(target); qnotused(fullvalue); qnotused(from); qnotused(getn_flags); return 0;} +virtual int set_proc_options(const char * options) {qnotused(options); return 0;} +virtual int adjust_libfunc_ea(const idasgn_t * sig, const libfunc_t * libfun, ea_t * ea) {qnotused(sig); qnotused(libfun); qnotused(ea); return 0;} +virtual void extlang_changed(int kind, const extlang_t * el) {qnotused(kind); qnotused(el); } +virtual int delay_slot_insn(ea_t * ea) {qnotused(ea); return 0;} +virtual int obsolete_get_operand_info() {return 0;} +virtual int get_jump_target(ea_t ea, int tid, processor_t::regval_getter_t getreg, const regval_t * regvalues, ea_t * target) {qnotused(ea); qnotused(tid); qnotused(getreg); qnotused(regvalues); qnotused(target); return 0;} +virtual int calc_step_over(ea_t ip, ea_t * target) {qnotused(ip); qnotused(target); return 0;} +virtual int get_macro_insn_head(ea_t ip, ea_t * head) {qnotused(ip); qnotused(head); return 0;} +virtual int get_dbr_opnum(ea_t ea, int * opnum) {qnotused(ea); qnotused(opnum); return 0;} +virtual int insn_reads_tbit(ea_t ea, processor_t::regval_getter_t getreg, const regval_t * regvalues) {qnotused(ea); qnotused(getreg); qnotused(regvalues); return 0;} +virtual int get_operand_info(ea_t ea, int n, int thread_id, processor_t::regval_getter_t getreg, const regval_t * regvalues, idd_opinfo_t * opinf) {qnotused(ea); qnotused(n); qnotused(thread_id); qnotused(getreg); qnotused(regvalues); qnotused(opinf); return 0;} +virtual int calc_next_eas(bool over, ea_t * res, int * nsubcalls) {qnotused(over); qnotused(res); qnotused(nsubcalls); return 0;} +virtual int clean_tbit(ea_t ea, processor_t::regval_getter_t getreg, const regval_t * regvalues) {qnotused(ea); qnotused(getreg); qnotused(regvalues); return 0;} +virtual int get_reg_info2(const char * regname, const char ** main_regname, bitrange_t * bitrange) {qnotused(regname); qnotused(main_regname); qnotused(bitrange); return 0;} +virtual void setup_til() {} +virtual int based_ptr(unsigned ptrt, const char ** ptrname) {qnotused(ptrt); qnotused(ptrname); return 0;} +virtual int max_ptr_size() {return 0;} +virtual int get_default_enum_size(cm_t cm) {qnotused(cm); return 0;} +virtual int calc_cdecl_purged_bytes2() {return 0;} +virtual int get_stkarg_offset2() {return 0;} +virtual int til_for_file() {return 0;} +virtual int equal_reglocs(argloc_t * a1, argloc_t * a2) {qnotused(a1); qnotused(a2); return 0;} +virtual int decorate_name3(qstring * outbuf, const char * name, bool mangle, int cc) {qnotused(outbuf); qnotused(name); qnotused(mangle); qnotused(cc); return 0;} +virtual int calc_retloc3(const tinfo_t * rettype, cm_t cc, argloc_t * retloc) {qnotused(rettype); qnotused(cc); qnotused(retloc); return 0;} +virtual int calc_varglocs3(const func_type_data_t * ftd, regobjs_t * regs, relobj_t * stkargs, int nfixed) {qnotused(ftd); qnotused(regs); qnotused(stkargs); qnotused(nfixed); return 0;} +virtual int calc_arglocs3(func_type_data_t * fti) {qnotused(fti); return 0;} +virtual int use_stkarg_type3(ea_t ea, const funcarg_t * arg) {qnotused(ea); qnotused(arg); return 0;} +virtual int use_regarg_type3(int * idx, ea_t ea, const funcargvec_t * rargs) {qnotused(idx); qnotused(ea); qnotused(rargs); return 0;} +virtual int use_arg_types3(ea_t ea, func_type_data_t * fti, funcargvec_t * rargs) {qnotused(ea); qnotused(fti); qnotused(rargs); return 0;} +virtual int calc_purged_bytes3(int * p_purged_bytes, const func_type_data_t * fti) {qnotused(p_purged_bytes); qnotused(fti); return 0;} +virtual int shadow_args_size(int * shadow_args_size, func_t * pfn) {qnotused(shadow_args_size); qnotused(pfn); return 0;} +virtual int get_varcall_regs3(callregs_t * regs) {qnotused(regs); return 0;} +virtual int get_fastcall_regs3(callregs_t * regs) {qnotused(regs); return 0;} +virtual int get_thiscall_regs3(callregs_t * regs) {qnotused(regs); return 0;} +virtual int get_func_cvtarg_map(const func_type_data_t * fti, intvec_t * argnums) {qnotused(fti); qnotused(argnums); return 0;} +virtual int get_simd_types(const simd_info_t * simd_attrs, const argloc_t * argloc, simd_info_vec_t * out, bool create_tifs) {qnotused(simd_attrs); qnotused(argloc); qnotused(out); qnotused(create_tifs); return 0;} +virtual int loader() {return 0;} }; enum areacb_type_t @@ -828,59 +872,6 @@ enum areacb_type_t AREACB_TYPE_HIDDEN_AREA, AREACB_TYPE_SRAREA, }; - -//--------------------------------------------------------------------------- -// IDB hooks -//--------------------------------------------------------------------------- -int idaapi IDB_Callback(void *ud, int notification_code, va_list va); -class IDB_Hooks -{ -public: - virtual ~IDB_Hooks() { unhook(); }; - - bool hook() - { - return hook_to_notification_point(HT_IDB, IDB_Callback, this); - } - bool unhook() - { - return unhook_from_notification_point(HT_IDB, IDB_Callback, this); - } - // Hook functions to override in Python - virtual int byte_patched(ea_t /*ea*/) { return 0; } - virtual int cmt_changed(ea_t, bool /*repeatable_cmt*/) { return 0; } - virtual int area_cmt_changed(areacb_t * /*areas*/, area_t * /*area*/, const char * /*cmt*/, bool /*repeatable*/) { return 0; } - virtual int ti_changed(ea_t /*ea*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; } - virtual int op_ti_changed(ea_t /*ea*/, int /*n*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; } - virtual int op_type_changed(ea_t /*ea*/, int /*n*/) { return 0; } - virtual int enum_created(enum_t /*id*/) { return 0; } - virtual int enum_deleted(enum_t /*id*/) { return 0; } - virtual int enum_bf_changed(enum_t /*id*/) { return 0; } - virtual int enum_renamed(enum_t /*id*/) { return 0; } - virtual int enum_cmt_changed(enum_t /*id*/) { return 0; } - virtual int enum_member_created(enum_t /*id*/, const_t cid) { return 0; } - virtual int enum_member_deleted(enum_t /*id*/, const_t cid) { return 0; } - virtual int struc_created(tid_t /*struc_id*/) { return 0; } - virtual int struc_deleted(tid_t /*struc_id*/) { return 0; } - virtual int struc_renamed(struc_t * /*sptr*/) { return 0; } - virtual int struc_expanded(struc_t * /*sptr*/) { return 0; } - virtual int struc_cmt_changed(tid_t /*struc_id*/) { return 0; } - virtual int struc_member_created(struc_t * /*sptr*/, member_t * /*mptr*/) { return 0; } - virtual int struc_member_deleted(struc_t * /*sptr*/, tid_t /*member_id*/, ea_t /*offset*/) { return 0; } - virtual int struc_member_renamed(struc_t * /*sptr*/, member_t * /*mptr*/) { return 0; } - virtual int struc_member_changed(struc_t * /*sptr*/, member_t * /*mptr*/) { return 0; } - virtual int thunk_func_created(func_t * /*pfn*/) { return 0; } - virtual int func_tail_appended(func_t * /*pfn*/, func_t * /*tail*/) { return 0; } - virtual int func_tail_removed(func_t * /*pfn*/, ea_t /*tail_ea*/) { return 0; } - virtual int tail_owner_changed(func_t * /*tail*/, ea_t /*owner_func*/) { return 0; } - virtual int func_noret_changed(func_t * /*pfn*/) { return 0; } - virtual int segm_added(segment_t * /*s*/) { return 0; } - virtual int segm_deleted(ea_t /*startEA*/) { return 0; } - virtual int segm_start_changed(segment_t * /*s*/) { return 0; } - virtual int segm_end_changed(segment_t * /*s*/) { return 0; } - virtual int segm_moved(ea_t /*from*/, ea_t /*to*/, asize_t /*size*/) { return 0; } -}; - // //------------------------------------------------------------------------- @@ -896,496 +887,943 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va) { switch ( notification_code ) { - case processor_t::custom_ana: - ret = proxy->custom_ana() ? 1 + cmd.size : 0; - break; + // hookgenIDP:notifications +case processor_t::init: +{ + const char * idp_modname = va_arg(va, const char *); + ret = proxy->init(idp_modname); +} +break; - case processor_t::custom_out: - ret = proxy->custom_out() ? 2 : 0; - break; +case processor_t::term: +{ + ret = proxy->term(); +} +break; - case processor_t::custom_emu: - ret = proxy->custom_emu() ? 2 : 0; - break; +case processor_t::newprc: +{ + int pnum = va_arg(va, int); + ret = proxy->newprc(pnum); +} +break; - case processor_t::custom_outop: - { - op_t *op = va_arg(va, op_t *); - ref_t py_obj(create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op)); - if ( py_obj == NULL ) - break; - ret = proxy->custom_outop(py_obj.o) ? 2 : 0; - break; - } +case processor_t::newasm: +{ + int asmnum = va_arg(va, int); + ret = proxy->newasm(asmnum); +} +break; - case processor_t::custom_mnem: - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_ret = proxy->custom_mnem(); - if ( py_ret != NULL && PyString_Check(py_ret) ) - { - char *outbuffer = va_arg(va, char *); - size_t bufsize = va_arg(va, size_t); +case processor_t::newfile: +{ + char * fname = va_arg(va, char *); + ret = proxy->newfile(fname); +} +break; - qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize); - ret = 2; - } - else - { - ret = 0; - } - Py_XDECREF(py_ret); - break; - } +case processor_t::oldfile: +{ + char * fname = va_arg(va, char *); + ret = proxy->oldfile(fname); +} +break; - case processor_t::is_sane_insn: - { - int no_crefs = va_arg(va, int); - ret = proxy->is_sane_insn(no_crefs); - break; - } +case processor_t::newbinary: +{ + char * filename = va_arg(va, char *); + uint32 fileoff = va_arg(va, uint32); + ea_t basepara = va_arg(va, ea_t); + ea_t binoff = va_arg(va, ea_t); + uint32 nbytes = va_arg(va, uint32); + ret = proxy->newbinary(filename, fileoff, basepara, binoff, nbytes); +} +break; - case processor_t::may_be_func: - { - int state = va_arg(va, int); - ret = proxy->may_be_func(state); - break; - } +case processor_t::endbinary: +{ + bool ok = bool(va_arg(va, int)); + ret = proxy->endbinary(ok); +} +break; - case processor_t::closebase: - { - proxy->closebase(); - break; - } +case processor_t::newseg: +{ + segment_t * seg = va_arg(va, segment_t *); + ret = proxy->newseg(seg); +} +break; - case processor_t::savebase: - { - proxy->savebase(); - break; - } +case processor_t::assemble: +{ + ea_t ea = va_arg(va, ea_t); + ea_t cs = va_arg(va, ea_t); + ea_t ip = va_arg(va, ea_t); + bool use32 = bool(va_arg(va, int)); + const char * line = va_arg(va, const char *); + uchar * bin = va_arg(va, uchar *); + PyObject * _tmp = proxy->assemble(ea, cs, ip, use32, line); + ret = IDP_Hooks::handle_assemble_output(_tmp, ea, cs, ip, use32, line, bin); +} +break; - case processor_t::auto_empty_finally: - { - proxy->auto_empty_finally(); - break; - } +case processor_t::obsolete_makemicro: +{ + mblock_t * block = va_arg(va, mblock_t *); + ret = proxy->obsolete_makemicro(block); +} +break; - case processor_t::rename: - { - ea_t ea = va_arg(va, ea_t); - const char *new_name = va_arg(va, const char *); - ret = proxy->rename(ea, new_name); - break; - } +case processor_t::outlabel: +{ + ea_t ea = va_arg(va, ea_t); + const char * colored_name = va_arg(va, const char *); + ret = proxy->outlabel(ea, colored_name); +} +break; - case processor_t::renamed: - { - ea_t ea = va_arg(va, ea_t); - const char *new_name = va_arg(va, const char *); - bool local_name = va_argi(va, bool); - proxy->renamed(ea, new_name, local_name); - break; - } +case processor_t::rename: +{ + ea_t ea = va_arg(va, ea_t); + const char * new_name = va_arg(va, const char *); + int flags = va_arg(va, int); + qnotused(flags); + ret = proxy->rename(ea, new_name); +} +break; - case processor_t::undefine: - { - ea_t ea = va_arg(va, ea_t); - ret = proxy->undefine(ea); - break; - } +case processor_t::may_show_sreg: +{ + ea_t current_ea = va_arg(va, ea_t); + ret = proxy->may_show_sreg(current_ea); +} +break; - case processor_t::make_code: - { - ea_t ea = va_arg(va, ea_t); - asize_t size = va_arg(va, asize_t); - ret = proxy->make_code(ea, size); - break; - } +case processor_t::closebase: +{ + ret = proxy->closebase(); +} +break; - case processor_t::make_data: - { - ea_t ea = va_arg(va, ea_t); - flags_t flags = va_arg(va, flags_t); - tid_t tid = va_arg(va, tid_t); - asize_t len = va_arg(va, asize_t); - ret = proxy->make_data(ea, flags, tid, len); - break; - } +case processor_t::load_idasgn: +{ + const char * short_sig_name = va_arg(va, const char *); + proxy->load_idasgn(short_sig_name); +} +break; - case processor_t::load_idasgn: - { - const char *short_sig_name = va_arg(va, const char *); - proxy->load_idasgn(short_sig_name); - break; - } +case processor_t::coagulate: +{ + ea_t start_ea = va_arg(va, ea_t); + ret = proxy->coagulate(start_ea); +} +break; - case processor_t::auto_empty: - { - proxy->auto_empty(); - break; - } +case processor_t::auto_empty: +{ + proxy->auto_empty(); +} +break; - case processor_t::auto_queue_empty: - { - atype_t type = va_arg(va, atype_t); - ret = proxy->auto_queue_empty(type); - break; - } +case processor_t::auto_queue_empty: +{ + atype_t type = va_arg(va, atype_t); + ret = proxy->auto_queue_empty(type); +} +break; - case processor_t::add_func: - { - func_t *func = va_arg(va, func_t *); - proxy->add_func(func); - break; - } +case processor_t::func_bounds: +{ + int * possible_return_code = va_arg(va, int *); + func_t * pfn = va_arg(va, func_t *); + ea_t max_func_end_ea = va_arg(va, ea_t); + proxy->func_bounds(possible_return_code, pfn, max_func_end_ea); +} +break; - case processor_t::del_func: - { - func_t *func = va_arg(va, func_t *); - ret = proxy->del_func(func); - break; - } +case processor_t::may_be_func: +{ + int state = va_arg(va, int); + ret = proxy->may_be_func(state); +} +break; - case processor_t::is_call_insn: - { - ea_t ea = va_arg(va, ea_t); - ret = proxy->is_call_insn(ea); - break; - } +case processor_t::is_sane_insn: +{ + int no_crefs = va_arg(va, int); + ret = proxy->is_sane_insn(no_crefs); +} +break; - case processor_t::is_ret_insn: - { - ea_t ea = va_arg(va, ea_t); - bool strict = va_argi(va, bool); - ret = proxy->is_ret_insn(ea, strict); - break; - } +case processor_t::is_jump_func: +{ + func_t * pfn = va_arg(va, func_t *); + ea_t * jump_target = va_arg(va, ea_t *); + ea_t * func_pointer = va_arg(va, ea_t *); + ret = proxy->is_jump_func(pfn, jump_target, func_pointer); +} +break; + +case processor_t::gen_regvar_def: +{ + regvar_t * v = va_arg(va, regvar_t *); + ret = proxy->gen_regvar_def(v); +} +break; + +case processor_t::setsgr: +{ + ea_t startEA = va_arg(va, ea_t); + ea_t endEA = va_arg(va, ea_t); + int regnum = va_arg(va, int); + sel_t value = va_arg(va, sel_t); + sel_t old_value = va_arg(va, sel_t); + uchar tag = uchar(va_arg(va, int)); + ret = proxy->setsgr(startEA, endEA, regnum, value, old_value, tag); +} +break; + +case processor_t::set_compiler: +{ + ret = proxy->set_compiler(); +} +break; + +case processor_t::is_basic_block_end: +{ + bool call_insn_stops_block = bool(va_arg(va, int)); + ret = proxy->is_basic_block_end(call_insn_stops_block); +} +break; + +case processor_t::reglink: +{ + ret = proxy->reglink(); +} +break; + +case processor_t::get_vxd_name: +{ + int vxdnum = va_arg(va, int); + int funcnum = va_arg(va, int); + char * outbuf = va_arg(va, char *); + proxy->get_vxd_name(vxdnum, funcnum, outbuf); +} +break; + +case processor_t::custom_ana: +{ + bool _tmp = proxy->custom_ana(); + ret = IDP_Hooks::bool_to_cmdsize(_tmp); +} +break; + +case processor_t::custom_out: +{ + bool _tmp = proxy->custom_out(); + ret = IDP_Hooks::bool_to_2or0(_tmp); +} +break; + +case processor_t::custom_emu: +{ + bool _tmp = proxy->custom_emu(); + ret = IDP_Hooks::bool_to_2or0(_tmp); +} +break; + +case processor_t::custom_outop: +{ + op_t * op = va_arg(va, op_t *); + ref_t clinked_op = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op); + if ( clinked_op == NULL ) + break; + bool _tmp = proxy->custom_outop(clinked_op.o); + ret = IDP_Hooks::bool_to_2or0(_tmp); +} +break; + +case processor_t::custom_mnem: +{ + char * buf = va_arg(va, char *); + size_t bufsize = va_arg(va, size_t); + PyObject * _tmp = proxy->custom_mnem(); + ret = IDP_Hooks::handle_custom_mnem_output(_tmp, buf, bufsize); +} +break; + +case processor_t::undefine: +{ + ea_t ea = va_arg(va, ea_t); + ret = proxy->undefine(ea); +} +break; + +case processor_t::make_code: +{ + ea_t ea = va_arg(va, ea_t); + asize_t size = va_arg(va, asize_t); + ret = proxy->make_code(ea, size); +} +break; + +case processor_t::make_data: +{ + ea_t ea = va_arg(va, ea_t); + flags_t flags = va_arg(va, flags_t); + tid_t tid = va_arg(va, tid_t); + asize_t len = va_arg(va, asize_t); + ret = proxy->make_data(ea, flags, tid, len); +} +break; + +case processor_t::moving_segm: +{ + segment_t * seg = va_arg(va, segment_t *); + ea_t to = va_arg(va, ea_t); + int flags = va_arg(va, int); + ret = proxy->moving_segm(seg, to, flags); +} +break; + +case processor_t::move_segm: +{ + ea_t from = va_arg(va, ea_t); + segment_t * seg = va_arg(va, segment_t *); + proxy->move_segm(from, seg); +} +break; + +case processor_t::is_call_insn: +{ + ea_t ea = va_arg(va, ea_t); + ret = proxy->is_call_insn(ea); +} +break; + +case processor_t::is_ret_insn: +{ + ea_t ea = va_arg(va, ea_t); + bool strict = bool(va_arg(va, int)); + ret = proxy->is_ret_insn(ea, strict); +} +break; + +case processor_t::get_stkvar_scale_factor: +{ + ret = proxy->get_stkvar_scale_factor(); +} +break; + +case processor_t::create_flat_group: +{ + ea_t image_base = va_arg(va, ea_t); + int bitness = va_arg(va, int); + sel_t dataseg_sel = va_arg(va, sel_t); + ret = proxy->create_flat_group(image_base, bitness, dataseg_sel); +} +break; + +case processor_t::kernel_config_loaded: +{ + proxy->kernel_config_loaded(); +} +break; + +case processor_t::might_change_sp: +{ + ea_t ea = va_arg(va, ea_t); + ret = proxy->might_change_sp(ea); +} +break; + +case processor_t::is_alloca_probe: +{ + ea_t ea = va_arg(va, ea_t); + ret = proxy->is_alloca_probe(ea); +} +break; + +case processor_t::out_3byte: +{ + ea_t dataea = va_arg(va, ea_t); + uint32 value = va_arg(va, uint32); + bool analyze_only = bool(va_arg(va, int)); + ret = proxy->out_3byte(dataea, value, analyze_only); +} +break; + +case processor_t::get_reg_name: +{ + int reg = va_arg(va, int); + size_t width = va_arg(va, size_t); + char * buf = va_arg(va, char *); + size_t bufsize = va_arg(va, size_t); + int reghi = va_arg(va, int); + ret = proxy->get_reg_name(reg, width, buf, bufsize, reghi); +} +break; + +case processor_t::savebase: +{ + proxy->savebase(); +} +break; + +case processor_t::gen_asm_or_lst: +{ + bool starting = bool(va_arg(va, int)); + FILE * fp = va_arg(va, FILE *); + bool is_asm = bool(va_arg(va, int)); + int flags = va_arg(va, int); + gen_outline_t ** outline = va_arg(va, gen_outline_t **); + proxy->gen_asm_or_lst(starting, fp, is_asm, flags, outline); +} +break; + +case processor_t::out_src_file_lnnum: +{ + ret = proxy->out_src_file_lnnum(); +} +break; + +case processor_t::get_autocmt: +{ + char * buf = va_arg(va, char *); + size_t bufsize = va_arg(va, size_t); + ret = proxy->get_autocmt(buf, bufsize); +} +break; + +case processor_t::is_insn_table_jump: +{ + ret = proxy->is_insn_table_jump(); +} +break; + +case processor_t::auto_empty_finally: +{ + proxy->auto_empty_finally(); +} +break; + +case processor_t::loader_finished: +{ + linput_t * li = va_arg(va, linput_t *); + uint16 neflags = uint16(va_arg(va, int)); + const char * filetypename = va_arg(va, const char *); + ret = proxy->loader_finished(li, neflags, filetypename); +} +break; + +case processor_t::loader_elf_machine: +{ + linput_t * li = va_arg(va, linput_t *); + int machine_type = va_arg(va, int); + const char ** p_procname = va_arg(va, const char **); + proc_def ** p_pd = va_arg(va, proc_def **); + set_elf_reloc_t * set_reloc = va_arg(va, set_elf_reloc_t *); + ret = proxy->loader_elf_machine(li, machine_type, p_procname, p_pd, set_reloc); +} +break; + +case processor_t::is_indirect_jump: +{ + ret = proxy->is_indirect_jump(); +} +break; + +case processor_t::verify_noreturn: +{ + func_t * pfn = va_arg(va, func_t *); + ret = proxy->verify_noreturn(pfn); +} +break; + +case processor_t::verify_sp: +{ + func_t * pfn = va_arg(va, func_t *); + ret = proxy->verify_sp(pfn); +} +break; + +case processor_t::renamed: +{ + ea_t ea = va_arg(va, ea_t); + const char * new_name = va_arg(va, const char *); + bool local_name = bool(va_arg(va, int)); + proxy->renamed(ea, new_name, local_name); +} +break; + +case processor_t::add_func: +{ + func_t * pfn = va_arg(va, func_t *); + proxy->add_func(pfn); +} +break; + +case processor_t::del_func: +{ + func_t * pfn = va_arg(va, func_t *); + ret = proxy->del_func(pfn); +} +break; + +case processor_t::set_func_start: +{ + func_t * pfn = va_arg(va, func_t *); + ea_t new_start = va_arg(va, ea_t); + ret = proxy->set_func_start(pfn, new_start); +} +break; + +case processor_t::set_func_end: +{ + func_t * pfn = va_arg(va, func_t *); + ea_t new_end = va_arg(va, ea_t); + ret = proxy->set_func_end(pfn, new_end); +} +break; + +case processor_t::treat_hindering_item: +{ + ea_t hindering_item_ea = va_arg(va, ea_t); + flags_t new_item_flags = va_arg(va, flags_t); + ea_t new_item_ea = va_arg(va, ea_t); + asize_t new_item_length = va_arg(va, asize_t); + ret = proxy->treat_hindering_item(hindering_item_ea, new_item_flags, new_item_ea, new_item_length); +} +break; + +case processor_t::str2reg: +{ + const char * regname = va_arg(va, const char *); + ret = proxy->str2reg(regname); +} +break; + +case processor_t::create_switch_xrefs: +{ + ea_t jumpea = va_arg(va, ea_t); + switch_info_ex_t * si = va_arg(va, switch_info_ex_t *); + ret = proxy->create_switch_xrefs(jumpea, si); +} +break; + +case processor_t::calc_switch_cases: +{ + ea_t insn_ea = va_arg(va, ea_t); + switch_info_ex_t * si = va_arg(va, switch_info_ex_t *); + casevec_t * casevec = va_arg(va, casevec_t *); + eavec_t * targets = va_arg(va, eavec_t *); + ret = proxy->calc_switch_cases(insn_ea, si, casevec, targets); +} +break; + +case processor_t::determined_main: +{ + ea_t main = va_arg(va, ea_t); + proxy->determined_main(main); +} +break; + +case processor_t::preprocess_chart: +{ + qflow_chart_t * fc = va_arg(va, qflow_chart_t *); + proxy->preprocess_chart(fc); +} +break; + +case processor_t::get_bg_color: +{ + ea_t ea = va_arg(va, ea_t); + bgcolor_t color = va_arg(va, bgcolor_t); + ret = proxy->get_bg_color(ea, color); +} +break; + +case processor_t::validate_flirt_func: +{ + ea_t start_ea = va_arg(va, ea_t); + const char * funcname = va_arg(va, const char *); + ret = proxy->validate_flirt_func(start_ea, funcname); +} +break; + +case processor_t::get_operand_string: +{ + int opnum = va_arg(va, int); + char * buf = va_arg(va, char *); + size_t buflen = va_arg(va, size_t); + ret = proxy->get_operand_string(opnum, buf, buflen); +} +break; + +case processor_t::add_cref: +{ + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + cref_t type = cref_t(va_arg(va, int)); + ret = proxy->add_cref(from, to, type); +} +break; + +case processor_t::add_dref: +{ + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + dref_t type = dref_t(va_arg(va, int)); + ret = proxy->add_dref(from, to, type); +} +break; + +case processor_t::del_cref: +{ + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + bool expand = bool(va_arg(va, int)); + ret = proxy->del_cref(from, to, expand); +} +break; + +case processor_t::del_dref: +{ + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + ret = proxy->del_dref(from, to); +} +break; + +case processor_t::coagulate_dref: +{ + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + bool may_define = bool(va_arg(va, int)); + ea_t * code_ea = va_arg(va, ea_t *); + ret = proxy->coagulate_dref(from, to, may_define, code_ea); +} +break; + +case processor_t::register_custom_fixup: +{ + const char * name = va_arg(va, const char *); + ret = proxy->register_custom_fixup(name); +} +break; + +case processor_t::custom_refinfo: +{ + ea_t ea = va_arg(va, ea_t); + int numop = va_arg(va, int); + ea_t * opval = va_arg(va, ea_t *); + const refinfo_t* ri = va_arg(va, const refinfo_t*); + char * buf = va_arg(va, char *); + size_t bufsize = va_arg(va, size_t); + ea_t * target = va_arg(va, ea_t *); + ea_t * fullvalue = va_arg(va, ea_t *); + ea_t from = va_arg(va, ea_t); + int getn_flags = va_arg(va, int); + ret = proxy->custom_refinfo(ea, numop, opval, ri, buf, bufsize, target, fullvalue, from, getn_flags); +} +break; + +case processor_t::set_proc_options: +{ + const char * options = va_arg(va, const char *); + ret = proxy->set_proc_options(options); +} +break; + +case processor_t::adjust_libfunc_ea: +{ + const idasgn_t * sig = va_arg(va, const idasgn_t *); + const libfunc_t * libfun = va_arg(va, const libfunc_t *); + ea_t * ea = va_arg(va, ea_t *); + ret = proxy->adjust_libfunc_ea(sig, libfun, ea); +} +break; + +case processor_t::extlang_changed: +{ + int kind = va_arg(va, int); + const extlang_t * el = va_arg(va, const extlang_t *); + proxy->extlang_changed(kind, el); +} +break; + +case processor_t::delay_slot_insn: +{ + ea_t * ea = va_arg(va, ea_t *); + ret = proxy->delay_slot_insn(ea); +} +break; + +case processor_t::obsolete_get_operand_info: +{ + ret = proxy->obsolete_get_operand_info(); +} +break; + +case processor_t::get_jump_target: +{ + ea_t ea = va_arg(va, ea_t); + int tid = va_arg(va, int); + processor_t::regval_getter_t getreg = va_arg(va, processor_t::regval_getter_t); + const regval_t * regvalues = va_arg(va, const regval_t *); + ea_t * target = va_arg(va, ea_t *); + ret = proxy->get_jump_target(ea, tid, getreg, regvalues, target); +} +break; + +case processor_t::calc_step_over: +{ + ea_t ip = va_arg(va, ea_t); + ea_t * target = va_arg(va, ea_t *); + ret = proxy->calc_step_over(ip, target); +} +break; + +case processor_t::get_macro_insn_head: +{ + ea_t ip = va_arg(va, ea_t); + ea_t * head = va_arg(va, ea_t *); + ret = proxy->get_macro_insn_head(ip, head); +} +break; + +case processor_t::get_dbr_opnum: +{ + ea_t ea = va_arg(va, ea_t); + int * opnum = va_arg(va, int *); + ret = proxy->get_dbr_opnum(ea, opnum); +} +break; + +case processor_t::insn_reads_tbit: +{ + ea_t ea = va_arg(va, ea_t); + processor_t::regval_getter_t getreg = va_arg(va, processor_t::regval_getter_t); + const regval_t * regvalues = va_arg(va, const regval_t *); + ret = proxy->insn_reads_tbit(ea, getreg, regvalues); +} +break; + +case processor_t::get_operand_info: +{ + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + int thread_id = va_arg(va, int); + processor_t::regval_getter_t getreg = va_arg(va, processor_t::regval_getter_t); + const regval_t * regvalues = va_arg(va, const regval_t *); + idd_opinfo_t * opinf = va_arg(va, idd_opinfo_t *); + ret = proxy->get_operand_info(ea, n, thread_id, getreg, regvalues, opinf); +} +break; + +case processor_t::calc_next_eas: +{ + bool over = bool(va_arg(va, int)); + ea_t * res = va_arg(va, ea_t *); + int * nsubcalls = va_arg(va, int *); + ret = proxy->calc_next_eas(over, res, nsubcalls); +} +break; + +case processor_t::clean_tbit: +{ + ea_t ea = va_arg(va, ea_t); + processor_t::regval_getter_t getreg = va_arg(va, processor_t::regval_getter_t); + const regval_t * regvalues = va_arg(va, const regval_t *); + ret = proxy->clean_tbit(ea, getreg, regvalues); +} +break; + +case processor_t::get_reg_info2: +{ + const char * regname = va_arg(va, const char *); + const char ** main_regname = va_arg(va, const char **); + bitrange_t * bitrange = va_arg(va, bitrange_t *); + ret = proxy->get_reg_info2(regname, main_regname, bitrange); +} +break; + +case processor_t::setup_til: +{ + proxy->setup_til(); +} +break; + +case processor_t::based_ptr: +{ + unsigned ptrt = va_arg(va, unsigned); + const char ** ptrname = va_arg(va, const char **); + ret = proxy->based_ptr(ptrt, ptrname); +} +break; + +case processor_t::max_ptr_size: +{ + ret = proxy->max_ptr_size(); +} +break; + +case processor_t::get_default_enum_size: +{ + cm_t cm = cm_t(va_arg(va, int)); + ret = proxy->get_default_enum_size(cm); +} +break; + +case processor_t::calc_cdecl_purged_bytes2: +{ + ret = proxy->calc_cdecl_purged_bytes2(); +} +break; + +case processor_t::get_stkarg_offset2: +{ + ret = proxy->get_stkarg_offset2(); +} +break; + +case processor_t::til_for_file: +{ + ret = proxy->til_for_file(); +} +break; + +case processor_t::equal_reglocs: +{ + argloc_t * a1 = va_arg(va, argloc_t *); + argloc_t * a2 = va_arg(va, argloc_t *); + ret = proxy->equal_reglocs(a1, a2); +} +break; + +case processor_t::decorate_name3: +{ + qstring * outbuf = va_arg(va, qstring *); + const char * name = va_arg(va, const char *); + bool mangle = bool(va_arg(va, int)); + cm_t cc = cm_t(va_arg(va, int)); + ret = proxy->decorate_name3(outbuf, name, mangle, IDP_Hooks::cm_t_to_int(cc)); +} +break; + +case processor_t::calc_retloc3: +{ + const tinfo_t * rettype = va_arg(va, const tinfo_t *); + cm_t cc = cm_t(va_arg(va, int)); + argloc_t * retloc = va_arg(va, argloc_t *); + ret = proxy->calc_retloc3(rettype, cc, retloc); +} +break; + +case processor_t::calc_varglocs3: +{ + const func_type_data_t * ftd = va_arg(va, const func_type_data_t *); + regobjs_t * regs = va_arg(va, regobjs_t *); + relobj_t * stkargs = va_arg(va, relobj_t *); + int nfixed = va_arg(va, int); + ret = proxy->calc_varglocs3(ftd, regs, stkargs, nfixed); +} +break; + +case processor_t::calc_arglocs3: +{ + func_type_data_t * fti = va_arg(va, func_type_data_t *); + ret = proxy->calc_arglocs3(fti); +} +break; + +case processor_t::use_stkarg_type3: +{ + ea_t ea = va_arg(va, ea_t); + const funcarg_t * arg = va_arg(va, const funcarg_t *); + ret = proxy->use_stkarg_type3(ea, arg); +} +break; + +case processor_t::use_regarg_type3: +{ + int * idx = va_arg(va, int *); + ea_t ea = va_arg(va, ea_t); + const funcargvec_t * rargs = va_arg(va, const funcargvec_t *); + ret = proxy->use_regarg_type3(idx, ea, rargs); +} +break; + +case processor_t::use_arg_types3: +{ + ea_t ea = va_arg(va, ea_t); + func_type_data_t * fti = va_arg(va, func_type_data_t *); + funcargvec_t * rargs = va_arg(va, funcargvec_t *); + ret = proxy->use_arg_types3(ea, fti, rargs); +} +break; + +case processor_t::calc_purged_bytes3: +{ + int * p_purged_bytes = va_arg(va, int *); + const func_type_data_t * fti = va_arg(va, const func_type_data_t *); + ret = proxy->calc_purged_bytes3(p_purged_bytes, fti); +} +break; + +case processor_t::shadow_args_size: +{ + int * shadow_args_size = va_arg(va, int *); + func_t * pfn = va_arg(va, func_t *); + ret = proxy->shadow_args_size(shadow_args_size, pfn); +} +break; + +case processor_t::get_varcall_regs3: +{ + callregs_t * regs = va_arg(va, callregs_t *); + ret = proxy->get_varcall_regs3(regs); +} +break; + +case processor_t::get_fastcall_regs3: +{ + callregs_t * regs = va_arg(va, callregs_t *); + ret = proxy->get_fastcall_regs3(regs); +} +break; + +case processor_t::get_thiscall_regs3: +{ + callregs_t * regs = va_arg(va, callregs_t *); + ret = proxy->get_thiscall_regs3(regs); +} +break; + +case processor_t::get_func_cvtarg_map: +{ + const func_type_data_t * fti = va_arg(va, const func_type_data_t *); + intvec_t * argnums = va_arg(va, intvec_t *); + ret = proxy->get_func_cvtarg_map(fti, argnums); +} +break; + +case processor_t::get_simd_types: +{ + const simd_info_t * simd_attrs = va_arg(va, const simd_info_t *); + const argloc_t * argloc = va_arg(va, const argloc_t *); + simd_info_vec_t * out = va_arg(va, simd_info_vec_t *); + bool create_tifs = bool(va_arg(va, int)); + ret = proxy->get_simd_types(simd_attrs, argloc, out, create_tifs); +} +break; + +case processor_t::loader: +{ + ret = proxy->loader(); +} +break; - case processor_t::assemble: - { - ea_t ea = va_arg(va, ea_t); - ea_t cs = va_arg(va, ea_t); - ea_t ip = va_arg(va, ea_t); - bool use32 = va_argi(va, bool); - const char *line = va_arg(va, const char *); - // Extract user buffer (we hardcode the MAXSTR size limit) - uchar *bin = va_arg(va, uchar *); - // Call python - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line); - if ( py_buffer != NULL && PyString_Check(py_buffer) ) - { - char *s; - Py_ssize_t len; - if ( PyString_AsStringAndSize(py_buffer, &s, &len) != -1 ) - { - if ( len > MAXSTR ) - len = MAXSTR; - memcpy(bin, s, len); - ret = len; - } - } - // ret = 0 otherwise - Py_XDECREF(py_buffer); - break; - } - // validate_flirt_func, // flirt has recognized a library function - // // this callback can be used by a plugin or proc module - // // to intercept it and validate such a function - // // args: ea_t start_ea - // // const char *funcname - // // returns: -1-do not create a function, - // // 1-function is validated - // // the idp module is allowed to modify 'cmd' - // set_func_start, // Function chunk start address will be changed - // // args: func_t *pfn - // // ea_t new_start - // // Returns: 1-ok,<=0-do not change - // set_func_end, // Function chunk end address will be changed - // // args: func_t *pfn - // // ea_t new_end - // // Returns: 1-ok,<=0-do not change - // outlabel, // The kernel is going to generate an instruction - // // label line or a function header - // // args: - // // ea_t ea - - // // const char *colored_name - - // // If returns value <=0, then the kernel should - // // not generate the label - // may_show_sreg, // The kernel wants to display the segment registers - // // in the messages window. - // // arg - ea_t current_ea - // // if this function returns 0 - // // then the kernel will not show - // // the segment registers. - // // (assuming that the module have done it) - // coagulate, // Try to define some unexplored bytes - // // This notification will be called if the - // // kernel tried all possibilities and could - // // not find anything more useful than to - // // convert to array of bytes. - // // The module can help the kernel and convert - // // the bytes into something more useful. - // // arg: - // // ea_t start_ea - // // returns: number of converted bytes + 1 - // auto_empty, // Info: all analysis queues are empty - // // args: none - // // returns: none - // // This callback is called once when the - // // initial analysis is finished. If the queue is - // // not empty upon the return from this callback, - // // it will be called later again. - // // See also auto_empty_finally. - // auto_queue_empty, // One analysis queue is empty - // // args: atype_t type - // // returns: 1-yes, keep the queue empty - // // <=0-no, the queue is not empty anymore - // // This callback can be called many times, so - // // only the autoMark() functions can be used from it - // // (other functions may work but it is not tested) - // func_bounds, // find_func_bounds() finished its work - // // The module may fine tune the function bounds - // // args: int *possible_return_code - // // func_t *pfn - // // ea_t max_func_end_ea (from the kernel's point of view) - // // returns: none - // is_jump_func, // is the function a trivial "jump" function? - // // args: func_t *pfn - // // ea_t *jump_target - // // ea_t *func_pointer - // // returns: 0-no, 1-don't know, 2-yes, see jump_target - // // and func_pointer - // gen_regvar_def, // generate register variable definition line - // // args: regvar_t *v - // // returns: 0-ok - // setsgr, // The kernel has changed a segment register value - // // args: ea_t startEA - // // ea_t endEA - // // int regnum - // // sel_t value - // // sel_t old_value - // // uchar tag (SR_... values) - // // returns: 1-ok, 0-error - // set_compiler, // The kernel has changed the compiler information - // // (inf.cc structure) - // is_basic_block_end, // Is the current instruction end of a basic block? - // // This function should be defined for processors - // // with delayed jump slots. The current instruction - // // is stored in 'cmd' - // // args: bool call_insn_stops_block - // // returns: 1-unknown, 0-no, 2-yes - // reglink, // IBM PC only, ignore it - // get_vxd_name, // IBM PC only, ignore it - // // Get Vxd function name - // // args: int vxdnum - // // int funcnum - // // char *outbuf - // // returns: nothing - // - // - // moving_segm, // May the kernel move the segment? - // // args: segment_t - segment to move - // // ea_t to - new segment start address - // // returns: 1-yes, <=0-the kernel should stop - // move_segm, // A segment is moved - // // Fix processor dependent address sensitive information - // // args: ea_t from - old segment address - // // segment_t* - moved segment - // // returns: nothing - // - // - // get_stkvar_scale_factor,// Should stack variable references be multiplied by - // // a coefficient before being used in the stack frame? - // // Currently used by TMS320C55 because the references into - // // the stack should be multiplied by 2 - // // Returns: scaling factor - // // Note: PR_SCALE_STKVARS should be set to use this callback - // - // create_flat_group, // Create special segment representing the flat group - // // (to use for PC mainly) - // // args - ea_t image_base, int bitness, sel_t dataseg_sel - // - // kernel_config_loaded, // This callback is called when ida.cfg is parsed - // // args - none, returns - nothing - // - // might_change_sp, // Does the instruction at 'ea' modify the stack pointer? - // // args: ea_t ea - // // returns: 1-yes, 0-false - // // (not used yet) - // - // is_alloca_probe, // Does the function at 'ea' behave as __alloca_probe? - // // args: ea_t ea - // // returns: 2-yes, 1-false - // - // out_3byte, // Generate text representation of 3byte data - // // init_out_buffer() is called before this function - // // and all Out... function can be used. - // // uFlag contains the flags. - // // This callback might be implemented by the processor - // // module to generate custom representation of 3byte data. - // // args: - // // ea_t dataea - address of the data item - // // uint32 value - value to output - // // bool analyze_only - only create xrefs if necessary - // // do not generate text representation - // // returns: 2-yes, 1-false - // - // get_reg_name, // Generate text representation of a register - // // int reg - internal register number as defined in the processor module - // // size_t width - register width in bytes - // // char *buf - output buffer - // // size_t bufsize - size of output buffer - // // int reghi - if not -1 then this function will return the register pair - // // returns: -1 if error, strlen(buf)+2 otherwise - // // Most processor modules do not need to implement this callback - // // It is useful only if ph.regNames[reg] does not provide - // // the correct register names - // // save its local data - // out_src_file_lnnum, // Callback: generate analog of - // // #line "file.c" 123 - // // directive. - // // const char *file - source file (may be NULL) - // // size_t lnnum - line number - // // returns: 2-directive has been generated - // get_autocmt, // Callback: get dynamic auto comment - // // Will be called if the autocomments are enabled - // // and the comment retrieved from ida.int starts with - // // '$!'. 'cmd' is contains valid info. - // // char *buf - output buffer - // // size_t bufsize - output buffer size - // // returns: 2-new comment has been generated - // // 1-callback has not been handled - // // the buffer must not be changed in this case - // is_insn_table_jump, // Callback: determine if instruction is a table jump or call - // // If CF_JUMP bit can not describe all kinds of table - // // jumps, please define this callback. - // // It will be called for insns with CF_JUMP bit set. - // // input: cmd structure contains the current instruction - // // returns: 1-yes, 0-no - // auto_empty_finally, // Info: all analysis queues are empty definitively - // // args: none - // // returns: none - // // This callback is called only once. - // // See also auto_empty. - // loader_finished, // Event: external file loader finished its work - // // linput_t *li - // // uint16 neflags - // // const char *filetypename - // // Use this event to augment the existing loader functionality - // loader_elf_machine, // Event: ELF loader machine type checkpoint - // // linput_t *li - // // int machine_type - // // const char **p_procname - // // proc_def **p_pd (see ldr\elf.h) - // // set_elf_reloc_t *set_reloc - // // A plugin check the machine_type. If it is the desired one, - // // the the plugin fills p_procname with the processor name. - // // p_pd is used to handle relocations, otherwise can be left untouched - // // set_reloc can be later used by the plugin to specify relocations - // // returns: e_machine value (if it is different from the - // // original e_machine value, procname and p_pd will be ignored - // // and the new value will be used) - // // This event occurs for each loaded ELF file - // is_indirect_jump, // Callback: determine if instruction is an indrect jump - // // If CF_JUMP bit can not describe all jump types - // // jumps, please define this callback. - // // input: cmd structure contains the current instruction - // // returns: 1-use CF_JUMP, 2-no, 3-yes - // verify_noreturn, // The kernel wants to set 'noreturn' flags for a function - // // func_t *pfn - // // Returns: 1-ok, any other value-do not set 'noreturn' flag - // verify_sp, // All function instructions have been analyzed - // // Now the processor module can analyze the stack pointer - // // for the whole function - // // input: func_t *pfn - // // Returns: 1-ok, 0-bad stack pointer - // treat_hindering_item, // An item hinders creation of another item - // // args: ea_t hindering_item_ea - // // flags_t new_item_flags (0 for code) - // // ea_t new_item_ea - // // asize_t new_item_length - // // Returns: 1-no reaction, <=0-the kernel may delete the hindering item - // str2reg, // Convert a register name to a register number - // // args: const char *regname - // // Returns: register number + 2 - // // The register number is the register index in the regNames array - // // Most processor modules do not need to implement this callback - // // It is useful only if ph.regNames[reg] does not provide - // // the correct register names - // create_switch_xrefs, // Create xrefs for a custom jump table - // // in: ea_t jumpea; - address of the jump insn - // // switch_info_ex_t *; - switch information - // // returns: must return 2 - // calc_switch_cases, // Calculate case values and targets for a custom jump table - // // in: ea_t insn_ea - address of the 'indirect jump' instruction - // // switch_info_ex_t *si - switch information - // // casevec_t *casevec - vector of case values... - // // evec_t *targets - ...and corresponding target addresses - // // casevec and targets may be NULL - // // returns: 2-ok, 1-failed - // determined_main, // The main() function has been determined - // // in: ea_t main - address of the main() function - // // returns: none - // preprocess_chart, // gui has retrieved a function flow chart - // // in: qflow_chart_t *fc - // // returns: none - // // Plugins may modify the flow chart in this callback - // get_bg_color, // Get item background color - // // in: ea_t ea, bgcolor_t *color - // // Returns: 1-not implemented, 2-color set - // // Plugins can hook this callback to color disassembly lines - // // dynamically - // get_operand_string, // Request text string for operand (cli, java, ...) - // // args: int opnum - // // char *buf - // // size_t buflen - // // (cmd structure must contain info for the desired insn) - // // opnum is the operand number; -1 means any string operand - // // returns: 1 - no string (or empty string) - // // >1 - original string length with terminating zero - // - // // the following 5 events are very low level - // // take care of possible recursion - // add_cref, // a code reference is being created - // // args: ea_t from, ea_t to, cref_t type - // // returns: <0 - cancel cref creation - // add_dref, // a data reference is being created - // // args: ea_t from, ea_t to, dref_t type - // // returns: <0 - cancel dref creation - // del_cref, // a code reference is being deleted - // // args: ea_t from, ea_t to, bool expand - // // returns: <0 - cancel cref deletion - // del_dref, // a data reference is being deleted - // // args: ea_t from, ea_t to - // // returns: <0 - cancel dref deletion - // coagulate_dref, // data reference is being analyzed - // // args: ea_t from, ea_t to, bool may_define, ea_t *code_ea - // // plugin may correct code_ea (e.g. for thumb mode refs, we clear the last bit) - // // returns: <0 - cancel dref analysis - // custom_fixup, // mutipurpose notification for FIXUP_CUSTOM - // // args: cust_fix oper, ea_t ea, const fixup_data_t*, ... (see cust_fix) - // // returns: 1 - no accepted (fixup ignored by ida) - // // >1 - accepted (see cust_fix) - // off_preproc, // called from get_offset_expr, when refinfo_t - // // contain flag REFINFO_PREPROC. Normally this - // // notification used in a combination with custom_fixup - // // args: ea_t ea, int numop, ea_t* opval, const refinfo_t* ri, - // // char* buf, size_t bufsize, ea_t* target, - // // ea_t* fullvalue, ea_t from, int getn_flags - // // returns: 2 - buf filled as simple expression - // // 3 - buf filled as complex expression - // // 4 - apply standard processing (with - possible - changed values) - // // others - can't convert to offset expression - // - // set_proc_options, // called if the user specified an option string in the command line: - // // -p: - // // can be used for e.g. setting a processor subtype - // // also called if option string is passed to set_processor_type() - // // and IDC's SetProcessorType() - // // args: const char * options - // // returns: <0 - bad option string - // } } catch (Swig::DirectorException &e) @@ -1398,199 +1836,6 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va) return ret; } -//--------------------------------------------------------------------------- -int 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; - ea_t ea, ea2; - bool repeatable_cmt; - type_t *type; - p_list *fnames; - int n; - enum_t id; - const_t cid; - tid_t struc_id; - struc_t *sptr; - member_t *mptr; - tid_t member_id; - func_t *pfn; - func_t *tail; - segment_t *seg; - asize_t size; - - try { - switch (notification_code) - { - case idb_event::byte_patched: - ea = va_arg(va, ea_t); - return proxy->byte_patched(ea); - - case idb_event::cmt_changed: - ea = va_arg(va, ea_t); - repeatable_cmt = va_arg(va, int); - return proxy->cmt_changed(ea, repeatable_cmt); - - case idb_event::area_cmt_changed: - { - areacb_t *cb = va_arg(va, areacb_t*); - area_t *area = va_arg(va, area_t*); - const char *cmt = va_arg(va, char*); - repeatable_cmt = va_arg(va, int); - return proxy->area_cmt_changed(cb, area, cmt, repeatable_cmt); - } - - case idb_event::ti_changed: - ea = va_arg(va, ea_t); - type = va_arg(va, type_t *); - fnames = va_arg(va, p_list *); - return proxy->ti_changed(ea, type, fnames); - - case idb_event::op_ti_changed: - ea = va_arg(va, ea_t); - n = va_arg(va, int); - type = va_arg(va, type_t *); - fnames = va_arg(va, p_list *); - return proxy->op_ti_changed(ea, n, type, fnames); - - case idb_event::op_type_changed: - ea = va_arg(va, ea_t); - n = va_arg(va, int); - return proxy->op_type_changed(ea, n); - - case idb_event::enum_created: - id = va_arg(va, enum_t); - return proxy->enum_created(id); - - case idb_event::enum_deleted: - id = va_arg(va, enum_t); - return proxy->enum_deleted(id); - - case idb_event::enum_bf_changed: - id = va_arg(va, enum_t); - return proxy->enum_bf_changed(id); - - case idb_event::enum_cmt_changed: - id = va_arg(va, enum_t); - return proxy->enum_cmt_changed(id); - -#ifdef NO_OBSOLETE_FUNCS - case idb_event::enum_member_created: -#else - case idb_event::enum_const_created: -#endif - id = va_arg(va, enum_t); - cid = va_arg(va, const_t); - return proxy->enum_member_created(id, cid); - -#ifdef NO_OBSOLETE_FUNCS - case idb_event::enum_member_deleted: -#else - case idb_event::enum_const_deleted: -#endif - id = va_arg(va, enum_t); - cid = va_arg(va, const_t); - return proxy->enum_member_deleted(id, cid); - - case idb_event::struc_created: - struc_id = va_arg(va, tid_t); - return proxy->struc_created(struc_id); - - case idb_event::struc_deleted: - struc_id = va_arg(va, tid_t); - return proxy->struc_deleted(struc_id); - - case idb_event::struc_renamed: - sptr = va_arg(va, struc_t *); - return proxy->struc_renamed(sptr); - - case idb_event::struc_expanded: - sptr = va_arg(va, struc_t *); - return proxy->struc_expanded(sptr); - - case idb_event::struc_cmt_changed: - struc_id = va_arg(va, tid_t); - return proxy->struc_cmt_changed(struc_id); - - case idb_event::struc_member_created: - sptr = va_arg(va, struc_t *); - mptr = va_arg(va, member_t *); - return proxy->struc_member_created(sptr, mptr); - - case idb_event::struc_member_deleted: - sptr = va_arg(va, struc_t *); - member_id = va_arg(va, tid_t); - ea = va_arg(va, ea_t); - return proxy->struc_member_deleted(sptr, member_id, ea); - - case idb_event::struc_member_renamed: - sptr = va_arg(va, struc_t *); - mptr = va_arg(va, member_t *); - return proxy->struc_member_renamed(sptr, mptr); - - case idb_event::struc_member_changed: - sptr = va_arg(va, struc_t *); - mptr = va_arg(va, member_t *); - return proxy->struc_member_changed(sptr, mptr); - - case idb_event::thunk_func_created: - pfn = va_arg(va, func_t *); - return proxy->thunk_func_created(pfn); - - case idb_event::func_tail_appended: - pfn = va_arg(va, func_t *); - tail = va_arg(va, func_t *); - return proxy->func_tail_appended(pfn, tail); - - case idb_event::func_tail_removed: - pfn = va_arg(va, func_t *); - ea = va_arg(va, ea_t); - return proxy->func_tail_removed(pfn, ea); - - case idb_event::tail_owner_changed: - tail = va_arg(va, func_t *); - ea = va_arg(va, ea_t); - return proxy->tail_owner_changed(tail, ea); - - case idb_event::func_noret_changed: - pfn = va_arg(va, func_t *); - return proxy->func_noret_changed(pfn); - - case idb_event::segm_added: - seg = va_arg(va, segment_t *); - return proxy->segm_added(seg); - - case idb_event::segm_deleted: - ea = va_arg(va, ea_t); - return proxy->segm_deleted(ea); - - case idb_event::segm_start_changed: - seg = va_arg(va, segment_t *); - return proxy->segm_start_changed(seg); - - case idb_event::segm_end_changed: - seg = va_arg(va, segment_t *); - return proxy->segm_end_changed(seg); - - case idb_event::segm_moved: - ea = va_arg(va, ea_t); - ea2 = va_arg(va, ea_t); - size = va_arg(va, asize_t); - return proxy->segm_moved(ea, ea2, size); - } - } - catch (Swig::DirectorException &e) - { - msg("Exception in IDB Hook function: %s\n", e.getMessage()); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if (PyErr_Occurred()) - PyErr_Print(); - } - return 0; -} - //------------------------------------------------------------------------- static const regval_t *idaapi _py_getreg( const char *name, diff --git a/pywraps/py_kernwin.hpp b/pywraps/py_kernwin.hpp index 6452c10..a17d282 100644 --- a/pywraps/py_kernwin.hpp +++ b/pywraps/py_kernwin.hpp @@ -232,9 +232,9 @@ def umsg(text): pass # */ -static PyObject* py_umsg(PyObject *o) +static PyObject *py_umsg(PyObject *o) { - PyObject* utf8 = NULL; + PyObject *utf8 = NULL; if ( PyUnicode_Check(o) ) { utf8 = PyUnicode_AsUTF8String(o); @@ -267,7 +267,7 @@ def msg(text): pass # */ -static PyObject* py_msg(PyObject *o) +static PyObject *py_msg(PyObject *o) { if ( PyUnicode_Check(o) ) return py_umsg(o); @@ -463,53 +463,127 @@ PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc) idc_func_name.sprnt("py_hotkeycb_%p", pyfunc); // Can add the hotkey? - if ( add_idc_hotkey(hotkey, idc_func_name.c_str()) == IDCHK_OK ) do + if ( add_idc_hotkey(hotkey, idc_func_name.c_str()) == IDCHK_OK ) { - // Generate global variable name - qstring idc_gvarname; - idc_gvarname.sprnt("_g_pyhotkey_ref_%p", pyfunc); + do + { + // Generate global variable name + qstring idc_gvarname; + idc_gvarname.sprnt("_g_pyhotkey_ref_%p", pyfunc); - // Now add the global variable - idc_value_t *gvar = add_idc_gvar(idc_gvarname.c_str()); - if ( gvar == NULL ) - break; + // Now add the global variable + idc_value_t *gvar = add_idc_gvar(idc_gvarname.c_str()); + if ( gvar == NULL ) + break; - // The function body will call a registered IDC function that - // will take a global variable that wraps a PyCallable as a pvoid - qstring idc_func; - idc_func.sprnt("static %s() { %s(%s); }", - idc_func_name.c_str(), - S_PYINVOKE0, - idc_gvarname.c_str()); + // The function body will call a registered IDC function that + // will take a global variable that wraps a PyCallable as a pvoid + qstring idc_func; + idc_func.sprnt("static %s() { %s(%s); }", + idc_func_name.c_str(), + S_PYINVOKE0, + idc_gvarname.c_str()); - // Compile the IDC condition - char errbuf[MAXSTR]; - if ( !CompileLineEx(idc_func.c_str(), errbuf, sizeof(errbuf)) ) - break; + // Compile the IDC condition + char errbuf[MAXSTR]; + if ( !CompileLineEx(idc_func.c_str(), errbuf, sizeof(errbuf)) ) + break; - // Create new context - // Define context - py_idchotkey_ctx_t *ctx = new py_idchotkey_ctx_t(); + // Create new context + // Define context + py_idchotkey_ctx_t *ctx = new py_idchotkey_ctx_t(); - // Remember the hotkey - ctx->hotkey = hotkey; + // Remember the hotkey + ctx->hotkey = hotkey; - // Take reference to the callable - ctx->pyfunc = pyfunc; - Py_INCREF(pyfunc); + // Take reference to the callable + ctx->pyfunc = pyfunc; + Py_INCREF(pyfunc); - // Bind IDC variable w/ the PyCallable - gvar->set_pvoid(pyfunc); - - // Return the context - return PyCObject_FromVoidPtr(ctx, NULL); - } while (false); + // Bind IDC variable w/ the PyCallable + gvar->set_pvoid(pyfunc); + // Return the context + return PyCObject_FromVoidPtr(ctx, NULL); + } while (false); + } // Cleanup del_idc_hotkey(hotkey); Py_RETURN_NONE; } +//------------------------------------------------------------------------ +static PyObject *py_take_database_snapshot(snapshot_t *ss) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + qstring err_msg; + + bool b = take_database_snapshot(ss, &err_msg); + + // Return (b, err_msg) + return Py_BuildValue("(Ns)", PyBool_FromLong(b), err_msg.empty() ? NULL : err_msg.c_str()); +} + +//------------------------------------------------------------------------ +static void idaapi py_ss_restore_callback(const char *err_msg, void *userdata) +{ + PYW_GIL_GET; + + // userdata is a tuple of ( func, args ) + // func and args are borrowed references from userdata + PyObject *func = PyTuple_GET_ITEM(userdata, 0); + PyObject *args = PyTuple_GET_ITEM(userdata, 1); + + // Create arguments tuple for python function + PyObject *cb_args = Py_BuildValue("(sO)", err_msg, args); + + // Call the python function + newref_t result(PyEval_CallObject(func, cb_args)); + + // Free cb_args and userdata + Py_DECREF(cb_args); + Py_DECREF(userdata); + + // We cannot raise an exception in the callback, just print it. + if ( result == NULL ) + PyErr_Print(); +} +static PyObject *py_restore_database_snapshot( + const snapshot_t *ss, + PyObject *pyfunc_or_none, + PyObject *pytuple_or_none) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + // If there is no callback, just call the function directly + if ( pyfunc_or_none == Py_None ) + return PyBool_FromLong(restore_database_snapshot(ss, NULL, NULL)); + + // Create a new tuple or increase reference to pytuple_or_none + if ( pytuple_or_none == Py_None ) + { + pytuple_or_none = PyTuple_New(0); + if ( pytuple_or_none == NULL ) + return NULL; + } + else + { + Py_INCREF(pytuple_or_none); + } + + // Create callback data tuple (use 'N' for pytuple_or_none, since its + // reference has already been incremented) + PyObject *cb_data = Py_BuildValue("(ON)", pyfunc_or_none, pytuple_or_none); + + bool b = restore_database_snapshot(ss, py_ss_restore_callback, (void *) cb_data); + + if ( !b ) + Py_DECREF(cb_data); + + return PyBool_FromLong(b); +} + //------------------------------------------------------------------------ /* # @@ -931,52 +1005,85 @@ public: return unhook_from_notification_point(HT_UI, UI_Callback, this); } - virtual int preprocess(const char * /*name*/) + static int handle_get_ea_hint_output(PyObject *o, ea_t, char *buf, size_t bufsize) { - return 0; + int rc = 0; + char *_buf; + Py_ssize_t _len; + if ( o != NULL && PyString_Check(o) && PyString_AsStringAndSize(o, &_buf, &_len) != -1 ) + { + qstrncpy(buf, _buf, qmin(_len, bufsize)); + rc = 1; + } + Py_XDECREF(o); + return rc; } - virtual void postprocess() + static int handle_hint_output(PyObject *o, int *important_lines, qstring *hint) { + int rc = 0; + if ( o != NULL && PyTuple_Check(o) && PyTuple_Size(o) == 2 ) + { + borref_t el0(PyTuple_GetItem(o, 0)); + char *_buf; + Py_ssize_t _len; + if ( el0 != NULL + && PyString_Check(el0.o) + && PyString_AsStringAndSize(el0.o, &_buf, &_len) != -1 + && _len > 0 ) + { + borref_t el1(PyTuple_GetItem(o, 1)); + if ( el1 != NULL && PyInt_Check(el1.o) ) + { + long lns = PyInt_AsLong(el1.o); + if ( lns > 0 ) + { + *important_lines = lns; + hint->append(_buf, _len); + rc = 1; + } + } + } + } + return rc; } - virtual void saving() + static int handle_hint_output(PyObject *o, ea_t, int, int *important_lines, qstring *hint) { + return handle_hint_output(o, important_lines, hint); } - virtual void saved() + static int handle_hint_output(PyObject *o, TCustomControl *, place_t *, int *important_lines, qstring *hint) { + return handle_hint_output(o, important_lines, hint); } - virtual void term() - { - } - - virtual PyObject *get_ea_hint(ea_t /*ea*/) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - }; - - virtual void current_tform_changed(TForm * /*form*/, TForm * /*previous_form*/) - { - } - - virtual void updating_actions(action_update_ctx_t *ctx) - { - } - - virtual void updated_actions() - { - } - - virtual void populating_tform_popup(TForm * /*form*/, TPopupMenu * /*popup*/) - { - } - - virtual void finish_populating_tform_popup(TForm * /*form*/, TPopupMenu * /*popup*/) - { - } + // hookgenUI:methods +virtual void range() {} +virtual void idcstart() {} +virtual void idcstop() {} +virtual void suspend() {} +virtual void resume() {} +virtual void saving() {} +virtual void saved() {} +virtual void term() {} +virtual int debugger_menu_change(bool enable) {qnotused(enable); return 1;} +virtual void tform_visible(TForm * form, void * HWND) {qnotused(form); qnotused(HWND); } +virtual void tform_invisible(TForm * form, void * HWND) {qnotused(form); qnotused(HWND); } +virtual PyObject * get_ea_hint(ea_t ea) {qnotused(ea); Py_RETURN_NONE;} +virtual PyObject * get_item_hint(ea_t ea, int max_lines) {qnotused(ea); qnotused(max_lines); Py_RETURN_NONE;} +virtual PyObject * get_custom_viewer_hint(TCustomControl* viewer, place_t * place) {qnotused(viewer); qnotused(place); Py_RETURN_NONE;} +virtual void database_inited(int is_new_database, const char * idc_script) {qnotused(is_new_database); qnotused(idc_script); } +virtual void ready_to_run() {} +virtual void preprocess(const char * name) {qnotused(name); } +virtual void postprocess() {} +virtual void updating_actions(action_update_ctx_t * ctx) {qnotused(ctx); } +virtual void updated_actions() {} +virtual void populating_tform_popup(TForm * form, TPopupMenu * popup_handle) {qnotused(form); qnotused(popup_handle); } +virtual void finish_populating_tform_popup(TForm * form, TPopupMenu * popup_handle) {qnotused(form); qnotused(popup_handle); } +virtual void plugin_loaded(const plugin_info_t * plugin_info) {qnotused(plugin_info); } +virtual void plugin_unloading(const plugin_info_t * plugin_info) {qnotused(plugin_info); } +virtual void current_tform_changed(TForm * form, TForm * prev_form) {qnotused(form); qnotused(prev_form); } }; //------------------------------------------------------------------------- @@ -1167,8 +1274,8 @@ nav_colorizer_t *py_set_nav_colorizer(PyObject *new_py_colorizer) bool need_install = py_colorizer == NULL; py_colorizer = borref_t(new_py_colorizer); return need_install - ? set_nav_colorizer(lambda_t::call_py_colorizer) - : NULL; + ? set_nav_colorizer(lambda_t::call_py_colorizer) + : NULL; } //------------------------------------------------------------------------- @@ -1192,13 +1299,10 @@ uint32 py_call_nav_colorizer( { return col(ea, nbytes); } - // //--------------------------------------------------------------------------- // -//--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- int idaapi UI_Callback(void *ud, int notification_code, va_list va) { @@ -1208,87 +1312,190 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va) int ret = 0; try { - switch (notification_code) + switch ( notification_code ) { - case ui_preprocess: - { - const char *name = va_arg(va, const char *); - return proxy->preprocess(name); - } + // hookgenUI:notifications +case ui_range: +{ + proxy->range(); +} +break; - case ui_postprocess: - proxy->postprocess(); - break; +case ui_idcstart: +{ + proxy->idcstart(); +} +break; - case ui_saving: - proxy->saving(); - break; +case ui_idcstop: +{ + proxy->idcstop(); +} +break; - case ui_saved: - proxy->saved(); - break; +case ui_suspend: +{ + proxy->suspend(); +} +break; - case ui_term: - proxy->term(); - break; +case ui_resume: +{ + proxy->resume(); +} +break; - case ui_get_ea_hint: - { - ea_t ea = va_arg(va, ea_t); - char *buf = va_arg(va, char *); - size_t sz = va_arg(va, size_t); - char *_buf; - Py_ssize_t _len; +case ui_saving: +{ + proxy->saving(); +} +break; - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_str = proxy->get_ea_hint(ea); - if ( py_str != NULL - && PyString_Check(py_str) - && PyString_AsStringAndSize(py_str, &_buf, &_len) != - 1 ) - { - qstrncpy(buf, _buf, qmin(_len, sz)); - ret = 1; - } - break; - } +case ui_saved: +{ + proxy->saved(); +} +break; - case ui_current_tform_changed: - { - TForm *form = va_arg(va, TForm *); - TForm *prev_form = va_arg(va, TForm *); - proxy->current_tform_changed(form, prev_form); - } - break; +case ui_term: +{ + proxy->term(); +} +break; - case ui_updating_actions: - { - action_update_ctx_t *ctx = va_arg(va, action_update_ctx_t *); - proxy->updating_actions(ctx); - } - break; +case ui_debugger_menu_change: +{ + bool enable = bool(va_arg(va, int)); + ret = proxy->debugger_menu_change(enable); +} +break; +case ui_tform_visible: +{ + TForm * form = va_arg(va, TForm *); + void * HWND = va_arg(va, void *); + proxy->tform_visible(form, HWND); +} +break; - case ui_updated_actions: - { - proxy->updated_actions(); - } - break; +case ui_tform_invisible: +{ + TForm * form = va_arg(va, TForm *); + void * HWND = va_arg(va, void *); + proxy->tform_invisible(form, HWND); +} +break; - case ui_populating_tform_popup: - { - TForm *form = va_arg(va, TForm *); - TPopupMenu *popup = va_arg(va, TPopupMenu *); - proxy->populating_tform_popup(form, popup); - } - break; +case ui_get_ea_hint: +{ + ea_t ea = va_arg(va, ea_t); + char * buf = va_arg(va, char *); + size_t bufsize = va_arg(va, size_t); + PyObject * _tmp = proxy->get_ea_hint(ea); + ret = UI_Hooks::handle_get_ea_hint_output(_tmp, ea, buf, bufsize); +} +break; + +case ui_get_item_hint: +{ + ea_t ea = va_arg(va, ea_t); + int max_lines = va_arg(va, int); + int * important_lines = va_arg(va, int *); + qstring * hint = va_arg(va, qstring *); + PyObject * _tmp = proxy->get_item_hint(ea, max_lines); + ret = UI_Hooks::handle_hint_output(_tmp, ea, max_lines, important_lines, hint); +} +break; + +case ui_get_custom_viewer_hint: +{ + TCustomControl* viewer = va_arg(va, TCustomControl*); + place_t * place = va_arg(va, place_t *); + int * important_lines = va_arg(va, int *); + qstring * hint = va_arg(va, qstring *); + PyObject * _tmp = proxy->get_custom_viewer_hint(viewer, place); + ret = UI_Hooks::handle_hint_output(_tmp, viewer, place, important_lines, hint); +} +break; + +case ui_database_inited: +{ + int is_new_database = va_arg(va, int); + const char * idc_script = va_arg(va, const char *); + proxy->database_inited(is_new_database, idc_script); +} +break; + +case ui_ready_to_run: +{ + proxy->ready_to_run(); +} +break; + +case ui_preprocess: +{ + const char * name = va_arg(va, const char *); + proxy->preprocess(name); +} +break; + +case ui_postprocess: +{ + proxy->postprocess(); +} +break; + +case ui_updating_actions: +{ + action_update_ctx_t * ctx = va_arg(va, action_update_ctx_t *); + proxy->updating_actions(ctx); +} +break; + +case ui_updated_actions: +{ + proxy->updated_actions(); +} +break; + +case ui_populating_tform_popup: +{ + TForm * form = va_arg(va, TForm *); + TPopupMenu * popup_handle = va_arg(va, TPopupMenu *); + proxy->populating_tform_popup(form, popup_handle); +} +break; + +case ui_finish_populating_tform_popup: +{ + TForm * form = va_arg(va, TForm *); + TPopupMenu * popup_handle = va_arg(va, TPopupMenu *); + proxy->finish_populating_tform_popup(form, popup_handle); +} +break; + +case ui_plugin_loaded: +{ + const plugin_info_t * plugin_info = va_arg(va, const plugin_info_t *); + proxy->plugin_loaded(plugin_info); +} +break; + +case ui_plugin_unloading: +{ + const plugin_info_t * plugin_info = va_arg(va, const plugin_info_t *); + proxy->plugin_unloading(plugin_info); +} +break; + +case ui_current_tform_changed: +{ + TForm * form = va_arg(va, TForm *); + TForm * prev_form = va_arg(va, TForm *); + proxy->current_tform_changed(form, prev_form); +} +break; - case ui_finish_populating_tform_popup: - { - TForm *form = va_arg(va, TForm *); - TPopupMenu *popup = va_arg(va, TPopupMenu *); - proxy->finish_populating_tform_popup(form, popup); - } - break; } } catch (Swig::DirectorException &e) diff --git a/pywraps/py_kernwin.py b/pywraps/py_kernwin.py old mode 100644 new mode 100755 diff --git a/pywraps/py_lines.py b/pywraps/py_lines.py old mode 100644 new mode 100755 diff --git a/pywraps/py_linput.hpp b/pywraps/py_linput.hpp index 4dd725c..3144878 100644 --- a/pywraps/py_linput.hpp +++ b/pywraps/py_linput.hpp @@ -2,7 +2,7 @@ #define __PY_IDA_LINPUT__ //-------------------------------------------------------------------------- -// +// /* # class loader_input_t(pyidc_opaque_object_t): @@ -412,6 +412,6 @@ public: return Py_BuildValue("c", ch); } }; -// +// #endif diff --git a/pywraps/py_nalt.hpp b/pywraps/py_nalt.hpp index 4564d82..15be50f 100644 --- a/pywraps/py_nalt.hpp +++ b/pywraps/py_nalt.hpp @@ -294,7 +294,7 @@ static bool switch_info_ex_t_assign(PyObject *self, PyObject *other) { switch_info_ex_t *lhs = switch_info_ex_t_get_clink(self); switch_info_ex_t *rhs = switch_info_ex_t_get_clink(other); - if (lhs == NULL || rhs == NULL) + if ( lhs == NULL || rhs == NULL ) return false; *lhs = *rhs; diff --git a/pywraps/py_nalt.py b/pywraps/py_nalt.py old mode 100644 new mode 100755 diff --git a/pywraps/py_name.hpp b/pywraps/py_name.hpp index e36b991..c2cdda5 100644 --- a/pywraps/py_name.hpp +++ b/pywraps/py_name.hpp @@ -14,9 +14,9 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) get_debug_names(ea1, ea2, names); Py_END_ALLOW_THREADS; PyObject *dict = Py_BuildValue("{}"); - if (dict != NULL) + if ( dict != NULL ) { - for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it) + for ( ea_name_vec_t::iterator it=names.begin(); it!=names.end(); ++it ) { PyDict_SetItem(dict, Py_BuildValue(PY_FMT64, it->ea), diff --git a/pywraps/py_notifywhen.hpp b/pywraps/py_notifywhen.hpp deleted file mode 100644 index 2ecbf3c..0000000 --- a/pywraps/py_notifywhen.hpp +++ /dev/null @@ -1,310 +0,0 @@ -#ifndef __PYWRAPS_NOTIFY_WHEN__ -#define __PYWRAPS_NOTIFY_WHEN__ - -//------------------------------------------------------------------------ -// -//------------------------------------------------------------------------ - -//------------------------------------------------------------------------ -class pywraps_notify_when_t -{ - ref_vec_t table[NW_EVENTSCNT]; - qstring err; - bool in_notify; - struct notify_when_args_t - { - int when; - PyObject *py_callable; - }; - typedef qvector notify_when_args_vec_t; - notify_when_args_vec_t delayed_notify_when_list; - - //------------------------------------------------------------------------ - static int idaapi idp_callback(void *ud, int event_id, va_list va) - { - // This hook gets called from the kernel. Ensure we hold the GIL. - PYW_GIL_GET; - pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud; - switch ( event_id ) - { - case processor_t::newfile: - case processor_t::oldfile: - { - int old = event_id == processor_t::oldfile ? 1 : 0; - char *dbname = va_arg(va, char *); - _this->notify(NW_OPENIDB_SLOT, old); - } - break; - case processor_t::closebase: - _this->notify(NW_CLOSEIDB_SLOT); - break; - } - // event not processed, let other plugins or the processor module handle it - return 0; - } - - //------------------------------------------------------------------------ - bool unnotify_when(int when, PyObject *py_callable) - { - int cnt = 0; - for ( int slot=0; slot 0; - } - - //------------------------------------------------------------------------ - void register_callback(int slot, PyObject *py_callable) - { - borref_t callable_ref(py_callable); - ref_vec_t &tbl = table[slot]; - ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref); - - // Already added - if ( it != it_end ) - return; - - // Insert the element - tbl.push_back(callable_ref); - } - - //------------------------------------------------------------------------ - void unregister_callback(int slot, PyObject *py_callable) - { - borref_t callable_ref(py_callable); - ref_vec_t &tbl = table[slot]; - ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref); - - // Not found? - if ( it == it_end ) - return; - - // Delete the element - tbl.erase(it); - } - -public: - //------------------------------------------------------------------------ - bool init() - { - return hook_to_notification_point(HT_IDP, idp_callback, this); - } - - //------------------------------------------------------------------------ - bool deinit() - { - // Uninstall all objects - ref_vec_t::iterator it, it_end; - for ( int slot=0; sloto); - } - // ...and remove the notification - return unhook_from_notification_point(HT_IDP, idp_callback, this); - } - - //------------------------------------------------------------------------ - bool notify_when(int when, PyObject *py_callable) - { - // While in notify() do not allow insertion or deletion to happen on the spot - // Instead we will queue them so that notify() will carry the action when it finishes - // dispatching the notification handlers - if ( in_notify ) - { - notify_when_args_t &args = delayed_notify_when_list.push_back(); - args.when = when; - args.py_callable = py_callable; - return true; - } - // Uninstalling the notification? - if ( (when & NW_REMOVE) != 0 ) - return unnotify_when(when & ~NW_REMOVE, py_callable); - - int cnt = 0; - for ( int slot=0; slot 0; - } - - //------------------------------------------------------------------------ - bool notify(int slot, ...) - { - va_list va; - va_start(va, slot); - bool ok = notify_va(slot, va); - va_end(va); - return ok; - } - - //------------------------------------------------------------------------ - bool notify_va(int slot, va_list va) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Sanity bounds check! - if ( slot < 0 || slot >= NW_EVENTSCNT ) - return false; - - bool ok = true; - in_notify = true; - int old = slot == NW_OPENIDB_SLOT ? va_arg(va, int) : 0; - - { - for (ref_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end(); - it != it_end; - ++it) - { - // Form the notification code - newref_t py_code(PyInt_FromLong(1 << slot)); - ref_t py_result; - switch ( slot ) - { - case NW_CLOSEIDB_SLOT: - case NW_INITIDA_SLOT: - case NW_TERMIDA_SLOT: - { - py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, NULL)); - break; - } - case NW_OPENIDB_SLOT: - { - newref_t py_old(PyInt_FromLong(old)); - py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, py_old.o, NULL)); - } - break; - } - if ( PyW_GetError(&err) || py_result == NULL ) - { - PyErr_Clear(); - warning("notify_when(): Error occured while notifying object.\n%s", err.c_str()); - ok = false; - } - } - } - in_notify = false; - - // Process any delayed notify_when() calls that - if ( !delayed_notify_when_list.empty() ) - { - for (notify_when_args_vec_t::iterator it = delayed_notify_when_list.begin(), it_end=delayed_notify_when_list.end(); - it != it_end; - ++it) - { - notify_when(it->when, it->py_callable); - } - delayed_notify_when_list.qclear(); - } - - return ok; - } - - //------------------------------------------------------------------------ - pywraps_notify_when_t() - { - in_notify = false; - } -}; - -static pywraps_notify_when_t *g_nw = NULL; - -//------------------------------------------------------------------------ -// Initializes the notify_when mechanism -// (Normally called by IDAPython plugin.init()) -bool pywraps_nw_init() -{ - if ( g_nw != NULL ) - return true; - - g_nw = new pywraps_notify_when_t(); - if ( g_nw->init() ) - return true; - - // Things went bad, undo! - delete g_nw; - g_nw = NULL; - return false; -} - -//------------------------------------------------------------------------ -bool pywraps_nw_notify(int slot, ...) -{ - if ( g_nw == NULL ) - return false; - - // Appears to be called from 'driver_notifywhen.cpp', which - // itself is called from possibly non-python code. - // I.e., we must acquire the GIL. - PYW_GIL_GET; - va_list va; - va_start(va, slot); - bool ok = g_nw->notify_va(slot, va); - va_end(va); - - return ok; -} - -//------------------------------------------------------------------------ -// Deinitializes the notify_when mechanism -bool pywraps_nw_term() -{ - if ( g_nw == NULL ) - return true; - - // If could not deinitialize then return w/o stopping nw - if ( !g_nw->deinit() ) - return false; - - // Cleanup - delete g_nw; - g_nw = NULL; - return true; -} - -// -//------------------------------------------------------------------------ - -// - -//------------------------------------------------------------------------ -/* -# -def notify_when(when, callback): - """ - Register a callback that will be called when an event happens. - @param when: one of NW_XXXX constants - @param callback: This callback prototype varies depending on the 'when' parameter: - The general callback format: - def notify_when_callback(nw_code) - In the case of NW_OPENIDB: - def notify_when_callback(nw_code, is_old_database) - @return: Boolean - """ - pass -# -*/ -static bool notify_when(int when, PyObject *py_callable) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( g_nw == NULL || !PyCallable_Check(py_callable) ) - return false; - return g_nw->notify_when(when, py_callable); -} - -// -//------------------------------------------------------------------------ - -#endif diff --git a/pywraps/py_notifywhen.py b/pywraps/py_notifywhen.py deleted file mode 100644 index 4789d9c..0000000 --- a/pywraps/py_notifywhen.py +++ /dev/null @@ -1,63 +0,0 @@ -# ----------------------------------------------------------------------- -# Standalone and testing code -import sys -try: - import pywraps - pywraps_there = True - print "Using pywraps" -except: - pywraps_there = False - print "Not using pywraps" - -try: - import _idaapi -except: - print "Please try me from inside IDA" - sys.exit(0) - -import struct - -if pywraps_there: - _idaapi.notify_when = pywraps.notify_when - -# ----------------------------------------------------------------------- -# -# The general callback format of notify_when() is: -# def notify_when_callback(nw_code) -# In the case of NW_OPENIDB, the callback is: -# def notify_when_callback(nw_code, is_old_database) -NW_OPENIDB = 0x0001 -"""Notify when the database is opened. Its callback is of the form: def notify_when_callback(nw_code, is_old_database)""" -NW_CLOSEIDB = 0x0002 -"""Notify when the database is closed. Its callback is of the form: def notify_when_callback(nw_code)""" -NW_INITIDA = 0x0004 -"""Notify when the IDA starts. Its callback is of the form: def notify_when_callback(nw_code)""" -NW_TERMIDA = 0x0008 -"""Notify when the IDA terminates. Its callback is of the form: def notify_when_callback(nw_code)""" -NW_REMOVE = 0x0010 -"""Use this flag with other flags to uninstall a notifywhen callback""" - -# -# ----------------------------------------------------------------------- - -def nw_openidb(code, old): - print "Open IDB, old=", old - -def nw_closeidb(code): - print "Close IDB" - -def nw_openclose(code, old = None): - if code == NW_CLOSEIDB: - print "openclose: Close IDB" - elif code == NW_OPENIDB: - print "openclose: Open IDB, old=", old - -def nw_closeida(code): - import ctypes - user32 = ctypes.windll.user32 - user32.MessageBoxA(0, "Close IDA", "Info", 0) - -print "registering nw_openidb->", _idaapi.notify_when(NW_OPENIDB, nw_openidb) -print "registering nw_closeidb->", _idaapi.notify_when(NW_CLOSEIDB, nw_closeidb) -print "registering nw_openclose->", _idaapi.notify_when(NW_OPENIDB|NW_CLOSEIDB, nw_openclose) -print "registering nw_closeida->", _idaapi.notify_when(NW_TERMIDA, nw_closeida) diff --git a/pywraps/py_plgform.py b/pywraps/py_plgform.py old mode 100644 new mode 100755 index bddb02f..fe47a1a --- a/pywraps/py_plgform.py +++ b/pywraps/py_plgform.py @@ -49,7 +49,17 @@ class PluginForm(object): @param ctx: Context. Reference to a module that already imported SIP and QtGui modules """ - return ctx.sip.wrapinstance(ctx.sip.voidptr(form).__int__(), ctx.QtGui.QWidget) + 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)) + vptr = ctx.sip.voidptr(ptr_l) + return ctx.sip.wrapinstance(vptr.__int__(), ctx.QtWidgets.QWidget) @staticmethod diff --git a/pywraps/py_segment.hpp b/pywraps/py_segment.hpp new file mode 100644 index 0000000..6078646 --- /dev/null +++ b/pywraps/py_segment.hpp @@ -0,0 +1,47 @@ + +// +void segment_t_startEA_set(segment_t *segm, ea_t newea) +{ + if ( getseg(segm->startEA) == segm ) + { + PyErr_SetString(PyExc_AttributeError, "Can't modify startEA, please use set_segm_start() instead"); + } + else + { + segm->startEA = newea; + } +} + +ea_t segment_t_startEA_get(segment_t *segm) +{ + return segm->startEA; +} + +void segment_t_endEA_set(segment_t *segm, ea_t newea) +{ + if ( getseg(segm->startEA) == segm ) + { + PyErr_SetString(PyExc_AttributeError, "Can't modify endEA, please use set_segm_end() instead"); + } + else + { + segm->endEA = newea; + } +} + +ea_t segment_t_endEA_get(segment_t *segm) +{ + return segm->endEA; +} +// + +// +sel_t get_defsr(segment_t *s, int reg) +{ + return s->defsr[reg]; +} +void set_defsr(segment_t *s, int reg, sel_t value) +{ + s->defsr[reg] = value; +} +// diff --git a/pywraps/py_struct.hpp b/pywraps/py_struct.hpp new file mode 100644 index 0000000..03c278a --- /dev/null +++ b/pywraps/py_struct.hpp @@ -0,0 +1,8 @@ + +#ifndef __PY_STRUCT__ +#define __PY_STRUCT__ + +// +// + +#endif // __PY_STRUCT__ diff --git a/pywraps/py_typeinf.hpp b/pywraps/py_typeinf.hpp index e04c625..9441b2f 100644 --- a/pywraps/py_typeinf.hpp +++ b/pywraps/py_typeinf.hpp @@ -176,7 +176,7 @@ PyObject *py_unpack_object_from_idb( borref_t py_fields_ref(py_fields); // Unpack - type_t *type = (type_t *) PyString_AsString(py_type); + type_t *type = (type_t *) PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); idc_value_t idc_obj; error_t err; @@ -244,7 +244,7 @@ PyObject *py_unpack_object_from_bv( borref_t py_fields_ref(py_fields); // Get type strings - type_t *type = (type_t *) PyString_AsString(py_type); + type_t *type = (type_t *) PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); // Make a byte vector @@ -322,7 +322,7 @@ PyObject *py_pack_object_to_idb( borref_t py_fields_ref(py_fields); // Get type strings - type_t *type = (type_t *)PyString_AsString(py_type); + type_t *type = (type_t *)PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); // Pack @@ -379,7 +379,7 @@ PyObject *py_pack_object_to_bv( borref_t py_fields_ref(py_fields); // Get type strings - type_t *type = (type_t *)PyString_AsString(py_type); + type_t *type = (type_t *)PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); // Pack @@ -409,8 +409,8 @@ int idc_parse_types(const char *input, int flags) { int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT; - if ((flags & 1) != 0) - hti |= HTI_FIL; + if ( (flags & 1) != 0 ) + hti |= HTI_FIL; return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti); } @@ -471,7 +471,7 @@ char *idc_get_type(ea_t ea, char *buf, size_t bufsize) //------------------------------------------------------------------------- int idc_set_local_type(int ordinal, const char *dcl, int flags) { - if (dcl == NULL || dcl[0] == '\0') + if ( dcl == NULL || dcl[0] == '\0' ) { if ( !del_numbered_type(idati, ordinal) ) return 0; @@ -650,6 +650,25 @@ int py_print_decls(text_sink_t &printer, til_t *til, PyObject *py_ordinals, uint return print_decls(printer, til, ordinals.empty() ? NULL : &ordinals, flags); } +//------------------------------------------------------------------------- +til_t *load_til(const char *tildir, const char *name) +{ + char errbuf[MAXSTR]; + til_t *res = load_til(tildir, name, errbuf, sizeof(errbuf)); + if ( res == NULL ) + PyErr_SetString(PyExc_RuntimeError, errbuf); + return res; +} + +//------------------------------------------------------------------------- +til_t *load_til_header_wrap(const char *tildir, const char *name) +{ + char errbuf[MAXSTR]; + til_t *res = load_til_header(tildir, name, errbuf, sizeof(errbuf)); + if ( res == NULL ) + PyErr_SetString(PyExc_RuntimeError, errbuf); + return res; +} // // diff --git a/pywraps/py_ua.hpp b/pywraps/py_ua.hpp index 0189435..556121d 100644 --- a/pywraps/py_ua.hpp +++ b/pywraps/py_ua.hpp @@ -186,7 +186,7 @@ bool py_apply_type_to_stkarg( uint64 v; PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *op = op_t_get_clink(py_op); - if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type)) + if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type) ) { return false; } @@ -393,7 +393,7 @@ static bool op_t_assign(PyObject *self, PyObject *other) PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *lhs = op_t_get_clink(self); op_t *rhs = op_t_get_clink(other); - if (lhs == NULL || rhs == NULL) + if ( lhs == NULL || rhs == NULL ) return false; *lhs = *rhs; @@ -406,7 +406,7 @@ static bool insn_t_assign(PyObject *self, PyObject *other) PYW_GIL_CHECK_LOCKED_SCOPE(); insn_t *lhs = insn_t_get_clink(self); insn_t *rhs = insn_t_get_clink(other); - if (lhs == NULL || rhs == NULL) + if ( lhs == NULL || rhs == NULL ) return false; *lhs = *rhs; diff --git a/pywraps/py_view_base.hpp b/pywraps/py_view.hpp similarity index 91% rename from pywraps/py_view_base.hpp rename to pywraps/py_view.hpp index 858a12b..4d78738 100644 --- a/pywraps/py_view_base.hpp +++ b/pywraps/py_view.hpp @@ -1,8 +1,5 @@ -#ifndef __PY_VIEW_BASE__ -#define __PY_VIEW_BASE__ - -// +// //------------------------------------------------------------------------- class py_customidamemo_t; class lookup_info_t @@ -145,15 +142,6 @@ class py_customidamemo_t protected: ref_t self; TCustomControl *view; - // This is called after having modified the - // node properties in the IDB. In case an - // implementation is performing some caching, - // this is a chance to update that cache. - // If 'ni' is NULL, then the node info was deleted. - virtual void node_info_modified( - int /*n*/, - const node_info_t * /*ni*/, - uint32 /*flags*/) {} struct callback_id_t { @@ -332,7 +320,6 @@ void py_customidamemo_t::set_node_info( int idx = PyInt_AsLong(py_idx.o); uint32 flgs = PyLong_AsLong(py_fl.o); viewer_set_node_info(view, idx, ni, flgs); - node_info_modified(idx, &ni, flgs); } //------------------------------------------------------------------------- @@ -353,7 +340,6 @@ void py_customidamemo_t::set_nodes_infos(PyObject *dict) convert_node_info(&ni, &flags, value); int idx = PyInt_AsLong(key.o); viewer_set_node_info(view, idx, ni, flags); - node_info_modified(idx, &ni, flags); } } @@ -381,7 +367,6 @@ void py_customidamemo_t::del_nodes_infos(PyObject *py_nodes) continue; int idx = PyInt_AsLong(item.o); viewer_del_node_info(view, idx); - node_info_modified(idx, NULL, 0); } } @@ -584,9 +569,9 @@ bool py_customidamemo_t::collect_pyobject_callbacks(PyObject *o) ref_t attr(PyW_TryGetAttrString(o, cbid.name.c_str())); int have = cbid.have; // Mandatory fields not present? - if ( (attr == NULL && have <= 0 ) + if ( (attr == NULL && have <= 0) // Mandatory callback fields present but not callable? - || (attr != NULL && have >= 0 && PyCallable_Check(attr.o) == 0)) + || (attr != NULL && have >= 0 && PyCallable_Check(attr.o) == 0) ) { return false; } @@ -845,7 +830,7 @@ void py_customidamemo_t::on_view_mouse_moved(const view_mouse_event_t *event) #define CHK_THIS() \ GET_THIS(); \ if ( _this == NULL ) \ - return + return; #define CHK_THIS_OR_NULL() \ GET_THIS(); \ if ( _this == NULL ) \ @@ -958,9 +943,94 @@ TCustomControl *pycim_get_tcustom_control(PyObject *self) //------------------------------------------------------------------------- lookup_info_t py_customidamemo_t::lookup_info; -// -// +//------------------------------------------------------------------------- +// py_idaview_t +//------------------------------------------------------------------------- +class py_idaview_t : public py_customidamemo_t +{ + typedef py_customidamemo_t inherited; + +public: + static bool Bind(PyObject *self); + static bool Unbind(PyObject *self); +}; + +//------------------------------------------------------------------------- +bool py_idaview_t::Bind(PyObject *self) +{ + // Already a py_idaview_t associated to this object? + py_idaview_t *_this = view_extract_this(self); + if ( _this != NULL ) + return false; + + qstring title; + if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) ) + return false; + + // Get the IDAView associated to this TForm + TForm *tform = find_tform(title.c_str()); + if ( tform == NULL ) + return false; + TCustomControl *v = get_tform_idaview(tform); + if ( v == NULL ) + return false; + + // Get unique py_idaview_t associated to that tform + py_idaview_t *py_view; + TCustomControl *found_view; + if ( lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) ) + { + // If we have a py_idaview_t for that form, ensure it has + // the expected view. + QASSERT(30451, found_view == v); + } + else + { + py_view = new py_idaview_t(); + lookup_info_t::entry_t &e = lookup_info.new_entry(py_view); + lookup_info.commit(e, tform, v); + } + + // Finally, bind: + // py_idaview_t <=> IDAViewWrapper + // py_idaview_t => TCustomControl + bool ok = py_view->bind(self, v); + if ( ok ) + { + ok = py_view->collect_pyobject_callbacks(self); + if ( ok ) + py_view->install_custom_viewer_handlers(); + else + delete py_view; + } + return ok; +} + +//------------------------------------------------------------------------- +bool py_idaview_t::Unbind(PyObject *self) +{ + py_idaview_t *_this = view_extract_this(self); + if ( _this == NULL ) + return false; + _this->unbind(true); + return true; +} + +//------------------------------------------------------------------------- +bool pyidag_bind(PyObject *self) +{ + return py_idaview_t::Bind(self); +} + +//------------------------------------------------------------------------- +bool pyidag_unbind(PyObject *self) +{ + return py_idaview_t::Unbind(self); +} +// + +// void pygc_refresh(PyObject *self); void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags); void pygc_set_nodes_infos(PyObject *self, PyObject *values); @@ -973,9 +1043,10 @@ PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_cur PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current); TForm *pycim_get_tform(PyObject *self); TCustomControl *pycim_get_tcustom_control(PyObject *self); -// - - - -#endif // __PY_VIEW_BASE__ +//------------------------------------------------------------------------- +// py_idaview_t +//------------------------------------------------------------------------- +bool pyidag_bind(PyObject *self); +bool pyidag_unbind(PyObject *self); +// diff --git a/pywraps/py_view_base.py b/pywraps/py_view.py similarity index 84% rename from pywraps/py_view_base.py rename to pywraps/py_view.py index 2d68c93..b2d22d5 100644 --- a/pywraps/py_view_base.py +++ b/pywraps/py_view.py @@ -1,5 +1,5 @@ -# +# class CustomIDAMemo(object): def Refresh(self): """ @@ -121,4 +121,24 @@ class CustomIDAMemo(object): return _idaapi.pycim_get_tcustom_control(self) -# +#------------------------------------------------------------------------- +# IDAViewWrapper +#------------------------------------------------------------------------- +class IDAViewWrapper(CustomIDAMemo): + """This class wraps access to native IDA views. See kernwin.hpp file""" + def __init__(self, title): + """ + Constructs the IDAViewWrapper object around the view + whose title is 'title'. + + @param title: The title of the existing IDA view. E.g., 'IDA View-A' + """ + self._title = title + + def Bind(self): + return _idaapi.pyidag_bind(self) + + def Unbind(self): + return _idaapi.pyidag_unbind(self) + +# diff --git a/pywraps/readme.txt b/pywraps/readme.txt deleted file mode 100644 index dfc562d..0000000 --- a/pywraps/readme.txt +++ /dev/null @@ -1,116 +0,0 @@ -============================ -deploy.py - usage -============================ - -The deploy script is used to deploy python and c++ code into SWIG interface files appropriately. -The reason it was created was because working with .i files to put a mixture of C++ and Python code is not practical for testing and development process. - -In SWIG, there are three sections: - -Inline ---------- - -C++ code will be wrapped by SWIG. - -In SWIG .i files the inline code is marked with: - %inline %{ - C++ code - %} - -In deploy.py supporting files the code to be pasted into .i files is marked with: - // - C++ code - // - - -Code -------- -C++ code will be pasted and compiled into the wrapped module but will not be wrapped by SWIG. - -In SWIG .i files the code is marked with: - %{ - C++ code - %} - -Similarly, for deploy.py supporting files should be marked with: - // - C++ code - // - -Pythoncode --------------- - -Python code allows you to insert Python code into the final Python module. - -In SWIG .i files, the extra python code is marked with: - %pythoncode %{ - Py code - %} - -In deploy.py supporting python files, it is marked with: - # - Py code - # - -Using deploy.py ------------------- -Make sure that all of the 3 code markers exist in the interface files and deploy.py support files (C++ or Python). - -As an example, let us interpret the meaning of: - deploy.py py_idaapi py_idaapi.hpp,py_idaapi.py ..\swig\idaapi.i -It means: - NAME = py_idaapi - ...take code snips from py_idaapi.hpp and py_idaapi.py - ...and paste the code there into idaapi.i SWIG interface file - -Now remember that both the input files have the special markers (discussed above) and so does idaapi.i file - - -============================ -linkgen.py - usage -============================ -TODO - - -============================ -swigdocs.py - usage -============================ - -The swigdocs script will extract python comments from SWIG interface files (*.i). - -There are two places where Python code documentation can be found: - 1. In the "%pythoncode %{" section, we extract all the python code because it could contain docstrings. - Inside the pythoncode section, one can find embedded commented that are commented out. - Because they are commented out, the documentation generator will miss them. The swigdocs script will remove the comment character: -# -# def OnClose(self): -# """ -# Called when the window is being closed. -# This callback is mandatory. -# @return: nothing -# """ -# pass -# - After swigdocs finishes, the output will contain all the python code and all the commented code (now uncommented). - - 2. In the "%inline %{" section (in C++ code), one can find functions comments like this: -/* -# -def dbg_read_memory(ea, sz): - """ - Reads from the debugee's memory at the specified ea - @return: - - The read buffer (as a string) - - Or None on failure - """ - pass -# -*/ -static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) -{ - ...... -} - In this case, the code inside tag will be extracted as well. - - -After swigdocs finishes, the output is a Python file containing all code and comments extracted from the *.i file(s). \ No newline at end of file diff --git a/pywraps/sidaapi.py b/pywraps/sidaapi.py old mode 100644 new mode 100755 diff --git a/pywraps/sidc.py b/pywraps/sidc.py old mode 100644 new mode 100755 diff --git a/pywraps/swig_stub.cpp b/pywraps/swig_stub.cpp deleted file mode 100644 index 343a24e..0000000 --- a/pywraps/swig_stub.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "swig_stub.h" - -PyObject *SWIG_NewPointerObj(void *ptr, void *type, int flags) -{ - return PyCObject_FromVoidPtr(ptr, NULL); -} diff --git a/pywraps/swig_stub.h b/pywraps/swig_stub.h deleted file mode 100644 index 0880d15..0000000 --- a/pywraps/swig_stub.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __SWIG_STUB__ -#define __SWIG_STUB__ - -#include - -#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) - -PyObject *SWIG_NewPointerObj(void *ptr, void *type, int flags); - -namespace Swig -{ - class DirectorException - { - public: - const char *getMessage() const - { - return "NULL"; - } - }; -} - -#define SWIG_RUNTIME_VERSION "4" - -// Some fake SWIG types -#define SWIGTYPE_p_member_t NULL - -#endif \ No newline at end of file diff --git a/swig/askusingform.i b/swig/askusingform.i new file mode 100644 index 0000000..17f24e3 --- /dev/null +++ b/swig/askusingform.i @@ -0,0 +1,17 @@ + +// relies on kernwin.i to include kernwin.hpp + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/bytes.i b/swig/bytes.i index 522d552..0c3018d 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -49,7 +49,13 @@ %ignore unlock_dbgmem_config; %ignore set_op_type_no_event; %ignore shuffle_tribytes; +%ignore set_stroff_path; +%ignore del_stroff_path; %ignore set_enum_id; +%ignore del_enum_id; +%ignore enum_encode; +%ignore enum_decode; +%ignore mark_dirty_tof; %ignore validate_tofs; %ignore set_flags_nomark; %ignore set_flbits_nomark; @@ -58,6 +64,8 @@ %ignore ida_vpages; %ignore ida_npagesize; %ignore ida_npages; +%ignore max_cache_count; + %ignore fpnum_digits; %ignore fpnum_length; %ignore FlagsInit; @@ -79,6 +87,7 @@ %ignore get_many_bytes; %ignore get_ascii_contents; %ignore get_ascii_contents2; +%ignore get_hex_string; // TODO: This could be fixed (if needed) %ignore set_dbgmem_source; @@ -105,1121 +114,15 @@ %rename (get_ascii_contents2) py_get_ascii_contents2; %{ // -//------------------------------------------------------------------------ -static bool idaapi py_testf_cb(flags_t flags, void *ud) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_flags(PyLong_FromUnsignedLong(flags)); - newref_t result(PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags.o, NULL)); - return result != NULL && PyObject_IsTrue(result.o); -} - -//------------------------------------------------------------------------ -// Wraps the (next|prev)that() -static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCallable_Check(py_callable) ) - return BADADDR; - else - return (next ? nextthat : prevthat)(ea, bound, py_testf_cb, py_callable); -} - -//--------------------------------------------------------------------------- -static int idaapi py_visit_patched_bytes_cb( - ea_t ea, - int32 fpos, - uint32 o, - uint32 v, - void *ud) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result( - PyObject_CallFunction( - (PyObject *)ud, - PY_FMT64 "iII", - pyul_t(ea), - fpos, - o, - v)); - PyW_ShowCbErr("visit_patched_bytes"); - return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0; -} - - - -//------------------------------------------------------------------------ -class py_custom_data_type_t -{ - data_type_t dt; - qstring dt_name, dt_menu_name, dt_hotkey, dt_asm_keyword; - int dtid; // The data format id - PyObject *py_self; // Associated Python object - - // may create data? NULL means always may - static bool idaapi s_may_create_at( - void *ud, // user-defined data - ea_t ea, // address of the future item - size_t nbytes) // size of the future item - { - py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; - - PYW_GIL_GET; - newref_t py_result( - PyObject_CallMethod( - _this->py_self, - (char *)S_MAY_CREATE_AT, - PY_FMT64 PY_FMT64, - pyul_t(ea), - pyul_t(nbytes))); - - PyW_ShowCbErr(S_MAY_CREATE_AT); - return py_result != NULL && PyObject_IsTrue(py_result.o); - } - - // !=NULL means variable size datatype - static asize_t idaapi s_calc_item_size( - // This function is used to determine - // size of the (possible) item at 'ea' - void *ud, // user-defined data - ea_t ea, // address of the item - asize_t maxsize) // maximal size of the item - { - PYW_GIL_GET; - // Returns: 0-no such item can be created/displayed - // this callback is required only for varsize datatypes - py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; - newref_t py_result( - PyObject_CallMethod( - _this->py_self, - (char *)S_CALC_ITEM_SIZE, - PY_FMT64 PY_FMT64, - pyul_t(ea), - pyul_t(maxsize))); - - if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL ) - return 0; - - uint64 num = 0; - PyW_GetNumber(py_result.o, &num); - return asize_t(num); - } - -public: - const char *get_name() const - { - return dt_name.c_str(); - } - - py_custom_data_type_t() - { - dtid = -1; - py_self = NULL; - } - - int register_dt(PyObject *py_obj) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Already registered? - if ( dtid >= 0 ) - return dtid; - - memset(&dt, 0, sizeof(dt)); - dt.cbsize = sizeof(dt); - dt.ud = this; - - do - { - ref_t py_attr; - - // name - if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) ) - break; - - dt.name = dt_name.c_str(); - - // menu_name (optional) - if ( PyW_GetStringAttr(py_obj, S_MENU_NAME, &dt_menu_name) ) - dt.menu_name = dt_menu_name.c_str(); - - // asm_keyword (optional) - if ( PyW_GetStringAttr(py_obj, S_ASM_KEYWORD, &dt_asm_keyword) ) - dt.asm_keyword = dt_asm_keyword.c_str(); - - // hotkey (optional) - if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &dt_hotkey) ) - dt.hotkey = dt_hotkey.c_str(); - - // value_size - py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - dt.value_size = PyInt_AsLong(py_attr.o); - py_attr = ref_t(); - - // props - py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - dt.props = PyInt_AsLong(py_attr.o); - py_attr = ref_t(); - - // may_create_at - py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - dt.may_create_at = s_may_create_at; - py_attr = ref_t(); - - // calc_item_size - py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - dt.calc_item_size = s_calc_item_size; - py_attr = ref_t(); - - // Now try to register - dtid = register_custom_data_type(&dt); - if ( dtid < 0 ) - break; - - // Hold reference to the PyObject - Py_INCREF(py_obj); - py_self = py_obj; - - py_attr = newref_t(PyInt_FromLong(dtid)); - PyObject_SetAttrString(py_obj, S_ID, py_attr.o); - } while ( false ); - return dtid; - } - - bool unregister_dt() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( dtid < 0 ) - return true; - - if ( !unregister_custom_data_type(dtid) ) - return false; - - // Release reference of Python object - Py_XDECREF(py_self); - py_self = NULL; - dtid = -1; - return true; - } - - ~py_custom_data_type_t() - { - unregister_dt(); - } -}; -typedef std::map py_custom_data_type_map_t; -static py_custom_data_type_map_t py_dt_map; - -//------------------------------------------------------------------------ -class py_custom_data_format_t -{ -private: - data_format_t df; - int dfid; - PyObject *py_self; - qstring df_name, df_menu_name, df_hotkey; - - static bool idaapi s_print( // convert to colored string - void *ud, // user-defined data - qstring *out, // output buffer. may be NULL - const void *value, // value to print. may not be NULL - asize_t size, // size of value in bytes - ea_t current_ea, // current address (BADADDR if unknown) - int operand_num, // current operand number - int dtid) // custom data type id - { - PYW_GIL_GET; - - // Build a string from the buffer - newref_t py_value(PyString_FromStringAndSize( - (const char *)value, - Py_ssize_t(size))); - if ( py_value == NULL ) - return false; - - py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; - newref_t py_result(PyObject_CallMethod( - _this->py_self, - (char *)S_PRINTF, - "O" PY_FMT64 "ii", - py_value.o, - pyul_t(current_ea), - operand_num, - dtid)); - - // Error while calling the function? - if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL ) - return false; - - bool ok = false; - if ( PyString_Check(py_result.o) ) - { - Py_ssize_t len; - char *buf; - if ( out != NULL && PyString_AsStringAndSize(py_result.o, &buf, &len) != -1 ) - { - out->qclear(); - out->append(buf, len); - } - ok = true; - } - return ok; - } - - static bool idaapi s_scan( // convert from uncolored string - void *ud, // user-defined data - bytevec_t *value, // output buffer. may be NULL - const char *input, // input string. may not be NULL - ea_t current_ea, // current address (BADADDR if unknown) - int operand_num, // current operand number (-1 if unknown) - qstring *errstr) // buffer for error message - { - PYW_GIL_GET; - - py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; - newref_t py_result( - PyObject_CallMethod( - _this->py_self, - (char *)S_SCAN, - "s" PY_FMT64, - input, - pyul_t(current_ea), - operand_num)); - - // Error while calling the function? - if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL) - return false; - - bool ok = false; - do - { - // We expect a tuple(bool, string|None) - if ( !PyTuple_Check(py_result.o) || PyTuple_Size(py_result.o) != 2 ) - break; - - borref_t py_bool(PyTuple_GetItem(py_result.o, 0)); - borref_t py_val(PyTuple_GetItem(py_result.o, 1)); - - // Get return code from Python - ok = PyObject_IsTrue(py_bool.o); - - // We expect None or the value (depending on probe) - if ( ok ) - { - // Probe-only? Then okay, no need to extract the 'value' - if ( value == NULL ) - break; - - Py_ssize_t len; - char *buf; - if ( PyString_AsStringAndSize(py_val.o, &buf, &len) != -1 ) - { - value->qclear(); - value->append(buf, len); - } - } - // An error occured? - else - { - // Make sure the user returned (False, String) - if ( py_bool.o != Py_False || !PyString_Check(py_val.o) ) - { - *errstr = "Invalid return value returned from the Python callback!"; - break; - } - // Get the error message - *errstr = PyString_AsString(py_val.o); - } - } while ( false ); - return ok; - } - - static void idaapi s_analyze( // analyze custom data format occurrence - void *ud, // user-defined data - ea_t current_ea, // current address (BADADDR if unknown) - int operand_num) // current operand number - // this callback can be used to create - // xrefs from the current item. - // this callback may be missing. - { - PYW_GIL_GET; - - py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; - newref_t py_result( - PyObject_CallMethod( - _this->py_self, - (char *)S_ANALYZE, - PY_FMT64 "i", - pyul_t(current_ea), - operand_num)); - - PyW_ShowCbErr(S_ANALYZE); - } -public: - py_custom_data_format_t() - { - dfid = -1; - py_self = NULL; - } - - const char *get_name() const - { - return df_name.c_str(); - } - - int register_df(int dtid, PyObject *py_obj) - { - // Already registered? - if ( dfid >= 0 ) - return dfid; - - memset(&df, 0, sizeof(df)); - df.cbsize = sizeof(df); - df.ud = this; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - ref_t py_attr; - - // name - if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) ) - break; - df.name = df_name.c_str(); - - // menu_name (optional) - if ( PyW_GetStringAttr(py_obj, S_MENU_NAME, &df_menu_name) ) - df.menu_name = df_menu_name.c_str(); - - // props - py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - df.props = PyInt_AsLong(py_attr.o); - - // hotkey - if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) ) - df.hotkey = df_hotkey.c_str(); - - // value_size - py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - df.value_size = PyInt_AsLong(py_attr.o); - - // text_width - py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - df.text_width = PyInt_AsLong(py_attr.o); - - // print cb - py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - df.print = s_print; - - // scan cb - py_attr = PyW_TryGetAttrString(py_obj, S_SCAN); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - df.scan = s_scan; - - // analyze cb - py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - df.analyze = s_analyze; - - // Now try to register - dfid = register_custom_data_format(dtid, &df); - if ( dfid < 0 ) - break; - - // Hold reference to the PyObject - Py_INCREF(py_obj); - py_self = py_obj; - - // Update the format ID - py_attr = newref_t(PyInt_FromLong(dfid)); - PyObject_SetAttrString(py_obj, S_ID, py_attr.o); - } while ( false ); - return dfid; - } - - bool unregister_df(int dtid) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Never registered? - if ( dfid < 0 ) - return true; - - if ( !unregister_custom_data_format(dtid, dfid) ) - return false; - - // Release reference of Python object - Py_XDECREF(py_self); - py_self = NULL; - dfid = -1; - return true; - } - - ~py_custom_data_format_t() - { - } -}; - -//------------------------------------------------------------------------ -// Helper class to bind pairs to py_custom_data_format_t -class py_custom_data_format_list_t -{ - struct py_custom_data_format_entry_t - { - int dtid; - int dfid; - py_custom_data_format_t *df; - }; - typedef qvector ENTRY; - ENTRY entries; -public: - typedef ENTRY::iterator POS; - void add(int dtid, int dfid, py_custom_data_format_t *df) - { - py_custom_data_format_entry_t &e = entries.push_back(); - e.dtid = dtid; - e.dfid = dfid; - e.df = df; - } - py_custom_data_format_t *find(int dtid, int dfid, POS *loc = NULL) - { - for ( POS it=entries.begin(), it_end = entries.end(); it!=it_end; ++it ) - { - if ( it->dfid == dfid && it->dtid == dtid ) - { - if ( loc != NULL ) - *loc = it; - return it->df; - } - } - return NULL; - } - void erase(POS &pos) - { - entries.erase(pos); - } -}; -static py_custom_data_format_list_t py_df_list; - -//------------------------------------------------------------------------ -static PyObject *py_data_type_to_py_dict(const data_type_t *dt) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - return Py_BuildValue("{s:" PY_FMT64 ",s:i,s:i,s:s,s:s,s:s,s:s}", - S_VALUE_SIZE, pyul_t(dt->value_size), - S_PROPS, dt->props, - S_CBSIZE, dt->cbsize, - S_NAME, dt->name == NULL ? "" : dt->name, - S_MENU_NAME, dt->menu_name == NULL ? "" : dt->menu_name, - S_HOTKEY, dt->hotkey == NULL ? "" : dt->hotkey, - S_ASM_KEYWORD, dt->asm_keyword == NULL ? "" : dt->asm_keyword); -} - -//------------------------------------------------------------------------ -static PyObject *py_data_format_to_py_dict(const data_format_t *df) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - return Py_BuildValue("{s:i,s:i,s:i,s:" PY_FMT64 ",s:s,s:s,s:s}", - S_PROPS, df->props, - S_CBSIZE, df->cbsize, - S_TEXT_WIDTH, df->text_width, - S_VALUE_SIZE, pyul_t(df->value_size), - S_NAME, df->name == NULL ? "" : df->name, - S_MENU_NAME, df->menu_name == NULL ? "" : df->menu_name, - S_HOTKEY, df->hotkey == NULL ? "" : df->hotkey); -} // %} %inline %{ // - -//------------------------------------------------------------------------ -/* -# -def visit_patched_bytes(ea1, ea2, callable): - """ - Enumerates patched bytes in the given range and invokes a callable - @param ea1: start address - @param ea2: end address - @param callable: a Python callable with the following prototype: - callable(ea, fpos, org_val, patch_val). - If the callable returns non-zero then that value will be - returned to the caller and the enumeration will be - interrupted. - @return: Zero if the enumeration was successful or the return - value of the callback if enumeration was interrupted. - """ - pass -# -*/ -static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCallable_Check(py_callable) ) - return 0; - else - return visit_patched_bytes(ea1, ea2, py_visit_patched_bytes_cb, py_callable); -} - -//------------------------------------------------------------------------ -/* -# -def nextthat(ea, maxea, callable): - """ - Find next address with a flag satisfying the function 'testf'. - Start searching from address 'ea'+1 and inspect bytes up to 'maxea'. - maxea is not included in the search range. - - @param callable: a Python callable with the following prototype: - callable(flags). Return True to stop enumeration. - @return: the found address or BADADDR. - """ - pass -# -*/ -static ea_t py_nextthat(ea_t ea, ea_t maxea, PyObject *callable) -{ - return py_npthat(ea, maxea, callable, true); -} - -//--------------------------------------------------------------------------- -static ea_t py_prevthat(ea_t ea, ea_t minea, PyObject *callable) -{ - return py_npthat(ea, minea, callable, false); -} - -//------------------------------------------------------------------------ -/* -# -def get_many_bytes(ea, size): - """ - Get the specified number of bytes of the program into the buffer. - @param ea: program address - @param size: number of bytes to return - @return: None or the string buffer - """ - pass -# -*/ -static PyObject *py_get_many_bytes(ea_t ea, unsigned int size) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - if ( size <= 0 ) - break; - - // Allocate memory via Python - newref_t py_buf(PyString_FromStringAndSize(NULL, Py_ssize_t(size))); - if ( py_buf == NULL ) - break; - - // Read bytes - if ( !get_many_bytes(ea, PyString_AsString(py_buf.o), size) ) - Py_RETURN_NONE; - - py_buf.incref(); - return py_buf.o; - } while ( false ); - Py_RETURN_NONE; -} - -//--------------------------------------------------------------------------- -/* -# -# Conversion options for get_ascii_contents2(): -ACFOPT_ASCII = 0x00000000 # convert Unicode strings to ASCII -ACFOPT_UTF16 = 0x00000001 # return UTF-16 (aka wide-char) array for Unicode strings - # ignored for non-Unicode strings -ACFOPT_UTF8 = 0x00000002 # convert Unicode strings to UTF-8 - # ignored for non-Unicode strings -ACFOPT_CONVMASK = 0x0000000F -ACFOPT_ESCAPE = 0x00000010 # for ACFOPT_ASCII, convert non-printable - # characters to C escapes (\n, \xNN, \uNNNN) - -def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII): - """ - Get bytes contents at location, possibly converted. - It works even if the string has not been created in the database yet. - - Note that this will always return a simple string of bytes - (i.e., a 'str' instance), and not a string of unicode characters. - - If you want auto-conversion to unicode strings (that is: real strings), - you should probably be using the idautils.Strings class. - - @param ea: linear address of the string - @param len: length of the string in bytes (including terminating 0) - @param type: type of the string. Represents both the character encoding, - and the 'type' of string at the given location. - @param flags: combination of ACFOPT_..., to perform output conversion. - @return: a bytes-filled str object. - """ - pass -# -*/ -static PyObject *py_get_ascii_contents2( - ea_t ea, - size_t len, - int32 type, - int flags = ACFOPT_ASCII) -{ - char *buf = (char *)qalloc(len+1); - if ( buf == NULL ) - return NULL; - - size_t used_size; - if ( !get_ascii_contents2(ea, len, type, buf, len+1, &used_size, flags) ) - { - qfree(buf); - Py_RETURN_NONE; - } - if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' ) - used_size--; - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_buf(PyString_FromStringAndSize((const char *)buf, used_size)); - qfree(buf); - py_buf.incref(); - return py_buf.o; -} -//--------------------------------------------------------------------------- -/* -# -def get_ascii_contents(ea, len, type): - """ - Get contents of ascii string - This function returns the displayed part of the string - It works even if the string has not been created in the database yet. - - @param ea: linear address of the string - @param len: length of the string in bytes (including terminating 0) - @param type: type of the string - @return: string contents (not including terminating 0) or None - """ - pass -# -*/ -static PyObject *py_get_ascii_contents( - ea_t ea, - size_t len, - int32 type) -{ - return py_get_ascii_contents2(ea, len, type); -} - - - -//------------------------------------------------------------------------ -/* -# -def register_custom_data_type(dt): - """ - Registers a custom data type. - @param dt: an instance of the data_type_t class - @return: - < 0 if failed to register - > 0 data type id - """ - pass -# -*/ -// Given a py.data_format_t object, this function will register a datatype -static int py_register_custom_data_type(PyObject *py_dt) -{ - py_custom_data_type_t *inst = new py_custom_data_type_t(); - int r = inst->register_dt(py_dt); - if ( r < 0 ) - { - delete inst; - return r; - } - // Insert the instance to the map - py_dt_map[r] = inst; - return r; -} - -//------------------------------------------------------------------------ -/* -# -def unregister_custom_data_type(dtid): - """ - Unregisters a custom data type. - @param dtid: the data type id - @return: Boolean - """ - pass -# -*/ -static bool py_unregister_custom_data_type(int dtid) -{ - py_custom_data_type_map_t::iterator it = py_dt_map.find(dtid); - - // Maybe the user is trying to unregister a C api dt? - if ( it == py_dt_map.end() ) - return unregister_custom_data_type(dtid); - - py_custom_data_type_t *inst = it->second; - bool ok = inst->unregister_dt(); - - // Perhaps it was automatically unregistered because the idb was close? - if ( !ok ) - { - // Is this type still registered with IDA? - // If not found then mark the context for deletion - ok = find_custom_data_type(inst->get_name()) < 0; - } - - if ( ok ) - { - py_dt_map.erase(it); - delete inst; - } - return ok; -} - -//------------------------------------------------------------------------ -/* -# -def register_custom_data_format(dtid, df): - """ - Registers a custom data format with a given data type. - @param dtid: data type id - @param df: an instance of data_format_t - @return: - < 0 if failed to register - > 0 data format id - """ - pass -# -*/ -static int py_register_custom_data_format(int dtid, PyObject *py_df) -{ - py_custom_data_format_t *inst = new py_custom_data_format_t(); - int r = inst->register_df(dtid, py_df); - if ( r < 0 ) - { - delete inst; - return r; - } - // Insert the instance - py_df_list.add(dtid, r, inst); - return r; -} - -//------------------------------------------------------------------------ -/* -# -def unregister_custom_data_format(dtid, dfid): - """ - Unregisters a custom data format - @param dtid: data type id - @param dfid: data format id - @return: Boolean - """ - pass -# -*/ -static bool py_unregister_custom_data_format(int dtid, int dfid) -{ - py_custom_data_format_list_t::POS pos; - py_custom_data_format_t *inst = py_df_list.find(dtid, dfid, &pos); - // Maybe the user is trying to unregister a C api data format? - if ( inst == NULL ) - return unregister_custom_data_format(dtid, dfid); - - bool ok = inst->unregister_df(dtid); - - // Perhaps it was automatically unregistered because the type was unregistered? - if ( !ok ) - { - // Is this format still registered with IDA? - // If not, mark the context for deletion - ok = find_custom_data_format(inst->get_name()) < 0; - } - - if ( ok ) - { - py_df_list.erase(pos); - delete inst; - } - return ok; -} - -//------------------------------------------------------------------------ -/* -# -def get_custom_data_format(dtid, dfid): - """ - Returns a dictionary populated with the data format values or None on failure. - @param dtid: data type id - @param dfid: data format id - """ - pass -# -*/ -// Get definition of a registered custom data format and returns a dictionary -static PyObject *py_get_custom_data_format(int dtid, int fid) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - const data_format_t *df = get_custom_data_format(dtid, fid); - if ( df == NULL ) - Py_RETURN_NONE; - return py_data_format_to_py_dict(df); -} - -//------------------------------------------------------------------------ -/* -# -def get_custom_data_type(dtid): - """ - Returns a dictionary populated with the data type values or None on failure. - @param dtid: data type id - """ - pass -# -*/ -// Get definition of a registered custom data format and returns a dictionary -static PyObject *py_get_custom_data_type(int dtid) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - const data_type_t *dt = get_custom_data_type(dtid); - if ( dt == NULL ) - Py_RETURN_NONE; - return py_data_type_to_py_dict(dt); -} - // %} %pythoncode %{ # -DTP_NODUP = 0x0001 - -class data_type_t(object): - """ - Custom data type definition. All data types should inherit from this class. - """ - - def __init__(self, name, value_size = 0, menu_name = None, hotkey = None, asm_keyword = None, props = 0): - """Please refer to bytes.hpp / data_type_t in the SDK""" - self.name = name - self.props = props - self.menu_name = menu_name - self.hotkey = hotkey - self.asm_keyword = asm_keyword - self.value_size = value_size - - self.id = -1 # Will be initialized after registration - """Contains the data type id after the data type is registered""" - - def register(self): - """Registers the data type and returns the type id or < 0 on failure""" - return _idaapi.register_custom_data_type(self) - - def unregister(self): - """Unregisters the data type and returns True on success""" - # Not registered? - if self.id < 0: - return True - - # Try to unregister - r = _idaapi.unregister_custom_data_type(self.id) - - # Clear the ID - if r: - self.id = -1 - return r -# -# def may_create_at(self, ea, nbytes): -# """ -# (optional) If this callback is not defined then this means always may create data type at the given ea. -# @param ea: address of the future item -# @param nbytes: size of the future item -# @return: Boolean -# """ -# -# return False -# -# def calc_item_size(self, ea, maxsize): -# """ -# (optional) If this callback is defined it means variable size datatype -# This function is used to determine size of the (possible) item at 'ea' -# @param ea: address of the item -# @param maxsize: maximal size of the item -# @return: integer -# Returns: 0-no such item can be created/displayed -# this callback is required only for varsize datatypes -# """ -# return 0 -# -# ----------------------------------------------------------------------- -# Uncomment the corresponding callbacks in the inherited class -class data_format_t(object): - """Information about a data format""" - def __init__(self, name, value_size = 0, menu_name = None, props = 0, hotkey = None, text_width = 0): - """Custom data format definition. - @param name: Format name, must be unique - @param menu_name: Visible format name to use in menus - @param props: properties (currently 0) - @param hotkey: Hotkey for the corresponding menu item - @param value_size: size of the value in bytes. 0 means any size is ok - @text_width: Usual width of the text representation - """ - self.name = name - self.menu_name = menu_name - self.props = props - self.hotkey = hotkey - self.value_size = value_size - self.text_width = text_width - - self.id = -1 # Will be initialized after registration - """contains the format id after the format gets registered""" - - def register(self, dtid): - """Registers the data format with the given data type id and returns the type id or < 0 on failure""" - return _idaapi.register_custom_data_format(dtid, self) - - def unregister(self, dtid): - """Unregisters the data format with the given data type id""" - - # Not registered? - if self.id < 0: - return True - - # Unregister - r = _idaapi.unregister_custom_data_format(dtid, self.id) - - # Clear the ID - if r: - self.id = -1 - return r -# -# def printf(self, value, current_ea, operand_num, dtid): -# """ -# Convert a value buffer to colored string. -# -# @param value: The value to be printed -# @param current_ea: The ea of the value -# @param operand_num: The affected operand -# @param dtid: custom data type id (0-standard built-in data type) -# @return: a colored string representing the passed 'value' or None on failure -# """ -# return None -# -# def scan(self, input, current_ea, operand_num): -# """ -# Convert from uncolored string 'input' to byte value -# -# @param input: input string -# @param current_ea: current address (BADADDR if unknown) -# @param operand_num: current operand number (-1 if unknown) -# -# @return: tuple (Boolean, string) -# - (False, ErrorMessage) if conversion fails -# - (True, Value buffer) if conversion succeeds -# """ -# return (False, "Not implemented") -# -# def analyze(self, current_ea, operand_num): -# """ -# (optional) Analyze custom data format occurrence. -# It can be used to create xrefs from the current item. -# -# @param current_ea: current address (BADADDR if unknown) -# @param operand_num: current operand number -# @return: None -# """ -# -# pass -# -# ----------------------------------------------------------------------- -def __walk_types_and_formats(formats, type_action, format_action, installing): - broken = False - for f in formats: - if len(f) == 1: - if not format_action(f[0], 0): - broken = True - break - else: - dt = f[0] - dfs = f[1:] - # install data type before installing formats - if installing and not type_action(dt): - broken = True - break - # process formats using the correct dt.id - for df in dfs: - if not format_action(df, dt.id): - broken = True - break - # uninstall data type after uninstalling formats - if not installing and not type_action(dt): - broken = True - break - return not broken - -# ----------------------------------------------------------------------- -def register_data_types_and_formats(formats): - """ - Registers multiple data types and formats at once. - To register one type/format at a time use register_custom_data_type/register_custom_data_format - - It employs a special table of types and formats described below: - - The 'formats' is a list of tuples. If a tuple has one element then it is the format to be registered with dtid=0 - If the tuple has more than one element, then tuple[0] is the data type and tuple[1:] are the data formats. For example: - many_formats = [ - (pascal_data_type(), pascal_data_format()), - (simplevm_data_type(), simplevm_data_format()), - (makedword_data_format(),), - (simplevm_data_format(),) - ] - The first two tuples describe data types and their associated formats. - The last two tuples describe two data formats to be used with built-in data types. - """ - def __reg_format(df, dtid): - df.register(dtid) - if dtid == 0: - print "Registered format '%s' with built-in types, ID=%d" % (df.name, df.id) - else: - print " Registered format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid) - return df.id != -1 - - def __reg_type(dt): - dt.register() - print "Registered type '%s', ID=%d" % (dt.name, dt.id) - return dt.id != -1 - ok = __walk_types_and_formats(formats, __reg_type, __reg_format, True) - return 1 if ok else -1 - -# ----------------------------------------------------------------------- -def unregister_data_types_and_formats(formats): - """As opposed to register_data_types_and_formats(), this function - unregisters multiple data types and formats at once. - """ - def __unreg_format(df, dtid): - print "%snregistering format '%s'" % ("U" if dtid == 0 else " u", df.name) - df.unregister(dtid) - return True - - def __unreg_type(dt): - print "Unregistering type '%s', ID=%d" % (dt.name, dt.id) - dt.unregister() - return True - ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format, False) - return 1 if ok else -1 - # %} diff --git a/swig/choose.i b/swig/choose.i new file mode 100644 index 0000000..08486fe --- /dev/null +++ b/swig/choose.i @@ -0,0 +1,12 @@ + +// relies on kernwin.i to include kernwin.hpp + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/choose2.i b/swig/choose2.i new file mode 100644 index 0000000..199c87d --- /dev/null +++ b/swig/choose2.i @@ -0,0 +1,17 @@ + +// relies on kernwin.i to include kernwin.hpp + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/cli.i b/swig/cli.i new file mode 100644 index 0000000..abef900 --- /dev/null +++ b/swig/cli.i @@ -0,0 +1,17 @@ + +// relies on kernwin.i to include kernwin.hpp + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/custdata.i b/swig/custdata.i new file mode 100644 index 0000000..38de684 --- /dev/null +++ b/swig/custdata.i @@ -0,0 +1,15 @@ + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/custview.i b/swig/custview.i new file mode 100644 index 0000000..778fa46 --- /dev/null +++ b/swig/custview.i @@ -0,0 +1,17 @@ + +// relies on kernwin.i to include kernwin.hpp + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/dbg.i b/swig/dbg.i index f884462..ae7db6e 100644 --- a/swig/dbg.i +++ b/swig/dbg.i @@ -52,11 +52,10 @@ typedef struct %include "dbg.hpp" %nothread; %ignore DBG_Callback; -%feature("director") DBG_Hooks; +%ignore DBG_Hooks::store_int; %{ // -static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas); // %} @@ -98,366 +97,8 @@ void bpt_t_elang_set(bpt_t *bpt, PyObject *val) } } %} + %inline %{ - // - -//------------------------------------------------------------------------- -/* -# -def get_manual_regions(): - """ - Returns the manual memory regions - @return: list(startEA, endEA, name, sclass, sbase, bitness, perm) - """ - pass -# -*/ -static PyObject *py_get_manual_regions() -{ - meminfo_vec_t areas; - get_manual_regions(&areas); - return meminfo_vec_t_to_py(areas); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_is_loaded(): - """ - Checks if a debugger is loaded - @return: Boolean - """ - pass -# -*/ -static bool dbg_is_loaded() -{ - return dbg != NULL; -} - -//------------------------------------------------------------------------- -/* -# -def refresh_debugger_memory(): - """ - Refreshes the debugger memory - @return: Nothing - """ - pass -# -*/ -static PyObject *refresh_debugger_memory() -{ - invalidate_dbgmem_config(); - invalidate_dbgmem_contents(BADADDR, 0); - - // Ask the debugger to populate debug names - if ( dbg != NULL && dbg->stopped_at_debug_event != NULL ) - dbg->stopped_at_debug_event(true); - - // Invalidate the cache - isEnabled(0); - - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; -} - -int idaapi DBG_Callback(void *ud, int notification_code, va_list va); -class DBG_Hooks -{ -public: - virtual ~DBG_Hooks() { unhook(); } - - bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); } - bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); } - /* Hook functions to be overridden in Python */ - virtual void dbg_process_start(pid_t pid, - thid_t tid, - ea_t ea, - char *name, - ea_t base, - asize_t size) {} - virtual void dbg_process_exit(pid_t pid, - thid_t tid, - ea_t ea, - int exit_code) {} - virtual void dbg_process_attach(pid_t pid, - thid_t tid, - ea_t ea, - char *name, - ea_t base, - asize_t size) {} - virtual void dbg_process_detach(pid_t pid, - thid_t tid, - ea_t ea) {} - virtual void dbg_thread_start(pid_t pid, - thid_t tid, - ea_t ea) {} - virtual void dbg_thread_exit(pid_t pid, - thid_t tid, - ea_t ea, - int exit_code) {} - virtual void dbg_library_load(pid_t pid, - thid_t tid, - ea_t ea, - char *name, - ea_t base, - asize_t size) {} - virtual void dbg_library_unload(pid_t pid, - thid_t tid, - ea_t ea, - char *libname) {} - virtual void dbg_information(pid_t pid, - thid_t tid, - ea_t ea, - char *info) {} - virtual int dbg_exception(pid_t pid, - thid_t tid, - ea_t ea, - int code, - bool can_cont, - ea_t exc_ea, - char *info) { return 0; } - virtual void dbg_suspend_process(void) {} - virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; } - virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; } - virtual void dbg_request_error(int failed_command, - int failed_dbg_notification) {} - virtual void dbg_step_into(void) {} - virtual void dbg_step_over(void) {} - virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) {} - virtual void dbg_step_until_ret(void) {} -}; - -int idaapi DBG_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 DBG_Hooks *proxy = (class DBG_Hooks *)ud; - debug_event_t *event; - int code = 0; - - try - { - switch (notification_code) - { - case dbg_process_start: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_start(event->pid, - event->tid, - event->ea, - event->modinfo.name, - event->modinfo.base, - event->modinfo.size); - break; - - case dbg_process_exit: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_exit( - event->pid, - event->tid, - event->ea, - event->exit_code); - break; - - case dbg_process_attach: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_attach( - event->pid, - event->tid, - event->ea, - event->modinfo.name, - event->modinfo.base, - event->modinfo.size); - break; - - case dbg_process_detach: - event = va_arg(va, debug_event_t *); - proxy->dbg_process_detach( - event->pid, - event->tid, - event->ea); - break; - - case dbg_thread_start: - event = va_arg(va, debug_event_t *); - proxy->dbg_thread_start( - event->pid, - event->tid, - event->ea); - break; - - case dbg_thread_exit: - event = va_arg(va, debug_event_t *); - proxy->dbg_thread_exit( - event->pid, - event->tid, - event->ea, - event->exit_code); - break; - - case dbg_library_load: - event = va_arg(va, debug_event_t *); - proxy->dbg_library_load( - event->pid, - event->tid, - event->ea, - event->modinfo.name, - event->modinfo.base, - event->modinfo.size); - break; - - case dbg_library_unload: - event = va_arg(va, debug_event_t *); - proxy->dbg_library_unload( - event->pid, - event->tid, - event->ea, - event->info); - break; - - case dbg_information: - event = va_arg(va, debug_event_t *); - proxy->dbg_information( - event->pid, - event->tid, - event->ea, - event->info); - break; - - case dbg_exception: - { - event = va_arg(va, debug_event_t *); - int *warn = va_arg(va, int *); - *warn = proxy->dbg_exception( - event->pid, - event->tid, - event->ea, - event->exc.code, - event->exc.can_cont, - event->exc.ea, - event->exc.info); - break; - } - - case dbg_suspend_process: - proxy->dbg_suspend_process(); - break; - - case dbg_bpt: - { - thid_t tid = va_arg(va, thid_t); - ea_t breakpoint_ea = va_arg(va, ea_t); - int *warn = va_arg(va, int *); - *warn = proxy->dbg_bpt(tid, breakpoint_ea); - break; - } - - case dbg_trace: - { - thid_t tid = va_arg(va, thid_t); - ea_t ip = va_arg(va, ea_t); - code = proxy->dbg_trace(tid, ip); - break; - } - - case dbg_request_error: - { - int failed_command = (int)va_argi(va, ui_notification_t); - int failed_dbg_notification = (int)va_argi(va, dbg_notification_t); - proxy->dbg_request_error(failed_command, failed_dbg_notification); - break; - } - - case dbg_step_into: - proxy->dbg_step_into(); - break; - - case dbg_step_over: - proxy->dbg_step_over(); - break; - - case dbg_run_to: - event = va_arg(va, debug_event_t *); - proxy->dbg_run_to( - event->pid, - event->tid, - event->ea); - break; - - case dbg_step_until_ret: - proxy->dbg_step_until_ret(); - break; - } - } - catch (Swig::DirectorException &e) - { - msg("Exception in DBG Hook function: %s\n", e.getMessage()); - if (PyErr_Occurred()) - PyErr_Print(); - } - return code; -} - -//------------------------------------------------------------------------ -/* -# -def py_list_bptgrps(): - """ - Returns list of breakpoint group names - @return: A list of strings or None on failure - """ - pass -# -*/ -static PyObject *py_list_bptgrps() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - qstrvec_t args; - if ( list_bptgrps(&args) == 0 ) - Py_RETURN_NONE; - return qstrvec2pylist(args); -} - -//------------------------------------------------------------------------ -/* -# -def move_bpt_to_grp(): - """ - Sets new group for the breakpoint - """ - pass -# -*/ -static void move_bpt_to_grp(bpt_t *bpt, const char *grp_name) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - set_bpt_group(*bpt, grp_name); -} - -/* -# -def internal_get_sreg_base(): - """ - Get the sreg base, for the given thread. - - @return: The sreg base, or BADADDR on failure. - """ - pass -# -*/ -static ea_t py_internal_get_sreg_base(thid_t tid, int sreg_value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ea_t answer; - return internal_get_sreg_base(tid, sreg_value, &answer) < 1 - ? BADADDR - : answer; -} - // - %} diff --git a/swig/diskio.i b/swig/diskio.i index 6f77fbf..82cacf5 100644 --- a/swig/diskio.i +++ b/swig/diskio.i @@ -31,6 +31,7 @@ %ignore unmake_linput; %ignore create_remote_linput; %ignore make_filehandle_linput; +%ignore get_default_userdir; // FIXME: These should be wrapped for completeness %ignore eread; @@ -48,483 +49,15 @@ %{ // -//-------------------------------------------------------------------------- -int idaapi py_enumerate_files_cb(const char *file, void *ud) -{ - // No need to 'PYW_GIL_GET' here, as this is called synchronously - // and from the same thread as the one that executes - // 'py_enumerate_files'. - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_file(PyString_FromString(file)); - newref_t py_ret( - PyObject_CallFunctionObjArgs( - (PyObject *)ud, - py_file.o, - NULL)); - return (py_ret == NULL || !PyNumber_Check(py_ret.o)) ? 1 /* stop enum on failure */ : PyInt_AsLong(py_ret.o); -} // %} %inline %{ // -/* -# -class loader_input_t(pyidc_opaque_object_t): - """A helper class to work with linput_t related functions. - This class is also used by file loaders scripts. - """ - def __init__(self): - pass - - def close(self): - """Closes the file""" - pass - - def open(self, filename, remote = False): - """Opens a file (or a remote file) - @return: Boolean - """ - pass - - def set_linput(self, linput): - """Links the current loader_input_t instance to a linput_t instance""" - pass - - @staticmethod - def from_fp(fp): - """A static method to construct an instance from a FILE*""" - pass - - def open_memory(self, start, size): - """Create a linput for process memory (By internally calling idaapi.create_memory_linput()) - This linput will use dbg->read_memory() to read data - @param start: starting address of the input - @param size: size of the memory area to represent as linput - if unknown, may be passed as 0 - """ - pass - - def seek(self, pos, whence = SEEK_SET): - """Set input source position - @return: the new position (not 0 as fseek!) - """ - pass - - def tell(self): - """Returns the current position""" - pass - - def getz(self, sz, fpos = -1): - """Returns a zero terminated string at the given position - @param sz: maximum size of the string - @param fpos: if != -1 then seek will be performed before reading - @return: The string or None on failure. - """ - pass - - def gets(self, len): - """Reads a line from the input file. Returns the read line or None""" - pass - - def read(self, size): - """Reads from the file. Returns the buffer or None""" - pass - - def readbytes(self, size, big_endian): - """Similar to read() but it respect the endianness""" - pass - - def file2base(self, pos, ea1, ea2, patchable): - """ - Load portion of file into the database - This function will include (ea1..ea2) into the addressing space of the - program (make it enabled) - @param li: pointer ot input source - @param pos: position in the file - @param (ea1..ea2): range of destination linear addresses - @param patchable: should the kernel remember correspondance of - file offsets to linear addresses. - @return: 1-ok,0-read error, a warning is displayed - """ - pass - - def get_char(self): - """Reads a single character from the file. Returns None if EOF or the read character""" - pass - - def opened(self): - """Checks if the file is opened or not""" - pass -# -*/ -class loader_input_t -{ -private: - linput_t *li; - int own; - qstring fn; - enum - { - OWN_NONE = 0, // li not created yet - OWN_CREATE = 1, // Owns li because we created it - OWN_FROM_LI = 2, // No ownership we borrowed the li from another class - OWN_FROM_FP = 3, // We got an li instance from an fp instance, we have to unmake_linput() on Close - }; - - //-------------------------------------------------------------------------- - void _from_cobject(PyObject *pycobject) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - this->set_linput((linput_t *)PyCObject_AsVoidPtr(pycobject)); - } - - //-------------------------------------------------------------------------- - void assign(const loader_input_t &rhs) - { - fn = rhs.fn; - li = rhs.li; - own = OWN_FROM_LI; - } - - //-------------------------------------------------------------------------- - loader_input_t(const loader_input_t &rhs) - { - assign(rhs); - } -public: - // Special attribute that tells the pyvar_to_idcvar how to convert this - // class from and to IDC. The value of this variable must be set to two - int __idc_cvt_id__; - //-------------------------------------------------------------------------- - loader_input_t(PyObject *pycobject = NULL): li(NULL), own(OWN_NONE), __idc_cvt_id__(PY_ICID_OPAQUE) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( pycobject != NULL && PyCObject_Check(pycobject) ) - _from_cobject(pycobject); - } - - //-------------------------------------------------------------------------- - void close() - { - if ( li == NULL ) - return; - - PYW_GIL_GET; - Py_BEGIN_ALLOW_THREADS; - if ( own == OWN_CREATE ) - close_linput(li); - else if ( own == OWN_FROM_FP ) - unmake_linput(li); - Py_END_ALLOW_THREADS; - li = NULL; - own = OWN_NONE; - } - - //-------------------------------------------------------------------------- - ~loader_input_t() - { - close(); - } - - //-------------------------------------------------------------------------- - bool open(const char *filename, bool remote = false) - { - close(); - PYW_GIL_GET; - Py_BEGIN_ALLOW_THREADS; - li = open_linput(filename, remote); - if ( li != NULL ) - { - // Save file name - fn = filename; - own = OWN_CREATE; - } - Py_END_ALLOW_THREADS; - return li != NULL; - } - - //-------------------------------------------------------------------------- - void set_linput(linput_t *linput) - { - close(); - own = OWN_FROM_LI; - li = linput; - fn.sprnt("", linput); - } - - //-------------------------------------------------------------------------- - static loader_input_t *from_linput(linput_t *linput) - { - loader_input_t *l = new loader_input_t(); - l->set_linput(linput); - return l; - } - - //-------------------------------------------------------------------------- - // This method can be used to pass a linput_t* from C code - static loader_input_t *from_cobject(PyObject *pycobject) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(pycobject) ) - return NULL; - loader_input_t *l = new loader_input_t(); - l->_from_cobject(pycobject); - return l; - } - - //-------------------------------------------------------------------------- - static loader_input_t *from_fp(FILE *fp) - { - PYW_GIL_GET; - loader_input_t *l = NULL; - Py_BEGIN_ALLOW_THREADS; - linput_t *fp_li = make_linput(fp); - if ( fp_li != NULL ) - { - l = new loader_input_t(); - l->own = OWN_FROM_FP; - l->fn.sprnt("", fp); - l->li = fp_li; - } - Py_END_ALLOW_THREADS; - return l; - } - - //-------------------------------------------------------------------------- - linput_t *get_linput() - { - return li; - } - - //-------------------------------------------------------------------------- - bool open_memory(ea_t start, asize_t size = 0) - { - PYW_GIL_GET; - linput_t *l; - Py_BEGIN_ALLOW_THREADS; - l = create_memory_linput(start, size); - if ( l != NULL ) - { - close(); - li = l; - fn = ""; - own = OWN_CREATE; - } - Py_END_ALLOW_THREADS; - return l != NULL; - } - - //-------------------------------------------------------------------------- - int32 seek(int32 pos, int whence = SEEK_SET) - { - int32 r; - PYW_GIL_GET; - Py_BEGIN_ALLOW_THREADS; - r = qlseek(li, pos, whence); - Py_END_ALLOW_THREADS; - return r; - } - - //-------------------------------------------------------------------------- - int32 tell() - { - int32 r; - PYW_GIL_GET; - Py_BEGIN_ALLOW_THREADS; - r = qltell(li); - Py_END_ALLOW_THREADS; - return r; - } - - //-------------------------------------------------------------------------- - PyObject *getz(size_t sz, int32 fpos = -1) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - char *buf = (char *) malloc(sz + 5); - if ( buf == NULL ) - break; - Py_BEGIN_ALLOW_THREADS; - qlgetz(li, fpos, buf, sz); - Py_END_ALLOW_THREADS; - PyObject *ret = PyString_FromString(buf); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - PyObject *gets(size_t len) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - char *buf = (char *) malloc(len + 5); - if ( buf == NULL ) - break; - bool ok; - Py_BEGIN_ALLOW_THREADS; - ok = qlgets(buf, len, li) != NULL; - Py_END_ALLOW_THREADS; - if ( !ok ) - { - free(buf); - break; - } - PyObject *ret = PyString_FromString(buf); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - PyObject *read(size_t size) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - char *buf = (char *) malloc(size + 5); - if ( buf == NULL ) - break; - ssize_t r; - Py_BEGIN_ALLOW_THREADS; - r = qlread(li, buf, size); - Py_END_ALLOW_THREADS; - if ( r == -1 ) - { - free(buf); - break; - } - PyObject *ret = PyString_FromStringAndSize(buf, r); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - bool opened() - { - return li != NULL; - } - - //-------------------------------------------------------------------------- - PyObject *readbytes(size_t size, bool big_endian) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - char *buf = (char *) malloc(size + 5); - if ( buf == NULL ) - break; - int r; - Py_BEGIN_ALLOW_THREADS; - r = lreadbytes(li, buf, size, big_endian); - Py_END_ALLOW_THREADS; - if ( r == -1 ) - { - free(buf); - break; - } - PyObject *ret = PyString_FromStringAndSize(buf, r); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - int file2base(int32 pos, ea_t ea1, ea_t ea2, int patchable) - { - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = ::file2base(li, pos, ea1, ea2, patchable); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - int32 size() - { - int32 rc; - Py_BEGIN_ALLOW_THREADS; - rc = qlsize(li); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - PyObject *filename() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyString_FromString(fn.c_str()); - } - - //-------------------------------------------------------------------------- - PyObject *get_char() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - int ch; - Py_BEGIN_ALLOW_THREADS; - ch = qlgetc(li); - Py_END_ALLOW_THREADS; - if ( ch == EOF ) - Py_RETURN_NONE; - return Py_BuildValue("c", ch); - } -}; - - -//-------------------------------------------------------------------------- -/* -# -def enumerate_files(path, fname, callback): - """ - Enumerate files in the specified directory while the callback returns 0. - @param path: directory to enumerate files in - @param fname: mask of file names to enumerate - @param callback: a callable object that takes the filename as - its first argument and it returns 0 to continue - enumeration or non-zero to stop enumeration. - @return: - None in case of script errors - tuple(code, fname) : If the callback returns non-zero - """ - pass -# -*/ -PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - do - { - if ( !PyString_Check(path) || !PyString_Check(fname) || !PyCallable_Check(callback) ) - break; - - const char *_path = PyString_AsString(path); - const char *_fname = PyString_AsString(fname); - if ( _path == NULL || _fname == NULL ) - break; - - char answer[MAXSTR]; - answer[0] = '\0'; - int r = enumerate_files(answer, sizeof(answer), _path, _fname, py_enumerate_files_cb, callback); - return Py_BuildValue("(is)", r, answer); - } while ( false ); - Py_RETURN_NONE; -} // %} %pythoncode %{ # -def enumerate_system_files(subdir, fname, callback): - """Similar to enumerate_files() however it searches inside IDA directory or its subdirectories""" - return enumerate_files(idadir(subdir), fname, callback) # %} diff --git a/swig/entry.i b/swig/entry.i index 4fb1cf9..bebc381 100644 --- a/swig/entry.i +++ b/swig/entry.i @@ -4,4 +4,3 @@ %ignore set_entry_name; %include "entry.hpp" - diff --git a/swig/expr.i b/swig/expr.i index 316a35c..7407bf4 100644 --- a/swig/expr.i +++ b/swig/expr.i @@ -53,6 +53,7 @@ %ignore idc_resolve_label; %ignore idc_resolver_ea; %ignore setup_lowcnd_regfuncs; +%ignore syntax_highlighter_t; %cstring_output_maxstr_none(char *errbuf, size_t errbufsize); %ignore CompileEx; @@ -69,271 +70,17 @@ %rename (CompileLine) CompileLine_wrap; %{ // -struct py_idcfunc_ctx_t -{ - PyObject *py_func; - qstring name; - int nargs; - py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_INCREF(py_func); - } - ~py_idcfunc_ctx_t() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_DECREF(py_func); - } -}; - -//--------------------------------------------------------------------------- -static error_t py_call_idc_func( - void *_ctx, - idc_value_t *argv, - idc_value_t *r) -{ - // Convert IDC arguments to Python list - py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx; - int cvt; - char errbuf[MAXSTR]; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_vec_t pargs; - if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, true, errbuf, sizeof(errbuf)) ) - { - // Error during conversion? Create an IDC exception - return PyW_CreateIdcException(r, errbuf); - } - - // Call the Python function - newref_t py_result(PyObject_CallObject( - ctx->py_func, - pargs.empty() ? NULL : pargs[0].o)); - - error_t err; - if ( PyW_GetError(errbuf, sizeof(errbuf)) ) - { - err = PyW_CreateIdcException(r, errbuf); - } - else - { - // Convert the result to IDC - r->clear(); - cvt = pyvar_to_idcvar(py_result, r); - if ( cvt < CIP_OK ) - err = PyW_CreateIdcException(r, "ERROR: bad return value"); - else - err = eOk; - } - - return err; -} - // %} %inline %{ // - -//--------------------------------------------------------------------------- -static size_t py_get_call_idc_func() -{ - return (size_t)py_call_idc_func; -} - -//--------------------------------------------------------------------------- -// Internal function: -// - capture the python callable -// - return a C context as a numeric value -static size_t pyw_register_idc_func( - const char *name, - const char *args, - PyObject *py_fp) -{ - return (size_t)new py_idcfunc_ctx_t(py_fp, name, strlen(args)); -} - -//--------------------------------------------------------------------------- -// Internal function: -// - free the C context -static bool pyw_unregister_idc_func(size_t ctxptr) -{ - // Unregister the function - py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)ctxptr; - bool ok = set_idc_func_ex(ctx->name.c_str(), NULL, NULL, 0); - - // Delete the context - delete ctx; - - return ok; -} - -//--------------------------------------------------------------------------- -static bool py_set_idc_func_ex( - const char *name, - size_t fp_ptr, - const char *args, - int flags) -{ - return set_idc_func_ex(name, (idc_func_t *)fp_ptr, args, flags); -} - -//--------------------------------------------------------------------------- -// Compile* functions return false when error so the return -// value must be negated for the error string to be returned -bool CompileEx_wrap( - const char *file, - bool del_macros, - char *errbuf, size_t errbufsize) -{ - return !CompileEx(file, del_macros, errbuf, errbufsize); -} - -bool Compile_wrap(const char *file, char *errbuf, size_t errbufsize) -{ - return !Compile(file, errbuf, errbufsize); -} - -bool calcexpr_wrap( - ea_t where, - const char *line, - idc_value_t *rv, - char *errbuf, size_t errbufsize) -{ - return !calcexpr(where, line, rv, errbuf, errbufsize); -} - -bool calc_idc_expr_wrap( - ea_t where, - const char *line, - idc_value_t *rv, - char *errbuf, size_t errbufsize) -{ - return !calc_idc_expr(where, line, rv, errbuf, errbufsize); -} - -bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize) -{ - return !CompileLineEx(line, errbuf, errbufsize); -} - // %} %include "expr.hpp" %pythoncode %{ - # -try: - import types - import ctypes - # Callback for IDC func callback (On Windows, we use stdcall) - # typedef error_t idaapi idc_func_t(idc_value_t *argv,idc_value_t *r); - _IDCFUNC_CB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) - - # A trampoline function that is called from idcfunc_t that will - # call the Python callback with the argv and r properly serialized to python - call_idc_func__ = ctypes.CFUNCTYPE(ctypes.c_long)(_idaapi.py_get_call_idc_func()) -except: - def call_idc_func__(*args): - warning("IDC extensions need ctypes library in order to work") - return 0 - try: - _IDCFUNC_CB_T = CFUNCTYPE(c_int, c_void_p, c_void_p) - except: - _IDCFUNC_CB_T = None - - -# -------------------------------------------------------------------------- -EXTFUN_BASE = 0x0001 -"""requires open database""" -EXTFUN_NORET = 0x0002 -"""does not return. the interpreter may clean up its state before calling it.""" -EXTFUN_SAFE = 0x0004 -"""thread safe function. may be called""" - -# -------------------------------------------------------------------------- -class _IdcFunction(object): - """ - Internal class that calls pyw_call_idc_func() with a context - """ - def __init__(self, ctxptr): - self.ctxptr = ctxptr - # Take a reference to the ctypes callback - # (note: this will create a circular reference) - self.cb = _IDCFUNC_CB_T(self) - - fp_ptr = property(lambda self: ctypes.cast(self.cb, ctypes.c_void_p).value) - - def __call__(self, args, res): - return call_idc_func__(self.ctxptr, args, res) - - -# -------------------------------------------------------------------------- -# Dictionary to remember IDC function names along with the context pointer -# retrieved by using the internal pyw_register_idc_func() -__IDC_FUNC_CTXS = {} - -# -------------------------------------------------------------------------- -def set_idc_func_ex(name, fp=None, args=(), flags=0): - """ - Extends the IDC language by exposing a new IDC function that is backed up by a Python function - This function also unregisters the IDC function if 'fp' was passed as None - - @param name: IDC function name to expose - @param fp: Python callable that will receive the arguments and return a tuple. - If this argument is None then the IDC function is unregistered - @param args: Arguments. A tuple of idaapi.VT_XXX constants - @param flags: IDC function flags. A combination of EXTFUN_XXX constants - - @return: Boolean. - """ - global __IDC_FUNC_CTXS - - # Get the context - f = __IDC_FUNC_CTXS.get(name, None) - - # Unregistering? - if fp is None: - # Not registered? - if f is None: - return False - - # Break circular reference - del f.cb - - # Delete the name from the dictionary - del __IDC_FUNC_CTXS[name] - - # Delete the context and unregister the function - return _idaapi.pyw_unregister_idc_func(f.ctxptr) - - # Registering a function that is already registered? - if f is not None: - # Unregister it first - set_idc_func_ex(name, None) - - # Convert the tupple argument info to a string - args = "".join([chr(x) for x in args]) - - # Create a context - ctxptr = _idaapi.pyw_register_idc_func(name, args, fp) - if ctxptr == 0: - return False - - # Bind the context with the IdcFunc object - f = _IdcFunction(ctxptr) - - # Remember the Python context - __IDC_FUNC_CTXS[name] = f - - # Register IDC function with a callback - return _idaapi.py_set_idc_func_ex( - name, - f.fp_ptr, - args, - flags) - # -%} \ No newline at end of file +%} diff --git a/swig/fpro.i b/swig/fpro.i index 7adaf16..8dc23f9 100644 --- a/swig/fpro.i +++ b/swig/fpro.i @@ -1,404 +1,4 @@ %inline %{ -// -/* -# -class qfile_t(pyidc_opaque_object_t): - """A helper class to work with FILE related functions.""" - def __init__(self): - pass - - def close(self): - """Closes the file""" - pass - - def open(self, filename, mode): - """Opens a file - @param filename: the file name - @param mode: The mode string, ala fopen() style - @return: Boolean - """ - pass - - def set_linput(self, linput): - """Links the current loader_input_t instance to a linput_t instance""" - pass - - @staticmethod - def tmpfile(): - """A static method to construct an instance using a temporary file""" - pass - - def seek(self, pos, whence = SEEK_SET): - """Set input source position - @return: the new position (not 0 as fseek!) - """ - pass - - def tell(self): - """Returns the current position""" - pass - - def gets(self, len): - """Reads a line from the input file. Returns the read line or None""" - pass - - def read(self, size): - """Reads from the file. Returns the buffer or None""" - pass - - def write(self, buf): - """Writes to the file. Returns 0 or the number of bytes written""" - pass - - def readbytes(self, size, big_endian): - """Similar to read() but it respect the endianness""" - pass - - def writebytes(self, size, big_endian): - """Similar to write() but it respect the endianness""" - pass - - def flush(self): - pass - - def get_char(self): - """Reads a single character from the file. Returns None if EOF or the read character""" - pass - - def put_char(self): - """Writes a single character to the file""" - pass - - def opened(self): - """Checks if the file is opened or not""" - pass -# -*/ -class qfile_t -{ -private: - FILE *fp; - bool own; - qstring fn; - - //-------------------------------------------------------------------------- - void assign(const qfile_t &rhs) - { - fn = rhs.fn; - fp = rhs.fp; - own = false; - } - //-------------------------------------------------------------------------- - bool _from_fp(FILE *fp) - { - if ( fp == NULL ) - return false; - own = false; - fn.sprnt("", fp); - this->fp = fp; - return true; - } - inline void _from_cobject(PyObject *pycobject) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - _from_fp((FILE *)PyCObject_AsVoidPtr(pycobject)); - } -public: - int __idc_cvt_id__; - //-------------------------------------------------------------------------- - qfile_t(const qfile_t &rhs) - { - assign(rhs); - } - - //-------------------------------------------------------------------------- - qfile_t(PyObject *pycobject = NULL) - { - fp = NULL; - own = true; - fn.qclear(); - __idc_cvt_id__ = PY_ICID_OPAQUE; - bool ok; - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - ok = pycobject != NULL && PyCObject_Check(pycobject); - } - if ( ok ) - _from_cobject(pycobject); - } - - //-------------------------------------------------------------------------- - bool opened() - { - return fp != NULL; - } - - //-------------------------------------------------------------------------- - void close() - { - if ( fp == NULL ) - return; - if ( own ) - { - Py_BEGIN_ALLOW_THREADS; - qfclose(fp); - Py_END_ALLOW_THREADS; - } - fp = NULL; - own = true; - } - - //-------------------------------------------------------------------------- - ~qfile_t() - { - close(); - } - - //-------------------------------------------------------------------------- - bool open(const char *filename, const char *mode) - { - close(); - Py_BEGIN_ALLOW_THREADS; - fp = qfopen(filename, mode); - Py_END_ALLOW_THREADS; - if ( fp == NULL ) - return false; - // Save file name - fn = filename; - own = true; - return true; - } - - //-------------------------------------------------------------------------- - static qfile_t *from_fp(FILE *fp) - { - if ( fp == NULL ) - return NULL; - qfile_t *qf = new qfile_t(); - qf->own = false; - qf->fn.sprnt("", fp); - qf->fp = fp; - return qf; - } - - //-------------------------------------------------------------------------- - // This method can be used to pass a FILE* from C code - static qfile_t *from_cobject(PyObject *pycobject) - { - return PyCObject_Check(pycobject) ? from_fp((FILE *)PyCObject_AsVoidPtr(pycobject)) : NULL; - } - - //-------------------------------------------------------------------------- - static qfile_t *tmpfile() - { - FILE *fp; - Py_BEGIN_ALLOW_THREADS; - fp = qtmpfile(); - Py_END_ALLOW_THREADS; - return from_fp(fp); - } - - //-------------------------------------------------------------------------- - FILE *get_fp() - { - return fp; - } - - //-------------------------------------------------------------------------- - int seek(int32 offset, int whence = SEEK_SET) - { - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = qfseek(fp, offset, whence); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - int32 tell() - { - int32 rc; - Py_BEGIN_ALLOW_THREADS; - rc = qftell(fp); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - PyObject *readbytes(int size, bool big_endian) - { - do - { - char *buf = (char *) malloc(size + 5); - if ( buf == NULL ) - break; - PYW_GIL_CHECK_LOCKED_SCOPE(); - int r; - Py_BEGIN_ALLOW_THREADS; - r = freadbytes(fp, buf, size, big_endian); - Py_END_ALLOW_THREADS; - if ( r != 0 ) - { - free(buf); - break; - } - - PyObject *ret = PyString_FromStringAndSize(buf, r); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - PyObject *read(int size) - { - do - { - char *buf = (char *) malloc(size + 5); - if ( buf == NULL ) - break; - PYW_GIL_CHECK_LOCKED_SCOPE(); - int r; - Py_BEGIN_ALLOW_THREADS; - r = qfread(fp, buf, size); - Py_END_ALLOW_THREADS; - if ( r <= 0 ) - { - free(buf); - break; - } - PyObject *ret = PyString_FromStringAndSize(buf, r); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - PyObject *gets(int size) - { - do - { - char *buf = (char *) malloc(size + 5); - if ( buf == NULL ) - break; - PYW_GIL_CHECK_LOCKED_SCOPE(); - char *p; - Py_BEGIN_ALLOW_THREADS; - p = qfgets(buf, size, fp); - Py_END_ALLOW_THREADS; - if ( p == NULL ) - { - free(buf); - break; - } - PyObject *ret = PyString_FromString(buf); - free(buf); - return ret; - } while ( false ); - Py_RETURN_NONE; - } - - //-------------------------------------------------------------------------- - int writebytes(PyObject *py_buf, bool big_endian) - { - Py_ssize_t sz; - void *buf; - PYW_GIL_CHECK_LOCKED_SCOPE(); - sz = PyString_GET_SIZE(py_buf); - buf = (void *)PyString_AS_STRING(py_buf); - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = fwritebytes(fp, buf, int(sz), big_endian); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - int write(PyObject *py_buf) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_buf) ) - return 0; - // Just so that there is no risk that the buffer returned by - // 'PyString_AS_STRING' gets deallocated within the - // Py_BEGIN|END_ALLOW_THREADS section. - borref_t py_buf_ref(py_buf); - void *p = (void *)PyString_AS_STRING(py_buf); - Py_ssize_t sz = PyString_GET_SIZE(py_buf); - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = qfwrite(fp, p, sz); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - int puts(const char *str) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = qfputs(str, fp); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - int32 size() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - int32 r; - Py_BEGIN_ALLOW_THREADS; - int pos = qfseek(fp, 0, SEEK_END); - r = qftell(fp); - qfseek(fp, pos, SEEK_SET); - Py_END_ALLOW_THREADS; - return r; - } - - //-------------------------------------------------------------------------- - int flush() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = qflush(fp); - Py_END_ALLOW_THREADS; - return rc; - } - - //-------------------------------------------------------------------------- - PyObject *filename() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyString_FromString(fn.c_str()); - } - - //-------------------------------------------------------------------------- - PyObject *get_char() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - int ch; - Py_BEGIN_ALLOW_THREADS; - ch = qfgetc(fp); - Py_END_ALLOW_THREADS; - if ( ch == EOF ) - Py_RETURN_NONE; - return Py_BuildValue("c", ch); - } - - //-------------------------------------------------------------------------- - int put_char(char chr) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = qfputc(chr, fp); - Py_END_ALLOW_THREADS; - return rc; - } -}; -// +// +// %} diff --git a/swig/funcs.i b/swig/funcs.i index 77b6411..505fdd9 100644 --- a/swig/funcs.i +++ b/swig/funcs.i @@ -29,90 +29,17 @@ %ignore get_idasgn_desc; %rename (get_idasgn_desc) py_get_idasgn_desc; +%rename (get_idasgn_desc_with_matches) py_get_idasgn_desc_with_matches; %ignore get_func_cmt; %rename (get_func_cmt) py_get_func_cmt; %include "funcs.hpp" -%inline %{ -#ifndef FUNC_STATICDEF -#define FUNC_STATICDEF 0x00000008 -#endif -%} - %clear(char *buf); %clear(char *optlibs); %inline %{ -//----------------------------------------------------------------------- -/* -# -def get_fchunk_referer(ea, idx): - pass -# -*/ -static ea_t get_fchunk_referer(ea_t ea, size_t idx) -{ - func_t *pfn = get_fchunk(ea); - func_parent_iterator_t dummy(pfn); // read referer info - if (idx >= pfn->refqty || pfn->referers == NULL) - return BADADDR; - else - return pfn->referers[idx]; -} - -//----------------------------------------------------------------------- -/* -# -def get_idasgn_desc(n): - """ - Get information about a signature in the list. - It returns both: the name of the signature, and names of the - optional libraries - - @param n: number of signature in the list (0..get_idasgn_qty()-1) - @return: None on failure or tuple(signame, optlibs) - """ - pass -# -*/ -static PyObject *py_get_idasgn_desc(int n) -{ - char signame[MAXSTR]; - char optlibs[MAXSTR]; - - if ( get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)) == -1 ) - Py_RETURN_NONE; - else - return Py_BuildValue("(ss)", signame, optlibs); -} - -//----------------------------------------------------------------------- -/* -# -def get_func_cmt(fn, repeatable): - """ - Retrieve function comment - @param fn: function instance - @param repeatable: retrieve repeatable or non-repeatable comments - @return: None on failure or the comment - """ - pass -# -*/ -static PyObject *py_get_func_cmt(func_t *fn, bool repeatable) -{ - char *s = get_func_cmt(fn, repeatable); - if ( s == NULL ) - { - Py_RETURN_NONE; - } - else - { - PyObject *py_s = PyString_FromString(s); - qfree(s); - return py_s; - } -} +// +// %} diff --git a/swig/gdl.i b/swig/gdl.i index c5823b8..bb975b4 100644 --- a/swig/gdl.i +++ b/swig/gdl.i @@ -24,91 +24,5 @@ %pythoncode %{ # -# ----------------------------------------------------------------------- -class BasicBlock(object): - """Basic block class. It is returned by the Flowchart class""" - def __init__(self, id, bb, fc): - self._fc = fc - - self.id = id - """Basic block ID""" - - self.startEA = bb.startEA - """startEA of basic block""" - - self.endEA = bb.endEA - """endEA of basic block""" - - self.type = self._fc._q.calc_block_type(self.id) - """Block type (check fc_block_type_t enum)""" - - - def preds(self): - """ - Iterates the predecessors list - """ - q = self._fc._q - for i in xrange(0, self._fc._q.npred(self.id)): - yield self._fc[q.pred(self.id, i)] - - - def succs(self): - """ - Iterates the successors list - """ - q = self._fc._q - for i in xrange(0, q.nsucc(self.id)): - yield self._fc[q.succ(self.id, i)] - -# ----------------------------------------------------------------------- -class FlowChart(object): - """ - Flowchart class used to determine basic blocks. - Check ex_gdl_qflow_chart.py for sample usage. - """ - def __init__(self, f=None, bounds=None, flags=0): - """ - Constructor - @param f: A func_t type, use get_func(ea) to get a reference - @param bounds: A tuple of the form (start, end). Used if "f" is None - @param flags: one of the FC_xxxx flags. One interesting flag is FC_PREDS - """ - if (f is None) and (bounds is None or type(bounds) != types.TupleType): - raise Exception("Please specifiy either a function or start/end pair") - - if bounds is None: - bounds = (BADADDR, BADADDR) - - # Create the flowchart - self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags) - - size = property(lambda self: self._q.size()) - """Number of blocks in the flow chart""" - - - def refresh(): - """Refreshes the flow chart""" - self._q.refresh() - - - def _getitem(self, index): - return BasicBlock(index, self._q[index], self) - - - def __iter__(self): - return (self._getitem(index) for index in xrange(0, self.size)) - - - def __getitem__(self, index): - """ - Returns a basic block - - @return: BasicBlock - """ - if index >= self.size: - raise KeyError - else: - return self._getitem(index) - # %} diff --git a/swig/graph.i b/swig/graph.i index c3fc1b1..6f59647 100644 --- a/swig/graph.i +++ b/swig/graph.i @@ -5,979 +5,15 @@ %{ // -class py_graph_t : public py_customidamemo_t -{ - typedef py_customidamemo_t inherited; - -protected: - - virtual void node_info_modified(int n, const node_info_t *ni, uint32 flags) - { - if ( ni == NULL ) - { - node_cache.erase(n); - } - else - { - nodetext_cache_t *c = node_cache.get(n); - if ( c != NULL ) - { - if ( (flags & NIF_TEXT) == NIF_TEXT ) - c->text = ni->text; - if ( (flags & NIF_BG_COLOR) == NIF_BG_COLOR ) - c->bgcolor = ni->bg_color; - } - } - } - - void collect_class_callbacks_ids(callbacks_ids_t *out); - -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_COMMAND = 0x00400000, - GRCODE_HAVE_CREATING_GROUP = 0x00800000, - GRCODE_HAVE_DELETING_GROUP = 0x01000000, - GRCODE_HAVE_GROUP_VISIBILITY = 0x02000000, - }; - struct nodetext_cache_t - { - qstring text; - bgcolor_t bgcolor; - nodetext_cache_t(const nodetext_cache_t &rhs): text(rhs.text), bgcolor(rhs.bgcolor) { } - nodetext_cache_t(const char *t, bgcolor_t c): text(t), bgcolor(c) { } - nodetext_cache_t() { } - }; - - class nodetext_cache_map_t: public std::map - { - public: - nodetext_cache_t *get(int node_id) - { - iterator it = find(node_id); - if ( it == end() ) - return NULL; - return &it->second; - } - nodetext_cache_t *add(const int node_id, const char *text, bgcolor_t bgcolor = DEFCOLOR) - { - return &(insert(std::make_pair(node_id, nodetext_cache_t(text, bgcolor))).first->second); - } - }; - - class cmdid_map_t: public std::map - { - private: - Py_ssize_t uid; - public: - - cmdid_map_t() - { - // We start by one and keep zero for error id - uid = 1; - } - - void add(py_graph_t *pyg) - { - (*this)[uid] = pyg; - ++uid; - } - - const Py_ssize_t id() const - { - return uid; - } - - void clear(py_graph_t *pyg) - { - iterator e = end(); - for (iterator it=begin();it!=end();) - { - if ( it->second == pyg ) - { - iterator temp = it++; - erase(temp); - } - else - ++it; - } - } - - py_graph_t *get(Py_ssize_t id) - { - iterator it = find(id); - return it == end() ? NULL : it->second; - } - }; - - static cmdid_map_t cmdid_pyg; - - bool refresh_needed; - nodetext_cache_map_t node_cache; - - // instance callback - int gr_callback(int code, va_list va); - - // static callback - static int idaapi s_callback(void *obj, int code, va_list va) - { - QASSERT(30453, py_customidamemo_t::lookup_info.find_by_py_view(NULL, NULL, (py_graph_t *) obj)); - PYW_GIL_GET; - return ((py_graph_t *)obj)->gr_callback(code, va); - } - - static bool idaapi s_menucb(void *ud) - { - PYW_GIL_GET; - Py_ssize_t id = (Py_ssize_t)ud; - py_graph_t *_this = cmdid_pyg.get(id); - if ( _this != NULL ) - _this->on_command(id); - - return true; - } - - void on_command(Py_ssize_t id) - { - // Check return value to OnRefresh() call - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t ret(PyObject_CallMethod(self.o, (char *)S_ON_COMMAND, "n", id)); - PyW_ShowCbErr(S_ON_COMMAND); - } - - // Refresh user-defined graph node number and edges - // It calls Python method and expects that the user already filled - // the nodes and edges. The nodes and edges are retrieved and passed to IDA - void on_user_refresh(mutable_graph_t *g); - - // Retrieves the text for user-defined graph node - // It expects either a string or a tuple (string, bgcolor) - bool on_user_text(mutable_graph_t * /*g*/, int node, const char **str, bgcolor_t *bg_color); - - // 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); - - // graph is being destroyed - void on_graph_destroyed(mutable_graph_t * /*g*/ = NULL) - { - refresh_needed = true; - node_cache.clear(); - } - - // graph is being clicked - int on_clicked( - graph_viewer_t * /*view*/, - selection_item_t * /*item1*/, - graph_item_t *item2) - { - // in: graph_viewer_t *view - // selection_item_t *current_item1 - // graph_item_t *current_item2 - // out: 0-ok, 1-ignore click - // this callback allows you to ignore some clicks. - // it occurs too early, internal graph variables are not updated yet - // current_item1, current_item2 point to the same thing - // item2 has more information. - // see also: kernwin.hpp, custom_viewer_click_t - if ( item2->n == -1 ) - return 1; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_CLICK, - "i", - item2->n)); - PyW_ShowCbErr(S_ON_CLICK); - return result == NULL || !PyObject_IsTrue(result.o); - } - - // a graph node has been double clicked - int on_dblclicked(graph_viewer_t * /*view*/, selection_item_t *item) - { - // in: graph_viewer_t *view - // selection_item_t *current_item - // out: 0-ok, 1-ignore click - //graph_viewer_t *v = va_arg(va, graph_viewer_t *); - //selection_item_t *s = va_arg(va, selection_item_t *); - if ( item == NULL || !item->is_node ) - return 1; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_DBL_CLICK, - "i", - item->node)); - PyW_ShowCbErr(S_ON_DBL_CLICK); - return result == NULL || !PyObject_IsTrue(result.o); - } - - // a graph viewer got focus - void on_gotfocus(graph_viewer_t * /*view*/) - { - if ( self.o == NULL ) - return; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_ACTIVATE, - NULL)); - PyW_ShowCbErr(S_ON_ACTIVATE); - } - - // a graph viewer lost focus - void on_lostfocus(graph_viewer_t * /*view*/) - { - if ( self.o == NULL ) - return; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_DEACTIVATE, - NULL)); - PyW_ShowCbErr(S_ON_DEACTIVATE); - } - - // a new graph node became the current node - int on_changed_current(graph_viewer_t * /*view*/, int curnode) - { - // in: graph_viewer_t *view - // int curnode - // out: 0-ok, 1-forbid to change the current node - if ( curnode < 0 ) - return 0; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_SELECT, - "i", - curnode)); - PyW_ShowCbErr(S_ON_SELECT); - return !(result != NULL && PyObject_IsTrue(result.o)); - } - - // a group is being created - int on_creating_group(mutable_graph_t *my_g, intvec_t *my_nodes) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_nodes(PyList_New(my_nodes->size())); - int i; - intvec_t::const_iterator p; - for ( i = 0, p=my_nodes->begin(); p != my_nodes->end(); ++p, ++i ) - PyList_SetItem(py_nodes.o, i, PyInt_FromLong(*p)); - newref_t py_result( - PyObject_CallMethod( - self.o, - (char *)S_ON_CREATING_GROUP, - "O", - py_nodes.o)); - PyW_ShowCbErr(S_ON_CREATING_GROUP); - return (py_result == NULL || !PyInt_Check(py_result.o)) ? 1 : PyInt_AsLong(py_result.o); - } - - // a group is being deleted - int on_deleting_group(mutable_graph_t * /*g*/, int old_group) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - // TODO - return 0; - } - - // a group is being collapsed/uncollapsed - int on_group_visibility(mutable_graph_t * /*g*/, int group, bool expand) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - // TODO - return 0; - } - - - void show() - { - TForm *form; - if ( lookup_info.find_by_py_view(&form, NULL, this) ) - open_tform(form, FORM_TAB|FORM_MENU|FORM_QWIDGET); - } - - void jump_to_node(int nid) - { - ref_t nodes(PyW_TryGetAttrString(self.o, S_M_NODES)); - if ( nid >= PyList_Size(nodes.o) ) - return; - - viewer_center_on(view, nid); - int x, y; - - // will return a place only when a node was previously selected - place_t *old_pl = get_custom_viewer_place(view, false, &x, &y); - if ( old_pl != NULL ) - { - user_graph_place_t *new_pl = (user_graph_place_t *) old_pl->clone(); - new_pl->node = nid; - jumpto(view, new_pl, x, y); - delete new_pl; - } - } - - virtual void refresh() - { - refresh_needed = true; - inherited::refresh(); - } - - int initialize(PyObject *self, const char *title) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !collect_pyobject_callbacks(self) ) - return -1; - - // Create form - HWND hwnd = NULL; - TForm *form = create_tform(title, &hwnd); - if ( hwnd != NULL ) // Created new tform - { - lookup_info_t::entry_t &e = lookup_info.new_entry(this); - // get a unique graph id - netnode id; - char grnode[MAXSTR]; - qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title); - id.create(grnode); - graph_viewer_t *pview = create_graph_viewer(form, id, s_callback, this, 0); - open_tform(form, FORM_TAB | FORM_MENU | FORM_QWIDGET); - if ( pview != NULL ) - viewer_fit_window(pview); - bind(self, pview); - install_custom_viewer_handlers(); - refresh(); - lookup_info.commit(e, form, view); - } - else - { - show(); - } - - viewer_fit_window(view); - return 0; - } - - Py_ssize_t add_command(const char *title, const char *hotkey) - { - if ( !has_callback(GRCODE_HAVE_COMMAND) || view == NULL) - return 0; - Py_ssize_t cmd_id = cmdid_pyg.id(); - bool ok = viewer_add_menu_item(view, title, s_menucb, (void *)cmd_id, hotkey, 0); - if ( !ok ) - return 0; - cmdid_pyg.add(this); - return cmd_id; - } - -public: - py_graph_t() - { - // form = NULL; - refresh_needed = true; - } - - virtual ~py_graph_t() - { - // Remove all associated commands from the list - cmdid_pyg.clear(this); - } - - static void SelectNode(PyObject *self, int nid) - { - if ( nid < 0 ) - return; - - py_graph_t *_this = view_extract_this(self); - if ( _this == NULL || !lookup_info.find_by_py_view(NULL, NULL, _this) ) - return; - - _this->jump_to_node(nid); - } - - static Py_ssize_t AddCommand(PyObject *self, const char *title, const char *hotkey) - { - py_graph_t *_this = view_extract_this(self); - if ( _this == NULL || !lookup_info.find_by_py_view(NULL, NULL, _this) ) - return 0; - - return _this->add_command(title, hotkey); - } - - static void Close(PyObject *self) - { - TForm *form; - py_graph_t *_this = view_extract_this(self); - if ( _this == NULL || !lookup_info.find_by_py_view(&form, NULL, _this) ) - return; - close_tform(form, FORM_CLOSE_LATER); - } - - static py_graph_t *Show(PyObject *self) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - py_graph_t *py_graph = view_extract_this(self); - - // New instance? - if ( py_graph == NULL ) - { - qstring title; - if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) ) - return NULL; - - // Form already created? try to get associated py_graph instance - // so that we reuse it - graph_viewer_t *found_view; - TForm *form = find_tform(title.c_str()); - if ( form != NULL ) - lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_graph, form); - - if ( py_graph == NULL ) - { - py_graph = new py_graph_t(); - } - else - { - // unbind so we are rebound - py_graph->unbind(false); - py_graph->refresh_needed = true; - } - if ( py_graph->initialize(self, title.c_str()) < 0 ) - { - delete py_graph; - py_graph = NULL; - } - } - else - { - py_graph->show(); - } - return py_graph; - } -}; - -//------------------------------------------------------------------------- -void py_graph_t::collect_class_callbacks_ids(callbacks_ids_t *out) -{ - inherited::collect_class_callbacks_ids(out); - out->add(S_ON_REFRESH, 0); - 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_CLICK, GRCODE_HAVE_CLICKED); - out->add(S_ON_DBL_CLICK, GRCODE_HAVE_DBL_CLICKED); - out->add(S_ON_COMMAND, GRCODE_HAVE_COMMAND); - out->add(S_ON_SELECT, GRCODE_HAVE_CHANGED_CURRENT); - out->add(S_ON_ACTIVATE, GRCODE_HAVE_GOTFOCUS); - out->add(S_ON_DEACTIVATE, GRCODE_HAVE_LOSTFOCUS); - out->add(S_ON_CREATING_GROUP, GRCODE_HAVE_CREATING_GROUP); - out->add(S_ON_DELETING_GROUP, GRCODE_HAVE_DELETING_GROUP); - out->add(S_ON_GROUP_VISIBILITY, GRCODE_HAVE_GROUP_VISIBILITY); -} - -//------------------------------------------------------------------------- -void py_graph_t::on_user_refresh(mutable_graph_t *g) -{ - if ( !refresh_needed || self == NULL /* Happens at creation-time */ ) - return; - - // Check return value to OnRefresh() call - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t ret(PyObject_CallMethod(self.o, (char *)S_ON_REFRESH, NULL)); - PyW_ShowCbErr(S_ON_REFRESH); - if ( ret != NULL && PyObject_IsTrue(ret.o) ) - { - // Refer to the nodes - ref_t nodes(PyW_TryGetAttrString(self.o, S_M_NODES)); - if ( ret != NULL && PyList_Check(nodes.o) ) - { - // Refer to the edges - ref_t edges(PyW_TryGetAttrString(self.o, S_M_EDGES)); - if ( ret != NULL && PyList_Check(edges.o) ) - { - // Resize the nodes - int max_nodes = abs(int(PyList_Size(nodes.o))); - g->clear(); - g->resize(max_nodes); - - // Mark that we refreshed already - refresh_needed = false; - - // Clear cached nodes - node_cache.clear(); - - // Get the edges - for ( int i=(int)PyList_Size(edges.o)-1; i>=0; i-- ) - { - // Each list item is a sequence (id1, id2) - borref_t item(PyList_GetItem(edges.o, i)); - if ( !PySequence_Check(item.o) ) - continue; - - // Get and validate each of the two elements in the sequence - int edge_ids[2]; - int j; - for ( j=0; j max_nodes ) - break; - edge_ids[j] = v; - } - - // Incomplete? - if ( j != qnumber(edge_ids) ) - break; - - // Add the edge - g->add_edge(edge_ids[0], edge_ids[1], NULL); - } - } - } - } -} - -//------------------------------------------------------------------------- -bool py_graph_t::on_user_text(mutable_graph_t * /*g*/, int node, const char **str, bgcolor_t *bg_color) -{ - // If already cached then return the value - nodetext_cache_t *c = node_cache.get(node); - if ( c != NULL ) - { - *str = c->text.c_str(); - if ( bg_color != NULL ) - *bg_color = c->bgcolor; - return true; - } - - // Not cached, call Python - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_GETTEXT, "i", node)); - PyW_ShowCbErr(S_ON_GETTEXT); - if ( result == NULL ) - return false; - - bgcolor_t cl = bg_color == NULL ? DEFCOLOR : *bg_color; - const char *s; - - // User returned a string? - if ( PyString_Check(result.o) ) - { - s = PyString_AsString(result.o); - if ( s == NULL ) - s = ""; - c = node_cache.add(node, s, cl); - } - // User returned a sequence of text and bgcolor - else if ( PySequence_Check(result.o) && PySequence_Size(result.o) == 2 ) - { - newref_t py_str(PySequence_GetItem(result.o, 0)); - newref_t py_color(PySequence_GetItem(result.o, 1)); - - if ( py_str == NULL || !PyString_Check(py_str.o) || (s = PyString_AsString(py_str.o)) == NULL ) - s = ""; - if ( py_color != NULL && PyNumber_Check(py_color.o) ) - cl = bgcolor_t(PyLong_AsUnsignedLong(py_color.o)); - - c = node_cache.add(node, s, cl); - } - - *str = c->text.c_str(); - if ( bg_color != NULL ) - *bg_color = c->bgcolor; - - return true; -} - -//------------------------------------------------------------------------- -int py_graph_t::on_user_hint(mutable_graph_t *, int mousenode, int /*mouseedge_src*/, int /*mouseedge_dst*/, char **hint) -{ - // '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 -} - - -//------------------------------------------------------------------------- -int py_graph_t::gr_callback(int code, va_list va) -{ - int ret; - switch ( code ) - { - // - case grcode_user_text: - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - int node = va_arg(va, int); - const char **result = va_arg(va, const char **); - bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); - ret = on_user_text(g, node, result, bgcolor); - break; - } - // - case grcode_destroyed: - on_graph_destroyed(va_arg(va, mutable_graph_t *)); - ret = 0; - break; - - // - case grcode_clicked: - if ( has_callback(GRCODE_HAVE_CLICKED) ) - { - graph_viewer_t *view = va_arg(va, graph_viewer_t *); - selection_item_t *item = va_arg(va, selection_item_t *); - graph_item_t *gitem = va_arg(va, graph_item_t *); - ret = on_clicked(view, item, gitem); - } - else - { - // Ignore the click - ret = 1; - } - break; - // - case grcode_dblclicked: - if ( has_callback(GRCODE_HAVE_DBL_CLICKED) ) - { - graph_viewer_t *view = va_arg(va, graph_viewer_t *); - selection_item_t *item = va_arg(va, selection_item_t *); - ret = on_dblclicked(view, item); - } - else - ret = 0; // We don't want to ignore the double click, but rather - // fallback to the default behavior (e.g., double-clicking - // on an edge will to jump to the node on the other side - // of that edge.) - break; - // - case grcode_gotfocus: - if ( has_callback(GRCODE_HAVE_GOTFOCUS) ) - on_gotfocus(va_arg(va, graph_viewer_t *)); - - ret = 0; - break; - // - case grcode_lostfocus: - if ( has_callback(GRCODE_HAVE_LOSTFOCUS) ) - on_lostfocus(va_arg(va, graph_viewer_t *)); - - ret = 0; - break; - // - case grcode_user_refresh: - on_user_refresh(va_arg(va, mutable_graph_t *)); - - ret = 1; - 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; - } - break; - // - case grcode_changed_current: - if ( has_callback(GRCODE_HAVE_CHANGED_CURRENT) ) - { - graph_viewer_t *view = va_arg(va, graph_viewer_t *); - int cur_node = va_arg(va, int); - ret = on_changed_current(view, cur_node); - } - else - ret = 0; // allow selection change - break; - // - case grcode_creating_group: // a group is being created - if ( has_callback(GRCODE_HAVE_CREATING_GROUP) ) - { - mutable_graph_t *g = va_arg(va, mutable_graph_t*); - intvec_t *nodes = va_arg(va, intvec_t*); - ret = on_creating_group(g, nodes); - } - else - { - ret = 0; // Ok to create - } - break; - // - case grcode_deleting_group: // a group is being deleted - if ( has_callback(GRCODE_HAVE_DELETING_GROUP) ) - { - mutable_graph_t *g = va_arg(va, mutable_graph_t*); - int old_group = va_arg(va, int); - ret = on_deleting_group(g, old_group); - } - else - { - ret = 0; // Ok to delete - } - break; - // - case grcode_group_visibility: // a group is being collapsed/uncollapsed - if ( has_callback(GRCODE_HAVE_GROUP_VISIBILITY) ) - { - mutable_graph_t *g = va_arg(va, mutable_graph_t*); - int group = va_arg(va, int); - bool expand = bool(va_arg(va, int)); - ret = on_group_visibility(g, group, expand); - } - else - { - ret = 0; // Ok. - } - break; - // - default: - ret = 0; - break; - } - //grcode_changed_graph, // new graph has been set - //grcode_user_size, // calculate node size for user-defined graph - //grcode_user_title, // render node title of a user-defined graph - //grcode_user_draw, // render node of a user-defined graph - return ret; -} - -//------------------------------------------------------------------------- -py_graph_t::cmdid_map_t py_graph_t::cmdid_pyg; - -bool pyg_show(PyObject *self) -{ - return py_graph_t::Show(self) != NULL; -} - -void pyg_close(PyObject *self) -{ - py_graph_t::Close(self); -} - -PyObject *pyg_add_command(PyObject *self, const char *title, const char *hotkey) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return Py_BuildValue("n", py_graph_t::AddCommand(self, title, hotkey)); -} - -void pyg_select_node(PyObject *self, int nid) -{ - py_graph_t::SelectNode(self, nid); -} // %} %inline %{ // -void pyg_close(PyObject *self); -PyObject *pyg_add_command(PyObject *self, const char *title, const char *hotkey); -void pyg_select_node(PyObject *self, int nid); -bool pyg_show(PyObject *self); // %} %pythoncode %{ # -class GraphViewer(CustomIDAMemo): - """This class wraps the user graphing facility provided by the graph.hpp file""" - def __init__(self, title, close_open = False): - """ - Constructs the GraphView object. - Please do not remove or rename the private fields - - @param title: The title of the graph window - @param close_open: Should it attempt to close an existing graph (with same title) before creating this graph? - """ - self._title = title - self._nodes = [] - self._edges = [] - self._close_open = close_open - - def AddNode(self, obj): - """Creates a node associated with the given object and returns the node id""" - id = len(self._nodes) - self._nodes.append(obj) - return id - - def AddEdge(self, src_node, dest_node): - """Creates an edge between two given node ids""" - self._edges.append( (src_node, dest_node) ) - - def Clear(self): - """Clears all the nodes and edges""" - self._nodes = [] - self._edges = [] - - - def __iter__(self): - return (self._nodes[index] for index in xrange(0, len(self._nodes))) - - - def __getitem__(self, idx): - """Returns a reference to the object associated with this node id""" - if idx >= len(self._nodes): - raise KeyError - else: - return self._nodes[idx] - - def Count(self): - """Returns the node count""" - return len(self._nodes) - - def Close(self): - """ - Closes the graph. - It is possible to call Show() again (which will recreate the graph) - """ - _idaapi.pyg_close(self) - - def Show(self): - """ - Shows an existing graph or creates a new one - - @return: Boolean - """ - if self._close_open: - frm = _idaapi.find_tform(self._title) - if frm: - _idaapi.close_tform(frm, 0) - return _idaapi.pyg_show(self) - - def Select(self, node_id): - """Selects a node on the graph""" - _idaapi.pyg_select_node(self, node_id) - - def AddCommand(self, title, hotkey): - """ - Deprecated: Use - - register_action() - - attach_action_to_popup() - """ - return _idaapi.pyg_add_command(self, title, hotkey) - - def OnRefresh(self): - """ - Event called when the graph is refreshed or first created. - From this event you are supposed to create nodes and edges. - This callback is mandatory. - - @note: ***It is important to clear previous nodes before adding nodes.*** - @return: Returning True tells the graph viewer to use the items. Otherwise old items will be used. - """ - self.Clear() - - return True -# -# def OnGetText(self, node_id): -# """ -# Triggered when the graph viewer wants the text and color for a given node. -# This callback is triggered one time for a given node (the value will be cached and used later without calling Python). -# When you call refresh then again this callback will be called for each node. -# -# This callback is mandatory. -# -# @return: Return a string to describe the node text or return a tuple (node_text, node_color) to describe both text and color -# """ -# return str(self[node_id]) -# -# def OnActivate(self): -# """ -# Triggered when the graph window gets the focus -# @return: None -# """ -# print "Activated...." -# -# def OnDeactivate(self): -# """Triggered when the graph window loses the focus -# @return: None -# """ -# print "Deactivated...." -# -# def OnSelect(self, node_id): -# """ -# Triggered when a node is being selected -# @return: Return True to allow the node to be selected or False to disallow node selection change -# """ -# # allow selection change -# return True -# -# def OnHint(self, node_id): -# """ -# Triggered when the graph viewer wants to retrieve hint text associated with a given node -# -# @return: None if no hint is avail or a string designating the hint -# """ -# return "hint for " + str(node_id) -# -# def OnClose(self): -# """Triggered when the graph viewer window is being closed -# @return: None -# """ -# print "Closing......." -# -# def OnClick(self, node_id): -# """ -# Triggered when a node is clicked -# @return: False to ignore the click and True otherwise -# """ -# print "clicked on", self[node_id] -# return True -# -# def OnDblClick(self, node_id): -# """ -# Triggerd when a node is double-clicked. -# @return: False to ignore the click and True otherwise -# """ -# print "dblclicked on", self[node_id] -# return True -# -# def OnCommand(self, cmd_id): -# """ -# Deprecated -# """ -# pass -# # %} diff --git a/swig/hexrays.i b/swig/hexrays.i index c557d69..cc39bc5 100644 --- a/swig/hexrays.i +++ b/swig/hexrays.i @@ -55,8 +55,14 @@ %ignore cexpr_t::contains_expr; %ignore cexpr_t::contains_expr; %ignore cexpr_t::cexpr_t(mbl_array_t *mba, const lvar_t &v); +%ignore cexpr_t::is_type_partial; +%ignore cexpr_t::set_type_partial; %ignore lvar_t::is_promoted_arg; %ignore lvar_t::lvar_t; +%ignore lvar_t::is_partialy_typed; +%ignore lvar_t::set_partialy_typed; +%ignore lvar_t::clr_partialy_typed; +%ignore lvar_t::force_lvar_type; %ignore vdloc_t::is_fpu_mreg; %ignore strtype_info_t::find_strmem; %ignore file_printer_t::_print; @@ -66,7 +72,7 @@ %extend cfunc_t { %immutable argidx; - qstring __str__() { + qstring __str__() const { qstring qs; qstring_printer_t p($self, qs, 0); $self->print_func(p); @@ -293,9 +299,15 @@ class qlist_cinsn_t_iterator {}; %template(qlist_cinsn_t) qlist; %template(qvector_carg_t) qvector; %template(qvector_ccase_t) qvector; +%template(lvar_saved_infos_t) qvector; %extend citem_cmt_t { const char *c_str() const { return self->c_str(); } + + const char *__str__() const + { + return $self->c_str(); + } }; void qswap(cinsn_t &a, cinsn_t &b); @@ -710,16 +722,6 @@ cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf); %ignore cexpr_t::find_ptr_or_array(bool) const; #pragma SWIG nowarn=503 -%warnfilter(514) user_lvar_visitor_t; // Director base class 'x' has no virtual destructor. -%warnfilter(514) ctree_visitor_t; // ditto -%warnfilter(514) ctree_parentee_t; // ditto -%warnfilter(514) cfunc_parentee_t; // ditto -%warnfilter(473) user_lvar_visitor_t::get_info_mapping_for_saving; // Returning a pointer or reference in a director method is not recommended. - -%feature("director") ctree_visitor_t; -%feature("director") ctree_parentee_t; -%feature("director") cfunc_parentee_t; -%feature("director") user_lvar_visitor_t; // http://www.swig.org/Doc2.0/SWIGDocumentation.html#Python_nn36 // http://www.swig.org/Doc2.0/SWIGDocumentation.html#Customization_exception_special_variables @@ -791,7 +793,8 @@ _listify_types(cinsnptrvec_t, qvector_carg_t, qvector_ccase_t, hexwarns_t, - history_t) + history_t, + lvar_saved_infos_t) def citem_to_specific_type(self): """ cast the citem_t object to its more specific type, either cexpr_t or cinsn_t. """ diff --git a/swig/ida.i b/swig/ida.i index e3576a1..0752a56 100644 --- a/swig/ida.i +++ b/swig/ida.i @@ -14,6 +14,7 @@ %ignore idainfo::align_short_demnames; %ignore idainfo::align_strtype; %ignore idainfo::align_long_demnames; +%ignore idainfo::store_user_info; %ignore setflag(uchar &where,uchar bit,int value); %ignore setflag(ushort &where,ushort bit,int value); diff --git a/swig/idaapi.i b/swig/idaapi.i index 1cc9c69..ef47c5f 100644 --- a/swig/idaapi.i +++ b/swig/idaapi.i @@ -1,4 +1,27 @@ %module(docstring="IDA Plugin SDK API wrapper",directors="1",threads="1") idaapi +// generate directors for all classes that have virtual methods +%feature("director"); +// exceptions +%feature("nodirector") const_visitor_t; +%feature("nodirector") const_vloc_visitor_t; +%feature("nodirector") enumplace_t; +%feature("nodirector") generic_linput64_t; +%feature("nodirector") generic_linput_t; +%feature("nodirector") place_t; +%feature("nodirector") idaplace_t; +%feature("nodirector") qrefcnt_obj_t; +%feature("nodirector") qstring_printer_t; +%feature("nodirector") simpleline_place_t; +%feature("nodirector") structplace_t; +%feature("nodirector") type_mapper_t; +%feature("nodirector") type_visitor_t; +%feature("nodirector") vc_printer_t; +%feature("nodirector") vd_printer_t; +%feature("nodirector") vloc_visitor_t; +%feature("nodirector") qflow_chart_t; +%feature("nodirector") lowertype_helper_t; +%feature("nodirector") ida_lowertype_helper_t; +%warnfilter(473) user_lvar_visitor_t::get_info_mapping_for_saving; // Returning a pointer or reference in a director method is not recommended // * http://swig.10945.n7.nabble.com/How-to-release-Python-GIL-td5027.html // * http://stackoverflow.com/questions/1576737/releasing-python-gil-in-c-code // * http://matt.eifelle.com/2007/11/23/enabling-thread-support-in-swig-and-python/ @@ -15,6 +38,7 @@ #pragma SWIG nowarn=401 #pragma SWIG nowarn=451 #pragma SWIG nowarn=454 // Setting a pointer/reference variable may leak memory +#pragma SWIG nowarn=514 // Director base class 'x' has no virtual destructor. %constant size_t SIZE_MAX = size_t(-1); %{ @@ -50,6 +74,19 @@ void raise_python_stl_exception(const std::exception &e) PyErr_SetString(PyExc_RuntimeError, what); } } + +void raise_python_swig_director_exception(const Swig::DirectorException &e) +{ + Py_INCREF(PyExc_RuntimeError); + PyErr_SetString(PyExc_RuntimeError, e.getMessage()); +} + +void raise_python_out_of_range_exception(const std::out_of_range &e) +{ + Py_INCREF(PyExc_RuntimeError); + PyErr_SetString(PyExc_IndexError, e.what()); +} + %} %define %exception_set_default_handlers() @@ -59,8 +96,10 @@ void raise_python_stl_exception(const std::exception &e) $action } catch ( const std::bad_alloc &ba ) { raise_python_stl_bad_alloc(ba); SWIG_fail; } + catch ( const std::out_of_range &e ) { raise_python_out_of_range_exception(e); SWIG_fail; } catch ( const std::exception &e ) { raise_python_stl_exception(e); SWIG_fail; } - catch (...) { raise_python_unknown_exception(); SWIG_fail; } + catch ( const Swig::DirectorException &e ) { raise_python_swig_director_exception(e); SWIG_fail; } + catch ( ... ) { raise_python_unknown_exception(); SWIG_fail; } } %enddef %exception_set_default_handlers(); @@ -108,7 +147,7 @@ static PyObject *type##_get_clink_ptr(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); return PyLong_FromUnsignedLongLong( - (unsigned PY_LONG_LONG)pyobj_get_clink(self)); + PTR2U64(pyobj_get_clink(self))); } %} %enddef @@ -175,1652 +214,6 @@ static PyObject *type##_get_clink_ptr(PyObject *self) #include "pywraps.hpp" // - -//------------------------------------------------------------------------ -// String constants used -static const char S_PY_IDCCVT_VALUE_ATTR[] = "__idc_cvt_value__"; -static const char S_PY_IDCCVT_ID_ATTR[] = "__idc_cvt_id__"; -static const char S_PY_IDC_OPAQUE_T[] = "py_idc_cvt_helper_t"; -static const char S_PY_IDC_GLOBAL_VAR_FMT[] = "__py_cvt_gvar_%d"; - -// Constants used by get_idaapi_class_reference() -#define PY_CLSID_CVT_INT64 0 -#define PY_CLSID_APPCALL_SKEL_OBJ 1 -#define PY_CLSID_CVT_BYREF 2 -#define PY_CLSID_LAST 3 - -//--------------------------------------------------------------------------- -// Use these macros to define script<->C fields -#define DEFINE_SCFIELDX(name, type, is_opt) { #name, type, qoffsetof(CUR_STRUC, name), is_opt } -#define DEFINE_SCFIELD(name, type) DEFINE_SCFIELDX(name, type, 0) -#define DEFINE_SCFIELD_OPT(name, type) DEFINE_SCFIELDX(name, type, 1) - -//--------------------------------------------------------------------------- -enum scfield_types_t -{ - // Numeric fields - FT_FIRST_NUM, - FT_INT, - FT_SIZET, - FT_SSIZET, - FT_NUM16, - FT_NUM32, - FT_LAST_NUM, - // String field - FT_STR, - FT_CHAR, - // Object fields - FT_ARR, - // Allocated array of strings - FT_STRARR, - // Allocated array of 16bit numbers - FT_NUM16ARR, - // Fixed size character array. The size must be passed in the definition - FT_CHRARR_STATIC, -}; - -//--------------------------------------------------------------------------- -struct scfld_t -{ - const char *field_name; - uint32 field_type; - size_t field_offs; - bool is_optional; -}; - -#define FT_VALUE_MASK 0xFFFF0000 -// Possible return values of conversion functions -#define FT_NOT_FOUND -1 -#define FT_BAD_TYPE -2 -#define FT_OK 1 - -//------------------------------------------------------------------------- -Py_ssize_t pyvar_walk_list( - const ref_t &py_list, - int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud), - void *ud) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - Py_ssize_t size = CIP_FAILED; - do - { - PyObject *o = py_list.o; - if ( !PyList_CheckExact(o) && !PyW_IsSequenceType(o) ) - break; - - bool is_seq = !PyList_CheckExact(o); - size = is_seq ? PySequence_Size(o) : PyList_Size(o); - if ( cb == NULL ) - break; - - Py_ssize_t i; - for ( i=0; i= CIP_OK; - if ( !ok ) - PyErr_SetString(PyExc_ValueError, "Could not convert Python object to IDC object!"); - return ok; -} - -//------------------------------------------------------------------------ -static idc_class_t *get_py_idc_cvt_opaque() -{ - return find_idc_class(S_PY_IDC_OPAQUE_T); -} - -//------------------------------------------------------------------------- -// Utility function to create opaque / convertible Python <-> IDC variables -// The referred Python variable will have its reference increased -static bool wrap_PyObject_ptr(const ref_t &py_var, idc_value_t *idc_var) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Create an IDC object of this special helper class - if ( VarObject(idc_var, get_py_idc_cvt_opaque()) != eOk ) - return false; - - // Store the CVT id - idc_value_t idc_val; - idc_val.set_long(PY_ICID_OPAQUE); - VarSetAttr(idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val); - - // Store the value as a PVOID referencing the given Python object - py_var.incref(); - idc_val.set_pvoid(py_var.o); - VarSetAttr(idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val); - - return true; -} - -//------------------------------------------------------------------------ -// IDC Opaque object destructor: when the IDC object dies we kill the -// opaque Python object along with it -static const char py_idc_cvt_helper_dtor_args[] = { VT_OBJ, 0 }; -static error_t idaapi py_idc_opaque_dtor( - idc_value_t *argv, - idc_value_t * /*res*/) -{ - // This can be called at plugin registration time, when a - // 'script_plugin_t' instance is ::free()'d. It is - // not guaranteed that we have the GIL at that point. - PYW_GIL_GET; - - // Get the value from the object - idc_value_t idc_val; - VarGetAttr(&argv[0], S_PY_IDCCVT_VALUE_ATTR, &idc_val); - - // Extract the Python object reference - PyObject *py_obj = (PyObject *)idc_val.pvoid; - - // Decrease its reference (and eventually destroy it) - Py_DECREF(py_obj); - - return eOk; -} - -//------------------------------------------------------------------------- -// Converts a Python variable into an IDC variable -// This function returns on one CIP_XXXX -int pyvar_to_idcvar( - const ref_t &py_var, - idc_value_t *idc_var, - int *gvar_sn) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // None / NULL - if ( py_var == NULL || py_var.o == Py_None ) - { - idc_var->set_long(0); - } - // Numbers? - else if ( PyW_GetNumberAsIDC(py_var.o, idc_var) ) - { - return CIP_OK; - } - // String - else if ( PyString_Check(py_var.o) ) - { - idc_var->_set_string(PyString_AsString(py_var.o), PyString_Size(py_var.o)); - } - // Boolean - else if ( PyBool_Check(py_var.o) ) - { - idc_var->set_long(py_var.o == Py_True ? 1 : 0); - } - // Float - else if ( PyFloat_Check(py_var.o) ) - { - double dresult = PyFloat_AsDouble(py_var.o); - ieee_realcvt((void *)&dresult, idc_var->e, 3); - idc_var->vtype = VT_FLOAT; - } - // void* - else if ( PyCObject_Check(py_var.o) ) - { - idc_var->set_pvoid(PyCObject_AsVoidPtr(py_var.o)); - } - // Python list? - else if ( PyList_CheckExact(py_var.o) || PyW_IsSequenceType(py_var.o) ) - { - // Create the object - VarObject(idc_var); - - // Determine list size and type - bool is_seq = !PyList_CheckExact(py_var.o); - Py_ssize_t size = is_seq ? PySequence_Size(py_var.o) : PyList_Size(py_var.o); - bool ok = true; - qstring attr_name; - - // Convert each item - for ( Py_ssize_t i=0; i= CIP_OK; - if ( ok ) - { - // Form the attribute name - newref_t py_int(PyInt_FromSsize_t(i)); - ok = PyW_ObjectToString(py_int.o, &attr_name); - if ( !ok ) - break; - // Store the attribute - VarSetAttr(idc_var, attr_name.c_str(), &v); - } - if ( !ok ) - break; - } - return ok ? CIP_OK : CIP_FAILED; - } - // Dictionary: we convert to an IDC object - else if ( PyDict_Check(py_var.o) ) - { - // Create an empty IDC object - VarObject(idc_var); - - // Get the dict.items() list - newref_t py_items(PyDict_Items(py_var.o)); - - // Get the size of the list - qstring key_name; - bool ok = true; - Py_ssize_t size = PySequence_Size(py_items.o); - for ( Py_ssize_t i=0; i (key, value) - PyObject *py_item = PyList_GetItem(py_items.o, i); - - // Extract key/value - newref_t key(PySequence_GetItem(py_item, 0)); - newref_t val(PySequence_GetItem(py_item, 1)); - - // Get key's string representation - PyW_ObjectToString(key.o, &key_name); - - // Convert the attribute into an IDC value - idc_value_t v; - ok = pyvar_to_idcvar(val, &v, gvar_sn) >= CIP_OK; - if ( ok ) - { - // Store the attribute - VarSetAttr(idc_var, key_name.c_str(), &v); - } - if ( !ok ) - break; - } - return ok ? CIP_OK : CIP_FAILED; - } - // Possible function? - else if ( PyCallable_Check(py_var.o) ) - { - idc_var->clear(); - idc_var->vtype = VT_FUNC; - idc_var->funcidx = -1; // Does not apply - return CIP_OK; - } - // Objects: - // - pyidc_cvt objects: int64, byref, opaque - // - other python objects - else - { - // Get the type - int cvt_id = get_pyidc_cvt_type(py_var.o); - switch ( cvt_id ) - { - // - // 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; - } - // - // 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 ) - { - (*gvar_sn)++; - // Create a reference to this global variable - VarRef(idc_var, gvar); - } - return ok ? CIP_OK : CIP_FAILED; - } - // - // 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 - VarObject(idc_var); - for ( Py_ssize_t i=0; i 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 - VarSetAttr(idc_var, field_name, &v); - } - } - } - return CIP_OK; -} - -//------------------------------------------------------------------------- -inline PyObject *cvt_to_pylong(int32 v) -{ - return PyLong_FromLong(v); -} - -inline PyObject *cvt_to_pylong(int64 v) -{ - return PyLong_FromLongLong(v); -} - -//------------------------------------------------------------------------- -// Converts an IDC variable to a Python variable -// If py_var points to an existing object then the object will be updated -// If py_var points to an existing immutable object then ZERO is returned -// Returns one of CIP_xxxx. Check pywraps.hpp -int idcvar_to_pyvar( - const idc_value_t &idc_var, - ref_t *py_var) -{ - 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: - { - // 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; - } - -#if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC) - case VT_STR: - *py_var = newref_t(PyString_FromString(idc_var.str)); - break; - -#endif - case VT_STR2: - 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) != 0 ) - 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 = VarDeref(const_cast(&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 ( VarGetAttr(&idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val) == eOk - && VarGetAttr(&idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val) == 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 = VarFirstAttr(&idc_var); - attr_name != NULL; - attr_name = VarNextAttr(&idc_var, attr_name) ) - { - // Get the attribute - idc_value_t v; - VarGetAttr(&idc_var, attr_name, &v, 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; -} - -//------------------------------------------------------------------------- -// Converts IDC arguments to Python argument list or just one tuple -// If 'decref' is NULL then 'pargs' will contain one element which is the tuple -bool pyw_convert_idc_args( - const idc_value_t args[], - int nargs, - ref_vec_t &pargs, - bool as_tupple, - char *errbuf, - size_t errbufsize) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - ref_t py_tuple; - - pargs.qclear(); - - if ( as_tupple ) - { - py_tuple = newref_t(PyTuple_New(nargs)); - if ( py_tuple == NULL ) - { - if ( errbuf != 0 && errbufsize > 0 ) - qstrncpy(errbuf, "Failed to create a new tuple to store arguments!", errbufsize); - return false; - } - } - - for ( int i=0; i 0 ) - qsnprintf(errbuf, errbufsize, "arg#%d has wrong type %d", i, args[i].vtype); - return false; - } - - if ( as_tupple ) - { - // PyTuple_SetItem() steals the reference. - py_obj.incref(); - QASSERT(30412, PyTuple_SetItem(py_tuple.o, i, py_obj.o) == 0); - } - else - { - pargs.push_back(py_obj); - } - } - - // Add the tuple to the list of args only now. Doing so earlier will - // cause the py_tuple.o->ob_refcnt to be 2 and not 1, and that will - // cause 'PyTuple_SetItem()' to fail. - if ( as_tupple ) - pargs.push_back(py_tuple); - - return true; -} - - - - -//------------------------------------------------------------------------ -// String constants used -static const char S_PYINVOKE0[] = "_py_invoke0"; -static const char S_PY_SWIEX_CLSNAME[] = "switch_info_ex_t"; -static const char S_PY_OP_T_CLSNAME[] = "op_t"; -static const char S_PROPS[] = "props"; -static const char S_NAME[] = "name"; -static const char S_TITLE[] = "title"; -static const char S_ASM_KEYWORD[] = "asm_keyword"; -static const char S_MENU_NAME[] = "menu_name"; -static const char S_HOTKEY[] = "hotkey"; -static const char S_EMBEDDED[] = "embedded"; -static const char S_POPUP_NAMES[] = "popup_names"; -static const char S_FLAGS[] = "flags"; -static const char S_VALUE_SIZE[] = "value_size"; -static const char S_MAY_CREATE_AT[] = "may_create_at"; -static const char S_CALC_ITEM_SIZE[] = "calc_item_size"; -static const char S_ID[] = "id"; -static const char S_PRINTF[] = "printf"; -static const char S_TEXT_WIDTH[] = "text_width"; -static const char S_SCAN[] = "scan"; -static const char S_ANALYZE[] = "analyze"; -static const char S_CBSIZE[] = "cbsize"; -static const char S_ON_CLICK[] = "OnClick"; -static const char S_ON_CLOSE[] = "OnClose"; -static const char S_ON_DBL_CLICK[] = "OnDblClick"; -static const char S_ON_CURSOR_POS_CHANGED[] = "OnCursorPosChanged"; -static const char S_ON_KEYDOWN[] = "OnKeydown"; -static const char S_ON_COMPLETE_LINE[] = "OnCompleteLine"; -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_POPUP_MENU[] = "OnPopupMenu"; -static const char S_ON_EDIT_LINE[] = "OnEditLine"; -static const char S_ON_INSERT_LINE[] = "OnInsertLine"; -static const char S_ON_GET_LINE[] = "OnGetLine"; -static const char S_ON_DELETE_LINE[] = "OnDeleteLine"; -static const char S_ON_REFRESH[] = "OnRefresh"; -static const char S_ON_REFRESHED[] = "OnRefreshed"; -static const char S_ON_EXECUTE_LINE[] = "OnExecuteLine"; -static const char S_ON_SELECT_LINE[] = "OnSelectLine"; -static const char S_ON_SELECTION_CHANGE[] = "OnSelectionChange"; -static const char S_ON_COMMAND[] = "OnCommand"; -static const char S_ON_GET_ICON[] = "OnGetIcon"; -static const char S_ON_GET_LINE_ATTR[] = "OnGetLineAttr"; -static const char S_ON_GET_SIZE[] = "OnGetSize"; -static const char S_ON_GETTEXT[] = "OnGetText"; -static const char S_ON_ACTIVATE[] = "OnActivate"; -static const char S_ON_DEACTIVATE[] = "OnDeactivate"; -static const char S_ON_SELECT[] = "OnSelect"; -static const char S_ON_CREATING_GROUP[] = "OnCreatingGroup"; -static const char S_ON_DELETING_GROUP[] = "OnDeletingGroup"; -static const char S_ON_GROUP_VISIBILITY[] = "OnGroupVisibility"; -static const char S_M_EDGES[] = "_edges"; -static const char S_M_NODES[] = "_nodes"; -static const char S_M_THIS[] = "_this"; -static const char S_M_TITLE[] = "_title"; -static const char S_CLINK_NAME[] = "__clink__"; -static const char S_ON_VIEW_ACTIVATED[] = "OnViewActivated"; -static const char S_ON_VIEW_DEACTIVATED[] = "OnViewDeactivated"; -static const char S_ON_VIEW_KEYDOWN[] = "OnViewKeydown"; -static const char S_ON_VIEW_CLICK[] = "OnViewClick"; -static const char S_ON_VIEW_DBLCLICK[] = "OnViewDblclick"; -static const char S_ON_VIEW_CURPOS[] = "OnViewCurpos"; -static const char S_ON_VIEW_SWITCHED[] = "OnViewSwitched"; -static const char S_ON_VIEW_MOUSE_OVER[] = "OnViewMouseOver"; -static const char S_ON_VIEW_MOUSE_MOVED[] = "OnViewMouseMoved"; - - -#ifdef __PYWRAPS__ -static const char S_PY_IDAAPI_MODNAME[] = "__main__"; -#else -static const char S_PY_IDAAPI_MODNAME[] = S_IDAAPI_MODNAME; -#endif - -//------------------------------------------------------------------------ -static ref_t py_cvt_helper_module; -static bool pywraps_initialized = false; - -//--------------------------------------------------------------------------- -// Context structure used by add|del_menu_item() -struct py_add_del_menu_item_ctx -{ - qstring menupath; - PyObject *cb_data; -}; - -//--------------------------------------------------------------------------- -// Context structure used by add|del_idc_hotkey() -struct py_idchotkey_ctx_t -{ - qstring hotkey; - PyObject *pyfunc; -}; - -//--------------------------------------------------------------------------- -// Context structure used by register/unregister timer -struct py_timer_ctx_t -{ - qtimer_t timer_id; - PyObject *pycallback; -}; - -//------------------------------------------------------------------------ -// check if we have a file which is known to be executed automatically -// by SWIG or Python runtime -bool pywraps_check_autoscripts(char *buf, size_t bufsize) -{ - static const char *const exts[] = - { - "py", - "pyc", - "pyd", - "pyo", - "pyw", - }; - - static const char *const fns[] = - { - "swig_runtime_data" SWIG_RUNTIME_VERSION, - "sitecustomize", - "usercustomize" - }; - - for ( size_t ifn=0; ifn < qnumber(fns); ++ifn ) - { - // check for a script or module with several possible extensions - for ( size_t iext=0; iext < qnumber(exts); ++iext ) - { - qsnprintf(buf, bufsize, "%s.%s", fns[ifn], exts[iext]); - if ( qfileexist(buf) ) - return true; - } - // check for a subdirectory under current directory - if ( qfileexist(fns[ifn]) ) - { - qstrncpy(buf, fns[ifn], bufsize); - return true; - } - } - return false; -} - -//------------------------------------------------------------------------ -error_t PyW_CreateIdcException(idc_value_t *res, const char *msg) -{ - // Create exception object - VarObject(res, find_idc_class("exception")); - - // Set the message field - idc_value_t v; - v.set_string(msg); - VarSetAttr(res, "message", &v); - - // Throw exception - return set_qerrno(eExecThrow); -} - -//------------------------------------------------------------------------ -// Calls a Python callable encoded in IDC.pvoid member -static const char idc_py_invoke0_args[] = { VT_PVOID, 0 }; -static error_t idaapi idc_py_invoke0( - idc_value_t *argv, - idc_value_t *res) -{ - PYW_GIL_GET; - PyObject *pyfunc = (PyObject *) argv[0].pvoid; - newref_t py_result(PyObject_CallFunctionObjArgs(pyfunc, NULL)); - - // Report Python error as IDC exception - qstring err; - error_t err_code = eOk; - if ( PyW_GetError(&err) ) - err_code = PyW_CreateIdcException(res, err.c_str()); - return err_code; -} - -//------------------------------------------------------------------------ -// This function must be called on initialization -bool init_pywraps() -{ - if ( pywraps_initialized ) - return true; - - // Take a reference to the idaapi python module - // (We need it to create instances of certain classes) - if ( py_cvt_helper_module == NULL ) - { - // Take a reference to the module so we can create the needed class instances - py_cvt_helper_module = PyW_TryImportModule(S_PY_IDAAPI_MODNAME); - if ( py_cvt_helper_module == NULL ) - return false; - } - - // Register the IDC PyInvoke0 method (helper function for add_idc_hotkey()) - if ( !set_idc_func_ex(S_PYINVOKE0, idc_py_invoke0, idc_py_invoke0_args, 0) ) - return false; - - // IDC opaque class not registered? - if ( get_py_idc_cvt_opaque() == NULL ) - { - // Add the class - idc_class_t *idc_cvt_opaque = add_idc_class(S_PY_IDC_OPAQUE_T); - if ( idc_cvt_opaque == NULL ) - return false; - - // Form the dtor name - char dtor_name[MAXSTR]; - qsnprintf(dtor_name, sizeof(dtor_name), "%s.dtor", S_PY_IDC_OPAQUE_T); - - // Register the dtor function - if ( !set_idc_func_ex(dtor_name, py_idc_opaque_dtor, py_idc_cvt_helper_dtor_args, 0) ) - return false; - - // Link the dtor function to the class - set_idc_dtor(idc_cvt_opaque, dtor_name); - } - - pywraps_initialized = true; - return true; -} - -//------------------------------------------------------------------------ -// This function must be called on de-initialization -void deinit_pywraps() -{ - if ( !pywraps_initialized ) - return; - - pywraps_initialized = false; - - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - py_cvt_helper_module = ref_t(); // Deref. - } - - // Unregister the IDC PyInvoke0 method (helper function for add_idc_hotkey()) - set_idc_func_ex(S_PYINVOKE0, NULL, idc_py_invoke0_args, 0); -} - -//------------------------------------------------------------------------ -// Utility function to create a class instance whose constructor takes zero arguments -ref_t create_idaapi_class_instance0(const char *clsname) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t py_cls(get_idaapi_attr(clsname)); - if ( py_cls == NULL ) - return ref_t(); - - ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL)); - if ( PyW_GetError() || py_obj == NULL ) - py_obj = ref_t(); - return py_obj; -} - -//------------------------------------------------------------------------ -// Utility function to create linked class instances -ref_t create_idaapi_linked_class_instance( - const char *clsname, - void *lnk) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t py_cls(get_idaapi_attr(clsname)); - if ( py_cls == NULL ) - return ref_t(); - - newref_t py_lnk(PyCObject_FromVoidPtr(lnk, NULL)); - ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, py_lnk.o, NULL)); - if ( PyW_GetError() || py_obj == NULL ) - py_obj = ref_t(); - return py_obj; -} - -//------------------------------------------------------------------------ -// Gets a class type reference in idaapi -// With the class type reference we can create a new instance of that type -// This function takes a reference to the idaapi module and keeps the reference -ref_t get_idaapi_attr_by_id(const int class_id) -{ - if ( class_id >= PY_CLSID_LAST || py_cvt_helper_module == NULL ) - return ref_t(); - - // Some class names. The array is parallel with the PY_CLSID_xxx consts - static const char *class_names[]= - { - "PyIdc_cvt_int64__", - "object_t", - "PyIdc_cvt_refclass__" - }; - PYW_GIL_CHECK_LOCKED_SCOPE(); - return newref_t(PyObject_GetAttrString(py_cvt_helper_module.o, class_names[class_id])); -} - -//------------------------------------------------------------------------ -// Gets a class reference by name -ref_t get_idaapi_attr(const char *attrname) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return py_cvt_helper_module == NULL - ? ref_t() - : PyW_TryGetAttrString(py_cvt_helper_module.o, attrname); -} - -//------------------------------------------------------------------------ -// Returns a qstring from an object attribute -bool PyW_GetStringAttr( - PyObject *py_obj, - const char *attr_name, - qstring *str) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t py_attr(PyW_TryGetAttrString(py_obj, attr_name)); - if ( py_attr == NULL ) - return false; - - bool ok = PyString_Check(py_attr.o) != 0; - if ( ok ) - *str = PyString_AsString(py_attr.o); - - return ok; -} - -//------------------------------------------------------------------------ -// Returns an attribute or NULL -// No errors will be set if the attribute did not exist -ref_t PyW_TryGetAttrString(PyObject *py_obj, const char *attr) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t o; - if ( PyObject_HasAttrString(py_obj, attr) ) - o = newref_t(PyObject_GetAttrString(py_obj, attr)); - return o; -} - -//------------------------------------------------------------------------ -// Tries to import a module and clears the exception on failure -ref_t PyW_TryImportModule(const char *name) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t result(PyImport_ImportModule(name)); - if ( result == NULL && PyErr_Occurred() ) - PyErr_Clear(); - return result; -} - -//------------------------------------------------------------------------- -// Converts a Python number into an IDC value (32 or 64bits) -// The function will first try to convert the number into a 32bit value -// If the number does not fit then VT_INT64 will be used -// NB: This function cannot properly detect if the Python value should be -// converted to a VT_INT64 or not. For example: 2**32-1 = 0xffffffff which -// can fit in a C long but Python creates a PyLong object for it. -// And because of that we are confused as to whether to convert to 32 or 64 -bool PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool rc = true; - do - { - if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) ) - { - rc = false; - break; - } - - // Can we convert to C long? - long l = PyInt_AsLong(py_var); - if ( !PyErr_Occurred() ) - { - idc_var->set_long(l); - break; - } - // Clear last error - PyErr_Clear(); - // Can be fit into a C unsigned long? - l = (long) PyLong_AsUnsignedLong(py_var); - if ( !PyErr_Occurred() ) - { - idc_var->set_long(l); - break; - } - PyErr_Clear(); - idc_var->set_int64(PyLong_AsLongLong(py_var)); - } while ( false ); - return rc; -} - -//------------------------------------------------------------------------- -// Parses a Python object as a long or long long -bool PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool rc = true; -#define SETNUM(numexpr, is64_expr) \ - do \ - { \ - if ( num != NULL ) \ - *num = numexpr; \ - if ( is_64 != NULL ) \ - *is_64 = is64_expr; \ - } while ( false ) - - do - { - if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) ) - { - rc = false; - break; - } - - // Can we convert to C long? - long l = PyInt_AsLong(py_var); - if ( !PyErr_Occurred() ) - { - SETNUM(uint64(l), false); - break; - } - - // Clear last error - PyErr_Clear(); - - // Can be fit into a C unsigned long? - unsigned long ul = PyLong_AsUnsignedLong(py_var); - if ( !PyErr_Occurred() ) - { - SETNUM(uint64(ul), false); - break; - } - PyErr_Clear(); - - // Try to parse as int64 - PY_LONG_LONG ll = PyLong_AsLongLong(py_var); - if ( !PyErr_Occurred() ) - { - SETNUM(uint64(ll), true); - break; - } - PyErr_Clear(); - - // Try to parse as uint64 - unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var); - PyObject *err = PyErr_Occurred(); - if ( err == NULL ) - { - SETNUM(uint64(ull), true); - break; - } - // Negative number? _And_ it with uint64(-1) - rc = false; - if ( err == PyExc_TypeError ) - { - newref_t py_mask(Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull)); - newref_t py_num(PyNumber_And(py_var, py_mask.o)); - if ( py_num != NULL && py_mask != NULL ) - { - PyErr_Clear(); - ull = PyLong_AsUnsignedLongLong(py_num.o); - if ( !PyErr_Occurred() ) - { - SETNUM(uint64(ull), true); - rc = true; - } - } - } - PyErr_Clear(); - } while ( false ); - return rc; -#undef SETNUM -} - -//------------------------------------------------------------------------- -// Checks if a given object is of sequence type -bool PyW_IsSequenceType(PyObject *obj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool rc = true; - do - { - if ( !PySequence_Check(obj) ) - { - rc = false; - break; - } - - Py_ssize_t sz = PySequence_Size(obj); - if ( sz == -1 || PyErr_Occurred() != NULL ) - { - PyErr_Clear(); - rc = false; - break; - } - } while ( false ); - return rc; -} - -//------------------------------------------------------------------------- -// Returns the string representation of an object -bool PyW_ObjectToString(PyObject *obj, qstring *out) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_str(PyObject_Str(obj)); - bool ok = py_str != NULL; - if ( ok ) - *out = PyString_AsString(py_str.o); - else - out->qclear(); - return ok; -} - -//-------------------------------------------------------------------------- -// Checks if a Python error occured and fills the out parameter with the -// exception string -bool PyW_GetError(qstring *out, bool clear_err) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( PyErr_Occurred() == NULL ) - return false; - - // Error occurred but details not needed? - if ( out == NULL ) - { - // Just clear the error - if ( clear_err ) - PyErr_Clear(); - return true; - } - - // Get the exception info - PyObject *err_type, *err_value, *err_traceback, *py_ret(NULL); - PyErr_Fetch(&err_type, &err_value, &err_traceback); - - if ( !clear_err ) - PyErr_Restore(err_type, err_value, err_traceback); - - // Resolve FormatExc() - ref_t py_fmtexc(get_idaapi_attr(S_IDAAPI_FORMATEXC)); - - // Helper there? - if ( py_fmtexc != NULL ) - { - // Call helper - py_ret = PyObject_CallFunctionObjArgs( - py_fmtexc.o, - err_type, - err_value, - err_traceback, - NULL); - } - - // Clear the error - if ( clear_err ) - PyErr_Clear(); - - // Helper failed?! - if ( py_ret == NULL ) - { - // Just convert the 'value' part of the original error - py_ret = PyObject_Str(err_value); - } - - // No exception text? - if ( py_ret == NULL ) - { - *out = "IDAPython: unknown error!"; - } - else - { - *out = PyString_AsString(py_ret); - Py_DECREF(py_ret); - } - - if ( clear_err ) - { - Py_XDECREF(err_traceback); - Py_XDECREF(err_value); - Py_XDECREF(err_type); - } - return true; -} - -//------------------------------------------------------------------------- -bool PyW_GetError(char *buf, size_t bufsz, bool clear_err) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - qstring s; - if ( !PyW_GetError(&s, clear_err) ) - return false; - - qstrncpy(buf, s.c_str(), bufsz); - return true; -} - -//------------------------------------------------------------------------- -// A loud version of PyGetError() which gets the error and displays it -// This method is used to display errors that occurred in a callback -bool PyW_ShowCbErr(const char *cb_name) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - static qstring err_str; - if ( !PyW_GetError(&err_str) ) - return false; - - warning("IDAPython: Error while calling Python callback <%s>:\n%s", cb_name, err_str.c_str()); - return true; -} - -//--------------------------------------------------------------------------- -void *pyobj_get_clink(PyObject *pyobj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Try to query the link attribute - ref_t attr(PyW_TryGetAttrString(pyobj, S_CLINK_NAME)); - void *t = attr != NULL && PyCObject_Check(attr.o) ? PyCObject_AsVoidPtr(attr.o) : NULL; - return t; -} - - - -//------------------------------------------------------------------------ - -//------------------------------------------------------------------------ -class pywraps_notify_when_t -{ - ref_vec_t table[NW_EVENTSCNT]; - qstring err; - bool in_notify; - struct notify_when_args_t - { - int when; - PyObject *py_callable; - }; - typedef qvector notify_when_args_vec_t; - notify_when_args_vec_t delayed_notify_when_list; - - //------------------------------------------------------------------------ - static int idaapi idp_callback(void *ud, int event_id, va_list va) - { - // This hook gets called from the kernel. Ensure we hold the GIL. - PYW_GIL_GET; - pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud; - switch ( event_id ) - { - case processor_t::newfile: - case processor_t::oldfile: - { - int old = event_id == processor_t::oldfile ? 1 : 0; - char *dbname = va_arg(va, char *); - _this->notify(NW_OPENIDB_SLOT, old); - } - break; - case processor_t::closebase: - _this->notify(NW_CLOSEIDB_SLOT); - break; - } - // event not processed, let other plugins or the processor module handle it - return 0; - } - - //------------------------------------------------------------------------ - bool unnotify_when(int when, PyObject *py_callable) - { - int cnt = 0; - for ( int slot=0; slot 0; - } - - //------------------------------------------------------------------------ - void register_callback(int slot, PyObject *py_callable) - { - borref_t callable_ref(py_callable); - ref_vec_t &tbl = table[slot]; - ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref); - - // Already added - if ( it != it_end ) - return; - - // Insert the element - tbl.push_back(callable_ref); - } - - //------------------------------------------------------------------------ - void unregister_callback(int slot, PyObject *py_callable) - { - borref_t callable_ref(py_callable); - ref_vec_t &tbl = table[slot]; - ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref); - - // Not found? - if ( it == it_end ) - return; - - // Delete the element - tbl.erase(it); - } - -public: - //------------------------------------------------------------------------ - bool init() - { - return hook_to_notification_point(HT_IDP, idp_callback, this); - } - - //------------------------------------------------------------------------ - bool deinit() - { - // Uninstall all objects - ref_vec_t::iterator it, it_end; - for ( int slot=0; sloto); - } - // ...and remove the notification - return unhook_from_notification_point(HT_IDP, idp_callback, this); - } - - //------------------------------------------------------------------------ - bool notify_when(int when, PyObject *py_callable) - { - // While in notify() do not allow insertion or deletion to happen on the spot - // Instead we will queue them so that notify() will carry the action when it finishes - // dispatching the notification handlers - if ( in_notify ) - { - notify_when_args_t &args = delayed_notify_when_list.push_back(); - args.when = when; - args.py_callable = py_callable; - return true; - } - // Uninstalling the notification? - if ( (when & NW_REMOVE) != 0 ) - return unnotify_when(when & ~NW_REMOVE, py_callable); - - int cnt = 0; - for ( int slot=0; slot 0; - } - - //------------------------------------------------------------------------ - bool notify(int slot, ...) - { - va_list va; - va_start(va, slot); - bool ok = notify_va(slot, va); - va_end(va); - return ok; - } - - //------------------------------------------------------------------------ - bool notify_va(int slot, va_list va) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Sanity bounds check! - if ( slot < 0 || slot >= NW_EVENTSCNT ) - return false; - - bool ok = true; - in_notify = true; - int old = slot == NW_OPENIDB_SLOT ? va_arg(va, int) : 0; - - { - for (ref_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end(); - it != it_end; - ++it) - { - // Form the notification code - newref_t py_code(PyInt_FromLong(1 << slot)); - ref_t py_result; - switch ( slot ) - { - case NW_CLOSEIDB_SLOT: - case NW_INITIDA_SLOT: - case NW_TERMIDA_SLOT: - { - py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, NULL)); - break; - } - case NW_OPENIDB_SLOT: - { - newref_t py_old(PyInt_FromLong(old)); - py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, py_old.o, NULL)); - } - break; - } - if ( PyW_GetError(&err) || py_result == NULL ) - { - PyErr_Clear(); - warning("notify_when(): Error occured while notifying object.\n%s", err.c_str()); - ok = false; - } - } - } - in_notify = false; - - // Process any delayed notify_when() calls that - if ( !delayed_notify_when_list.empty() ) - { - for (notify_when_args_vec_t::iterator it = delayed_notify_when_list.begin(), it_end=delayed_notify_when_list.end(); - it != it_end; - ++it) - { - notify_when(it->when, it->py_callable); - } - delayed_notify_when_list.qclear(); - } - - return ok; - } - - //------------------------------------------------------------------------ - pywraps_notify_when_t() - { - in_notify = false; - } -}; - -static pywraps_notify_when_t *g_nw = NULL; - -//------------------------------------------------------------------------ -// Initializes the notify_when mechanism -// (Normally called by IDAPython plugin.init()) -bool pywraps_nw_init() -{ - if ( g_nw != NULL ) - return true; - - g_nw = new pywraps_notify_when_t(); - if ( g_nw->init() ) - return true; - - // Things went bad, undo! - delete g_nw; - g_nw = NULL; - return false; -} - -//------------------------------------------------------------------------ -bool pywraps_nw_notify(int slot, ...) -{ - if ( g_nw == NULL ) - return false; - - // Appears to be called from 'driver_notifywhen.cpp', which - // itself is called from possibly non-python code. - // I.e., we must acquire the GIL. - PYW_GIL_GET; - va_list va; - va_start(va, slot); - bool ok = g_nw->notify_va(slot, va); - va_end(va); - - return ok; -} - -//------------------------------------------------------------------------ -// Deinitializes the notify_when mechanism -bool pywraps_nw_term() -{ - if ( g_nw == NULL ) - return true; - - // If could not deinitialize then return w/o stopping nw - if ( !g_nw->deinit() ) - return false; - - // Cleanup - delete g_nw; - g_nw = NULL; - return true; -} - // %} @@ -1852,614 +245,6 @@ typedef int error_t; %pythoncode %{ # - -import struct -import traceback -import os -import sys -import bisect -import __builtin__ -import imp - -def require(modulename, package=None): - """ - Load, or reload a module. - - When under heavy development, a user's tool might consist of multiple - modules. If those are imported using the standard 'import' mechanism, - there is no guarantee that the Python implementation will re-read - and re-evaluate the module's Python code. In fact, it usually doesn't. - What should be done instead is 'reload()'-ing that module. - - This is a simple helper function that will do just that: In case the - module doesn't exist, it 'import's it, and if it does exist, - 'reload()'s it. - - For more information, see: . - """ - if modulename in sys.modules.keys(): - reload(sys.modules[modulename]) - else: - import importlib - import inspect - m = importlib.import_module(modulename, package) - frame_obj, filename, line_number, function_name, lines, index = inspect.stack()[1] - importer_module = inspect.getmodule(frame_obj) - if importer_module is None: # No importer module; called from command line - importer_module = sys.modules['__main__'] - setattr(importer_module, modulename, m) - sys.modules[modulename] = m - -# ----------------------------------------------------------------------- - -# Seek constants -SEEK_SET = 0 # from the file start -SEEK_CUR = 1 # from the current position -SEEK_END = 2 # from the file end - -# Plugin constants -PLUGIN_MOD = 0x0001 -PLUGIN_DRAW = 0x0002 -PLUGIN_SEG = 0x0004 -PLUGIN_UNL = 0x0008 -PLUGIN_HIDE = 0x0010 -PLUGIN_DBG = 0x0020 -PLUGIN_PROC = 0x0040 -PLUGIN_FIX = 0x0080 -PLUGIN_SKIP = 0 -PLUGIN_OK = 1 -PLUGIN_KEEP = 2 - -# PyIdc conversion object IDs -PY_ICID_INT64 = 0 -"""int64 object""" -PY_ICID_BYREF = 1 -"""byref object""" -PY_ICID_OPAQUE = 2 -"""opaque object""" - -# Step trace options (used with set_step_trace_options()) -ST_OVER_DEBUG_SEG = 0x01 -"""step tracing will be disabled when IP is in a debugger segment""" - -ST_OVER_LIB_FUNC = 0x02 -"""step tracing will be disabled when IP is in a library function""" - -# ----------------------------------------------------------------------- -class pyidc_opaque_object_t(object): - """This is the base class for all Python<->IDC opaque objects""" - __idc_cvt_id__ = PY_ICID_OPAQUE - -# ----------------------------------------------------------------------- -class py_clinked_object_t(pyidc_opaque_object_t): - """ - This is a utility and base class for C linked objects - """ - def __init__(self, lnk = None): - # static link: if a link was provided - self.__static_clink__ = True if lnk else False - - # Create link if it was not provided - self.__clink__ = lnk if lnk else self._create_clink() - - def __del__(self): - """Delete the link upon object destruction (only if not static)""" - self._free() - - def _free(self): - """Explicitly delete the link (only if not static)""" - if not self.__static_clink__ and self.__clink__ is not None: - self._del_clink(self.__clink__) - self.__clink__ = None - - def copy(self): - """Returns a new copy of this class""" - - # Create an unlinked instance - inst = self.__class__() - - # Assign self to the new instance - inst.assign(self) - - return inst - - # - # Methods to be overwritten - # - def _create_clink(self): - """ - Overwrite me. - Creates a new clink - @return: PyCObject representing the C link - """ - pass - - def _del_clink(self, lnk): - """ - Overwrite me. - This method deletes the link - """ - pass - - def _get_clink_ptr(self): - """ - Overwrite me. - Returns the C link pointer as a 64bit number - """ - pass - - def assign(self, other): - """ - Overwrite me. - This method allows you to assign an instance contents to anothers - @return: Boolean - """ - pass - - clink = property(lambda self: self.__clink__) - """Returns the C link as a PyObject""" - - clink_ptr = property(lambda self: self._get_clink_ptr()) - """Returns the C link pointer as a number""" - -# ----------------------------------------------------------------------- -class object_t(object): - """Helper class used to initialize empty objects""" - def __init__(self, **kwds): - self.__dict__ = kwds - - def __getitem__(self, idx): - """Allow access to object attributes by index (like dictionaries)""" - return getattr(self, idx) - -# ----------------------------------------------------------------------- -def _bounded_getitem_iterator(self): - """Helper function, to be set as __iter__ method for qvector-, or array-based classes.""" - for i in range(len(self)): - yield self[i] - -# ----------------------------------------------------------------------- -class plugin_t(pyidc_opaque_object_t): - """Base class for all scripted plugins.""" - pass - -# ----------------------------------------------------------------------- -class pyidc_cvt_helper__(object): - """ - This is a special helper object that helps detect which kind - of object is this python object wrapping and how to convert it - back and from IDC. - This object is characterized by its special attribute and its value - """ - def __init__(self, cvt_id, value): - self.__idc_cvt_id__ = cvt_id - self.value = value - - def __set_value(self, v): - self.__idc_cvt_value__ = v - def __get_value(self): - return self.__idc_cvt_value__ - value = property(__get_value, __set_value) - -# ----------------------------------------------------------------------- -class PyIdc_cvt_int64__(pyidc_cvt_helper__): - """Helper class for explicitly representing VT_INT64 values""" - - def __init__(self, v): - # id = 0 = int64 object - super(self.__class__, self).__init__(PY_ICID_INT64, v) - - # operation table - __op_table = \ - { - 0: lambda a, b: a + b, - 1: lambda a, b: a - b, - 2: lambda a, b: a * b, - 3: lambda a, b: a / b - } - # carries the operation given its number - def __op(self, op_n, other, rev=False): - a = self.value - # other operand of same type? then take its value field - if type(other) == type(self): - b = other.value - else: - b = other - if rev: - t = a - a = b - b = t - # construct a new object and return as the result - return self.__class__(self.__op_table[op_n](a, b)) - - # overloaded operators - def __add__(self, other): return self.__op(0, other) - def __sub__(self, other): return self.__op(1, other) - def __mul__(self, other): return self.__op(2, other) - def __div__(self, other): return self.__op(3, other) - def __radd__(self, other): return self.__op(0, other, True) - def __rsub__(self, other): return self.__op(1, other, True) - def __rmul__(self, other): return self.__op(2, other, True) - def __rdiv__(self, other): return self.__op(3, other, True) - -# ----------------------------------------------------------------------- -# qstrvec_t clinked object -class _qstrvec_t(py_clinked_object_t): - """ - WARNING: It is very unlikely an IDAPython user should ever, ever - have to use this type. It should only be used for IDAPython internals. - - For example, in py_askusingform.py, we ctypes-expose to the IDA - kernel & UI a qstrvec instance, in case a DropdownListControl is - constructed. - That's because that's what AskUsingForm expects, and we have no - choice but to make a DropdownListControl hold a qstrvec_t. - This is, afaict, the only situation where a Python - _qstrvec_t is required. - """ - - def __init__(self, items=None): - py_clinked_object_t.__init__(self) - # Populate the list if needed - if items: - self.from_list(items) - - def _create_clink(self): - return _idaapi.qstrvec_t_create() - - def _del_clink(self, lnk): - return _idaapi.qstrvec_t_destroy(lnk) - - def _get_clink_ptr(self): - return _idaapi.qstrvec_t_get_clink_ptr(self) - - def assign(self, other): - """Copies the contents of 'other' to 'self'""" - return _idaapi.qstrvec_t_assign(self, other) - - def __setitem__(self, idx, s): - """Sets string at the given index""" - return _idaapi.qstrvec_t_set(self, idx, s) - - def __getitem__(self, idx): - """Gets the string at the given index""" - return _idaapi.qstrvec_t_get(self, idx) - - def __get_size(self): - return _idaapi.qstrvec_t_size(self) - - size = property(__get_size) - """Returns the count of elements""" - - def addressof(self, idx): - """Returns the address (as number) of the qstring at the given index""" - return _idaapi.qstrvec_t_addressof(self, idx) - - def add(self, s): - """Add a string to the vector""" - return _idaapi.qstrvec_t_add(self, s) - - def from_list(self, lst): - """Populates the vector from a Python string list""" - return _idaapi.qstrvec_t_from_list(self, lst) - - def clear(self, qclear=False): - """ - Clears all strings from the vector. - @param qclear: Just reset the size but do not actually free the memory - """ - return _idaapi.qstrvec_t_clear(self, qclear) - - def insert(self, idx, s): - """Insert a string into the vector""" - return _idaapi.qstrvec_t_insert(self, idx, s) - - def remove(self, idx): - """Removes a string from the vector""" - return _idaapi.qstrvec_t_remove(self, idx) - -# ----------------------------------------------------------------------- -class PyIdc_cvt_refclass__(pyidc_cvt_helper__): - """Helper class for representing references to immutable objects""" - def __init__(self, v): - # id = one = byref object - super(self.__class__, self).__init__(PY_ICID_BYREF, v) - - def cstr(self): - """Returns the string as a C string (up to the zero termination)""" - return as_cstr(self.value) - -# ----------------------------------------------------------------------- -def as_cstr(val): - """ - Returns a C str from the passed value. The passed value can be of type refclass (returned by a call to buffer() or byref()) - It scans for the first \x00 and returns the string value up to that point. - """ - if isinstance(val, PyIdc_cvt_refclass__): - val = val.value - - n = val.find('\x00') - return val if n == -1 else val[:n] - -# ----------------------------------------------------------------------- -def as_unicode(s): - """Convenience function to convert a string into appropriate unicode format""" - # use UTF16 big/little endian, depending on the environment? - return unicode(s).encode("UTF-16" + ("BE" if _idaapi.cvar.inf.mf else "LE")) - -# ----------------------------------------------------------------------- -def as_uint32(v): - """Returns a number as an unsigned int32 number""" - return v & 0xffffffff - -# ----------------------------------------------------------------------- -def as_int32(v): - """Returns a number as a signed int32 number""" - return -((~v & 0xffffffff)+1) - -# ----------------------------------------------------------------------- -def as_signed(v, nbits = 32): - """ - Returns a number as signed. The number of bits are specified by the user. - The MSB holds the sign. - """ - return -(( ~v & ((1 << nbits)-1) ) + 1) if v & (1 << nbits-1) else v - -# ---------------------------------------------------------------------- -def copy_bits(v, s, e=-1): - """ - Copy bits from a value - @param v: the value - @param s: starting bit (0-based) - @param e: ending bit - """ - # end-bit not specified? use start bit (thus extract one bit) - if e == -1: - e = s - # swap start and end if start > end - if s > e: - e, s = s, e - - mask = ~(((1 << (e-s+1))-1) << s) - - return (v & mask) >> s - -# ---------------------------------------------------------------------- -__struct_unpack_table = { - 1: ('b', 'B'), - 2: ('h', 'H'), - 4: ('l', 'L'), - 8: ('q', 'Q') -} - -# ---------------------------------------------------------------------- -def struct_unpack(buffer, signed = False, offs = 0): - """ - Unpack a buffer given its length and offset using struct.unpack_from(). - This function will know how to unpack the given buffer by using the lookup table '__struct_unpack_table' - If the buffer is of unknown length then None is returned. Otherwise the unpacked value is returned. - """ - # Supported length? - n = len(buffer) - if n not in __struct_unpack_table: - return None - # Conver to number - signed = 1 if signed else 0 - - # Unpack - return struct.unpack_from(__struct_unpack_table[n][signed], buffer, offs)[0] - - -# ------------------------------------------------------------ -def IDAPython_ExecSystem(cmd): - """ - Executes a command with popen(). - """ - try: - f = os.popen(cmd, "r") - s = ''.join(f.readlines()) - f.close() - return s - except Exception as e: - return "%s\n%s" % (str(e), traceback.format_exc()) - -# ------------------------------------------------------------ -def IDAPython_FormatExc(etype, value, tb, limit=None): - """ - This function is used to format an exception given the - values returned by a PyErr_Fetch() - """ - try: - return ''.join(traceback.format_exception(etype, value, tb, limit)) - except: - return str(value) - - -# ------------------------------------------------------------ -def IDAPython_ExecScript(script, g): - """ - Run the specified script. - It also addresses http://code.google.com/p/idapython/issues/detail?id=42 - - This function is used by the low-level plugin code. - """ - scriptpath = os.path.dirname(script) - if len(scriptpath) and scriptpath not in sys.path: - sys.path.append(scriptpath) - - argv = sys.argv - sys.argv = [ script ] - - # Adjust the __file__ path in the globals we pass to the script - old__file__ = g['__file__'] if '__file__' in g else '' - g['__file__'] = script - - try: - execfile(script, g) - PY_COMPILE_ERR = None - except Exception as e: - PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc()) - print(PY_COMPILE_ERR) - finally: - # Restore state - g['__file__'] = old__file__ - sys.argv = argv - - return PY_COMPILE_ERR - -# ------------------------------------------------------------ -def IDAPython_LoadProcMod(script, g): - """ - Load processor module. - """ - pname = g['__name__'] if g and g.has_key("__name__") else '__main__' - parent = sys.modules[pname] - - scriptpath, scriptname = os.path.split(script) - if len(scriptpath) and scriptpath not in sys.path: - sys.path.append(scriptpath) - - procmod_name = os.path.splitext(scriptname)[0] - procobj = None - fp = None - try: - fp, pathname, description = imp.find_module(procmod_name) - procmod = imp.load_module(procmod_name, fp, pathname, description) - if parent: - setattr(parent, procmod_name, procmod) - # export attrs from parent to processor module - parent_attrs = getattr(parent, '__all__', - (attr for attr in dir(parent) if not attr.startswith('_'))) - for pa in parent_attrs: - setattr(procmod, pa, getattr(parent, pa)) - # instantiate processor object - if getattr(procmod, 'PROCESSOR_ENTRY', None): - procobj = procmod.PROCESSOR_ENTRY() - PY_COMPILE_ERR = None - except Exception as e: - PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc()) - print(PY_COMPILE_ERR) - finally: - if fp: fp.close() - - sys.path.remove(scriptpath) - - return (PY_COMPILE_ERR, procobj) - -# ------------------------------------------------------------ -def IDAPython_UnLoadProcMod(script, g): - """ - Unload processor module. - """ - pname = g['__name__'] if g and g.has_key("__name__") else '__main__' - parent = sys.modules[pname] - - scriptname = os.path.split(script)[1] - procmod_name = os.path.splitext(scriptname)[0] - if getattr(parent, procmod_name, None): - delattr(parent, procmod_name) - del sys.modules[procmod_name] - PY_COMPILE_ERR = None - return PY_COMPILE_ERR - -# ---------------------------------------------------------------------- -class __IDAPython_Completion_Util(object): - """Internal utility class for auto-completion support""" - def __init__(self): - self.n = 0 - self.completion = None - self.lastmodule = None - - @staticmethod - def parse_identifier(line, prefix, prefix_start): - """ - Parse a line and extracts identifier - """ - id_start = prefix_start - while id_start > 0: - ch = line[id_start] - if not ch.isalpha() and ch != '.' and ch != '_': - id_start += 1 - break - id_start -= 1 - - return line[id_start:prefix_start + len(prefix)] - - @staticmethod - def dir_of(m, prefix): - return [x for x in dir(m) if x.startswith(prefix)] - - @classmethod - def get_completion(cls, id, prefix): - try: - m = sys.modules['__main__'] - - parts = id.split('.') - c = len(parts) - - for i in xrange(0, c-1): - m = getattr(m, parts[i]) - except Exception as e: - return (None, None) - else: - # search in the module - completion = cls.dir_of(m, prefix) - - # no completion found? looking from the global scope? then try the builtins - if not completion and c == 1: - completion = cls.dir_of(__builtin__, prefix) - - return (m, completion) if completion else (None, None) - - def __call__(self, prefix, n, line, prefix_start): - if n == 0: - self.n = n - id = self.parse_identifier(line, prefix, prefix_start) - self.lastmodule, self.completion = self.get_completion(id, prefix) - - if self.completion is None or n >= len(self.completion): - return None - - s = self.completion[n] - try: - attr = getattr(self.lastmodule, s) - # Is it callable? - if callable(attr): - return s + ("" if line.startswith("?") else "(") - # Is it iterable? - elif isinstance(attr, basestring) or getattr(attr, '__iter__', False): - return s + "[" - except: - pass - - return s - -# Instantiate an IDAPython command completion object (for use with IDA's CLI bar) -IDAPython_Completion = __IDAPython_Completion_Util() - -def _listify_types(*classes): - for cls in classes: - cls.__getitem__ = cls.at - cls.__len__ = cls.size - cls.__iter__ = _bounded_getitem_iterator - - - -# The general callback format of notify_when() is: -# def notify_when_callback(nw_code) -# In the case of NW_OPENIDB, the callback is: -# def notify_when_callback(nw_code, is_old_database) -NW_OPENIDB = 0x0001 -"""Notify when the database is opened. Its callback is of the form: def notify_when_callback(nw_code, is_old_database)""" -NW_CLOSEIDB = 0x0002 -"""Notify when the database is closed. Its callback is of the form: def notify_when_callback(nw_code)""" -NW_INITIDA = 0x0004 -"""Notify when the IDA starts. Its callback is of the form: def notify_when_callback(nw_code)""" -NW_TERMIDA = 0x0008 -"""Notify when the IDA terminates. Its callback is of the form: def notify_when_callback(nw_code)""" -NW_REMOVE = 0x0010 -"""Use this flag with other flags to uninstall a notifywhen callback""" - # %} @@ -2494,6 +279,7 @@ NW_REMOVE = 0x0010 %include "ida.i" %include "idd.i" %include "idp.i" +%include "idbhooks.i" %include "netnode.i" %include "nalt.i" @@ -2501,8 +287,10 @@ NW_REMOVE = 0x0010 %include "area.i" %include "auto.i" %include "bytes.i" +%include "custdata.i" %include "dbg.i" %include "diskio.i" +%include "linput.i" %include "entry.i" %include "enum.i" %include "expr.i" @@ -2528,244 +316,19 @@ PyObject *qstrvec2pylist(qstrvec_t &vec) %} %inline %{ - // -//------------------------------------------------------------------------ -/* -# -def parse_command_line(cmdline): - """ - Parses a space separated string (quotes and escape character are supported) - @param cmdline: The command line to parse - @return: A list of strings or None on failure - """ - pass -# -*/ -static PyObject *py_parse_command_line(const char *cmdline) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - qstrvec_t args; - if ( parse_command_line3(cmdline, &args, NULL, LP_PATH_WITH_ARGS) == 0 ) - Py_RETURN_NONE; - return qstrvec2pylist(args); -} - -//------------------------------------------------------------------------- -/* -# -def get_inf_structure(): - """ - Returns the global variable 'inf' (an instance of idainfo structure, see ida.hpp) - """ - pass -# -*/ -idainfo *get_inf_structure(void) -{ - return &inf; -} - -//------------------------------------------------------------------------- -// Declarations from Python.cpp -/* -# -def set_script_timeout(timeout): - """ - Changes the script timeout value. The script wait box dialog will be hidden and shown again when the timeout elapses. - See also L{disable_script_timeout}. - - @param timeout: This value is in seconds. - If this value is set to zero then the script will never timeout. - @return: Returns the old timeout value - """ - pass -# -*/ -int set_script_timeout(int timeout); - -/* -# -def disable_script_timeout(): - """ - Disables the script timeout and hides the script wait box. - Calling L{set_script_timeout} will not have any effects until the script is compiled and executed again - - @return: None - """ - pass -# -*/ -void disable_script_timeout(); - -/* -# -def enable_extlang_python(enable): - """ - Enables or disables Python extlang. - When enabled, all expressions will be evaluated by Python. - @param enable: Set to True to enable, False otherwise - """ - pass -# -*/ -void enable_extlang_python(bool enable); -void enable_python_cli(bool enable); - -/* -# -def RunPythonStatement(stmt): - """ - This is an IDC function exported from the Python plugin. - It is used to evaluate Python statements from IDC. - @param stmt: The statement to evaluate - @return: 0 - on success otherwise a string containing the error - """ - pass -# -*/ - -//--------------------------------------------------------------------------- -// qstrvec_t wrapper (INTERNAL! Don't expose. See py_idaapi.py) -//--------------------------------------------------------------------------- -static bool qstrvec_t_assign(PyObject *self, PyObject *other) -{ - qstrvec_t *lhs = qstrvec_t_get_clink(self); - qstrvec_t *rhs = qstrvec_t_get_clink(other); - if (lhs == NULL || rhs == NULL) - return false; - *lhs = *rhs; - return true; -} - -static PyObject *qstrvec_t_addressof(PyObject *self, size_t idx) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL || idx >= sv->size() ) - Py_RETURN_NONE; - else - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)&sv->at(idx)); -} - - -static bool qstrvec_t_set( - PyObject *self, - size_t idx, - const char *s) -{ - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL || idx >= sv->size() ) - return false; - (*sv)[idx] = s; - return true; -} - -static bool qstrvec_t_from_list( - PyObject *self, - PyObject *py_list) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - qstrvec_t *sv = qstrvec_t_get_clink(self); - return sv == NULL ? false : PyW_PyListToStrVec(py_list, *sv); -} - -static size_t qstrvec_t_size(PyObject *self) -{ - qstrvec_t *sv = qstrvec_t_get_clink(self); - return sv == NULL ? 0 : sv->size(); -} - -static PyObject *qstrvec_t_get(PyObject *self, size_t idx) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL || idx >= sv->size() ) - Py_RETURN_NONE; - return PyString_FromString(sv->at(idx).c_str()); -} - -static bool qstrvec_t_add(PyObject *self, const char *s) -{ - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL ) - return false; - sv->push_back(s); - return true; -} - -static bool qstrvec_t_clear(PyObject *self, bool qclear) -{ - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL ) - return false; - - if ( qclear ) - sv->qclear(); - else - sv->clear(); - - return true; -} - -static bool qstrvec_t_insert( - PyObject *self, - size_t idx, - const char *s) -{ - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL || idx >= sv->size() ) - return false; - sv->insert(sv->begin() + idx, s); - return true; -} - -static bool qstrvec_t_remove(PyObject *self, size_t idx) -{ - qstrvec_t *sv = qstrvec_t_get_clink(self); - if ( sv == NULL || idx >= sv->size() ) - return false; - - sv->erase(sv->begin()+idx); - return true; -} - -//--------------------------------------------------------------------------- - - - -//------------------------------------------------------------------------ -/* -# -def notify_when(when, callback): - """ - Register a callback that will be called when an event happens. - @param when: one of NW_XXXX constants - @param callback: This callback prototype varies depending on the 'when' parameter: - The general callback format: - def notify_when_callback(nw_code) - In the case of NW_OPENIDB: - def notify_when_callback(nw_code, is_old_database) - @return: Boolean - """ - pass -# -*/ -static bool notify_when(int when, PyObject *py_callable) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( g_nw == NULL || !PyCallable_Check(py_callable) ) - return false; - return g_nw->notify_when(when, py_callable); -} - // %} %include "gdl.i" %include "ints.i" %include "kernwin.i" +%include "cli.i" +%include "choose.i" +%include "choose2.i" +%include "plgform.i" +%include "custview.i" +%include "askusingform.i" %include "lines.i" %include "loader.i" %include "moves.i" diff --git a/swig/idbhooks.i b/swig/idbhooks.i new file mode 100644 index 0000000..40c8f84 --- /dev/null +++ b/swig/idbhooks.i @@ -0,0 +1,10 @@ + +%inline %{ +// +// +%} + +%{ +// +// +%} diff --git a/swig/idd.i b/swig/idd.i index 48aa6b8..50b1720 100644 --- a/swig/idd.i +++ b/swig/idd.i @@ -14,890 +14,19 @@ %clear(char dtyp); -%pythoncode %{ -# -NO_PROCESS = 0xFFFFFFFF -NO_THREAD = 0 -# -%} +%rename (appcall) py_appcall; %{ // - -//------------------------------------------------------------------------- -static bool dbg_can_query() -{ - // Reject the request only if no debugger is set - // or the debugger cannot be queried while not in suspended state - return dbg != NULL && (dbg->may_disturb() || get_process_state() < DSTATE_NOTASK); -} - -//------------------------------------------------------------------------- -static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - PyObject *py_list = PyList_New(areas.size()); - meminfo_vec_t::const_iterator it, it_end(areas.end()); - Py_ssize_t i = 0; - for ( it=areas.begin(); it!=it_end; ++it, ++i ) - { - const memory_info_t &mi = *it; - // startEA endEA name sclass sbase bitness perm - PyList_SetItem(py_list, i, - Py_BuildValue("("PY_FMT64 PY_FMT64 "ss" PY_FMT64 "II)", - pyul_t(mi.startEA), - pyul_t(mi.endEA), - mi.name.c_str(), - mi.sclass.c_str(), - pyul_t(mi.sbase), - (unsigned int)(mi.bitness), - (unsigned int)mi.perm)); - } - return py_list; -} - -//------------------------------------------------------------------------- -PyObject *py_appcall( - ea_t func_ea, - thid_t tid, - PyObject *py_type, - PyObject *py_fields, - PyObject *arg_list) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !PyList_Check(arg_list) ) - return NULL; - - const char *type = py_type == Py_None ? NULL : PyString_AS_STRING(py_type); - const char *fields = py_fields == Py_None ? NULL : PyString_AS_STRING(py_fields); - - // Convert Python arguments into IDC values - qvector idc_args; - int sn = 0; - Py_ssize_t nargs = PyList_Size(arg_list); - idc_args.resize(nargs); - bool ok = true; - for ( Py_ssize_t i=0; i%s\n", int(i), s.c_str()); - } - // Convert it - if ( pyvar_to_idcvar(py_item, &idc_args[i], &sn) < CIP_OK ) - { - ok = false; - break; - } - } - - // Set exception message - if ( !ok ) - { - PyErr_SetString( - PyExc_ValueError, - "PyAppCall: Failed to convert Python values to IDC values"); - return NULL; - } - - error_t ret; - idc_value_t idc_result; - Py_BEGIN_ALLOW_THREADS; - - if ( (debug & IDA_DEBUG_APPCALL) != 0 ) - { - msg("input variables:\n" - "----------------\n"); - - qstring s; - for ( Py_ssize_t i=0; iob_refcnt == 1); - if ( (debug & IDA_DEBUG_APPCALL) != 0 ) - { - msg("return var:\n" - "-----------\n"); - qstring s; - VarPrint(&s, &idc_result); - msg("%s\n-----------\n", s.c_str()); - } - py_result.incref(); - return py_result.o; -} // %} -%rename (appcall) py_appcall; - %inline %{ - // - -//------------------------------------------------------------------------- -/* -# -def dbg_get_registers(): - """ - This function returns the register definition from the currently loaded debugger. - Basically, it returns an array of structure similar to to idd.hpp / register_info_t - @return: - None if no debugger is loaded - tuple(name, flags, class, dtyp, bit_strings, default_bit_strings_mask) - The bit_strings can be a tuple of strings or None (if the register does not have bit_strings) - """ - pass -# -*/ -static PyObject *dbg_get_registers() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( dbg == NULL ) - Py_RETURN_NONE; - - PyObject *py_list = PyList_New(dbg->registers_size); - - for ( int i=0; iregisters_size; i++ ) - { - register_info_t &ri = dbg->registers(i); - PyObject *py_bits; - - // Does this register have bit strings? - // (Make sure it does not use custom formats because bit_string would be the format name) - if ( ri.bit_strings != NULL && (ri.flags & REGISTER_CUSTFMT) == 0 ) - { - int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4; - py_bits = PyList_New(nbits); - for ( int i=0; i -def dbg_get_thread_sreg_base(tid, sreg_value): - """ - Returns the segment register base value - @param tid: thread id - @param sreg_value: segment register (selector) value - @return: - - The base as an 'ea' - - Or None on failure - """ - pass -# -*/ -static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) ) - Py_RETURN_NONE; - ea_t answer; - thid_t tid = PyInt_AsLong(py_tid); - int sreg_value = PyInt_AsLong(py_sreg_value); - if ( internal_get_sreg_base(tid, sreg_value, &answer) != 1 ) - Py_RETURN_NONE; - - return Py_BuildValue(PY_FMT64, pyul_t(answer)); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_read_memory(ea, sz): - """ - Reads from the debugee's memory at the specified ea - @return: - - The read buffer (as a string) - - Or None on failure - """ - pass -# -*/ -static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - uint64 ea, sz; - if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) ) - Py_RETURN_NONE; - - // Create a Python string - PyObject *ret = PyString_FromStringAndSize(NULL, Py_ssize_t(sz)); - if ( ret == NULL ) - Py_RETURN_NONE; - - // Get the internal buffer - Py_ssize_t len; - char *buf; - PyString_AsStringAndSize(ret, &buf, &len); - - if ( (size_t)read_dbg_memory(ea_t(ea), buf, size_t(sz)) != sz ) - { - // Release the string on failure - Py_DECREF(ret); - // Return None on failure - Py_RETURN_NONE; - } - return ret; -} - -//------------------------------------------------------------------------- -/* -# -def dbg_write_memory(ea, buffer): - """ - Writes a buffer to the debugee's memory - @return: Boolean - """ - pass -# -*/ -static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - uint64 ea; - if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) ) - Py_RETURN_NONE; - - size_t sz = PyString_GET_SIZE(py_buf); - void *buf = (void *)PyString_AS_STRING(py_buf); - if ( write_dbg_memory(ea_t(ea), buf, sz) != sz ) - Py_RETURN_FALSE; - Py_RETURN_TRUE; -} - -//------------------------------------------------------------------------- -/* -# -def dbg_get_name(): - """ - This function returns the current debugger's name. - @return: Debugger name or None if no debugger is active - """ - pass -# -*/ -static PyObject *dbg_get_name() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( dbg == NULL ) - Py_RETURN_NONE; - else - return PyString_FromString(dbg->name); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_get_memory_info(): - """ - This function returns the memory configuration of a debugged process. - @return: - None if no debugger is active - tuple(startEA, endEA, name, sclass, sbase, bitness, perm) - """ - pass -# -*/ -static PyObject *dbg_get_memory_info() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !dbg_can_query() ) - Py_RETURN_NONE; - - // Invalidate memory - meminfo_vec_t areas; - Py_BEGIN_ALLOW_THREADS; - invalidate_dbgmem_config(); - invalidate_dbgmem_contents(BADADDR, BADADDR); - - get_dbg_memory_info(&areas); - Py_END_ALLOW_THREADS; - return meminfo_vec_t_to_py(areas); -} - -//------------------------------------------------------------------------- -/* -# -def dbg_can_query(): - """ - This function can be used to check if the debugger can be queried: - - debugger is loaded - - process is suspended - - process is not suspended but can take requests. In this case some requests like - memory read/write, bpt management succeed and register querying will fail. - Check if idaapi.get_process_state() < 0 to tell if the process is suspended - @return: Boolean - """ - pass -# -*/ -static bool dbg_can_query(); -PyObject *py_appcall( - ea_t func_ea, - thid_t tid, - PyObject *py_type, - PyObject *py_fields, - PyObject *arg_list); // - -char get_event_module_name(const debug_event_t* ev, char *buf, size_t bufsize) -{ - qstrncpy(buf, ev->modinfo.name, bufsize); - return true; -} - -ea_t get_event_module_base(const debug_event_t* ev) -{ - return ev->modinfo.base; -} - -asize_t get_event_module_size(const debug_event_t* ev) -{ - return ev->modinfo.size; -} - -char get_event_exc_info(const debug_event_t* ev, char *buf, size_t bufsize) -{ - qstrncpy(buf, ev->exc.info, bufsize); - return true; -} - -char get_event_info(const debug_event_t* ev, char *buf, size_t bufsize) -{ - qstrncpy(buf, ev->info, bufsize); - return true; -} - -ea_t get_event_bpt_hea(const debug_event_t* ev) -{ - return ev->bpt.hea; -} - -uint get_event_exc_code(const debug_event_t* ev) -{ - return ev->exc.code; -} - -ea_t get_event_exc_ea(const debug_event_t* ev) -{ - return ev->exc.ea; -} - -bool can_exc_continue(const debug_event_t* ev) -{ - return ev->exc.can_cont; -} %} %pythoncode %{ # -import types - -# ----------------------------------------------------------------------- -class Appcall_array__(object): - """This class is used with Appcall.array() method""" - def __init__(self, tp): - self.__type = tp - - def pack(self, L): - """Packs a list or tuple into a byref buffer""" - t = type(L) - if not (t == types.ListType or t == types.TupleType): - raise ValueError, "Either a list or a tuple must be passed" - self.__size = len(L) - if self.__size == 1: - self.__typedobj = Appcall__.typedobj(self.__type + ";") - else: - self.__typedobj = Appcall__.typedobj("%s x[%d];" % (self.__type, self.__size)) - # Now store the object in a string buffer - ok, buf = self.__typedobj.store(L) - if ok: - return Appcall__.byref(buf) - else: - return None - - def try_to_convert_to_list(self, obj): - """Is this object a list? We check for the existance of attribute zero and attribute self.size-1""" - if not (hasattr(obj, "0") and hasattr(obj, str(self.__size-1))): - return obj - # at this point, we are sure we have an "idc list" - # let us convert to a Python list - return [getattr(obj, str(x)) for x in xrange(0, self.__size)] - - def unpack(self, buf, as_list=True): - """Unpacks an array back into a list or an object""" - # take the value from the special ref object - if isinstance(buf, PyIdc_cvt_refclass__): - buf = buf.value - - # we can only unpack from strings - if type(buf) != types.StringType: - raise ValueError, "Cannot unpack this type!" - # now unpack - ok, obj = self.__typedobj.retrieve(buf) - if not ok: - raise ValueError, "Failed while unpacking!" - if not as_list: - return obj - return self.try_to_convert_to_list(obj) - - -# ----------------------------------------------------------------------- -# Wrapper class for the appcall() -class Appcall_callable__(object): - """ - Helper class to issue appcalls using a natural syntax: - appcall.FunctionNameInTheDatabase(arguments, ....) - or - appcall["Function@8"](arguments, ...) - or - f8 = appcall["Function@8"] - f8(arg1, arg2, ...) - or - o = appcall.obj() - i = byref(5) - appcall.funcname(arg1, i, "hello", o) - """ - def __init__(self, ea, tp = None, fld = None): - """Initializes an appcall with a given function ea""" - self.__ea = ea - self.__type = tp - self.__fields = fld - self.__options = None # Appcall options - self.__timeout = None # Appcall timeout - - def __get_timeout(self): - return self.__timeout - - def __set_timeout(self, v): - self.__timeout = v - - timeout = property(__get_timeout, __set_timeout) - """An Appcall instance can change its timeout value with this attribute""" - - def __get_options(self): - return self.__options if self.__options != None else Appcall__.get_appcall_options() - - def __set_options(self, v): - if self.timeout: - # If timeout value is set, then put the timeout flag and encode the timeout value - v |= Appcall__.APPCALL_TIMEOUT | (self.timeout << 16) - else: - # Timeout is not set, then clear the timeout flag - v &= ~Appcall__.APPCALL_TIMEOUT - - self.__options = v - - options = property(__get_options, __set_options) - """Sets the Appcall options locally to this Appcall instance""" - - def __call__(self, *args): - """Make object callable. We redirect execution to idaapi.appcall()""" - if self.ea is None: - raise ValueError, "Object not callable!" - - # convert arguments to a list - arg_list = list(args) - - # Save appcall options and set new global options - old_opt = Appcall__.get_appcall_options() - Appcall__.set_appcall_options(self.options) - - # Do the Appcall (use the wrapped version) - e_obj = None - try: - r = _idaapi.appcall( - self.ea, - _idaapi.get_current_thread(), - self.type, - self.fields, - arg_list) - except Exception as e: - e_obj = e - - # Restore appcall options - Appcall__.set_appcall_options(old_opt) - - # Return or re-raise exception - if e_obj: - raise Exception, e_obj - - return r - - def __get_ea(self): - return self.__ea - - def __set_ea(self, val): - self.__ea = val - - ea = property(__get_ea, __set_ea) - """Returns or sets the EA associated with this object""" - - def __get_size(self): - if self.__type == None: - return -1 - r = _idaapi.calc_type_size(_idaapi.cvar.idati, self.__type) - if not r: - return -1 - return r - - size = property(__get_size) - """Returns the size of the type""" - - def __get_type(self): - return self.__type - - type = property(__get_type) - """Returns the typestring""" - - def __get_fields(self): - return self.__fields - - fields = property(__get_fields) - """Returns the field names""" - - - def retrieve(self, src=None, flags=0): - """ - Unpacks a typed object from the database if an ea is given or from a string if a string was passed - @param src: the address of the object or a string - @return: Returns a tuple of boolean and object or error number (Bool, Error | Object). - """ - - # Nothing passed? Take the address and unpack from the database - if src is None: - src = self.ea - - if type(src) == types.StringType: - return _idaapi.unpack_object_from_bv(_idaapi.cvar.idati, self.type, self.fields, src, flags) - else: - return _idaapi.unpack_object_from_idb(_idaapi.cvar.idati, self.type, self.fields, src, flags) - - def store(self, obj, dest_ea=None, base_ea=0, flags=0): - """ - Packs an object into a given ea if provided or into a string if no address was passed. - @param obj: The object to pack - @param dest_ea: If packing to idb this will be the store location - @param base_ea: If packing to a buffer, this will be the base that will be used to relocate the pointers - - @return: - - If packing to a string then a Tuple(Boolean, packed_string or error code) - - If packing to the database then a return code is returned (0 is success) - """ - - # no ea passed? thus pack to a string - if dest_ea is None: - return _idaapi.pack_object_to_bv(obj, - _idaapi.cvar.idati, - self.type, - self.fields, - base_ea, - flags) - else: - return _idaapi.pack_object_to_idb(obj, - _idaapi.cvar.idati, - self.type, - self.fields, - dest_ea, - flags) - -# ----------------------------------------------------------------------- -class Appcall_consts__(object): - """Helper class used by Appcall.Consts attribute - It is used to retrieve constants via attribute access""" - def __init__(self, default=0): - self.__default = default - - def __getattr__(self, attr): - return Appcall__.valueof(attr, self.__default) - -# ----------------------------------------------------------------------- -class Appcall__(object): - APPCALL_MANUAL = 0x1 - """ - Only set up the appcall, do not run it. - you should call CleanupAppcall() when finished - """ - - APPCALL_DEBEV = 0x2 - """ - Return debug event information - If this bit is set, exceptions during appcall - will generate idc exceptions with full - information about the exception - """ - - APPCALL_TIMEOUT = 0x4 - """ - Appcall with timeout - The timeout value in milliseconds is specified - in the high 2 bytes of the 'options' argument: - If timed out, errbuf will contain "timeout". - """ - - def __init__(self): - self.__consts = Appcall_consts__() - def __get_consts(self): - return self.__consts - Consts = property(__get_consts) - """Use Appcall.Consts.CONST_NAME to access constants""" - - @staticmethod - def __name_or_ea(name_or_ea): - """ - Function that accepts a name or an ea and checks if the address is enabled. - If a name is passed then idaapi.get_name_ea() is applied to retrieve the name - @return: - - Returns the resolved EA or - - Raises an exception if the address is not enabled - """ - - # a string? try to resolve it - if type(name_or_ea) == types.StringType: - ea = _idaapi.get_name_ea(_idaapi.BADADDR, name_or_ea) - else: - ea = name_or_ea - # could not resolve name or invalid address? - if ea == _idaapi.BADADDR or not _idaapi.isEnabled(ea): - raise ValueError, "Undefined function " + name_or_ea - return ea - - @staticmethod - def proto(name_or_ea, prototype, flags = None): - """ - Allows you to instantiate an appcall (callable object) with the desired prototype - @param name_or_ea: The name of the function (will be resolved with LocByName()) - @param prototype: - @return: - - On failure it raises an exception if the prototype could not be parsed - or the address is not resolvable - - Returns a callbable Appcall instance with the given prototypes and flags - """ - - # resolve and raise exception on error - ea = Appcall__.__name_or_ea(name_or_ea) - # parse the type - if flags is None: - flags = 1 | 2 | 4 # PT_SIL | PT_NDC | PT_TYP - - result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, prototype, flags) - if result is None: - raise ValueError, "Could not parse type: " + prototype - - # Return the callable method with type info - return Appcall_callable__(ea, result[1], result[2]) - - def __getattr__(self, name_or_ea): - """Allows you to call functions as if they were member functions (by returning a callable object)""" - # resolve and raise exception on error - ea = self.__name_or_ea(name_or_ea) - if ea == _idaapi.BADADDR: - raise ValueError, "Undefined function " + name - # Return the callable method - return Appcall_callable__(ea) - - def __getitem__(self, idx): - """ - Use self[func_name] syntax if the function name contains invalid characters for an attribute name - See __getattr___ - """ - return self.__getattr__(idx) - - @staticmethod - def valueof(name, default=0): - """ - Returns the numeric value of a given name string. - If the name could not be resolved then the default value will be returned - """ - t, v = _idaapi.get_name_value(_idaapi.BADADDR, name) - if t == 0: # NT_NONE - v = default - return v - - @staticmethod - def int64(v): - """Whenever a 64bit number is needed use this method to construct an object""" - return PyIdc_cvt_int64__(v) - - @staticmethod - def byref(val): - """ - Method to create references to immutable objects - Currently we support references to int/strings - Objects need not be passed by reference (this will be done automatically) - """ - return PyIdc_cvt_refclass__(val) - - @staticmethod - def buffer(str = None, size = 0, fill="\x00"): - """ - Creates a string buffer. The returned value (r) will be a byref object. - Use r.value to get the contents and r.size to get the buffer's size - """ - if str is None: - str = "" - left = size - len(str) - if left > 0: - str = str + (fill * left) - r = Appcall__.byref(str) - r.size = size - return r - - @staticmethod - def obj(**kwds): - """Returns an empty object or objects with attributes as passed via its keywords arguments""" - return object_t(**kwds) - - @staticmethod - def cstr(val): - return as_cstr(val) - - @staticmethod - def unicode(s): - return as_unicode(s) - - @staticmethod - def array(type_name): - """Defines an array type. Later you need to pack() / unpack()""" - return Appcall_array__(type_name) - - @staticmethod - def typedobj(typestr, ea=None): - """ - Parses a type string and returns an appcall object. - One can then use retrieve() member method - @param ea: Optional parameter that later can be used to retrieve the type - @return: Appcall object or raises ValueError exception - """ - # parse the type - result = _idaapi.idc_parse_decl(_idaapi.cvar.idati, typestr, 1 | 2 | 4) # PT_SIL | PT_NDC | PT_TYP - if result is None: - raise ValueError, "Could not parse type: " + typestr - # Return the callable method with type info - return Appcall_callable__(ea, result[1], result[2]) - - @staticmethod - def set_appcall_options(opt): - """Method to change the Appcall options globally (not per Appcall)""" - old_opt = Appcall__.get_appcall_options() - _idaapi.cvar.inf.appcall_options = opt - return old_opt - - @staticmethod - def get_appcall_options(): - """Return the global Appcall options""" - return _idaapi.cvar.inf.appcall_options - - @staticmethod - def cleanup_appcall(tid = 0): - """Equivalent to IDC's CleanupAppcall()""" - return _idaapi.cleanup_appcall(tid) - -Appcall = Appcall__() # %} diff --git a/swig/idp.i b/swig/idp.i index 15a2f81..dfcc795 100644 --- a/swig/idp.i +++ b/swig/idp.i @@ -17,6 +17,18 @@ %ignore IDPOPT_BADVALUE; %ignore set_options_t; %ignore read_user_config_file; +%ignore read_config; +%ignore read_config_file; +%ignore read_config_string; +%ignore read_kernel_config_file; +%ignore split_path_envvar; +%ignore get_user_idadirs; +%ignore find_cfg_files; +%ignore cfgopt_t; +%ignore cfgopt_t__apply; +%ignore parse_config_value; +%ignore get_idptype_and_data; + %ignore s_preline; %ignore ca_operation_t; @@ -34,14 +46,12 @@ %ignore IDP_Callback; %ignore _py_getreg; %ignore free_processor_module; -%ignore read_config_file; %ignore cfg_compiler_changed; %ignore gen_idb_event; +%ignore print_spec_entry; %include "idp.hpp" -%feature("director") IDB_Hooks; -%feature("director") IDP_Hooks; %extend areacb_t { areacb_type_t get_type() @@ -57,1612 +67,18 @@ } } +%ignore IDP_Hooks::bool_to_cmdsize; +%ignore IDP_Hooks::bool_to_2or0; +%ignore IDP_Hooks::cm_t_to_int; +%ignore IDP_Hooks::handle_custom_mnem_output; +%ignore IDP_Hooks::handle_assemble_output; + %inline %{ - // -//------------------------------------------------------------------------- - -//------------------------------------------------------------------------- -/* -# -def AssembleLine(ea, cs, ip, use32, line): - """ - Assemble an instruction to a string (display a warning if an error is found) - - @param ea: linear address of instruction - @param cs: cs of instruction - @param ip: ip of instruction - @param use32: is 32bit segment - @param line: line to assemble - @return: - - None on failure - - or a string containing the assembled instruction - """ - pass -# -*/ -static PyObject *AssembleLine( - ea_t ea, - ea_t cs, - ea_t ip, - bool use32, - const char *line) -{ - int inslen; - char buf[MAXSTR]; - bool ok = false; - if (ph.notify != NULL && - (inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0) - { - ok = true; - } - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return PyString_FromStringAndSize(buf, inslen); - else - Py_RETURN_NONE; -} - -//--------------------------------------------------------------------------- -/* -# -def assemble(ea, cs, ip, use32, line): - """ - Assemble an instruction into the database (display a warning if an error is found) - @param ea: linear address of instruction - @param cs: cs of instruction - @param ip: ip of instruction - @param use32: is 32bit segment? - @param line: line to assemble - - @return: Boolean. True on success. - """ -# -*/ -bool assemble( - ea_t ea, - ea_t cs, - ea_t ip, - bool use32, - const char *line) -{ - int inslen; - char buf[MAXSTR]; - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool rc = false; - Py_BEGIN_ALLOW_THREADS; - if (ph.notify != NULL) - { - inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf); - if (inslen > 0) - { - patch_many_bytes(ea, buf, inslen); - rc = true; - } - } - Py_END_ALLOW_THREADS; - return rc; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_id(): - """ - Returns the 'ph.id' field - """ - pass -# -*/ -static size_t ph_get_id() -{ - return ph.id; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_version(): - """ - Returns the 'ph.version' - """ - pass -# -*/ -static size_t ph_get_version() -{ - return ph.version; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_flag(): - """ - Returns the 'ph.flag' - """ - pass -# -*/ -static size_t ph_get_flag() -{ - return ph.flag; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_cnbits(): - """ - Returns the 'ph.cnbits' - """ - pass -# -*/ -static size_t ph_get_cnbits() -{ - return ph.cnbits; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_dnbits(): - """ - Returns the 'ph.dnbits' - """ - pass -# -*/ -static size_t ph_get_dnbits() -{ - return ph.dnbits; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_regFirstSreg(): - """ - Returns the 'ph.regFirstSreg' - """ - pass -# -*/ -static size_t ph_get_regFirstSreg() -{ - return ph.regFirstSreg; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_regLastSreg(): - """ - Returns the 'ph.regLastSreg' - """ - pass -# -*/ -static size_t ph_get_regLastSreg() -{ - return ph.regLastSreg; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_segreg_size(): - """ - Returns the 'ph.segreg_size' - """ - pass -# -*/ -static size_t ph_get_segreg_size() -{ - return ph.segreg_size; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_regCodeSreg(): - """ - Returns the 'ph.regCodeSreg' - """ - pass -# -*/ -static size_t ph_get_regCodeSreg() -{ - return ph.regCodeSreg; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_regDataSreg(): - """ - Returns the 'ph.regDataSreg' - """ - pass -# -*/ -static size_t ph_get_regDataSreg() -{ - return ph.regDataSreg; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_high_fixup_bits(): - """ - Returns the 'ph.high_fixup_bits' - """ - pass -# -*/ -static size_t ph_get_high_fixup_bits() -{ - return ph.high_fixup_bits; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_icode_return(): - """ - Returns the 'ph.icode_return' - """ - pass -# -*/ -static size_t ph_get_icode_return() -{ - return ph.icode_return; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_instruc_start(): - """ - Returns the 'ph.instruc_start' - """ - pass -# -*/ -static size_t ph_get_instruc_start() -{ - return ph.instruc_start; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_instruc_end(): - """ - Returns the 'ph.instruc_end' - """ - pass -# -*/ -static size_t ph_get_instruc_end() -{ - return ph.instruc_end; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_tbyte_size(): - """ - Returns the 'ph.tbyte_size' field as defined in he processor module - """ - pass -# -*/ -static size_t ph_get_tbyte_size() -{ - return ph.tbyte_size; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_instruc(): - """ - Returns a list of tuples (instruction_name, instruction_feature) containing the - instructions list as defined in he processor module - """ - pass -# -*/ -static PyObject *ph_get_instruc() -{ - Py_ssize_t i = 0; - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start); - for ( const instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end; - p != end; - ++p ) - { - PyTuple_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature)); - } - return py_result; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_regnames(): - """ - Returns the list of register names as defined in the processor module - """ - pass -# -*/ -static PyObject *ph_get_regnames() -{ - Py_ssize_t i = 0; - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_result = PyList_New(ph.regsNum); - for ( Py_ssize_t i=0; i -def ph_get_operand_info(): - """ - Returns the operand information given an ea and operand number. - - @param ea: address - @param n: operand number - - @return: Returns an idd_opinfo_t as a tuple: (modified, ea, reg_ival, regidx, value_size). - Please refer to idd_opinfo_t structure in the SDK. - """ - pass -# -*/ -static PyObject *ph_get_operand_info( - ea_t ea, - int n) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool ok = false; - idd_opinfo_t opinf; - Py_BEGIN_ALLOW_THREADS; - do - { - if ( dbg == NULL || n == - 1 ) - break; - - // Allocate register space - thid_t tid = get_current_thread(); - regvals_t regvalues; - regvalues.resize(dbg->registers_size); - // Read registers - if ( get_reg_vals(tid, -1, regvalues.begin()) != 1 ) - break; - - // Call the processor module - if ( ph.notify(ph.get_operand_info, - ea, - n, - tid, - _py_getreg, - regvalues.begin(), - &opinf) > 0 ) - { - break; - } - ok = true; - } while (false); - - Py_END_ALLOW_THREADS; - if ( ok ) - return Py_BuildValue("(i" PY_FMT64 "Kii)", - opinf.modified, - opinf.ea, - opinf.value.ival, - opinf.debregidx, - opinf.value_size); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -/* -# -class IDP_Hooks(object): - def hook(self): - """ - Creates an IDP hook - - @return: Boolean true on success - """ - pass - - - def unhook(self): - """ - Removes the IDP hook - @return: Boolean true on success - """ - pass - - - def custom_ana(self): - """ - Analyzes and decodes an instruction at idaapi.cmd.ea - - cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE - - cmd.size must be set to the instruction length - - @return: Boolean - - False if the instruction is not recognized - - True if the instruction was decoded. idaapi.cmd should be filled in that case. - """ - pass - - - def custom_out(self): - """ - Outputs the instruction defined in idaapi.cmd - - @return: Boolean (whether this instruction can be outputted or not) - """ - pass - - - def custom_emu(self): - """ - Emulate instruction, create cross-references, plan to analyze - subsequent instructions, modify flags etc. Upon entrance to this function - all information about the instruction is in 'cmd' structure. - - @return: Boolean (whether this instruction has been emulated or not) - """ - pass - - - def custom_outop(self, op): - """ - Notification to generate operand text. - If False was returned, then the standard operand output function will be called. - - The output buffer is inited with init_output_buffer() - and this notification may use out_...() functions to form the operand text - - @return: Boolean (whether the operand has been outputted or not) - """ - pass - - def custom_mnem(self): - """ - Prints the mnemonic of the instruction defined in idaapi.cmd - - @return: - - None: No mnemonic. IDA will use the default mnemonic value if present - - String: The desired mnemonic string - """ - pass - - - def is_sane_insn(self, no_crefs): - """ - is the instruction sane for the current file type? - @param no_crefs: - - 1: the instruction has no code refs to it. - ida just tries to convert unexplored bytes - to an instruction (but there is no other - reason to convert them into an instruction) - - 0: the instruction is created because - of some coderef, user request or another - weighty reason. - @return: 1-ok, <=0-no, the instruction isn't likely to appear in the program - """ - pass - - - def may_be_func(self, no_crefs): - """ - Can a function start here? - @param state: autoanalysis phase - 0: creating functions - 1: creating chunks - - @return: integer (probability 0..100) - """ - pass - - - def closebase(self): - """ - The database will be closed now - """ - pass - - - def savebase(self): - """ - The database is being saved. Processor module should - """ - pass - - - def rename(self, ea, new_name): - """ - The kernel is going to rename a byte. - - @param ea: Address - @param new_name: The new name - - @return: - - If returns value <=0, then the kernel should - not rename it. See also the 'renamed' event - """ - pass - - - def renamed(self, ea, new_name, local_name): - """ - The kernel has renamed a byte - - @param ea: Address - @param new_name: The new name - @param local_name: Is local name - - @return: Ignored - """ - pass - - - def undefine(self, ea): - """ - An item in the database (insn or data) is being deleted - @param ea: Address - @return: - - returns: >0-ok, <=0-the kernel should stop - - if the return value is positive: - bit0 - ignored - bit1 - do not delete srareas at the item end - """ - pass - - - def make_code(self, ea, size): - """ - An instruction is being created - @param ea: Address - @param size: Instruction size - @return: 1-ok, <=0-the kernel should stop - """ - pass - - - def make_code(self, ea, size): - """ - An instruction is being created - @param ea: Address - @param size: Instruction size - @return: 1-ok, <=0-the kernel should stop - """ - pass - - - def make_data(self, ea, flags, tid, len): - """ - A data item is being created - @param ea: Address - @param tid: type id - @param flags: item flags - @param len: data item size - @return: 1-ok, <=0-the kernel should stop - """ - pass - - - def load_idasgn(self, short_sig_name): - """ - FLIRT signature have been loaded for normal processing - (not for recognition of startup sequences) - @param short_sig_name: signature name - @return: Ignored - """ - pass - - - def add_func(self, func): - """ - The kernel has added a function - @param func: the func_t instance - @return: Ignored - """ - pass - - - def del_func(self, func): - """ - The kernel is about to delete a function - @param func: the func_t instance - @return: 1-ok,<=0-do not delete - """ - pass - - - def is_call_insn(self, ea, func_name): - """ - Is the instruction a "call"? - - @param ea: instruction address - @return: 1-unknown, 0-no, 2-yes - """ - pass - - - def is_ret_insn(self, ea, func_name): - """ - Is the instruction a "return"? - - @param ea: instruction address - @param strict: - True: report only ret instructions - False: include instructions like "leave" which begins the function epilog - @return: 1-unknown, 0-no, 2-yes - """ - pass - - - def assemble(self, ea, cs, ip, use32, line): - """ - Assembles an instruction - - @param ea: linear address of instruction - @param cs: cs of instruction - @param ip: ip of instruction - @param use32: is 32bit segment? - @param line: line to assemble - - @return: - None to let the underlying processor module assemble the line - - or a string containing the assembled buffer - """ - pass - -# -*/ -//--------------------------------------------------------------------------- -// IDP hooks -//--------------------------------------------------------------------------- -int idaapi IDP_Callback(void *ud, int notification_code, va_list va); -class IDP_Hooks -{ -public: - virtual ~IDP_Hooks() - { - unhook(); - } - - bool hook() - { - return hook_to_notification_point(HT_IDP, IDP_Callback, this); - } - - bool unhook() - { - return unhook_from_notification_point(HT_IDP, IDP_Callback, this); - } - - virtual bool custom_ana() - { - return false; - } - - virtual bool custom_out() - { - return false; - } - - virtual bool custom_emu() - { - return false; - } - - virtual bool custom_outop(PyObject *py_op) - { - return false; - } - - virtual PyObject *custom_mnem() - { - Py_RETURN_NONE; - } - - virtual int is_sane_insn(int no_crefs) - { - return 0; - } - - virtual int may_be_func(int state) - { - return 0; - } - - virtual int closebase() - { - return 0; - } - - virtual void savebase() - { - } - - virtual void auto_empty_finally() - { - } - - virtual int rename(ea_t ea, const char *new_name) - { - return 0; - } - - virtual void renamed(ea_t ea, const char *new_name, bool local_name) - { - } - - virtual int undefine(ea_t ea) - { - return 0; - } - - virtual int make_code(ea_t ea, asize_t size) - { - return 0; - } - - virtual int make_data(ea_t ea, flags_t flags, tid_t tid, asize_t len) - { - return 0; - } - - virtual void load_idasgn(const char *short_sig_name) - { - } - - virtual void auto_empty() - { - } - - virtual int auto_queue_empty(atype_t type) - { - return 1; // Keep the queue empty. - } - - virtual void add_func(func_t *func) - { - } - - virtual int del_func(func_t *func) - { - return 0; - } - - virtual int is_call_insn(ea_t /*ea*/) - { - return 0; - } - - virtual int is_ret_insn(ea_t /*ea*/, bool /*strict*/) - { - return 0; - } - - virtual PyObject *assemble( - ea_t /*ea*/, - ea_t /*cs*/, - ea_t /*ip*/, - bool /*use32*/, - const char * /*line*/) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - } -}; - -enum areacb_type_t -{ - AREACB_TYPE_UNKNOWN, - AREACB_TYPE_FUNC, - AREACB_TYPE_SEGMENT, - AREACB_TYPE_HIDDEN_AREA, - AREACB_TYPE_SRAREA, -}; - -//--------------------------------------------------------------------------- -// IDB hooks -//--------------------------------------------------------------------------- -int idaapi IDB_Callback(void *ud, int notification_code, va_list va); -class IDB_Hooks -{ -public: - virtual ~IDB_Hooks() { unhook(); }; - - bool hook() - { - return hook_to_notification_point(HT_IDB, IDB_Callback, this); - } - bool unhook() - { - return unhook_from_notification_point(HT_IDB, IDB_Callback, this); - } - // Hook functions to override in Python - virtual int byte_patched(ea_t /*ea*/) { return 0; } - virtual int cmt_changed(ea_t, bool /*repeatable_cmt*/) { return 0; } - virtual int area_cmt_changed(areacb_t * /*areas*/, area_t * /*area*/, const char * /*cmt*/, bool /*repeatable*/) { return 0; } - virtual int ti_changed(ea_t /*ea*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; } - virtual int op_ti_changed(ea_t /*ea*/, int /*n*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; } - virtual int op_type_changed(ea_t /*ea*/, int /*n*/) { return 0; } - virtual int enum_created(enum_t /*id*/) { return 0; } - virtual int enum_deleted(enum_t /*id*/) { return 0; } - virtual int enum_bf_changed(enum_t /*id*/) { return 0; } - virtual int enum_renamed(enum_t /*id*/) { return 0; } - virtual int enum_cmt_changed(enum_t /*id*/) { return 0; } - virtual int enum_member_created(enum_t /*id*/, const_t cid) { return 0; } - virtual int enum_member_deleted(enum_t /*id*/, const_t cid) { return 0; } - virtual int struc_created(tid_t /*struc_id*/) { return 0; } - virtual int struc_deleted(tid_t /*struc_id*/) { return 0; } - virtual int struc_renamed(struc_t * /*sptr*/) { return 0; } - virtual int struc_expanded(struc_t * /*sptr*/) { return 0; } - virtual int struc_cmt_changed(tid_t /*struc_id*/) { return 0; } - virtual int struc_member_created(struc_t * /*sptr*/, member_t * /*mptr*/) { return 0; } - virtual int struc_member_deleted(struc_t * /*sptr*/, tid_t /*member_id*/, ea_t /*offset*/) { return 0; } - virtual int struc_member_renamed(struc_t * /*sptr*/, member_t * /*mptr*/) { return 0; } - virtual int struc_member_changed(struc_t * /*sptr*/, member_t * /*mptr*/) { return 0; } - virtual int thunk_func_created(func_t * /*pfn*/) { return 0; } - virtual int func_tail_appended(func_t * /*pfn*/, func_t * /*tail*/) { return 0; } - virtual int func_tail_removed(func_t * /*pfn*/, ea_t /*tail_ea*/) { return 0; } - virtual int tail_owner_changed(func_t * /*tail*/, ea_t /*owner_func*/) { return 0; } - virtual int func_noret_changed(func_t * /*pfn*/) { return 0; } - virtual int segm_added(segment_t * /*s*/) { return 0; } - virtual int segm_deleted(ea_t /*startEA*/) { return 0; } - virtual int segm_start_changed(segment_t * /*s*/) { return 0; } - virtual int segm_end_changed(segment_t * /*s*/) { return 0; } - virtual int segm_moved(ea_t /*from*/, ea_t /*to*/, asize_t /*size*/) { return 0; } -}; - // %} %{ // -//------------------------------------------------------------------------- -int 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; - try - { - switch ( notification_code ) - { - case processor_t::custom_ana: - ret = proxy->custom_ana() ? 1 + cmd.size : 0; - break; - - case processor_t::custom_out: - ret = proxy->custom_out() ? 2 : 0; - break; - - case processor_t::custom_emu: - ret = proxy->custom_emu() ? 2 : 0; - break; - - case processor_t::custom_outop: - { - op_t *op = va_arg(va, op_t *); - ref_t py_obj(create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op)); - if ( py_obj == NULL ) - break; - ret = proxy->custom_outop(py_obj.o) ? 2 : 0; - break; - } - - case processor_t::custom_mnem: - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_ret = proxy->custom_mnem(); - if ( py_ret != NULL && PyString_Check(py_ret) ) - { - char *outbuffer = va_arg(va, char *); - size_t bufsize = va_arg(va, size_t); - - qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize); - ret = 2; - } - else - { - ret = 0; - } - Py_XDECREF(py_ret); - break; - } - - case processor_t::is_sane_insn: - { - int no_crefs = va_arg(va, int); - ret = proxy->is_sane_insn(no_crefs); - break; - } - - case processor_t::may_be_func: - { - int state = va_arg(va, int); - ret = proxy->may_be_func(state); - break; - } - - case processor_t::closebase: - { - proxy->closebase(); - break; - } - - case processor_t::savebase: - { - proxy->savebase(); - break; - } - - case processor_t::auto_empty_finally: - { - proxy->auto_empty_finally(); - break; - } - - case processor_t::rename: - { - ea_t ea = va_arg(va, ea_t); - const char *new_name = va_arg(va, const char *); - ret = proxy->rename(ea, new_name); - break; - } - - case processor_t::renamed: - { - ea_t ea = va_arg(va, ea_t); - const char *new_name = va_arg(va, const char *); - bool local_name = va_argi(va, bool); - proxy->renamed(ea, new_name, local_name); - break; - } - - case processor_t::undefine: - { - ea_t ea = va_arg(va, ea_t); - ret = proxy->undefine(ea); - break; - } - - case processor_t::make_code: - { - ea_t ea = va_arg(va, ea_t); - asize_t size = va_arg(va, asize_t); - ret = proxy->make_code(ea, size); - break; - } - - case processor_t::make_data: - { - ea_t ea = va_arg(va, ea_t); - flags_t flags = va_arg(va, flags_t); - tid_t tid = va_arg(va, tid_t); - asize_t len = va_arg(va, asize_t); - ret = proxy->make_data(ea, flags, tid, len); - break; - } - - case processor_t::load_idasgn: - { - const char *short_sig_name = va_arg(va, const char *); - proxy->load_idasgn(short_sig_name); - break; - } - - case processor_t::auto_empty: - { - proxy->auto_empty(); - break; - } - - case processor_t::auto_queue_empty: - { - atype_t type = va_arg(va, atype_t); - ret = proxy->auto_queue_empty(type); - break; - } - - case processor_t::add_func: - { - func_t *func = va_arg(va, func_t *); - proxy->add_func(func); - break; - } - - case processor_t::del_func: - { - func_t *func = va_arg(va, func_t *); - ret = proxy->del_func(func); - break; - } - - case processor_t::is_call_insn: - { - ea_t ea = va_arg(va, ea_t); - ret = proxy->is_call_insn(ea); - break; - } - - case processor_t::is_ret_insn: - { - ea_t ea = va_arg(va, ea_t); - bool strict = va_argi(va, bool); - ret = proxy->is_ret_insn(ea, strict); - break; - } - - case processor_t::assemble: - { - ea_t ea = va_arg(va, ea_t); - ea_t cs = va_arg(va, ea_t); - ea_t ip = va_arg(va, ea_t); - bool use32 = va_argi(va, bool); - const char *line = va_arg(va, const char *); - // Extract user buffer (we hardcode the MAXSTR size limit) - uchar *bin = va_arg(va, uchar *); - // Call python - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line); - if ( py_buffer != NULL && PyString_Check(py_buffer) ) - { - char *s; - Py_ssize_t len; - if ( PyString_AsStringAndSize(py_buffer, &s, &len) != -1 ) - { - if ( len > MAXSTR ) - len = MAXSTR; - memcpy(bin, s, len); - ret = len; - } - } - // ret = 0 otherwise - Py_XDECREF(py_buffer); - break; - } - // validate_flirt_func, // flirt has recognized a library function - // // this callback can be used by a plugin or proc module - // // to intercept it and validate such a function - // // args: ea_t start_ea - // // const char *funcname - // // returns: -1-do not create a function, - // // 1-function is validated - // // the idp module is allowed to modify 'cmd' - // set_func_start, // Function chunk start address will be changed - // // args: func_t *pfn - // // ea_t new_start - // // Returns: 1-ok,<=0-do not change - // set_func_end, // Function chunk end address will be changed - // // args: func_t *pfn - // // ea_t new_end - // // Returns: 1-ok,<=0-do not change - // outlabel, // The kernel is going to generate an instruction - // // label line or a function header - // // args: - // // ea_t ea - - // // const char *colored_name - - // // If returns value <=0, then the kernel should - // // not generate the label - // may_show_sreg, // The kernel wants to display the segment registers - // // in the messages window. - // // arg - ea_t current_ea - // // if this function returns 0 - // // then the kernel will not show - // // the segment registers. - // // (assuming that the module have done it) - // coagulate, // Try to define some unexplored bytes - // // This notification will be called if the - // // kernel tried all possibilities and could - // // not find anything more useful than to - // // convert to array of bytes. - // // The module can help the kernel and convert - // // the bytes into something more useful. - // // arg: - // // ea_t start_ea - // // returns: number of converted bytes + 1 - // auto_empty, // Info: all analysis queues are empty - // // args: none - // // returns: none - // // This callback is called once when the - // // initial analysis is finished. If the queue is - // // not empty upon the return from this callback, - // // it will be called later again. - // // See also auto_empty_finally. - // auto_queue_empty, // One analysis queue is empty - // // args: atype_t type - // // returns: 1-yes, keep the queue empty - // // <=0-no, the queue is not empty anymore - // // This callback can be called many times, so - // // only the autoMark() functions can be used from it - // // (other functions may work but it is not tested) - // func_bounds, // find_func_bounds() finished its work - // // The module may fine tune the function bounds - // // args: int *possible_return_code - // // func_t *pfn - // // ea_t max_func_end_ea (from the kernel's point of view) - // // returns: none - // is_jump_func, // is the function a trivial "jump" function? - // // args: func_t *pfn - // // ea_t *jump_target - // // ea_t *func_pointer - // // returns: 0-no, 1-don't know, 2-yes, see jump_target - // // and func_pointer - // gen_regvar_def, // generate register variable definition line - // // args: regvar_t *v - // // returns: 0-ok - // setsgr, // The kernel has changed a segment register value - // // args: ea_t startEA - // // ea_t endEA - // // int regnum - // // sel_t value - // // sel_t old_value - // // uchar tag (SR_... values) - // // returns: 1-ok, 0-error - // set_compiler, // The kernel has changed the compiler information - // // (inf.cc structure) - // is_basic_block_end, // Is the current instruction end of a basic block? - // // This function should be defined for processors - // // with delayed jump slots. The current instruction - // // is stored in 'cmd' - // // args: bool call_insn_stops_block - // // returns: 1-unknown, 0-no, 2-yes - // reglink, // IBM PC only, ignore it - // get_vxd_name, // IBM PC only, ignore it - // // Get Vxd function name - // // args: int vxdnum - // // int funcnum - // // char *outbuf - // // returns: nothing - // - // - // moving_segm, // May the kernel move the segment? - // // args: segment_t - segment to move - // // ea_t to - new segment start address - // // returns: 1-yes, <=0-the kernel should stop - // move_segm, // A segment is moved - // // Fix processor dependent address sensitive information - // // args: ea_t from - old segment address - // // segment_t* - moved segment - // // returns: nothing - // - // - // get_stkvar_scale_factor,// Should stack variable references be multiplied by - // // a coefficient before being used in the stack frame? - // // Currently used by TMS320C55 because the references into - // // the stack should be multiplied by 2 - // // Returns: scaling factor - // // Note: PR_SCALE_STKVARS should be set to use this callback - // - // create_flat_group, // Create special segment representing the flat group - // // (to use for PC mainly) - // // args - ea_t image_base, int bitness, sel_t dataseg_sel - // - // kernel_config_loaded, // This callback is called when ida.cfg is parsed - // // args - none, returns - nothing - // - // might_change_sp, // Does the instruction at 'ea' modify the stack pointer? - // // args: ea_t ea - // // returns: 1-yes, 0-false - // // (not used yet) - // - // is_alloca_probe, // Does the function at 'ea' behave as __alloca_probe? - // // args: ea_t ea - // // returns: 2-yes, 1-false - // - // out_3byte, // Generate text representation of 3byte data - // // init_out_buffer() is called before this function - // // and all Out... function can be used. - // // uFlag contains the flags. - // // This callback might be implemented by the processor - // // module to generate custom representation of 3byte data. - // // args: - // // ea_t dataea - address of the data item - // // uint32 value - value to output - // // bool analyze_only - only create xrefs if necessary - // // do not generate text representation - // // returns: 2-yes, 1-false - // - // get_reg_name, // Generate text representation of a register - // // int reg - internal register number as defined in the processor module - // // size_t width - register width in bytes - // // char *buf - output buffer - // // size_t bufsize - size of output buffer - // // int reghi - if not -1 then this function will return the register pair - // // returns: -1 if error, strlen(buf)+2 otherwise - // // Most processor modules do not need to implement this callback - // // It is useful only if ph.regNames[reg] does not provide - // // the correct register names - // // save its local data - // out_src_file_lnnum, // Callback: generate analog of - // // #line "file.c" 123 - // // directive. - // // const char *file - source file (may be NULL) - // // size_t lnnum - line number - // // returns: 2-directive has been generated - // get_autocmt, // Callback: get dynamic auto comment - // // Will be called if the autocomments are enabled - // // and the comment retrieved from ida.int starts with - // // '$!'. 'cmd' is contains valid info. - // // char *buf - output buffer - // // size_t bufsize - output buffer size - // // returns: 2-new comment has been generated - // // 1-callback has not been handled - // // the buffer must not be changed in this case - // is_insn_table_jump, // Callback: determine if instruction is a table jump or call - // // If CF_JUMP bit can not describe all kinds of table - // // jumps, please define this callback. - // // It will be called for insns with CF_JUMP bit set. - // // input: cmd structure contains the current instruction - // // returns: 1-yes, 0-no - // auto_empty_finally, // Info: all analysis queues are empty definitively - // // args: none - // // returns: none - // // This callback is called only once. - // // See also auto_empty. - // loader_finished, // Event: external file loader finished its work - // // linput_t *li - // // uint16 neflags - // // const char *filetypename - // // Use this event to augment the existing loader functionality - // loader_elf_machine, // Event: ELF loader machine type checkpoint - // // linput_t *li - // // int machine_type - // // const char **p_procname - // // proc_def **p_pd (see ldr\elf.h) - // // set_elf_reloc_t *set_reloc - // // A plugin check the machine_type. If it is the desired one, - // // the the plugin fills p_procname with the processor name. - // // p_pd is used to handle relocations, otherwise can be left untouched - // // set_reloc can be later used by the plugin to specify relocations - // // returns: e_machine value (if it is different from the - // // original e_machine value, procname and p_pd will be ignored - // // and the new value will be used) - // // This event occurs for each loaded ELF file - // is_indirect_jump, // Callback: determine if instruction is an indrect jump - // // If CF_JUMP bit can not describe all jump types - // // jumps, please define this callback. - // // input: cmd structure contains the current instruction - // // returns: 1-use CF_JUMP, 2-no, 3-yes - // verify_noreturn, // The kernel wants to set 'noreturn' flags for a function - // // func_t *pfn - // // Returns: 1-ok, any other value-do not set 'noreturn' flag - // verify_sp, // All function instructions have been analyzed - // // Now the processor module can analyze the stack pointer - // // for the whole function - // // input: func_t *pfn - // // Returns: 1-ok, 0-bad stack pointer - // treat_hindering_item, // An item hinders creation of another item - // // args: ea_t hindering_item_ea - // // flags_t new_item_flags (0 for code) - // // ea_t new_item_ea - // // asize_t new_item_length - // // Returns: 1-no reaction, <=0-the kernel may delete the hindering item - // str2reg, // Convert a register name to a register number - // // args: const char *regname - // // Returns: register number + 2 - // // The register number is the register index in the regNames array - // // Most processor modules do not need to implement this callback - // // It is useful only if ph.regNames[reg] does not provide - // // the correct register names - // create_switch_xrefs, // Create xrefs for a custom jump table - // // in: ea_t jumpea; - address of the jump insn - // // switch_info_ex_t *; - switch information - // // returns: must return 2 - // calc_switch_cases, // Calculate case values and targets for a custom jump table - // // in: ea_t insn_ea - address of the 'indirect jump' instruction - // // switch_info_ex_t *si - switch information - // // casevec_t *casevec - vector of case values... - // // evec_t *targets - ...and corresponding target addresses - // // casevec and targets may be NULL - // // returns: 2-ok, 1-failed - // determined_main, // The main() function has been determined - // // in: ea_t main - address of the main() function - // // returns: none - // preprocess_chart, // gui has retrieved a function flow chart - // // in: qflow_chart_t *fc - // // returns: none - // // Plugins may modify the flow chart in this callback - // get_bg_color, // Get item background color - // // in: ea_t ea, bgcolor_t *color - // // Returns: 1-not implemented, 2-color set - // // Plugins can hook this callback to color disassembly lines - // // dynamically - // get_operand_string, // Request text string for operand (cli, java, ...) - // // args: int opnum - // // char *buf - // // size_t buflen - // // (cmd structure must contain info for the desired insn) - // // opnum is the operand number; -1 means any string operand - // // returns: 1 - no string (or empty string) - // // >1 - original string length with terminating zero - // - // // the following 5 events are very low level - // // take care of possible recursion - // add_cref, // a code reference is being created - // // args: ea_t from, ea_t to, cref_t type - // // returns: <0 - cancel cref creation - // add_dref, // a data reference is being created - // // args: ea_t from, ea_t to, dref_t type - // // returns: <0 - cancel dref creation - // del_cref, // a code reference is being deleted - // // args: ea_t from, ea_t to, bool expand - // // returns: <0 - cancel cref deletion - // del_dref, // a data reference is being deleted - // // args: ea_t from, ea_t to - // // returns: <0 - cancel dref deletion - // coagulate_dref, // data reference is being analyzed - // // args: ea_t from, ea_t to, bool may_define, ea_t *code_ea - // // plugin may correct code_ea (e.g. for thumb mode refs, we clear the last bit) - // // returns: <0 - cancel dref analysis - // custom_fixup, // mutipurpose notification for FIXUP_CUSTOM - // // args: cust_fix oper, ea_t ea, const fixup_data_t*, ... (see cust_fix) - // // returns: 1 - no accepted (fixup ignored by ida) - // // >1 - accepted (see cust_fix) - // off_preproc, // called from get_offset_expr, when refinfo_t - // // contain flag REFINFO_PREPROC. Normally this - // // notification used in a combination with custom_fixup - // // args: ea_t ea, int numop, ea_t* opval, const refinfo_t* ri, - // // char* buf, size_t bufsize, ea_t* target, - // // ea_t* fullvalue, ea_t from, int getn_flags - // // returns: 2 - buf filled as simple expression - // // 3 - buf filled as complex expression - // // 4 - apply standard processing (with - possible - changed values) - // // others - can't convert to offset expression - // - // set_proc_options, // called if the user specified an option string in the command line: - // // -p: - // // can be used for e.g. setting a processor subtype - // // also called if option string is passed to set_processor_type() - // // and IDC's SetProcessorType() - // // args: const char * options - // // returns: <0 - bad option string - // - } - } - catch (Swig::DirectorException &e) - { - msg("Exception in IDP Hook function: %s\n", e.getMessage()); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( PyErr_Occurred() ) - PyErr_Print(); - } - return ret; -} - -//--------------------------------------------------------------------------- -int 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; - ea_t ea, ea2; - bool repeatable_cmt; - type_t *type; - p_list *fnames; - int n; - enum_t id; - const_t cid; - tid_t struc_id; - struc_t *sptr; - member_t *mptr; - tid_t member_id; - func_t *pfn; - func_t *tail; - segment_t *seg; - asize_t size; - - try { - switch (notification_code) - { - case idb_event::byte_patched: - ea = va_arg(va, ea_t); - return proxy->byte_patched(ea); - - case idb_event::cmt_changed: - ea = va_arg(va, ea_t); - repeatable_cmt = va_arg(va, int); - return proxy->cmt_changed(ea, repeatable_cmt); - - case idb_event::area_cmt_changed: - { - areacb_t *cb = va_arg(va, areacb_t*); - area_t *area = va_arg(va, area_t*); - const char *cmt = va_arg(va, char*); - repeatable_cmt = va_arg(va, int); - return proxy->area_cmt_changed(cb, area, cmt, repeatable_cmt); - } - - case idb_event::ti_changed: - ea = va_arg(va, ea_t); - type = va_arg(va, type_t *); - fnames = va_arg(va, p_list *); - return proxy->ti_changed(ea, type, fnames); - - case idb_event::op_ti_changed: - ea = va_arg(va, ea_t); - n = va_arg(va, int); - type = va_arg(va, type_t *); - fnames = va_arg(va, p_list *); - return proxy->op_ti_changed(ea, n, type, fnames); - - case idb_event::op_type_changed: - ea = va_arg(va, ea_t); - n = va_arg(va, int); - return proxy->op_type_changed(ea, n); - - case idb_event::enum_created: - id = va_arg(va, enum_t); - return proxy->enum_created(id); - - case idb_event::enum_deleted: - id = va_arg(va, enum_t); - return proxy->enum_deleted(id); - - case idb_event::enum_bf_changed: - id = va_arg(va, enum_t); - return proxy->enum_bf_changed(id); - - case idb_event::enum_cmt_changed: - id = va_arg(va, enum_t); - return proxy->enum_cmt_changed(id); - -#ifdef NO_OBSOLETE_FUNCS - case idb_event::enum_member_created: -#else - case idb_event::enum_const_created: -#endif - id = va_arg(va, enum_t); - cid = va_arg(va, const_t); - return proxy->enum_member_created(id, cid); - -#ifdef NO_OBSOLETE_FUNCS - case idb_event::enum_member_deleted: -#else - case idb_event::enum_const_deleted: -#endif - id = va_arg(va, enum_t); - cid = va_arg(va, const_t); - return proxy->enum_member_deleted(id, cid); - - case idb_event::struc_created: - struc_id = va_arg(va, tid_t); - return proxy->struc_created(struc_id); - - case idb_event::struc_deleted: - struc_id = va_arg(va, tid_t); - return proxy->struc_deleted(struc_id); - - case idb_event::struc_renamed: - sptr = va_arg(va, struc_t *); - return proxy->struc_renamed(sptr); - - case idb_event::struc_expanded: - sptr = va_arg(va, struc_t *); - return proxy->struc_expanded(sptr); - - case idb_event::struc_cmt_changed: - struc_id = va_arg(va, tid_t); - return proxy->struc_cmt_changed(struc_id); - - case idb_event::struc_member_created: - sptr = va_arg(va, struc_t *); - mptr = va_arg(va, member_t *); - return proxy->struc_member_created(sptr, mptr); - - case idb_event::struc_member_deleted: - sptr = va_arg(va, struc_t *); - member_id = va_arg(va, tid_t); - ea = va_arg(va, ea_t); - return proxy->struc_member_deleted(sptr, member_id, ea); - - case idb_event::struc_member_renamed: - sptr = va_arg(va, struc_t *); - mptr = va_arg(va, member_t *); - return proxy->struc_member_renamed(sptr, mptr); - - case idb_event::struc_member_changed: - sptr = va_arg(va, struc_t *); - mptr = va_arg(va, member_t *); - return proxy->struc_member_changed(sptr, mptr); - - case idb_event::thunk_func_created: - pfn = va_arg(va, func_t *); - return proxy->thunk_func_created(pfn); - - case idb_event::func_tail_appended: - pfn = va_arg(va, func_t *); - tail = va_arg(va, func_t *); - return proxy->func_tail_appended(pfn, tail); - - case idb_event::func_tail_removed: - pfn = va_arg(va, func_t *); - ea = va_arg(va, ea_t); - return proxy->func_tail_removed(pfn, ea); - - case idb_event::tail_owner_changed: - tail = va_arg(va, func_t *); - ea = va_arg(va, ea_t); - return proxy->tail_owner_changed(tail, ea); - - case idb_event::func_noret_changed: - pfn = va_arg(va, func_t *); - return proxy->func_noret_changed(pfn); - - case idb_event::segm_added: - seg = va_arg(va, segment_t *); - return proxy->segm_added(seg); - - case idb_event::segm_deleted: - ea = va_arg(va, ea_t); - return proxy->segm_deleted(ea); - - case idb_event::segm_start_changed: - seg = va_arg(va, segment_t *); - return proxy->segm_start_changed(seg); - - case idb_event::segm_end_changed: - seg = va_arg(va, segment_t *); - return proxy->segm_end_changed(seg); - - case idb_event::segm_moved: - ea = va_arg(va, ea_t); - ea2 = va_arg(va, ea_t); - size = va_arg(va, asize_t); - return proxy->segm_moved(ea, ea2, size); - } - } - catch (Swig::DirectorException &e) - { - msg("Exception in IDB Hook function: %s\n", e.getMessage()); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if (PyErr_Occurred()) - PyErr_Print(); - } - return 0; -} - -//------------------------------------------------------------------------- -static const regval_t *idaapi _py_getreg( - const char *name, - const regval_t *regvals) -{ - for ( int i=dbg->registers_size - 1; i >= 0; i-- ) - { - if ( strieq(name, dbg->registers(i).name) ) - return ®vals[i]; - } - static regval_t rv; - return &rv; -} - -//------------------------------------------------------------------------- // %} diff --git a/swig/kernwin.i b/swig/kernwin.i index f5fe6ba..0d1e2d1 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -38,8 +38,17 @@ %ignore askyn_v; %ignore add_custom_viewer_popup_item; %ignore create_custom_viewer; +%extend qvector< snapshot_t *> { + snapshot_t *at(size_t n) { return self->at(n); } +}; +%ignore qvector< snapshot_t *>::at(size_t) const; +%ignore qvector< snapshot_t *>::at(size_t); +%ignore qvector< snapshot_t *>::grow; +%template(qvector_snapshotvec_t) qvector; %ignore take_database_snapshot; +%rename (take_database_snapshot) py_take_database_snapshot; %ignore restore_database_snapshot; +%rename (restore_database_snapshot) py_restore_database_snapshot; %ignore destroy_custom_viewer; %ignore destroy_custom_viewerdestroy_custom_viewer; %ignore set_custom_viewer_popup_menu; @@ -62,13 +71,6 @@ %rename (get_highlighted_identifier) py_get_highlighted_identifier; -// CLI -%ignore cli_t; -%ignore install_command_interpreter; -%rename (install_command_interpreter) py_install_command_interpreter; -%ignore remove_command_interpreter; -%rename (remove_command_interpreter) py_remove_command_interpreter; - %ignore action_desc_t::handler; %ignore action_handler_t; %ignore register_action; @@ -115,6 +117,33 @@ %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; + +// We will %ignore those ATM, since they cannot be trivially +// wrapped: bytevec_t is not exposed. +// (besides, serializing/deserializing should probably +// be done by locstack_t instances only.) +%ignore place_t::serialize; +%ignore place_t__serialize; +%ignore place_t::deserialize; +%ignore place_t__deserialize; + +%ignore register_place_class; +%ignore register_enumplace; +%ignore register_idaplace; +%ignore register_simpleline_place; +%ignore register_structplace; +%ignore unregister_place_class; +%ignore unregister_place_classes_with_owner; +%ignore unregister_enumplace; +%ignore unregister_idaplace; +%ignore unregister_simpleline_place; +%ignore unregister_structplace; +%ignore register_loc_converter; +%ignore lookup_loc_converter; +%ignore unregister_loc_converters_for_class; + %feature("director") UI_Hooks; //------------------------------------------------------------------------- @@ -190,4253 +219,20 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); %inline %{ // -//------------------------------------------------------------------------ - -//------------------------------------------------------------------------ -/* -# -def register_timer(interval, callback): - """ - Register a timer - - @param interval: Interval in milliseconds - @param callback: A Python callable that takes no parameters and returns an integer. - The callback may return: - -1 : to unregister the timer - >= 0 : the new or same timer interval - @return: None or a timer object - """ - pass -# -*/ -static PyObject *py_register_timer(int interval, PyObject *py_callback) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( py_callback == NULL || !PyCallable_Check(py_callback) ) - Py_RETURN_NONE; - - // An inner class hosting the callback method - struct tmr_t - { - static int idaapi callback(void *ud) - { - 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); - - // Timer has been unregistered? - if ( ret == -1 ) - { - // Free the context - Py_DECREF(ctx->pycallback); - delete ctx; - } - return ret; - }; - }; - - py_timer_ctx_t *ctx = new py_timer_ctx_t(); - ctx->pycallback = py_callback; - Py_INCREF(py_callback); - ctx->timer_id = register_timer( - interval, - tmr_t::callback, - ctx); - - if ( ctx->timer_id == NULL ) - { - Py_DECREF(py_callback); - delete ctx; - Py_RETURN_NONE; - } - return PyCObject_FromVoidPtr(ctx, NULL); -} - -//------------------------------------------------------------------------ -/* -# -def unregister_timer(timer_obj): - """ - Unregister a timer - - @param timer_obj: a timer object previously returned by a register_timer() - @return: Boolean - @note: After the timer has been deleted, the timer_obj will become invalid. - """ - pass -# -*/ -static PyObject *py_unregister_timer(PyObject *py_timerctx) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( py_timerctx == NULL || !PyCObject_Check(py_timerctx) ) - Py_RETURN_FALSE; - - py_timer_ctx_t *ctx = (py_timer_ctx_t *) PyCObject_AsVoidPtr(py_timerctx); - if ( !unregister_timer(ctx->timer_id) ) - Py_RETURN_FALSE; - - Py_DECREF(ctx->pycallback); - delete ctx; - - Py_RETURN_TRUE; -} - -//------------------------------------------------------------------------ -/* -# -def choose_idasgn(): - """ - Opens the signature chooser - - @return: None or the selected signature name - """ - pass -# -*/ -static PyObject *py_choose_idasgn() -{ - char *name = choose_idasgn(); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( name == NULL ) - { - Py_RETURN_NONE; - } - else - { - PyObject *py_str = PyString_FromString(name); - qfree(name); - return py_str; - } -} - -//------------------------------------------------------------------------ -/* -# -def get_highlighted_identifier(flags = 0): - """ - Returns the currently highlighted identifier - - @param flags: reserved (pass 0) - @return: None or the highlighted identifier - """ - pass -# -*/ -static PyObject *py_get_highlighted_identifier(int flags = 0) -{ - char buf[MAXSTR]; - bool ok = get_highlighted_identifier(buf, sizeof(buf), flags); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !ok ) - Py_RETURN_NONE; - else - return PyString_FromString(buf); -} - -//------------------------------------------------------------------------ -static int py_load_custom_icon_fn(const char *filename) -{ - return load_custom_icon(filename); -} - -//------------------------------------------------------------------------ -static int py_load_custom_icon_data(PyObject *data, const char *format) -{ - Py_ssize_t len; - char *s; - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( PyString_AsStringAndSize(data, &s, &len) == -1 ) - return 0; - else - return load_custom_icon(s, len, format); -} - -//------------------------------------------------------------------------ -/* -# -def free_custom_icon(icon_id): - """ - Frees an icon loaded with load_custom_icon() - """ - pass -# -*/ - -//------------------------------------------------------------------------- -/* -# -def readsel2(view, p0, p1): - """ - Read the user selection, and store its information in p0 (from) and p1 (to). - - This can be used as follows: - - - >>> p0 = idaapi.twinpos_t() - p1 = idaapi.twinpos_t() - view = idaapi.get_current_viewer() - idaapi.readsel2(view, p0, p1) - - - At that point, p0 and p1 hold information for the selection. - But, the 'at' property of p0 and p1 is not properly typed. - To specialize it, call #place() on it, passing it the view - they were retrieved from. Like so: - - - >>> place0 = p0.place(view) - place1 = p1.place(view) - - - This will effectively "cast" the place into a specialized type, - holding proper information, depending on the view type (e.g., - disassembly, structures, enums, ...) - - @param view: The view to retrieve the selection for. - @param p0: Storage for the "from" part of the selection. - @param p1: Storage for the "to" part of the selection. - @return: a bool value indicating success. - """ - pass -# -*/ - -//------------------------------------------------------------------------ -/* -# -def umsg(text): - """ - Prints text into IDA's Output window - - @param text: text to print - Can be Unicode, or string in UTF-8 encoding - @return: number of bytes printed - """ - pass -# -*/ -static PyObject* py_umsg(PyObject *o) -{ - PyObject* utf8 = NULL; - if ( PyUnicode_Check(o) ) - { - utf8 = PyUnicode_AsUTF8String(o); - o = utf8; - } - else if ( !PyString_Check(o) ) - { - PyErr_SetString(PyExc_TypeError, "A unicode or UTF-8 string expected"); - return NULL; - } - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = umsg("%s", PyString_AsString(o)); - Py_END_ALLOW_THREADS; - Py_XDECREF(utf8); - return PyInt_FromLong(rc); -} - -//------------------------------------------------------------------------ -/* -# -def msg(text): - """ - Prints text into IDA's Output window - - @param text: text to print - Can be Unicode, or string in local encoding - @return: number of bytes printed - """ - pass -# -*/ -static PyObject* py_msg(PyObject *o) -{ - if ( PyUnicode_Check(o) ) - return py_umsg(o); - - if ( !PyString_Check(o) ) - { - PyErr_SetString(PyExc_TypeError, "A string expected"); - return NULL; - } - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = msg("%s", PyString_AsString(o)); - Py_END_ALLOW_THREADS; - return PyInt_FromLong(rc); -} - -//------------------------------------------------------------------------ -/* -# -def asktext(max_text, defval, prompt): - """ - Asks for a long text - - @param max_text: Maximum text length - @param defval: The default value - @param prompt: The prompt value - @return: None or the entered string - """ - pass -# -*/ -PyObject *py_asktext(int max_text, const char *defval, const char *prompt) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( max_text <= 0 ) - Py_RETURN_NONE; - - char *buf = new char[max_text]; - if ( buf == NULL ) - Py_RETURN_NONE; - - PyObject *py_ret; - if ( asktext(size_t(max_text), buf, defval, "%s", prompt) != NULL ) - { - py_ret = PyString_FromString(buf); - } - else - { - py_ret = Py_None; - Py_INCREF(py_ret); - } - delete [] buf; - return py_ret; -} - -//------------------------------------------------------------------------ -/* -# -def str2ea(addr): - """ - Converts a string express to EA. The expression evaluator may be called as well. - - @return: BADADDR or address value - """ - pass -# -*/ -ea_t py_str2ea(const char *str, ea_t screenEA = BADADDR) -{ - ea_t ea; - bool ok = str2ea(str, &ea, screenEA); - return ok ? ea : BADADDR; -} - -//------------------------------------------------------------------------ -/* -# -def str2user(str): - """ - Insert C-style escape characters to string - - @return: new string with escape characters inserted - """ - pass -# -*/ -PyObject *py_str2user(const char *str) -{ - qstring qstr(str); - qstring retstr; - qstr2user(&retstr, qstr); - return PyString_FromString(retstr.c_str()); -} - -//------------------------------------------------------------------------ -/* -# -def process_ui_action(name): - """ - Invokes an IDA UI action by name - - @param name: action name - @return: Boolean - """ - pass -# -*/ -static bool py_process_ui_action(const char *name, int flags = 0) -{ - return process_ui_action(name, flags, NULL); -} - -//------------------------------------------------------------------------ -/* -# -def del_menu_item(menu_ctx): - """Deprecated. Use detach_menu_item()/unregister_action() instead.""" - pass -# -*/ -static bool py_del_menu_item(PyObject *py_ctx) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_ctx) ) - return false; - - py_add_del_menu_item_ctx *ctx = (py_add_del_menu_item_ctx *)PyCObject_AsVoidPtr(py_ctx); - - bool ok = del_menu_item(ctx->menupath.c_str()); - if ( ok ) - { - Py_DECREF(ctx->cb_data); - delete ctx; - } - - return ok; -} - -//------------------------------------------------------------------------ -/* -# -def del_hotkey(ctx): - """ - Deletes a previously registered function hotkey - - @param ctx: Hotkey context previously returned by add_hotkey() - - @return: Boolean. - """ - pass -# -*/ -bool py_del_hotkey(PyObject *pyctx) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(pyctx) ) - return false; - - py_idchotkey_ctx_t *ctx = (py_idchotkey_ctx_t *) PyCObject_AsVoidPtr(pyctx); - if ( !del_idc_hotkey(ctx->hotkey.c_str()) ) - return false; - - Py_DECREF(ctx->pyfunc); - delete ctx; - return true; -} - -//------------------------------------------------------------------------ -/* -# -def add_hotkey(hotkey, pyfunc): - """ - Associates a function call with a hotkey. - Callable pyfunc will be called each time the hotkey is pressed - - @param hotkey: The hotkey - @param pyfunc: Callable - - @return: Context object on success or None on failure. - """ - pass -# -*/ -PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - // Make sure a callable was passed - if ( !PyCallable_Check(pyfunc) ) - return NULL; - - // Form the function name - qstring idc_func_name; - idc_func_name.sprnt("py_hotkeycb_%p", pyfunc); - - // Can add the hotkey? - if ( add_idc_hotkey(hotkey, idc_func_name.c_str()) == IDCHK_OK ) do - { - // Generate global variable name - qstring idc_gvarname; - idc_gvarname.sprnt("_g_pyhotkey_ref_%p", pyfunc); - - // Now add the global variable - idc_value_t *gvar = add_idc_gvar(idc_gvarname.c_str()); - if ( gvar == NULL ) - break; - - // The function body will call a registered IDC function that - // will take a global variable that wraps a PyCallable as a pvoid - qstring idc_func; - idc_func.sprnt("static %s() { %s(%s); }", - idc_func_name.c_str(), - S_PYINVOKE0, - idc_gvarname.c_str()); - - // Compile the IDC condition - char errbuf[MAXSTR]; - if ( !CompileLineEx(idc_func.c_str(), errbuf, sizeof(errbuf)) ) - break; - - // Create new context - // Define context - py_idchotkey_ctx_t *ctx = new py_idchotkey_ctx_t(); - - // Remember the hotkey - ctx->hotkey = hotkey; - - // Take reference to the callable - ctx->pyfunc = pyfunc; - Py_INCREF(pyfunc); - - // Bind IDC variable w/ the PyCallable - gvar->set_pvoid(pyfunc); - - // Return the context - return PyCObject_FromVoidPtr(ctx, NULL); - } while (false); - - // Cleanup - del_idc_hotkey(hotkey); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------ -/* -# -def add_menu_item(menupath, name, hotkey, flags, callback, args): - """Deprecated. Use register_action()/attach_menu_item() instead.""" - pass -# -*/ -bool idaapi py_menu_item_callback(void *userdata); -static PyObject *py_add_menu_item( - const char *menupath, - const char *name, - const char *hotkey, - int flags, - PyObject *pyfunc, - PyObject *args) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool no_args; - - // No slash in the menu path? - const char *p = strrchr(menupath, '/'); - if ( p == NULL ) - Py_RETURN_NONE; - - if ( args == Py_None ) - { - no_args = true; - args = PyTuple_New(0); - if ( args == NULL ) - return NULL; - } - else if ( !PyTuple_Check(args) ) - { - PyErr_SetString(PyExc_TypeError, "args must be a tuple or None"); - return NULL; - } - else - { - no_args = false; - } - - // Form a tuple holding the function to be called and its arguments - PyObject *cb_data = Py_BuildValue("(OO)", pyfunc, args); - - // If we created an empty tuple, then we must free it - if ( no_args ) - Py_DECREF(args); - - // Add the menu item - bool b = add_menu_item(menupath, name, hotkey, flags, py_menu_item_callback, (void *)cb_data); - - if ( !b ) - { - Py_XDECREF(cb_data); - Py_RETURN_NONE; - } - // Create a context (for the delete_menu_item()) - py_add_del_menu_item_ctx *ctx = new py_add_del_menu_item_ctx(); - - // Form the complete menu path - ctx->menupath.append(menupath, p - menupath + 1); - ctx->menupath.append(name); - // Save callback data - ctx->cb_data = cb_data; - - // Return context to user - return PyCObject_FromVoidPtr(ctx, NULL); -} - -//------------------------------------------------------------------------ -/* -# - -MFF_FAST = 0x0000 -"""execute code as soon as possible -this mode is ok call ui related functions -that do not query the database.""" - -MFF_READ = 0x0001 -"""execute code only when ida is idle and it is safe to query the database. -this mode is recommended only for code that does not modify the database. -(nb: ida may be in the middle of executing another user request, for example it may be waiting for him to enter values into a modal dialog box)""" - -MFF_WRITE = 0x0002 -"""execute code only when ida is idle and it is safe to modify the database. in particular, this flag will suspend execution if there is -a modal dialog box on the screen this mode can be used to call any ida api function. MFF_WRITE implies MFF_READ""" - -MFF_NOWAIT = 0x0004 -"""Do not wait for the request to be executed. -he caller should ensure that the request is not -destroyed until the execution completes. -if not, the request will be ignored. -the return code of execute_sync() is meaningless -in this case. -This flag can be used to delay the code execution -until the next UI loop run even from the main thread""" - -def execute_sync(callable, reqf): - """ - Executes a function in the context of the main thread. - If the current thread not the main thread, then the call is queued and - executed afterwards. - - @note: The Python version of execute_sync() cannot be called from a different thread - for the time being. - @param callable: A python callable object - @param reqf: one of MFF_ flags - @return: -1 or the return value of the callable - """ - pass -# -*/ -//------------------------------------------------------------------------ -static int py_execute_sync(PyObject *py_callable, int reqf) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - int rc = -1; - // Callable? - if ( PyCallable_Check(py_callable) ) - { - struct py_exec_request_t : exec_request_t - { - ref_t py_callable; - virtual int idaapi execute() - { - PYW_GIL_GET; - newref_t py_result(PyObject_CallFunctionObjArgs(py_callable.o, NULL)); - int ret = py_result == NULL || !PyInt_Check(py_result.o) - ? -1 - : PyInt_AsLong(py_result.o); - // if the requesting thread decided not to wait for the request to - // complete, we have to self-destroy, nobody else will do it - if ( (code & MFF_NOWAIT) != 0 ) - delete this; - return ret; - } - py_exec_request_t(PyObject *pyc) - { - // No need to GIL-ensure here, since this is created - // within the py_execute_sync() scope. - py_callable = borref_t(pyc); - } - virtual ~py_exec_request_t() - { - // Need to GIL-ensure here, since this might be called - // from the main thread. - PYW_GIL_GET; - py_callable = ref_t(); // Release callable - } - }; - py_exec_request_t *req = new py_exec_request_t(py_callable); - - // Release GIL before executing, or if this is running in the - // non-main thread, this will wait on the req.sem, while the main - // thread might be waiting for the GIL to be available. - Py_BEGIN_ALLOW_THREADS; - rc = execute_sync(*req, reqf); - Py_END_ALLOW_THREADS; - // destroy the request once it is finished. exception: NOWAIT requests - // will be handled in the future, so do not destroy them yet! - if ( (reqf & MFF_NOWAIT) == 0 ) - delete req; - } - return rc; -} - -//------------------------------------------------------------------------ -/* -# - -def execute_ui_requests(callable_list): - """ - Inserts a list of callables into the UI message processing queue. - When the UI is ready it will call one callable. - A callable can request to be called more than once if it returns True. - - @param callable_list: A list of python callable objects. - @note: A callable should return True if it wants to be called more than once. - @return: Boolean. False if the list contains a non callabale item - """ - pass -# -*/ -static bool py_execute_ui_requests(PyObject *py_list) -{ - struct py_ui_request_t: public ui_request_t - { - private: - ref_vec_t py_callables; - size_t py_callable_idx; - - static int idaapi s_py_list_walk_cb( - const ref_t &py_item, - Py_ssize_t index, - void *ud) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - // Not callable? Terminate iteration - if ( !PyCallable_Check(py_item.o) ) - return CIP_FAILED; - - // Append this callable and increment its reference - py_ui_request_t *_this = (py_ui_request_t *)ud; - _this->py_callables.push_back(py_item); - return CIP_OK; - } - public: - py_ui_request_t(): py_callable_idx(0) - { - } - - virtual bool idaapi run() - { - PYW_GIL_GET; - - // Get callable - ref_t py_callable = py_callables.at(py_callable_idx); - bool reschedule; - newref_t py_result(PyObject_CallFunctionObjArgs(py_callable.o, NULL)); - reschedule = py_result != NULL && PyObject_IsTrue(py_result.o); - - // No rescheduling? Then advance to the next callable - if ( !reschedule ) - ++py_callable_idx; - - // Reschedule this C callback only if there are more callables - return py_callable_idx < py_callables.size(); - } - - // Walk the list and extract all callables - bool init(PyObject *py_list) - { - Py_ssize_t count = pyvar_walk_list( - py_list, - s_py_list_walk_cb, - this); - return count > 0; - } - - virtual idaapi ~py_ui_request_t() - { - py_callables.clear(); - } - }; - - py_ui_request_t *req = new py_ui_request_t(); - if ( !req->init(py_list) ) - { - delete req; - return false; - } - execute_ui_requests(req, NULL); - return true; -} - -//------------------------------------------------------------------------ -/* -# -def set_dock_pos(src, dest, orient, left = 0, top = 0, right = 0, bottom = 0): - """ - Sets the dock orientation of a window relatively to another window. - - @param src: Source docking control - @param dest: Destination docking control - @param orient: One of DOR_XXXX constants - @param left, top, right, bottom: These parameter if DOR_FLOATING is used, or if you want to specify the width of docked windows - @return: Boolean - - Example: - set_dock_pos('Structures', 'Enums', DOR_RIGHT) <- docks the Structures window to the right of Enums window - """ - pass -# -*/ - -//------------------------------------------------------------------------ -/* -# -def is_idaq(): - """ - Returns True or False depending if IDAPython is hosted by IDAQ - """ -# -*/ - -//--------------------------------------------------------------------------- -// UI hooks -//--------------------------------------------------------------------------- -int idaapi UI_Callback(void *ud, int notification_code, va_list va); -/* -# -class UI_Hooks(object): - def hook(self): - """ - Creates an UI hook - - @return: Boolean true on success - """ - pass - - def unhook(self): - """ - Removes the UI hook - @return: Boolean true on success - """ - pass - - def preprocess(self, name): - """ - IDA ui is about to handle a user command - - @param name: ui command name - (these names can be looked up in ida[tg]ui.cfg) - @return: 0-ok, nonzero - a plugin has handled the command - """ - pass - - def postprocess(self): - """ - An ida ui command has been handled - - @return: Ignored - """ - pass - - def saving(self): - """ - The kernel is saving the database. - - @return: Ignored - """ - pass - - def saved(self): - """ - The kernel has saved the database. - - @return: Ignored - """ - pass - - def get_ea_hint(self, ea): - """ - 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 - """ - pass - - def updating_actions(self, ctx): - """ - The UI is about to batch-update some actions. - - @param ctx: The action_update_ctx_t instance - @return: Ignored - """ - pass - - def updated_actions(self): - """ - The UI is done updating actions. - - @return: Ignored - """ - pass - - def populating_tform_popup(self, form, popup): - """ - The UI is populating the TForm's popup menu. - Now is a good time to call idaapi.attach_action_to_popup() - - @param form: The form - @param popup: The popup menu. - @return: Ignored - """ - pass - - def finish_populating_tform_popup(self, form, popup): - """ - The UI is about to be done populating the TForm's popup menu. - Now is a good time to call idaapi.attach_action_to_popup() - - @param form: The form - @param popup: The popup menu. - @return: Ignored - """ - pass - - def term(self): - """ - IDA is terminated and the database is already closed. - The UI may close its windows in this callback. - """ - # if the user forgot to call unhook, do it for him - self.unhook() - - def __term__(self): - self.term() - -# -*/ -class UI_Hooks -{ -public: - virtual ~UI_Hooks() - { - unhook(); - } - - bool hook() - { - return hook_to_notification_point(HT_UI, UI_Callback, this); - } - - bool unhook() - { - return unhook_from_notification_point(HT_UI, UI_Callback, this); - } - - virtual int preprocess(const char * /*name*/) - { - return 0; - } - - virtual void postprocess() - { - } - - virtual void saving() - { - } - - virtual void saved() - { - } - - virtual void term() - { - } - - virtual PyObject *get_ea_hint(ea_t /*ea*/) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - }; - - virtual void current_tform_changed(TForm * /*form*/, TForm * /*previous_form*/) - { - } - - virtual void updating_actions(action_update_ctx_t *ctx) - { - } - - virtual void updated_actions() - { - } - - virtual void populating_tform_popup(TForm * /*form*/, TPopupMenu * /*popup*/) - { - } - - virtual void finish_populating_tform_popup(TForm * /*form*/, TPopupMenu * /*popup*/) - { - } -}; - -//------------------------------------------------------------------------- -bool py_register_action(action_desc_t *desc) -{ - bool ok = register_action(*desc); - if ( ok ) - { - // Success. We are managing this handler from now on, - // and must prevent it from being destroyed. - py_action_handlers[desc->name] = desc->handler; - // Let's set this to NULL, so when the wrapping Python action_desc_t - // instance is deleted, it doesn't try to delete the handler (See - // kernwin.i's action_desc_t::~action_desc_t()). - desc->handler = NULL; - } - return ok; -} - -//------------------------------------------------------------------------- -bool py_unregister_action(const char *name) -{ - bool ok = unregister_action(name); - if ( ok ) - { - py_action_handler_t *handler = - (py_action_handler_t *) py_action_handlers[name]; - delete handler; - py_action_handlers.erase(name); - } - return ok; -} - -//------------------------------------------------------------------------- -bool py_attach_dynamic_action_to_popup( - TForm *form, - TPopupMenu *popup_handle, - action_desc_t *desc, - const char *popuppath = NULL, - int flags = 0) -{ - bool ok = attach_dynamic_action_to_popup( - form, popup_handle, *desc, popuppath, flags); - if ( ok ) - // Set the handler to null, so the desc won't destroy - // it, as it noticed ownership was taken by IDA. - // In addition, we don't need to register into the - // 'py_action_handlers', because IDA will destroy the - // handler as soon as the popup menu is closed. - desc->handler = NULL; - return ok; -} - -// This is similar to a twinline_t, with improved memory management: -// twinline_t has a dummy destructor, that performs no cleanup. -struct disasm_line_t -{ - disasm_line_t() : at(NULL) {} - ~disasm_line_t() { qfree(at); } - disasm_line_t(const disasm_line_t &other) { *this = other; } - disasm_line_t &operator=(const disasm_line_t &other) - { - qfree(at); - at = other.at == NULL ? NULL : other.at->clone(); - return *this; - } - place_t *at; - qstring line; - color_t prefix_color; - bgcolor_t bg_color; - bool is_default; -}; -DECLARE_TYPE_AS_MOVABLE(disasm_line_t); -typedef qvector disasm_text_t; - -//------------------------------------------------------------------------- -void py_gen_disasm_text(ea_t ea1, ea_t ea2, disasm_text_t &text, bool truncate_lines) -{ - text_t _text; - gen_disasm_text(ea1, ea2, _text, truncate_lines); - for ( size_t i = 0, n = _text.size(); i < n; ++i ) - { - const twinline_t &tl = _text[i]; - disasm_line_t &dl = text.push_back(); - dl.at = tl.at; // Transfer ownership - dl.line.inject(tl.line); // Transfer ownership - } -} - -//------------------------------------------------------------------------- -// Although 'TCustomControl*' and 'TForm*' instances can both be used -// for attach_action_to_popup() at a binary-level, IDAPython SWIG bindings -// require that a 'TForm *' wrapper be passed to wrap_attach_action_to_popup(). -// Thus, we provide another attach_action_to_popup() version, that -// accepts a 'TCustomControl' as first argument. -// -// Since user-created GraphViewer are created like so: -// +-------- PluginForm ----------+ -// |+----- TCustomControl -------+| -// || || -// || || -// || || -// || || -// || || -// |+----------------------------+| -// +------------------------------+ -// The user cannot use GetTForm(), and use that to attach -// an action to, because that'll attach the action to the PluginForm -// instance. -// Instead, the user must use GetTCustomControl(), and call -// this function below with it. -bool attach_action_to_popup( - TCustomControl *tcc, - TPopupMenu *popup_handle, - const char *name, - const char *popuppath = NULL, - int flags = 0) -{ - return attach_action_to_popup((TForm*) tcc, popup_handle, name, popuppath, flags); -} - -//------------------------------------------------------------------------- -/* -# -def set_nav_colorizer(callback): - """ - Set a new colorizer for the navigation band. - - The 'callback' is a function of 2 arguments: - - ea (the EA to colorize for) - - nbytes (the number of bytes at that EA) - and must return a 'long' value. - - The previous colorizer is returned, allowing - the new 'callback' to use 'call_nav_colorizer' - with it. - - Note that the previous colorizer is returned - only the first time set_nav_colorizer() is called: - due to the way the colorizers API is defined in C, - it is impossible to chain more than 2 colorizers - in IDAPython: the original, IDA-provided colorizer, - and a user-provided one. - - Example: colorizer inverting the color provided by the IDA colorizer: - def my_colorizer(ea, nbytes): - global ida_colorizer - orig = idaapi.call_nav_colorizer(ida_colorizer, ea, nbytes) - return long(~orig) - - ida_colorizer = idaapi.set_nav_colorizer(my_colorizer) - """ - pass -# -*/ -nav_colorizer_t *py_set_nav_colorizer(PyObject *new_py_colorizer) -{ - static ref_t py_colorizer; - struct ida_local lambda_t - { - static uint32 idaapi call_py_colorizer(ea_t ea, asize_t nbytes) - { - PYW_GIL_GET; - - if ( py_colorizer == NULL ) // Shouldn't happen. - return 0; - newref_t pyres = PyObject_CallFunction( - py_colorizer.o, "KK", - (unsigned long long) ea, - (unsigned long long) nbytes); - PyW_ShowCbErr("nav_colorizer"); - if ( pyres.o == NULL ) - return 0; - if ( !PyLong_Check(pyres.o) ) - { - static bool warned = false; - if ( !warned ) - { - msg("WARNING: set_nav_colorizer() callback must return a 'long'.\n"); - warned = true; - } - return 0; - } - return PyLong_AsLong(pyres.o); - } - }; - - bool need_install = py_colorizer == NULL; - py_colorizer = borref_t(new_py_colorizer); - return need_install - ? set_nav_colorizer(lambda_t::call_py_colorizer) - : NULL; -} - -//------------------------------------------------------------------------- -/* -# -def call_nav_colorizer(colorizer, ea, nbytes): - """ - To be used with the IDA-provided colorizer, that is - returned as result of the first call to set_nav_colorizer(). - - This is a trivial trampoline, so that SWIG can generate a - wrapper that will do the types checking. - """ - pass -# -*/ -uint32 py_call_nav_colorizer( - nav_colorizer_t *col, - ea_t ea, - asize_t nbytes) -{ - return col(ea, nbytes); -} - - - -//--------------------------------------------------------------------------- -uint32 idaapi choose_sizer(void *self) -{ - PYW_GIL_GET; - newref_t pyres(PyObject_CallMethod((PyObject *)self, "sizer", "")); - return PyInt_AsLong(pyres.o); -} - -//--------------------------------------------------------------------------- -char *idaapi choose_getl(void *self, uint32 n, char *buf) -{ - PYW_GIL_GET; - newref_t pyres( - PyObject_CallMethod( - (PyObject *)self, - "getl", - "l", - n)); - - const char *res; - if (pyres == NULL || (res = PyString_AsString(pyres.o)) == NULL ) - qstrncpy(buf, "", MAXSTR); - else - qstrncpy(buf, res, MAXSTR); - return buf; -} - -//--------------------------------------------------------------------------- -void idaapi choose_enter(void *self, uint32 n) -{ - PYW_GIL_GET; - newref_t res(PyObject_CallMethod((PyObject *)self, "enter", "l", n)); -} - -//--------------------------------------------------------------------------- -uint32 choose_choose( - void *self, - int flags, - int x0,int y0, - int x1,int y1, - int width, - int deflt, - int icon) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t pytitle(PyObject_GetAttrString((PyObject *)self, "title")); - const char *title = pytitle != NULL ? PyString_AsString(pytitle.o) : "Choose"; - - int r = choose( - flags, - x0, y0, - x1, y1, - self, - width, - choose_sizer, - choose_getl, - title, - icon, - deflt, - NULL, /* del */ - NULL, /* inst */ - NULL, /* update */ - NULL, /* edit */ - choose_enter, - NULL, /* destroy */ - NULL, /* popup_names */ - NULL);/* get_icon */ - - return r; -} - - -PyObject *choose2_find(const char *title); -int choose2_add_command(PyObject *self, const char *caption, int flags, int menu_index, int icon); -void choose2_refresh(PyObject *self); -void choose2_close(PyObject *self); -int choose2_create(PyObject *self, bool embedded); -void choose2_activate(PyObject *self); -PyObject *choose2_get_embedded(PyObject *self); -PyObject *choose2_get_embedded_selection(PyObject *self); - - -#define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa; - -//--------------------------------------------------------------------------- -static bool textctrl_info_t_assign(PyObject *self, PyObject *other) -{ - textctrl_info_t *lhs = textctrl_info_t_get_clink(self); - textctrl_info_t *rhs = textctrl_info_t_get_clink(other); - if (lhs == NULL || rhs == NULL) - return false; - - *lhs = *rhs; - return true; -} - -//------------------------------------------------------------------------- -static bool textctrl_info_t_set_text(PyObject *self, const char *s) -{ - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); - if ( ti == NULL ) - return false; - ti->text = s; - return true; -} - -//------------------------------------------------------------------------- -static const char *textctrl_info_t_get_text(PyObject *self) -{ - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); - return ti == NULL ? "" : ti->text.c_str(); -} - -//------------------------------------------------------------------------- -static bool textctrl_info_t_set_flags(PyObject *self, unsigned int flags) -{ - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); - if ( ti == NULL ) - return false; - ti->flags = flags; - return true; -} - -//------------------------------------------------------------------------- -static unsigned int textctrl_info_t_get_flags( - PyObject *self, - unsigned int flags) -{ - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); - return ti == NULL ? 0 : ti->flags; -} - -//------------------------------------------------------------------------- -static bool textctrl_info_t_set_tabsize( - PyObject *self, - unsigned int tabsize) -{ - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); - if ( ti == NULL ) - return false; - ti->tabsize = tabsize; - return true; -} - -//------------------------------------------------------------------------- -static unsigned int textctrl_info_t_get_tabsize( - PyObject *self, - unsigned int tabsize) -{ - textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); - return ti == NULL ? 0 : ti->tabsize; -} - -//--------------------------------------------------------------------------- -static bool formchgcbfa_enable_field(size_t p_fa, int fid, bool enable) -{ - DECLARE_FORM_ACTIONS; - return fa->enable_field(fid, enable); -} - -//--------------------------------------------------------------------------- -static bool formchgcbfa_show_field(size_t p_fa, int fid, bool show) -{ - DECLARE_FORM_ACTIONS; - return fa->show_field(fid, show); -} - -//--------------------------------------------------------------------------- -static bool formchgcbfa_move_field( - size_t p_fa, - int fid, - int x, - int y, - int w, - int h) -{ - DECLARE_FORM_ACTIONS; - return fa->move_field(fid, x, y, w, h); -} - -//--------------------------------------------------------------------------- -static int formchgcbfa_get_focused_field(size_t p_fa) -{ - DECLARE_FORM_ACTIONS; - return fa->get_focused_field(); -} - -//--------------------------------------------------------------------------- -static bool formchgcbfa_set_focused_field(size_t p_fa, int fid) -{ - DECLARE_FORM_ACTIONS; - return fa->set_focused_field(fid); -} - -//--------------------------------------------------------------------------- -static void formchgcbfa_refresh_field(size_t p_fa, int fid) -{ - DECLARE_FORM_ACTIONS; - return fa->refresh_field(fid); -} - -//--------------------------------------------------------------------------- -static void formchgcbfa_close(size_t p_fa, int close_normally) -{ - DECLARE_FORM_ACTIONS; - fa->close(close_normally); -} - -//--------------------------------------------------------------------------- -static PyObject *formchgcbfa_get_field_value( - size_t p_fa, - int fid, - int ft, - size_t sz) -{ - DECLARE_FORM_ACTIONS; - PYW_GIL_CHECK_LOCKED_SCOPE(); - switch ( ft ) - { - // dropdown list - case 8: - { - // Readonly? Then return the selected index - if ( sz == 1 ) - { - int sel_idx; - if ( fa->get_combobox_value(fid, &sel_idx) ) - return PyLong_FromLong(sel_idx); - } - // Not readonly? Then return the qstring - else - { - qstring val; - if ( fa->get_combobox_value(fid, &val) ) - 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; - } - // button - uint32 - case 4: - { - 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; - } - // string label - case 1: - { - char val[MAXSTR]; - if ( fa->get_ascii_value(fid, val, sizeof(val)) ) - return PyString_FromString(val); - break; - } - // string input - case 3: - { - qstring val; - val.resize(sz + 1); - if ( fa->get_ascii_value(fid, val.begin(), val.size()) ) - return PyString_FromString(val.begin()); - break; - } - case 5: - { - intvec_t intvec; - // Returned as 1-base - if (fa->get_chooser_value(fid, &intvec)) - { - // Make 0-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it) - (*it)--; - ref_t l(PyW_IntVecToPyList(intvec)); - l.incref(); - return l.o; - } - break; - } - // Numeric control - case 6: - { - union - { - sel_t sel; - sval_t sval; - uval_t uval; - ulonglong ull; - } u; - switch ( sz ) - { - case 'S': // sel_t - { - if ( fa->get_segment_value(fid, &u.sel) ) - return Py_BuildValue(PY_FMT64, 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_SFMT64, 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_FMT64, u.uval); - break; - } - case '$': // ea_t - { - if ( fa->get_ea_value(fid, &u.uval) ) - return Py_BuildValue(PY_FMT64, u.uval); - break; - } - } - break; - } - } - Py_RETURN_NONE; -} - -//--------------------------------------------------------------------------- -static bool formchgcbfa_set_field_value( - size_t p_fa, - int fid, - int ft, - PyObject *py_val) -{ - DECLARE_FORM_ACTIONS; - PYW_GIL_CHECK_LOCKED_SCOPE(); - - switch ( ft ) - { - // dropdown list - case 8: - { - // Editable dropdown list - if ( PyString_Check(py_val) ) - { - qstring val(PyString_AsString(py_val)); - return fa->set_combobox_value(fid, &val); - } - // Readonly dropdown list - else - { - int sel_idx = PyLong_AsLong(py_val); - 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); - } - // button - uint32 - case 4: - { - 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); - } - // strings - case 3: - case 1: - return fa->set_ascii_value(fid, PyString_AsString(py_val)); - // intvec_t - case 5: - { - intvec_t intvec; - // Passed as 0-based - if ( !PyW_PyListToIntVec(py_val, intvec) ) - break; - - // Make 1-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it) - (*it)++; - - return fa->set_chooser_value(fid, &intvec); - } - // Numeric - case 6: - { - uint64 num; - if ( PyW_GetNumber(py_val, &num) ) - return fa->_set_field_value(fid, &num); - } - } - return false; -} - -#undef DECLARE_FORM_ACTIONS - -static size_t py_get_AskUsingForm() -{ - // Return a pointer to the function. Note that, although - // the C implementation of AskUsingForm_cv will do some - // Qt/txt widgets generation, the Python's ctypes - // implementation through which the call well go will first - // unblock other threads. No need to do it ourselves. - return (size_t)AskUsingForm_c; -} - -static size_t py_get_OpenForm() -{ - // See comments above. - return (size_t)OpenForm_c; -} - -static qvector py_compiled_form_vec; -static void py_register_compiled_form(PyObject *py_form) -{ - ref_t ref = borref_t(py_form); - if ( !py_compiled_form_vec.has(ref) ) - py_compiled_form_vec.push_back(ref); -} - -static void py_unregister_compiled_form(PyObject *py_form) -{ - ref_t ref = borref_t(py_form); - if ( py_compiled_form_vec.has(ref) ) - py_compiled_form_vec.del(ref); -} - // %} %{ // -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -int 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; - try - { - switch (notification_code) - { - case ui_preprocess: - { - const char *name = va_arg(va, const char *); - return proxy->preprocess(name); - } - - case ui_postprocess: - proxy->postprocess(); - break; - - case ui_saving: - proxy->saving(); - break; - - case ui_saved: - proxy->saved(); - break; - - case ui_term: - proxy->term(); - break; - - case ui_get_ea_hint: - { - ea_t ea = va_arg(va, ea_t); - char *buf = va_arg(va, char *); - size_t sz = va_arg(va, size_t); - char *_buf; - Py_ssize_t _len; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_str = proxy->get_ea_hint(ea); - if ( py_str != NULL - && PyString_Check(py_str) - && PyString_AsStringAndSize(py_str, &_buf, &_len) != - 1 ) - { - qstrncpy(buf, _buf, qmin(_len, sz)); - ret = 1; - } - break; - } - - case ui_current_tform_changed: - { - TForm *form = va_arg(va, TForm *); - TForm *prev_form = va_arg(va, TForm *); - proxy->current_tform_changed(form, prev_form); - } - break; - - case ui_updating_actions: - { - action_update_ctx_t *ctx = va_arg(va, action_update_ctx_t *); - proxy->updating_actions(ctx); - } - break; - - - case ui_updated_actions: - { - proxy->updated_actions(); - } - break; - - case ui_populating_tform_popup: - { - TForm *form = va_arg(va, TForm *); - TPopupMenu *popup = va_arg(va, TPopupMenu *); - proxy->populating_tform_popup(form, popup); - } - break; - - case ui_finish_populating_tform_popup: - { - TForm *form = va_arg(va, TForm *); - TPopupMenu *popup = va_arg(va, TPopupMenu *); - proxy->finish_populating_tform_popup(form, popup); - } - break; - } - } - catch (Swig::DirectorException &e) - { - msg("Exception in UI Hook function: %s\n", e.getMessage()); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( PyErr_Occurred() ) - PyErr_Print(); - } - return ret; -} - -//------------------------------------------------------------------------ -bool idaapi py_menu_item_callback(void *userdata) -{ - PYW_GIL_GET; - - // userdata is a tuple of ( func, args ) - // func and args are borrowed references from userdata - PyObject *func = PyTuple_GET_ITEM(userdata, 0); - PyObject *args = PyTuple_GET_ITEM(userdata, 1); - - // Call the python function - newref_t result(PyEval_CallObject(func, args)); - - // We cannot raise an exception in the callback, just print it. - if ( result == NULL ) - { - PyErr_Print(); - return false; - } - - return PyObject_IsTrue(result.o) != 0; -} - - - -//------------------------------------------------------------------------ -// Some defines -#define POPUP_NAMES_COUNT 4 -#define MAX_CHOOSER_MENU_COMMANDS 20 -#define thisobj ((py_choose2_t *) obj) -#define thisdecl py_choose2_t *_this = thisobj -#define MENU_COMMAND_CB(id) \ - static uint32 idaapi s_menu_command_##id(void *obj, uint32 n) \ - { \ - return thisobj->on_command(id, int(n)); \ - } - -//------------------------------------------------------------------------ -// Helper functions -class py_choose2_t; -typedef std::map pychoose2_to_choose2_map_t; -static pychoose2_to_choose2_map_t choosers; - -py_choose2_t *choose2_find_instance(PyObject *self) -{ - pychoose2_to_choose2_map_t::iterator it = choosers.find(self); - return it == choosers.end() ? NULL : it->second; -} - -void choose2_add_instance(PyObject *self, py_choose2_t *c2) -{ - choosers[self] = c2; -} - -void choose2_del_instance(PyObject *self) -{ - pychoose2_to_choose2_map_t::iterator it = choosers.find(self); - if ( it != choosers.end() ) - choosers.erase(it); -} - -//------------------------------------------------------------------------ -class py_choose2_t -{ -private: - enum - { - CHOOSE2_HAVE_DEL = 0x0001, - CHOOSE2_HAVE_INS = 0x0002, - CHOOSE2_HAVE_UPDATE = 0x0004, - CHOOSE2_HAVE_EDIT = 0x0008, - CHOOSE2_HAVE_ENTER = 0x0010, - CHOOSE2_HAVE_GETICON = 0x0020, - CHOOSE2_HAVE_GETATTR = 0x0040, - CHOOSE2_HAVE_COMMAND = 0x0080, - CHOOSE2_HAVE_ONCLOSE = 0x0100, - CHOOSE2_HAVE_SELECT = 0x0200, - CHOOSE2_HAVE_REFRESHED = 0x0400, - }; - // Chooser flags - int flags; - - // Callback flags (to tell which callback exists and which not) - // One of CHOOSE2_HAVE_xxxx - unsigned int cb_flags; - chooser_info_t *embedded; - intvec_t embedded_sel; - - // Menu callback index (in the menu_cbs array) - int menu_cb_idx; - - // Chooser title - qstring title; - - // Column widths - intvec_t widths; - - // Python object link - PyObject *self; - // Chooser columns - qstrvec_t cols; - const char **popup_names; - bool ui_cb_hooked; - - // The number of declarations should follow the MAX_CHOOSER_MENU_COMMANDS value - MENU_COMMAND_CB(0) MENU_COMMAND_CB(1) - MENU_COMMAND_CB(2) MENU_COMMAND_CB(3) - MENU_COMMAND_CB(4) MENU_COMMAND_CB(5) - MENU_COMMAND_CB(6) MENU_COMMAND_CB(7) - MENU_COMMAND_CB(8) MENU_COMMAND_CB(9) - MENU_COMMAND_CB(10) MENU_COMMAND_CB(11) - MENU_COMMAND_CB(12) MENU_COMMAND_CB(13) - MENU_COMMAND_CB(14) MENU_COMMAND_CB(15) - MENU_COMMAND_CB(16) MENU_COMMAND_CB(17) - MENU_COMMAND_CB(18) MENU_COMMAND_CB(19) - static chooser_cb_t *menu_cbs[MAX_CHOOSER_MENU_COMMANDS]; - - //------------------------------------------------------------------------ - // Static methods to dispatch to member functions - //------------------------------------------------------------------------ - static int idaapi ui_cb(void *obj, int notification_code, va_list va) - { - // This hook gets called from the kernel. Ensure we hold the GIL. - PYW_GIL_GET; - - // UI callback to handle chooser items with attributes - if ( notification_code != ui_get_chooser_item_attrs ) - return 0; - - // Pass events that belong to our chooser only - void *chooser_obj = va_arg(va, void *); - if ( obj != chooser_obj ) - return 0; - - int n = int(va_arg(va, uint32)); - chooser_item_attrs_t *attr = va_arg(va, chooser_item_attrs_t *); - thisobj->on_get_line_attr(n, attr); - return 1; - } - - static void idaapi s_select(void *obj, const intvec_t &sel) - { - thisobj->on_select(sel); - } - - static void idaapi s_refreshed(void *obj) - { - thisobj->on_refreshed(); - } - - static uint32 idaapi s_sizer(void *obj) - { - return (uint32)thisobj->on_get_size(); - } - - static void idaapi s_getl(void *obj, uint32 n, char * const *arrptr) - { - thisobj->on_get_line(int(n), arrptr); - } - - static uint32 idaapi s_del(void *obj, uint32 n) - { - return uint32(thisobj->on_delete_line(int(n))); - } - - static void idaapi s_ins(void *obj) - { - thisobj->on_insert_line(); - } - - static uint32 idaapi s_update(void *obj, uint32 n) - { - return uint32(thisobj->on_refresh(int(n))); - } - - static void idaapi s_edit(void *obj, uint32 n) - { - thisobj->on_edit_line(int(n)); - } - - static void idaapi s_enter(void * obj, uint32 n) - { - thisobj->on_enter(int(n)); - } - - static int idaapi s_get_icon(void *obj, uint32 n) - { - return thisobj->on_get_icon(int(n)); - } - - static void idaapi s_destroy(void *obj) - { - thisobj->on_close(); - } - - //------------------------------------------------------------------------ - // Member functions corresponding to each chooser2() callback - //------------------------------------------------------------------------ - void clear_popup_names() - { - if ( popup_names == NULL ) - return; - - for ( int i=0; i=0; i-- ) - line_arr[i][0] = '\0'; - - // Call Python - PYW_GIL_CHECK_LOCKED_SCOPE(); - pycall_res_t list(PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1)); - if ( list.result == NULL ) - return; - - // Go over the List returned by Python and convert to C strings - for ( int i=ncols-1; i>=0; i-- ) - { - borref_t item(PyList_GetItem(list.result.o, Py_ssize_t(i))); - if ( item == NULL ) - continue; - - const char *str = PyString_AsString(item.o); - if ( str != NULL ) - qstrncpy(line_arr[i], str, MAXSTR); - } - } - - size_t on_get_size() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL)); - if ( pyres.result == NULL ) - return 0; - - return PyInt_AsLong(pyres.result.o); - } - - void on_refreshed() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL)); - } - - void on_select(const intvec_t &intvec) - { - PYW_GIL_GET; - ref_t py_list(PyW_IntVecToPyList(intvec)); - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_SELECTION_CHANGE, "O", py_list.o)); - } - - void on_close() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL)); - - // Delete this instance if none modal and not embedded - if ( !is_modal() && get_embedded() == NULL ) - delete this; - } - - int on_delete_line(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_DELETE_LINE, - "i", - IS_CHOOSER_EVENT(lineno) ? lineno : lineno-1)); - return pyres.result == NULL ? 1 : PyInt_AsLong(pyres.result.o); - } - - int on_refresh(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_REFRESH, - "i", - lineno - 1)); - return pyres.result == NULL ? lineno : PyInt_AsLong(pyres.result.o) + 1; - } - - void on_insert_line() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_INSERT_LINE, NULL)); - } - - void on_enter(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_SELECT_LINE, - "i", - lineno - 1)); - } - - void on_edit_line(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_EDIT_LINE, - "i", - lineno - 1)); - } - - int on_command(int cmd_id, int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_COMMAND, - "ii", - lineno - 1, - cmd_id)); - return pyres.result == NULL ? lineno : PyInt_AsLong(pyres.result.o); - } - - int on_get_icon(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_GET_ICON, - "i", - lineno - 1)); - return PyInt_AsLong(pyres.result.o); - } - - void on_get_line_attr(int lineno, chooser_item_attrs_t *attr) - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1)); - if ( pyres.result != NULL ) - { - if ( PyList_Check(pyres.result.o) ) - { - PyObject *item; - if ( (item = PyList_GetItem(pyres.result.o, 0)) != NULL ) - attr->color = PyInt_AsLong(item); - if ( (item = PyList_GetItem(pyres.result.o, 1)) != NULL ) - attr->flags = PyInt_AsLong(item); - } - } - } - - bool split_chooser_caption(qstring *out_title, qstring *out_caption, const char *caption) const - { - if ( get_embedded() != NULL ) - { - // For embedded chooser, the "caption" will be overloaded to encode - // the AskUsingForm's title, caption and embedded chooser id - // Title:EmbeddedChooserID:Caption - - char title_buf[MAXSTR]; - const char *ptitle; - - static const char delimiter[] = ":"; - char temp[MAXSTR]; - qstrncpy(temp, caption, sizeof(temp)); - - char *ctx; - char *p = qstrtok(temp, delimiter, &ctx); - if ( p == NULL ) - return false; - - // Copy the title - char title_str[MAXSTR]; - qstrncpy(title_str, p, sizeof(title_str)); - - // Copy the echooser ID - p = qstrtok(NULL, delimiter, &ctx); - if ( p == NULL ) - return false; - - char id_str[10]; - qstrncpy(id_str, p, sizeof(id_str)); - - // Form the new title of the form: "AskUsingFormTitle:EchooserId" - qsnprintf(title_buf, sizeof(title_buf), "%s:%s", title_str, id_str); - - // Adjust the title - *out_title = title_buf; - - // Adjust the caption - p = qstrtok(NULL, delimiter, &ctx); - *out_caption = caption + (p - temp); - } - else - { - *out_title = title; - *out_caption = caption; - } - return true; - } - - // This must be called at the end of create(), when many dependencies - // have been computed (title, widths, popup_names, [cb_]flags, ...) - void fill_chooser_info( - chooser_info_t *out, - int deflt, - int desired_width, - int desired_height, - int icon) - { - memset(out, 0, sizeof(*out)); - out->obj = this; - out->cb = sizeof(*out); - out->title = title.c_str(); - out->columns = widths.size(); - out->deflt = deflt; - out->flags = flags; - out->width = desired_width; - out->height = desired_height; - out->icon = icon; - out->popup_names = popup_names; - out->widths = widths.begin(); - out->destroyer = s_destroy; - out->getl = s_getl; - out->sizer = s_sizer; - out->del = (cb_flags & CHOOSE2_HAVE_DEL) != 0 ? s_del : NULL; - out->edit = (cb_flags & CHOOSE2_HAVE_EDIT) != 0 ? s_edit : NULL; - out->enter = (cb_flags & CHOOSE2_HAVE_ENTER) != 0 ? s_enter : NULL; - out->get_icon = (cb_flags & CHOOSE2_HAVE_GETICON) != 0 ? s_get_icon : NULL; - out->ins = (cb_flags & CHOOSE2_HAVE_INS) != 0 ? s_ins : NULL; - out->update = (cb_flags & CHOOSE2_HAVE_UPDATE) != 0 ? s_update : NULL; - out->get_attrs = NULL; - out->initializer = NULL; - // Fill callbacks that are only present in idaq - if ( is_idaq() ) - { - out->select = (cb_flags & CHOOSE2_HAVE_SELECT) != 0 ? s_select : NULL; - out->refresh = (cb_flags & CHOOSE2_HAVE_REFRESHED)!= 0 ? s_refreshed : NULL; - } - else - { - out->select = NULL; - out->refresh = NULL; - } - } - -public: - //------------------------------------------------------------------------ - // Public methods - //------------------------------------------------------------------------ - py_choose2_t(): flags(0), cb_flags(0), - embedded(NULL), menu_cb_idx(0), - self(NULL), popup_names(NULL), ui_cb_hooked(false) - { - } - - ~py_choose2_t() - { - // Remove from list - choose2_del_instance(self); - - // Uninstall hooks - install_hooks(false); - - delete embedded; - Py_XDECREF(self); - clear_popup_names(); - } - - static py_choose2_t *find_chooser(const char *title) - { - return (py_choose2_t *) get_chooser_obj(title); - } - - void close() - { - // Will trigger on_close() - close_chooser(title.c_str()); - } - - bool activate() - { - TForm *frm = find_tform(title.c_str()); - if ( frm == NULL ) - return false; - - switchto_tform(frm, true); - return true; - } - - int add_command( - const char *_caption, - int flags=0, - int menu_index=-1, - int icon=-1) - { - if ( menu_cb_idx >= MAX_CHOOSER_MENU_COMMANDS ) - return -1; - - qstring title, caption; - if ( !split_chooser_caption(&title, &caption, _caption) - || !add_chooser_command( - title.c_str(), - caption.c_str(), - menu_cbs[menu_cb_idx], - menu_index, - icon, - flags) ) - return -1; - - return menu_cb_idx++; - } - - // Create a chooser. - // If it detects the "embedded" attribute, then it will create a chooser_info_t structure - // Otherwise the chooser window is created and displayed - int create(PyObject *self) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Get flags - ref_t flags_attr(PyW_TryGetAttrString(self, S_FLAGS)); - if ( flags_attr == NULL ) - return -1; - flags = PyInt_Check(flags_attr.o) != 0 ? PyInt_AsLong(flags_attr.o) : 0; - - // Get the title - if ( !PyW_GetStringAttr(self, S_TITLE, &title) ) - return -1; - - // Get columns - ref_t cols_attr(PyW_TryGetAttrString(self, "cols")); - if ( cols_attr == NULL ) - return -1; - - // Get col count - int ncols = int(PyList_Size(cols_attr.o)); - - // Get cols caption and widthes - cols.qclear(); - for ( int i=0; iself = self; - - // Hook to notification point (to handle chooser item attributes) - install_hooks(true); - - // Check if *embedded - ref_t emb_attr(PyW_TryGetAttrString(self, S_EMBEDDED)); - int rc; - if ( emb_attr != NULL && PyObject_IsTrue(emb_attr.o) == 1 ) - { - // Create an embedded chooser structure - embedded = new chooser_info_t(); - fill_chooser_info(embedded, deflt, pts[0], pts[1], icon); - rc = 1; // success - } - else - { - chooser_info_t ci; - fill_chooser_info(&ci, deflt, -1, -1, icon); - rc = choose3(&ci); - clear_popup_names(); - if ( is_modal() ) - --rc; // modal chooser return the index of the selected item - } - return rc; - } - - inline PyObject *get_self() - { - return self; - } - - void refresh() - { - refresh_chooser(title.c_str()); - } - - bool is_modal() - { - return (flags & CH_MODAL) != 0; - } - - intvec_t *get_sel_vec() - { - return &embedded_sel; - } - - chooser_info_t *get_embedded() const - { - return embedded; - } -}; - -//------------------------------------------------------------------------ -// Initialize the callback pointers -#define DECL_MENU_COMMAND_CB(id) s_menu_command_##id -chooser_cb_t *py_choose2_t::menu_cbs[MAX_CHOOSER_MENU_COMMANDS] = -{ - DECL_MENU_COMMAND_CB(0), DECL_MENU_COMMAND_CB(1), - DECL_MENU_COMMAND_CB(2), DECL_MENU_COMMAND_CB(3), - DECL_MENU_COMMAND_CB(4), DECL_MENU_COMMAND_CB(5), - DECL_MENU_COMMAND_CB(6), DECL_MENU_COMMAND_CB(7), - DECL_MENU_COMMAND_CB(8), DECL_MENU_COMMAND_CB(9), - DECL_MENU_COMMAND_CB(10), DECL_MENU_COMMAND_CB(11), - DECL_MENU_COMMAND_CB(12), DECL_MENU_COMMAND_CB(13), - DECL_MENU_COMMAND_CB(14), DECL_MENU_COMMAND_CB(15), - DECL_MENU_COMMAND_CB(16), DECL_MENU_COMMAND_CB(17), - DECL_MENU_COMMAND_CB(18), DECL_MENU_COMMAND_CB(19) -}; -#undef DECL_MENU_COMMAND_CB - -#undef POPUP_NAMES_COUNT -#undef MAX_CHOOSER_MENU_COMMANDS -#undef thisobj -#undef thisdecl -#undef MENU_COMMAND_CB - -//------------------------------------------------------------------------ -int choose2_create(PyObject *self, bool embedded) -{ - py_choose2_t *c2; - - c2 = choose2_find_instance(self); - if ( c2 != NULL ) - { - if ( !embedded ) - c2->activate(); - return 1; - } - - c2 = new py_choose2_t(); - - choose2_add_instance(self, c2); - - int r = c2->create(self); - // Non embedded chooser? Return immediately - if ( !embedded ) - return r; - - // Embedded chooser was not created? - if ( c2->get_embedded() == NULL || r != 1 ) - { - delete c2; - r = 0; - } - return r; -} - -//------------------------------------------------------------------------ -void choose2_close(PyObject *self) -{ - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 == NULL ) - return; - - // Modal or embedded chooser? - if ( c2->get_embedded() != NULL || c2->is_modal() ) - { - // Then simply delete the instance - delete c2; - } - else - { - // Close the chooser. - // In turn this will lead to the deletion of the object - c2->close(); - } -} - -//------------------------------------------------------------------------ -void choose2_refresh(PyObject *self) -{ - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 != NULL ) - c2->refresh(); -} - -//------------------------------------------------------------------------ -void choose2_activate(PyObject *self) -{ - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 != NULL ) - c2->activate(); -} - -//------------------------------------------------------------------------ -PyObject *choose2_get_embedded_selection(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - py_choose2_t *c2 = choose2_find_instance(self); - chooser_info_t *embedded; - - if ( c2 == NULL || (embedded = c2->get_embedded()) == NULL ) - Py_RETURN_NONE; - - // Returned as 1-based - intvec_t &intvec = *c2->get_sel_vec(); - - // Make 0-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it) - (*it)--; - - ref_t ret(PyW_IntVecToPyList(intvec)); - ret.incref(); - return ret.o; -} - -//------------------------------------------------------------------------ -// Return the C instances as 64bit numbers -PyObject *choose2_get_embedded(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - py_choose2_t *c2 = choose2_find_instance(self); - chooser_info_t *embedded; - - if ( c2 == NULL || (embedded = c2->get_embedded()) == NULL ) - Py_RETURN_NONE; - else - return Py_BuildValue("(KK)", - PY_ULONG_LONG(embedded), - PY_ULONG_LONG(c2->get_sel_vec())); -} - -//------------------------------------------------------------------------ -int choose2_add_command( - PyObject *self, - const char *caption, - int flags=0, - int menu_index=-1, - int icon=-1) -{ - py_choose2_t *c2 = choose2_find_instance(self); - return c2 == NULL ? -2 : c2->add_command(caption, flags, menu_index, icon); -} - -//------------------------------------------------------------------------ -PyObject *choose2_find(const char *title) -{ - py_choose2_t *c2 = py_choose2_t::find_chooser(title); - return c2 == NULL ? NULL : c2->get_self(); -} - - -void free_compiled_form_instances(void) -{ - while ( !py_compiled_form_vec.empty() ) - { - const ref_t &ref = py_compiled_form_vec[0]; - qstring title; - if ( !PyW_GetStringAttr(ref.o, "title", &title) ) - title = ""; - msg("WARNING: Form \"%s\" was not Free()d. Force-freeing.\n", title.c_str()); - // Will call 'py_unregister_compiled_form()', and thus trim the vector down. - newref_t unused(PyObject_CallMethod(ref.o, (char *)"Free", "()")); - } -} // - %} -%{ -// -//-------------------------------------------------------------------------- -#define MAX_PY_CLI 12 - -// Callbacks table -// This structure was devised because the cli callbacks have no user-data parameter -struct py_cli_cbs_t -{ - bool (idaapi *execute_line)(const char *line); - bool (idaapi *complete_line)( - qstring *completion, - const char *prefix, - int n, - const char *line, - int x); - bool (idaapi *keydown)( - qstring *line, - int *p_x, - int *p_sellen, - int *vk_key, - int shift); -}; - -// CLI Python wrapper class -class py_cli_t -{ -private: - //-------------------------------------------------------------------------- - cli_t cli; - PyObject *self; - qstring cli_sname, cli_lname, cli_hint; - - //-------------------------------------------------------------------------- - static py_cli_t *py_clis[MAX_PY_CLI]; - static const py_cli_cbs_t py_cli_cbs[MAX_PY_CLI]; - //-------------------------------------------------------------------------- -#define IMPL_PY_CLI_CB(CBN) \ - static bool idaapi s_keydown##CBN(qstring *line, int *p_x, int *p_sellen, int *vk_key, int shift) \ - { \ - return py_clis[CBN]->on_keydown(line, p_x, p_sellen, vk_key, shift); \ - } \ - static bool idaapi s_execute_line##CBN(const char *line) \ - { \ - return py_clis[CBN]->on_execute_line(line); \ - } \ - static bool idaapi s_complete_line##CBN(qstring *completion, const char *prefix, int n, const char *line, int x) \ - { \ - return py_clis[CBN]->on_complete_line(completion, prefix, n, line, x); \ - } - - IMPL_PY_CLI_CB(0); IMPL_PY_CLI_CB(1); IMPL_PY_CLI_CB(2); IMPL_PY_CLI_CB(3); - IMPL_PY_CLI_CB(4); IMPL_PY_CLI_CB(5); IMPL_PY_CLI_CB(6); IMPL_PY_CLI_CB(7); - IMPL_PY_CLI_CB(8); IMPL_PY_CLI_CB(9); IMPL_PY_CLI_CB(10); IMPL_PY_CLI_CB(11); -#undef IMPL_PY_CLI_CB - - //-------------------------------------------------------------------------- - // callback: the user pressed Enter - // CLI is free to execute the line immediately or ask for more lines - // Returns: true-executed line, false-ask for more lines - bool on_execute_line(const char *line) - { - PYW_GIL_GET; - newref_t result( - PyObject_CallMethod( - self, - (char *)S_ON_EXECUTE_LINE, - "s", - line)); - PyW_ShowCbErr(S_ON_EXECUTE_LINE); - return result != NULL && PyObject_IsTrue(result.o); - } - - //-------------------------------------------------------------------------- - // callback: a keyboard key has been pressed - // This is a generic callback and the CLI is free to do whatever - // it wants. - // line - current input line (in/out argument) - // p_x - pointer to current x coordinate of the cursor (in/out) - // p_sellen - pointer to current selection length (usually 0) - // p_vk_key - pointer to virtual key code (in/out) - // if the key has been handled, it should be reset to 0 by CLI - // shift - shift state - // Returns: true-modified input line or x coordinate or selection length - // This callback is optional - bool on_keydown( - qstring *line, - int *p_x, - int *p_sellen, - int *vk_key, - int shift) - { - PYW_GIL_GET; - newref_t result( - PyObject_CallMethod( - self, - (char *)S_ON_KEYDOWN, - "siiHi", - line->c_str(), - *p_x, - *p_sellen, - *vk_key, - shift)); - - bool ok = result != NULL && PyTuple_Check(result.o); - - PyW_ShowCbErr(S_ON_KEYDOWN); - - if ( ok ) - { - Py_ssize_t sz = PyTuple_Size(result.o); - PyObject *item; - -#define GET_TUPLE_ENTRY(col, PyThingy, AsThingy, out) \ - do \ - { \ - if ( sz > col ) \ - { \ - borref_t _r(PyTuple_GetItem(result.o, col)); \ - if ( _r != NULL && PyThingy##_Check(_r.o) ) \ - *out = PyThingy##_##AsThingy(_r.o); \ - } \ - } while ( false ) - - GET_TUPLE_ENTRY(0, PyString, AsString, line); - GET_TUPLE_ENTRY(1, PyInt, AsLong, p_x); - GET_TUPLE_ENTRY(2, PyInt, AsLong, p_sellen); - GET_TUPLE_ENTRY(3, PyInt, AsLong, vk_key); - *vk_key &= 0xffff; -#undef GET_TUPLE_ENTRY - } - return ok; - } - - // callback: the user pressed Tab - // Find a completion number N for prefix PREFIX - // LINE is given as context information. X is the index where PREFIX starts in LINE - // New prefix should be stored in PREFIX. - // Returns: true if generated a new completion - // This callback is optional - bool on_complete_line( - qstring *completion, - const char *prefix, - int n, - const char *line, - int x) - { - PYW_GIL_GET; - newref_t result( - PyObject_CallMethod( - self, - (char *)S_ON_COMPLETE_LINE, - "sisi", - prefix, - n, - line, - x)); - - bool ok = result != NULL && PyString_Check(result.o); - PyW_ShowCbErr(S_ON_COMPLETE_LINE); - if ( ok ) - *completion = PyString_AsString(result.o); - return ok; - } - - // Private ctor (use bind()) - py_cli_t() - { - } - -public: - //--------------------------------------------------------------------------- - static int bind(PyObject *py_obj) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - int cli_idx; - // Find an empty slot - for ( cli_idx = 0; cli_idx < MAX_PY_CLI; ++cli_idx ) - { - if ( py_clis[cli_idx] == NULL ) - break; - } - py_cli_t *py_cli = NULL; - do - { - // No free slots? - if ( cli_idx >= MAX_PY_CLI ) - break; - - // Create a new instance - py_cli = new py_cli_t(); - PyObject *attr; - - // Start populating the 'cli' member - py_cli->cli.size = sizeof(cli_t); - - // Store 'flags' - { - ref_t flags_attr(PyW_TryGetAttrString(py_obj, S_FLAGS)); - if ( flags_attr == NULL ) - py_cli->cli.flags = 0; - else - py_cli->cli.flags = PyLong_AsLong(flags_attr.o); - } - - // Store 'sname' - if ( !PyW_GetStringAttr(py_obj, "sname", &py_cli->cli_sname) ) - break; - py_cli->cli.sname = py_cli->cli_sname.c_str(); - - // Store 'lname' - if ( !PyW_GetStringAttr(py_obj, "lname", &py_cli->cli_lname) ) - break; - py_cli->cli.lname = py_cli->cli_lname.c_str(); - - // Store 'hint' - if ( !PyW_GetStringAttr(py_obj, "hint", &py_cli->cli_hint) ) - break; - py_cli->cli.hint = py_cli->cli_hint.c_str(); - - // Store callbacks - if ( !PyObject_HasAttrString(py_obj, S_ON_EXECUTE_LINE) ) - break; - py_cli->cli.execute_line = py_cli_cbs[cli_idx].execute_line; - - py_cli->cli.complete_line = PyObject_HasAttrString(py_obj, S_ON_COMPLETE_LINE) ? py_cli_cbs[cli_idx].complete_line : NULL; - py_cli->cli.keydown = PyObject_HasAttrString(py_obj, S_ON_KEYDOWN) ? py_cli_cbs[cli_idx].keydown : NULL; - - // install CLI - install_command_interpreter(&py_cli->cli); - - // Take reference to this object - py_cli->self = py_obj; - Py_INCREF(py_obj); - - // Save the instance - py_clis[cli_idx] = py_cli; - - return cli_idx; - } while (false); - - delete py_cli; - return -1; - } - - //--------------------------------------------------------------------------- - static void unbind(int cli_idx) - { - // Out of bounds or not set? - if ( cli_idx < 0 || cli_idx >= MAX_PY_CLI || py_clis[cli_idx] == NULL ) - return; - - py_cli_t *py_cli = py_clis[cli_idx]; - remove_command_interpreter(&py_cli->cli); - - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_DECREF(py_cli->self); - delete py_cli; - } - - py_clis[cli_idx] = NULL; - - return; - } -}; -py_cli_t *py_cli_t::py_clis[MAX_PY_CLI] = {NULL}; -#define DECL_PY_CLI_CB(CBN) { s_execute_line##CBN, s_complete_line##CBN, s_keydown##CBN } -const py_cli_cbs_t py_cli_t::py_cli_cbs[MAX_PY_CLI] = -{ - DECL_PY_CLI_CB(0), DECL_PY_CLI_CB(1), DECL_PY_CLI_CB(2), DECL_PY_CLI_CB(3), - DECL_PY_CLI_CB(4), DECL_PY_CLI_CB(5), DECL_PY_CLI_CB(6), DECL_PY_CLI_CB(7), - DECL_PY_CLI_CB(8), DECL_PY_CLI_CB(9), DECL_PY_CLI_CB(10), DECL_PY_CLI_CB(11) -}; -#undef DECL_PY_CLI_CB -// - -// -//--------------------------------------------------------------------------- -class plgform_t -{ -private: - ref_t py_obj; - TForm *form; - - static int idaapi s_callback(void *ud, int notification_code, va_list va) - { - // This hook gets called from the kernel. Ensure we hold the GIL. - PYW_GIL_GET; - - plgform_t *_this = (plgform_t *)ud; - if ( notification_code == ui_tform_visible ) - { - TForm *form = va_arg(va, TForm *); - if ( form == _this->form ) - { - // 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(form, NULL))); - PyW_ShowCbErr(S_ON_CREATE); - } - } - else if ( notification_code == ui_tform_invisible ) - { - TForm *form = va_arg(va, TForm *); - if ( form == _this->form ) - { - { - newref_t py_result( - PyObject_CallMethod( - _this->py_obj.o, - (char *)S_ON_CLOSE, "O", - PyCObject_FromVoidPtr(form, NULL))); - PyW_ShowCbErr(S_ON_CLOSE); - } - _this->unhook(); - } - } - return 0; - } - - void unhook() - { - unhook_from_notification_point(HT_UI, s_callback, this); - form = NULL; - - // Call DECREF at last, since it may trigger __del__ - PYW_GIL_CHECK_LOCKED_SCOPE(); - py_obj = ref_t(); - } - -public: - plgform_t(): form(NULL) - { - } - - bool show( - PyObject *obj, - const char *caption, - int options) - { - // Already displayed? - TForm *f = find_tform(caption); - if ( f != NULL ) - { - // Our form? - if ( f == form ) - { - // Switch to it - switchto_tform(form, true); - return true; - } - // Fail to create - return false; - } - - // Create a form - form = create_tform(caption, NULL); - if ( form == NULL ) - return false; - - if ( !hook_to_notification_point(HT_UI, s_callback, this) ) - { - form = NULL; - return false; - } - - py_obj = borref_t(obj); - - if ( is_idaq() ) - options |= FORM_QWIDGET; - - this->form = form; - open_tform(form, options); - return true; - } - - void close(int options = 0) - { - if ( form != NULL ) - close_tform(form, options); - } - - static PyObject *create() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(new plgform_t(), destroy); - } - - static void destroy(void *obj) - { - delete (plgform_t *)obj; - } -}; -// -%} - -%inline %{ -// -//--------------------------------------------------------------------------- -#define DECL_PLGFORM PYW_GIL_CHECK_LOCKED_SCOPE(); plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link); -static PyObject *plgform_new() -{ - return plgform_t::create(); -} - -static bool plgform_show( - PyObject *py_link, - PyObject *py_obj, - const char *caption, - int options = FORM_TAB|FORM_MENU|FORM_RESTORE) -{ - DECL_PLGFORM; - return plgform->show(py_obj, caption, options); -} - -static void plgform_close( - PyObject *py_link, - int options) -{ - DECL_PLGFORM; - plgform->close(options); -} -#undef DECL_PLGFORM -// -%} - -%{ -// -//--------------------------------------------------------------------------- -// Base class for all custviewer place_t providers -class custviewer_data_t -{ -public: - virtual void *get_ud() = 0; - virtual place_t *get_min() = 0; - virtual place_t *get_max() = 0; -}; - -//--------------------------------------------------------------------------- -class cvdata_simpleline_t: public custviewer_data_t -{ -private: - strvec_t lines; - simpleline_place_t pl_min, pl_max; -public: - - void *get_ud() - { - return &lines; - } - - place_t *get_min() - { - return &pl_min; - } - - place_t *get_max() - { - return &pl_max; - } - - strvec_t &get_lines() - { - return lines; - } - - void set_minmax(size_t start=0, size_t end=size_t(-1)) - { - if ( start == 0 && end == size_t(-1) ) - { - end = lines.size(); - pl_min.n = 0; - pl_max.n = end == 0 ? 0 : end - 1; - } - else - { - pl_min.n = start; - pl_max.n = end; - } - } - - bool set_line(size_t nline, simpleline_t &sl) - { - if ( nline >= lines.size() ) - return false; - lines[nline] = sl; - return true; - } - - bool del_line(size_t nline) - { - if ( nline >= lines.size() ) - return false; - lines.erase(lines.begin()+nline); - return true; - } - - void add_line(simpleline_t &line) - { - lines.push_back(line); - } - - void add_line(const char *str) - { - lines.push_back(simpleline_t(str)); - } - - bool insert_line(size_t nline, simpleline_t &line) - { - if ( nline >= lines.size() ) - return false; - lines.insert(lines.begin()+nline, line); - return true; - } - - bool patch_line(size_t nline, size_t offs, int value) - { - if ( nline >= lines.size() ) - return false; - qstring &L = lines[nline].line; - L[offs] = (uchar) value & 0xFF; - return true; - } - - const size_t to_lineno(place_t *pl) const - { - return ((simpleline_place_t *)pl)->n; - } - - bool curline(place_t *pl, size_t *n) - { - if ( pl == NULL ) - return false; - - *n = to_lineno(pl); - return true; - } - - simpleline_t *get_line(size_t nline) - { - return nline >= lines.size() ? NULL : &lines[nline]; - } - - simpleline_t *get_line(place_t *pl) - { - return pl == NULL ? NULL : get_line(((simpleline_place_t *)pl)->n); - } - - const size_t count() const - { - return lines.size(); - } - - void clear_lines() - { - lines.clear(); - set_minmax(); - } -}; - -//--------------------------------------------------------------------------- -// FIXME: This should inherit py_view_base.hpp's py_customidamemo_t, -// just like py_graph.hpp's py_graph_t does. -// There should be a way to "merge" the two mechanisms; they are similar. -class customviewer_t -{ -protected: - qstring _title; - TForm *_form; - TCustomControl *_cv; - custviewer_data_t *_data; - int _features; - enum - { - HAVE_HINT = 0x0001, - HAVE_KEYDOWN = 0x0002, - HAVE_POPUP = 0x0004, - HAVE_DBLCLICK = 0x0008, - HAVE_CURPOS = 0x0010, - HAVE_CLICK = 0x0020, - HAVE_CLOSE = 0x0040 - }; -private: - struct cvw_popupctx_t - { - size_t menu_id; - customviewer_t *cv; - cvw_popupctx_t(): menu_id(0), cv(NULL) { } - cvw_popupctx_t(size_t mid, customviewer_t *v): menu_id(mid), cv(v) { } - }; - typedef std::map cvw_popupmap_t; - static cvw_popupmap_t _global_popup_map; - static size_t _global_popup_id; - qstring _curline; - intvec_t _installed_popups; - - static bool idaapi s_popup_menu_cb(void *ud) - { - size_t mid = (size_t)ud; - cvw_popupmap_t::iterator it = _global_popup_map.find(mid); - if ( it == _global_popup_map.end() ) - return false; - - PYW_GIL_GET; - return it->second.cv->on_popup_menu(it->second.menu_id); - } - - static bool idaapi s_cv_keydown( - TCustomControl * /*cv*/, - int vk_key, - int shift, - void *ud) - { - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - return _this->on_keydown(vk_key, shift); - } - - // The popup menu is being constructed - static void idaapi s_cv_popup(TCustomControl * /*cv*/, void *ud) - { - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - _this->on_popup(); - } - - // The user clicked - static bool idaapi s_cv_click(TCustomControl * /*cv*/, int shift, void *ud) - { - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - return _this->on_click(shift); - } - - // The user double clicked - static bool idaapi s_cv_dblclick(TCustomControl * /*cv*/, int shift, void *ud) - { - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - return _this->on_dblclick(shift); - } - - // Cursor position has been changed - static void idaapi s_cv_curpos(TCustomControl * /*cv*/, void *ud) - { - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - _this->on_curpos_changed(); - } - - //-------------------------------------------------------------------------- - static int idaapi s_ui_cb(void *ud, int code, va_list va) - { - // This hook gets called from the kernel. Ensure we hold the GIL. - PYW_GIL_GET; - customviewer_t *_this = (customviewer_t *)ud; - switch ( code ) - { - case ui_get_custom_viewer_hint: - { - TCustomControl *viewer = va_arg(va, TCustomControl *); - place_t *place = va_arg(va, place_t *); - int *important_lines = va_arg(va, int *); - qstring &hint = *va_arg(va, qstring *); - if ( (_this->_features & HAVE_HINT) == 0 || place == NULL || _this->_cv != viewer ) - return 0; - else - return _this->on_hint(place, important_lines, hint) ? 1 : 0; - } - - case ui_tform_invisible: - { - TForm *form = va_arg(va, TForm *); - if ( _this->_form != form ) - break; - } - // fallthrough... - case ui_term: - unhook_from_notification_point(HT_UI, s_ui_cb, _this); - _this->on_close(); - _this->on_post_close(); - break; - } - - return 0; - } - - void on_post_close() - { - init_vars(); - clear_popup_menu(); - } - -public: - - inline TForm *get_tform() { return _form; } - inline TCustomControl *get_tcustom_control() { return _cv; } - - // - // All the overridable callbacks - // - - // OnClick - virtual bool on_click(int /*shift*/) { return false; } - - // OnDblClick - virtual bool on_dblclick(int /*shift*/) { return false; } - - // OnCurorPositionChanged - virtual void on_curpos_changed() { } - - // OnHostFormClose - virtual void on_close() { } - - // 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; } - - // OnPopupMenuClick - virtual bool on_popup_menu(size_t menu_id) { return false; } - - void init_vars() - { - _data = NULL; - _features = 0; - _curline.clear(); - _cv = NULL; - _form = NULL; - } - - customviewer_t() - { - init_vars(); - } - - ~customviewer_t() - { - } - - //-------------------------------------------------------------------------- - void close() - { - if ( _form != NULL ) - close_tform(_form, FORM_SAVE | FORM_CLOSE_LATER); - } - - //-------------------------------------------------------------------------- - bool set_range( - const place_t *minplace = NULL, - const place_t *maxplace = NULL) - { - if ( _cv == NULL ) - return false; - - set_custom_viewer_range( - _cv, - minplace == NULL ? _data->get_min() : minplace, - maxplace == NULL ? _data->get_max() : maxplace); - return true; - } - - place_t *get_place( - bool mouse = false, - int *x = 0, - int *y = 0) - { - return _cv == NULL ? NULL : get_custom_viewer_place(_cv, mouse, x, y); - } - - //-------------------------------------------------------------------------- - bool refresh() - { - if ( _cv == NULL ) - return false; - - refresh_custom_viewer(_cv); - return true; - } - - //-------------------------------------------------------------------------- - bool refresh_current() - { - int x, y; - place_t *pl = get_place(false, &x, &y); - if ( pl == NULL ) - return false; - - return jumpto(pl, x, y); - } - - //-------------------------------------------------------------------------- - bool get_current_word(bool mouse, qstring &word) - { - // query the cursor position - int x, y; - if ( get_place(mouse, &x, &y) == NULL ) - return false; - - // query the line at the cursor - const char *line = get_current_line(mouse, true); - if ( line == NULL ) - return false; - - if ( x >= (int)strlen(line) ) - return false; - - // find the beginning of the word - const char *ptr = line + x; - while ( ptr > line && !qisspace(ptr[-1]) ) - ptr--; - - // find the end of the word - const char *begin = ptr; - ptr = line + x; - while ( !qisspace(*ptr) && *ptr != '\0' ) - ptr++; - - word.qclear(); - word.append(begin, ptr-begin); - return true; - } - - //-------------------------------------------------------------------------- - const char *get_current_line(bool mouse, bool notags) - { - const char *r = get_custom_viewer_curline(_cv, mouse); - if ( r == NULL || !notags ) - return r; - - size_t sz = strlen(r); - if ( sz == 0 ) - return r; - - _curline.resize(sz + 5, '\0'); - tag_remove(r, &_curline[0], sz + 1); - return _curline.c_str(); - } - - //-------------------------------------------------------------------------- - bool is_focused() - { - return get_current_viewer() == _cv; - } - - //-------------------------------------------------------------------------- - bool jumpto(place_t *place, int x, int y) - { - return ::jumpto(_cv, place, x, y); - } - - //-------------------------------------------------------------------------- - void clear_popup_menu() - { - if ( _cv != NULL ) - set_custom_viewer_popup_menu(_cv, NULL); - - for (intvec_t::iterator it=_installed_popups.begin(), it_end=_installed_popups.end(); - it != it_end; - ++it) - { - _global_popup_map.erase(*it); - } - _installed_popups.clear(); - } - - //-------------------------------------------------------------------------- - size_t add_popup_menu( - const char *title, - const char *hotkey) - { - size_t menu_id = _global_popup_id + 1; - - // Overlap / already exists? - if (_cv == NULL || // No custviewer? - // Overlap? - menu_id == 0 || - // Already exists? - _global_popup_map.find(menu_id) != _global_popup_map.end()) - { - return 0; - } - add_custom_viewer_popup_item(_cv, title, hotkey, s_popup_menu_cb, (void *)menu_id); - - // Save global association - _global_popup_map[menu_id] = cvw_popupctx_t(menu_id, this); - _global_popup_id = menu_id; - - // Remember what menu IDs are set with this form - _installed_popups.push_back(menu_id); - return menu_id; - } - - //-------------------------------------------------------------------------- - bool create(const char *title, int features, custviewer_data_t *data) - { - // Already created? (in the instance) - if ( _form != NULL ) - return true; - - // Already created? (in IDA windows list) - HWND hwnd(NULL); - TForm *form = create_tform(title, &hwnd); - if ( hwnd == NULL ) - return false; - - _title = title; - _data = data; - _form = form; - _features = features; - - // Create the viewer - _cv = create_custom_viewer( - title, - (TWinControl *)_form, - _data->get_min(), - _data->get_max(), - _data->get_min(), - 0, - _data->get_ud()); - - // Set user-data - set_custom_viewer_handler(_cv, CVH_USERDATA, (void *)this); - - // - // Set other optional callbacks - // - if ( (features & HAVE_KEYDOWN) != 0 ) - set_custom_viewer_handler(_cv, CVH_KEYDOWN, (void *)s_cv_keydown); - - if ( (features & HAVE_POPUP) != 0 ) - set_custom_viewer_handler(_cv, CVH_POPUP, (void *)s_cv_popup); - - if ( (features & HAVE_DBLCLICK) != 0 ) - set_custom_viewer_handler(_cv, CVH_DBLCLICK, (void *)s_cv_dblclick); - - if ( (features & HAVE_CURPOS) != 0 ) - set_custom_viewer_handler(_cv, CVH_CURPOS, (void *)s_cv_curpos); - - if ( (features & HAVE_CLICK) != 0 ) - set_custom_viewer_handler(_cv, CVH_CLICK, (void *)s_cv_click); - - // Hook to UI notifications (for TForm close event) - hook_to_notification_point(HT_UI, s_ui_cb, this); - - return true; - } - - //-------------------------------------------------------------------------- - bool show() - { - // Closed already? - if ( _form == NULL ) - return false; - - open_tform(_form, FORM_TAB|FORM_MENU|FORM_RESTORE|FORM_QWIDGET); - return true; - } -}; - -customviewer_t::cvw_popupmap_t customviewer_t::_global_popup_map; -size_t customviewer_t::_global_popup_id = 0; -//--------------------------------------------------------------------------- -class py_simplecustview_t: public customviewer_t -{ -private: - cvdata_simpleline_t data; - PyObject *py_self, *py_this, *py_last_link; - int features; - - //-------------------------------------------------------------------------- - // Convert a tuple (String, [color, [bgcolor]]) to a simpleline_t - static bool py_to_simpleline(PyObject *py, simpleline_t &sl) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( PyString_Check(py) ) - { - sl.line = PyString_AsString(py); - return true; - } - Py_ssize_t sz; - if ( !PyTuple_Check(py) || (sz = PyTuple_Size(py)) <= 0 ) - return false; - - PyObject *py_val = PyTuple_GetItem(py, 0); - if ( !PyString_Check(py_val) ) - return false; - - sl.line = PyString_AsString(py_val); - - if ( (sz > 1) && (py_val = PyTuple_GetItem(py, 1)) && PyLong_Check(py_val) ) - sl.color = color_t(PyLong_AsUnsignedLong(py_val)); - - if ( (sz > 2) && (py_val = PyTuple_GetItem(py, 2)) && PyLong_Check(py_val) ) - sl.bgcolor = PyLong_AsUnsignedLong(py_val); - - return true; - } - - // - // Callbacks - // - virtual bool on_click(int shift) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift)); - PyW_ShowCbErr(S_ON_CLICK); - return py_result != NULL && PyObject_IsTrue(py_result.o); - } - - //-------------------------------------------------------------------------- - // OnDblClick - virtual bool on_dblclick(int shift) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift)); - PyW_ShowCbErr(S_ON_DBL_CLICK); - return py_result != NULL && PyObject_IsTrue(py_result.o); - } - - //-------------------------------------------------------------------------- - // OnCurorPositionChanged - virtual void on_curpos_changed() - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, NULL)); - PyW_ShowCbErr(S_ON_CURSOR_POS_CHANGED); - } - - //-------------------------------------------------------------------------- - // 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 ) - { - 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); - py_self = NULL; - } - } - - //-------------------------------------------------------------------------- - // OnKeyDown - virtual bool on_keydown(int vk_key, int shift) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result( - PyObject_CallMethod( - py_self, - (char *)S_ON_KEYDOWN, - "ii", - vk_key, - shift)); - - PyW_ShowCbErr(S_ON_KEYDOWN); - 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) - { - size_t ln = data.to_lineno(place); - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result( - PyObject_CallMethod( - py_self, - (char *)S_ON_HINT, - PY_FMT64, - pyul_t(ln))); - - PyW_ShowCbErr(S_ON_HINT); - bool ok = py_result != NULL && PyTuple_Check(py_result.o) && PyTuple_Size(py_result.o) == 2; - if ( ok ) - { - if ( important_lines != NULL ) - *important_lines = PyInt_AsLong(PyTuple_GetItem(py_result.o, 0)); - hint = PyString_AsString(PyTuple_GetItem(py_result.o, 1)); - } - return ok; - } - - //-------------------------------------------------------------------------- - // OnPopupMenuClick - virtual bool on_popup_menu(size_t menu_id) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_result( - PyObject_CallMethod( - py_self, - (char *)S_ON_POPUP_MENU, - PY_FMT64, - pyul_t(menu_id))); - PyW_ShowCbErr(S_ON_POPUP_MENU); - return py_result != NULL && PyObject_IsTrue(py_result.o); - } - - //-------------------------------------------------------------------------- - void refresh_range() - { - data.set_minmax(); - set_range(); - } - -public: - py_simplecustview_t() - { - py_this = py_self = py_last_link = NULL; - } - ~py_simplecustview_t() - { - } - - //-------------------------------------------------------------------------- - // Edits an existing line - bool edit_line(size_t nline, PyObject *py_sl) - { - simpleline_t sl; - if ( !py_to_simpleline(py_sl, sl) ) - return false; - - return data.set_line(nline, sl); - } - - // Low level: patches a line string directly - bool patch_line(size_t nline, size_t offs, int value) - { - return data.patch_line(nline, offs, value); - } - - // Insert a line - bool insert_line(size_t nline, PyObject *py_sl) - { - simpleline_t sl; - if ( !py_to_simpleline(py_sl, sl) ) - return false; - return data.insert_line(nline, sl); - } - - // Adds a line tuple - bool add_line(PyObject *py_sl) - { - simpleline_t sl; - if ( !py_to_simpleline(py_sl, sl) ) - return false; - data.add_line(sl); - refresh_range(); - return true; - } - - //-------------------------------------------------------------------------- - bool del_line(size_t nline) - { - bool ok = data.del_line(nline); - if ( ok ) - refresh_range(); - return ok; - } - - //-------------------------------------------------------------------------- - // Gets the position and returns a tuple (lineno, x, y) - PyObject *get_pos(bool mouse) - { - place_t *pl; - int x, y; - pl = get_place(mouse, &x, &y); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( pl == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("(" PY_FMT64 "ii)", pyul_t(data.to_lineno(pl)), x, y); - } - - //-------------------------------------------------------------------------- - // Returns the line tuple - PyObject *get_line(size_t nline) - { - simpleline_t *r = data.get_line(nline); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( r == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("(sII)", r->line.c_str(), (unsigned int)r->color, (unsigned int)r->bgcolor); - } - - // Returns the count of lines - const size_t count() const - { - return data.count(); - } - - // Clears lines - void clear() - { - data.clear_lines(); - refresh_range(); - } - - //-------------------------------------------------------------------------- - bool jumpto(size_t ln, int x, int y) - { - simpleline_place_t l(ln); - return customviewer_t::jumpto(&l, x, y); - } - - //-------------------------------------------------------------------------- - // Initializes and links the Python object to this class - bool init(PyObject *py_link, const char *title) - { - // Already created? - if ( _form != NULL ) - return true; - - // Probe callbacks - features = 0; - static struct - { - const char *cb_name; - int feature; - } const cbtable[] = - { - {S_ON_CLICK, HAVE_CLICK}, - {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} - }; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - for ( size_t i=0; i -%} - -%inline %{ -// -static int py_install_command_interpreter(PyObject *py_obj) -{ - return py_cli_t::bind(py_obj); -} - -static void py_remove_command_interpreter(int cli_idx) -{ - py_cli_t::unbind(cli_idx); -} -// - -// -// -// Pywraps Simple Custom Viewer functions -// -PyObject *pyscv_init(PyObject *py_link, const char *title) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - py_simplecustview_t *_this = new py_simplecustview_t(); - bool ok = _this->init(py_link, title); - if ( !ok ) - { - delete _this; - Py_RETURN_NONE; - } - return _this->get_pythis(); -} -#define DECL_THIS py_simplecustview_t *_this = py_simplecustview_t::get_this(py_this) - -//-------------------------------------------------------------------------- -bool pyscv_refresh(PyObject *py_this) -{ - DECL_THIS; - if ( _this == NULL ) - return false; - return _this->refresh(); -} - -//-------------------------------------------------------------------------- -bool pyscv_delete(PyObject *py_this) -{ - DECL_THIS; - if ( _this == NULL ) - return false; - _this->close(); - delete _this; - return true; -} - -//-------------------------------------------------------------------------- -bool pyscv_refresh_current(PyObject *py_this) -{ - DECL_THIS; - if ( _this == NULL ) - return false; - return _this->refresh_current(); -} - -//-------------------------------------------------------------------------- -PyObject *pyscv_get_current_line(PyObject *py_this, bool mouse, bool notags) -{ - DECL_THIS; - PYW_GIL_CHECK_LOCKED_SCOPE(); - const char *line; - if ( _this == NULL || (line = _this->get_current_line(mouse, notags)) == NULL ) - Py_RETURN_NONE; - return PyString_FromString(line); -} - -//-------------------------------------------------------------------------- -bool pyscv_is_focused(PyObject *py_this) -{ - DECL_THIS; - if ( _this == NULL ) - return false; - return _this->is_focused(); -} - -void pyscv_clear_popup_menu(PyObject *py_this) -{ - DECL_THIS; - if ( _this != NULL ) - _this->clear_popup_menu(); -} - -size_t pyscv_add_popup_menu(PyObject *py_this, const char *title, const char *hotkey) -{ - DECL_THIS; - return _this == NULL ? 0 : _this->add_popup_menu(title, hotkey); -} - -size_t pyscv_count(PyObject *py_this) -{ - DECL_THIS; - return _this == NULL ? 0 : _this->count(); -} - -bool pyscv_show(PyObject *py_this) -{ - DECL_THIS; - return _this == NULL ? false : _this->show(); -} - -void pyscv_close(PyObject *py_this) -{ - DECL_THIS; - if ( _this != NULL ) - _this->close(); -} - -bool pyscv_jumpto(PyObject *py_this, size_t ln, int x, int y) -{ - DECL_THIS; - if ( _this == NULL ) - return false; - return _this->jumpto(ln, x, y); -} - -// Returns the line tuple -PyObject *pyscv_get_line(PyObject *py_this, size_t nline) -{ - DECL_THIS; - if ( _this == NULL ) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - } - return _this->get_line(nline); -} - -//-------------------------------------------------------------------------- -// Gets the position and returns a tuple (lineno, x, y) -PyObject *pyscv_get_pos(PyObject *py_this, bool mouse) -{ - DECL_THIS; - if ( _this == NULL ) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - } - return _this->get_pos(mouse); -} - -//-------------------------------------------------------------------------- -PyObject *pyscv_clear_lines(PyObject *py_this) -{ - DECL_THIS; - if ( _this != NULL ) - _this->clear(); - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; -} - -//-------------------------------------------------------------------------- -// Adds a line tuple -bool pyscv_add_line(PyObject *py_this, PyObject *py_sl) -{ - DECL_THIS; - return _this == NULL ? false : _this->add_line(py_sl); -} - -//-------------------------------------------------------------------------- -bool pyscv_insert_line(PyObject *py_this, size_t nline, PyObject *py_sl) -{ - DECL_THIS; - return _this == NULL ? false : _this->insert_line(nline, py_sl); -} - -//-------------------------------------------------------------------------- -bool pyscv_patch_line(PyObject *py_this, size_t nline, size_t offs, int value) -{ - DECL_THIS; - return _this == NULL ? false : _this->patch_line(nline, offs, value); -} - -//-------------------------------------------------------------------------- -bool pyscv_del_line(PyObject *py_this, size_t nline) -{ - DECL_THIS; - return _this == NULL ? false : _this->del_line(nline); -} - -//-------------------------------------------------------------------------- -PyObject *pyscv_get_selection(PyObject *py_this) -{ - DECL_THIS; - if ( _this == NULL ) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_RETURN_NONE; - } - return _this->py_get_selection(); -} - -//-------------------------------------------------------------------------- -PyObject *pyscv_get_current_word(PyObject *py_this, bool mouse) -{ - DECL_THIS; - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( _this != NULL ) - { - qstring word; - if ( _this->get_current_word(mouse, word) ) - return PyString_FromString(word.c_str()); - } - Py_RETURN_NONE; -} - -//-------------------------------------------------------------------------- -// Edits an existing line -bool pyscv_edit_line(PyObject *py_this, size_t nline, PyObject *py_sl) -{ - DECL_THIS; - return _this == NULL ? false : _this->edit_line(nline, py_sl); -} - -//------------------------------------------------------------------------- -TForm *pyscv_get_tform(PyObject *py_this) -{ - DECL_THIS; - return _this == NULL ? NULL : _this->get_tform(); -} - -//------------------------------------------------------------------------- -TCustomControl *pyscv_get_tcustom_control(PyObject *py_this) -{ - DECL_THIS; - return _this == NULL ? NULL : _this->get_tcustom_control(); -} - - -#undef DECL_THIS -// -%} +// CLI +%ignore cli_t; +%ignore install_command_interpreter; +%rename (install_command_interpreter) py_install_command_interpreter; +%ignore remove_command_interpreter; +%rename (remove_command_interpreter) py_remove_command_interpreter; %include "kernwin.hpp" @@ -4479,14 +275,6 @@ TCustomControl *pyscv_get_tcustom_control(PyObject *py_this) } //------------------------------------------------------------------------- -uint32 choose_choose(PyObject *self, - int flags, - int x0,int y0, - int x1,int y1, - int width, - int deflt, - int icon); - %extend place_t { static idaplace_t *as_idaplace_t(place_t *p) { return (idaplace_t *) p; } static enumplace_t *as_enumplace_t(place_t *p) { return (enumplace_t *) p; } @@ -4522,2207 +310,6 @@ uint32 choose_choose(PyObject *self, } %pythoncode %{ - # -DP_LEFT = 0x0001 -DP_TOP = 0x0002 -DP_RIGHT = 0x0004 -DP_BOTTOM = 0x0008 -DP_INSIDE = 0x0010 -# if not before, then it is after -# (use DP_INSIDE | DP_BEFORE to insert a tab before a given tab) -# this flag alone cannot be used to determine orientation -DP_BEFORE = 0x0020 -# used with combination of other flags -DP_TAB = 0x0040 -DP_FLOATING = 0x0080 - -# ---------------------------------------------------------------------- -def load_custom_icon(file_name=None, data=None, format=None): - """ - Loads a custom icon and returns an identifier that can be used with other APIs - - If file_name is passed then the other two arguments are ignored. - - @param file_name: The icon file name - @param data: The icon data - @param format: The icon data format - - @return: Icon id or 0 on failure. - Use free_custom_icon() to free it - """ - if file_name is not None: - return _idaapi.py_load_custom_icon_fn(file_name) - elif not (data is None and format is None): - return _idaapi.py_load_custom_icon_data(data, format) - else: - return 0 - -# ---------------------------------------------------------------------- -def asklong(defval, format): - res, val = _idaapi._asklong(defval, format) - - if res == 1: - return val - else: - return None - -# ---------------------------------------------------------------------- -def askaddr(defval, format): - res, ea = _idaapi._askaddr(defval, format) - - if res == 1: - return ea - else: - return None - -# ---------------------------------------------------------------------- -def askseg(defval, format): - res, sel = _idaapi._askseg(defval, format) - - if res == 1: - return sel - else: - return None - -# ---------------------------------------------------------------------- -class action_handler_t: - def __init__(self): - pass - - def activate(self, ctx): - return 0 - - def update(self, ctx): - pass - - - -class Choose2(object): - """ - Choose2 wrapper class. - - Some constants are defined in this class. Please refer to kernwin.hpp for more information. - """ - - CH_MODAL = 0x01 - """Modal chooser""" - - CH_MULTI = 0x02 - """Allow multi selection""" - - CH_MULTI_EDIT = 0x04 - CH_NOBTNS = 0x08 - CH_ATTRS = 0x10 - CH_NOIDB = 0x20 - """use the chooser even without an open database, same as x0=-2""" - CH_UTF8 = 0x40 - """string encoding is utf-8""" - - CH_BUILTIN_MASK = 0xF80000 - - # column flags (are specified in the widths array) - CHCOL_PLAIN = 0x00000000 - CHCOL_PATH = 0x00010000 - CHCOL_HEX = 0x00020000 - CHCOL_DEC = 0x00030000 - CHCOL_FORMAT = 0x00070000 - - - def __init__(self, title, cols, flags=0, popup_names=None, - icon=-1, x1=-1, y1=-1, x2=-1, y2=-1, deflt=-1, - embedded=False, width=None, height=None): - """ - Constructs a chooser window. - @param title: The chooser title - @param cols: a list of colums; each list item is a list of two items - example: [ ["Address", 10 | Choose2.CHCOL_HEX], ["Name", 30 | Choose2.CHCOL_PLAIN] ] - @param flags: One of CH_XXXX constants - @param deflt: Default starting item - @param popup_names: list of new captions to replace this list ["Insert", "Delete", "Edit", "Refresh"] - @param icon: Icon index (the icon should exist in ida resources or an index to a custom loaded icon) - @param x1, y1, x2, y2: The default location - @param embedded: Create as embedded chooser - @param width: Embedded chooser width - @param height: Embedded chooser height - """ - self.title = title - self.flags = flags - self.cols = cols - self.deflt = deflt - self.popup_names = popup_names - self.icon = icon - self.x1 = x1 - self.y1 = y1 - self.x2 = x2 - self.y2 = y2 - self.embedded = embedded - if embedded: - self.x1 = width - self.y1 = height - - - def Embedded(self): - """ - Creates an embedded chooser (as opposed to Show()) - @return: Returns 1 on success - """ - return _idaapi.choose2_create(self, True) - - - def GetEmbSelection(self): - """ - Returns the selection associated with an embedded chooser - - @return: - - None if chooser is not embedded - - A list with selection indices (0-based) - """ - return _idaapi.choose2_get_embedded_selection(self) - - - def Show(self, modal=False): - """ - Activates or creates a chooser window - @param modal: Display as modal dialog - @return: For modal choosers it will return the selected item index (0-based) - """ - if modal: - self.flags |= Choose2.CH_MODAL - - # Disable the timeout - old = _idaapi.set_script_timeout(0) - n = _idaapi.choose2_create(self, False) - _idaapi.set_script_timeout(old) - - # Delete the modal chooser instance - self.Close() - - return n - else: - self.flags &= ~Choose2.CH_MODAL - return _idaapi.choose2_create(self, False) - - - def Activate(self): - """Activates a visible chooser""" - return _idaapi.choose2_activate(self) - - - def Refresh(self): - """Causes the refresh callback to trigger""" - return _idaapi.choose2_refresh(self) - - - def Close(self): - """Closes the chooser""" - return _idaapi.choose2_close(self) - - - def AddCommand(self, - caption, - flags = _idaapi.CHOOSER_POPUP_MENU, - menu_index = -1, - icon = -1, - emb=None): - """ - Deprecated: Use - - register_action() - - attach_action_to_menu() - - attach_action_to_popup() - """ - # Use the 'emb' as a sentinel. It will be passed the correct value from the EmbeddedChooserControl - if self.embedded and ((emb is None) or (emb != 2002)): - raise RuntimeError("Please add a command through EmbeddedChooserControl.AddCommand()") - return _idaapi.choose2_add_command(self, caption, flags, menu_index, icon) - - # - # Implement these methods in the subclass: - # -# -# def OnClose(self): -# """ -# Called when the window is being closed. -# This callback is mandatory. -# @return: nothing -# """ -# pass -# -# def OnGetLine(self, n): -# """Called when the chooser window requires lines. -# This callback is mandatory. -# @param n: Line number (0-based) -# @return: The user should return a list with ncols elements. -# example: a list [col1, col2, col3, ...] describing the n-th line -# """ -# return ["col1 val", "col2 val"] -# -# def OnGetSize(self): -# """Returns the element count. -# This callback is mandatory. -# @return: Number of elements -# """ -# return len(self.the_list) -# -# def OnEditLine(self, n): -# """ -# Called when an item is being edited. -# @param n: Line number (0-based) -# @return: Nothing -# """ -# pass -# -# def OnInsertLine(self): -# """ -# Called when 'Insert' is selected either via the hotkey or popup menu. -# @return: Nothing -# """ -# pass -# -# def OnSelectLine(self, n): -# """ -# Called when a line is selected and then Ok or double click was pressed -# @param n: Line number (0-based) -# """ -# pass -# -# def OnSelectionChange(self, sel_list): -# """ -# Called when the selection changes -# @param sel_list: A list of selected item indices -# """ -# pass -# -# def OnDeleteLine(self, n): -# """ -# Called when a line is about to be deleted -# @param n: Line number (0-based) -# """ -# return self.n -# -# def OnRefresh(self, n): -# """ -# Triggered when the 'Refresh' is called from the popup menu item. -# -# @param n: The currently selected line (0-based) at the time of the refresh call -# @return: Return the number of elements -# """ -# return self.n -# -# def OnRefreshed(self): -# """ -# Triggered when a refresh happens (for example due to column sorting) -# @param n: Line number (0-based) -# @return: Return the number of elements -# """ -# return self.n -# -# def OnCommand(self, n, cmd_id): -# """Return int ; check add_chooser_command()""" -# return 0 -# -# def OnGetIcon(self, n): -# """ -# Return icon number for a given item (or -1 if no icon is avail) -# @param n: Line number (0-based) -# """ -# return -1 -# -# def OnGetLineAttr(self, n): -# """ -# Return list [bgcolor, flags=CHITEM_XXXX] or None; check chooser_item_attrs_t -# @param n: Line number (0-based) -# """ -# return [0x0, CHITEM_BOLD] -# - - -#ICON WARNING|QUESTION|INFO|NONE -#AUTOHIDE NONE|DATABASE|REGISTRY|SESSION -#HIDECANCEL -#BUTTON YES|NO|CANCEL "Value|NONE" -#STARTITEM {id:ItemName} -#HELP / ENDHELP -try: - import types - from ctypes import * - # On Windows, we use stdcall - - # Callback for buttons - # typedef void (idaapi *formcb_t)(TView *fields[], int code); - - _FORMCB_T = WINFUNCTYPE(None, c_void_p, c_int) - - # Callback for form change - # typedef int (idaapi *formchgcb_t)(int field_id, form_actions_t &fa); - _FORMCHGCB_T = WINFUNCTYPE(c_int, c_int, c_void_p) -except: - try: - _FORMCB_T = CFUNCTYPE(None, c_void_p, c_int) - _FORMCHGCB_T = CFUNCTYPE(c_int, c_int, c_void_p) - except: - _FORMCHGCB_T = _FORMCB_T = None - - -# ----------------------------------------------------------------------- -# textctrl_info_t clinked object -class textctrl_info_t(py_clinked_object_t): - """Class representing textctrl_info_t""" - - # Some constants - TXTF_AUTOINDENT = 0x0001 - """Auto-indent on new line""" - TXTF_ACCEPTTABS = 0x0002 - """Tab key inserts 'tabsize' spaces""" - TXTF_READONLY = 0x0004 - """Text cannot be edited (but can be selected and copied)""" - TXTF_SELECTED = 0x0008 - """Shows the field with its text selected""" - TXTF_MODIFIED = 0x0010 - """Gets/sets the modified status""" - TXTF_FIXEDFONT = 0x0020 - """The control uses IDA's fixed font""" - - def __init__(self, text="", flags=0, tabsize=0): - py_clinked_object_t.__init__(self) - if text: - self.text = text - if flags: - self.flags = flags - if tabsize: - self.tabsize = tabsize - - def _create_clink(self): - return _idaapi.textctrl_info_t_create() - - def _del_clink(self, lnk): - return _idaapi.textctrl_info_t_destroy(lnk) - - def _get_clink_ptr(self): - return _idaapi.textctrl_info_t_get_clink_ptr(self) - - def assign(self, other): - """Copies the contents of 'other' to 'self'""" - return _idaapi.textctrl_info_t_assign(self, other) - - def __set_text(self, s): - """Sets the text value""" - return _idaapi.textctrl_info_t_set_text(self, s) - - def __get_text(self): - """Sets the text value""" - return _idaapi.textctrl_info_t_get_text(self) - - def __set_flags__(self, flags): - """Sets the flags value""" - return _idaapi.textctrl_info_t_set_flags(self, flags) - - def __get_flags__(self): - """Returns the flags value""" - return _idaapi.textctrl_info_t_get_flags(self) - - def __set_tabsize__(self, tabsize): - """Sets the tabsize value""" - return _idaapi.textctrl_info_t_set_tabsize(self, tabsize) - - def __get_tabsize__(self): - """Returns the tabsize value""" - return _idaapi.textctrl_info_t_get_tabsize(self) - - value = property(__get_text, __set_text) - """Alias for the text property""" - text = property(__get_text, __set_text) - """Text value""" - flags = property(__get_flags__, __set_flags__) - """Flags value""" - tabsize = property(__get_tabsize__, __set_tabsize__) - -# ----------------------------------------------------------------------- -class Form(object): - - FT_ASCII = 'A' - """Ascii string - char *""" - FT_SEG = 'S' - """Segment - sel_t *""" - FT_HEX = 'N' - """Hex number - uval_t *""" - FT_SHEX = 'n' - """Signed hex number - sval_t *""" - FT_COLOR = 'K' - """Color button - bgcolor_t *""" - FT_ADDR = '$' - """Address - ea_t *""" - FT_UINT64 = 'L' - """default base uint64 - uint64""" - FT_INT64 = 'l' - """default base int64 - int64""" - FT_RAWHEX = 'M' - """Hex number, no 0x prefix - uval_t *""" - FT_FILE = 'f' - """File browse - char * at least QMAXPATH""" - FT_DEC = 'D' - """Decimal number - sval_t *""" - FT_OCT = 'O' - """Octal number, C notation - sval_t *""" - FT_BIN = 'Y' - """Binary number, 0b prefix - sval_t *""" - FT_CHAR = 'H' - """Char value -- sval_t *""" - FT_IDENT = 'I' - """Identifier - char * at least MAXNAMELEN""" - FT_BUTTON = 'B' - """Button - def handler(code)""" - FT_DIR = 'F' - """Path to directory - char * at least QMAXPATH""" - FT_TYPE = 'T' - """Type declaration - char * at least MAXSTR""" - _FT_USHORT = '_US' - """Unsigned short""" - FT_FORMCHG = '%/' - """Form change callback - formchgcb_t""" - FT_ECHOOSER = 'E' - """Embedded chooser - idaapi.Choose2""" - FT_MULTI_LINE_TEXT = 't' - """Multi text control - textctrl_info_t""" - FT_DROPDOWN_LIST = 'b' - """Dropdown list control - Form.DropdownControl""" - - FT_CHKGRP = 'C' - FT_CHKGRP2= 'c' - FT_RADGRP = 'R' - FT_RADGRP2= 'r' - - @staticmethod - def fieldtype_to_ctype(tp, i64 = False): - """ - Factory method returning a ctype class corresponding to the field type string - """ - if tp in (Form.FT_SEG, Form.FT_HEX, Form.FT_RAWHEX, Form.FT_ADDR): - return c_ulonglong if i64 else c_ulong - elif tp in (Form.FT_SHEX, Form.FT_DEC, Form.FT_OCT, Form.FT_BIN, Form.FT_CHAR): - return c_longlong if i64 else c_long - elif tp == Form.FT_UINT64: - return c_ulonglong - elif tp == Form.FT_INT64: - return c_longlong - elif tp == Form.FT_COLOR: - return c_ulong - elif tp == Form._FT_USHORT: - return c_ushort - elif tp in (Form.FT_FORMCHG, Form.FT_ECHOOSER): - return c_void_p - else: - return None - - - # - # Generic argument helper classes - # - class NumericArgument(object): - """ - Argument representing various integer arguments (ushort, uint32, uint64, etc...) - @param tp: One of Form.FT_XXX - """ - DefI64 = False - def __init__(self, tp, value): - cls = Form.fieldtype_to_ctype(tp, self.DefI64) - if cls is None: - raise TypeError("Invalid numeric field type: %s" % tp) - # Get a pointer type to the ctype type - self.arg = pointer(cls(value)) - - def __set_value(self, v): - self.arg.contents.value = v - value = property(lambda self: self.arg.contents.value, __set_value) - - - class StringArgument(object): - """ - Argument representing a character buffer - """ - def __init__(self, size=None, value=None): - if size is None: - raise SyntaxError("The string size must be passed") - - if value is None: - self.arg = create_string_buffer(size) - else: - self.arg = create_string_buffer(value, size) - self.size = size - - def __set_value(self, v): - self.arg.value = v - value = property(lambda self: self.arg.value, __set_value) - - - # - # Base control class - # - class Control(object): - def __init__(self): - self.id = 0 - """Automatically assigned control ID""" - - self.arg = None - """Control argument value. This could be one element or a list/tuple (for multiple args per control)""" - - self.form = None - """Reference to the parent form. It is filled by Form.Add()""" - - - def get_tag(self): - """ - Control tag character. One of Form.FT_XXXX. - The form class will expand the {} notation and replace them with the tags - """ - pass - - def get_arg(self): - """ - Control returns the parameter to be pushed on the stack - (Of AskUsingForm()) - """ - return self.arg - - def free(self): - """ - Free the control - """ - # Release the parent form reference - self.form = None - - - # - # Label controls - # - class LabelControl(Control): - """ - Base class for static label control - """ - def __init__(self, tp): - Form.Control.__init__(self) - self.tp = tp - - def get_tag(self): - return '%%%d%s' % (self.id, self.tp) - - - class StringLabel(LabelControl): - """ - String label control - """ - def __init__(self, value, tp=None, sz=1024): - """ - Type field can be one of: - A - ascii string - T - type declaration - I - ident - F - folder - f - file - X - command - """ - if tp is None: - tp = Form.FT_ASCII - Form.LabelControl.__init__(self, tp) - self.size = sz - self.arg = create_string_buffer(value, sz) - - - class NumericLabel(LabelControl, NumericArgument): - """ - Numeric label control - """ - def __init__(self, value, tp=None): - if tp is None: - tp = Form.FT_HEX - Form.LabelControl.__init__(self, tp) - Form.NumericArgument.__init__(self, tp, value) - - - # - # Group controls - # - class GroupItemControl(Control): - """ - Base class for group control items - """ - def __init__(self, tag, parent): - Form.Control.__init__(self) - self.tag = tag - self.parent = parent - # Item position (filled when form is compiled) - self.pos = 0 - - def assign_pos(self): - self.pos = self.parent.next_child_pos() - - def get_tag(self): - return "%s%d" % (self.tag, self.id) - - - class ChkGroupItemControl(GroupItemControl): - """ - Checkbox group item control - """ - def __init__(self, tag, parent): - Form.GroupItemControl.__init__(self, tag, parent) - - def __get_value(self): - return (self.parent.value & (1 << self.pos)) != 0 - - def __set_value(self, v): - pv = self.parent.value - if v: - pv = pv | (1 << self.pos) - else: - pv = pv & ~(1 << self.pos) - - self.parent.value = pv - - checked = property(__get_value, __set_value) - """Get/Sets checkbox item check status""" - - - class RadGroupItemControl(GroupItemControl): - """ - Radiobox group item control - """ - def __init__(self, tag, parent): - Form.GroupItemControl.__init__(self, tag, parent) - - def __get_value(self): - return self.parent.value == self.pos - - def __set_value(self, v): - self.parent.value = self.pos - - selected = property(__get_value, __set_value) - """Get/Sets radiobox item selection status""" - - - class GroupControl(Control, NumericArgument): - """ - Base class for group controls - """ - def __init__(self, children_names, tag, value=0): - Form.Control.__init__(self) - self.children_names = children_names - self.tag = tag - self._reset() - Form.NumericArgument.__init__(self, Form._FT_USHORT, value) - - def _reset(self): - self.childpos = 0 - - def next_child_pos(self): - v = self.childpos - self.childpos += 1 - return v - - def get_tag(self): - return "%d" % self.id - - - class ChkGroupControl(GroupControl): - """ - Checkbox group control class. - It holds a set of checkbox controls - """ - ItemClass = None - """ - Group control item factory class instance - We need this because later we won't be treating ChkGroupControl or RadGroupControl - individually, instead we will be working with GroupControl in general. - """ - def __init__(self, children_names, value=0, secondary=False): - # Assign group item factory class - if Form.ChkGroupControl.ItemClass is None: - Form.ChkGroupControl.ItemClass = Form.ChkGroupItemControl - - Form.GroupControl.__init__( - self, - children_names, - Form.FT_CHKGRP2 if secondary else Form.FT_CHKGRP, - value) - - - class RadGroupControl(GroupControl): - """ - Radiobox group control class. - It holds a set of radiobox controls - """ - ItemClass = None - def __init__(self, children_names, value=0, secondary=False): - """ - Creates a radiogroup control. - @param children_names: A tuple containing group item names - @param value: Initial selected radio item - @param secondory: Allows rendering one the same line as the previous group control. - Use this if you have another group control on the same line. - """ - # Assign group item factory class - if Form.RadGroupControl.ItemClass is None: - Form.RadGroupControl.ItemClass = Form.RadGroupItemControl - - Form.GroupControl.__init__( - self, - children_names, - Form.FT_RADGRP2 if secondary else Form.FT_RADGRP, - value) - - - # - # Input controls - # - class InputControl(Control): - """ - Generic form input control. - It could be numeric control, string control, directory/file browsing, etc... - """ - def __init__(self, tp, width, swidth, hlp = None): - """ - @param width: Display width - @param swidth: String width - """ - Form.Control.__init__(self) - self.tp = tp - self.width = width - self.switdh = swidth - self.hlp = hlp - - def get_tag(self): - return "%s%d:%s:%s:%s" % ( - self.tp, self.id, - self.width, - self.switdh, - ":" if self.hlp is None else self.hlp) - - - class NumericInput(InputControl, NumericArgument): - """ - A composite class serving as a base numeric input control class - """ - def __init__(self, tp=None, value=0, width=50, swidth=10, hlp=None): - if tp is None: - tp = Form.FT_HEX - Form.InputControl.__init__(self, tp, width, swidth, hlp) - Form.NumericArgument.__init__(self, self.tp, value) - - - class ColorInput(NumericInput): - """ - Color button input control - """ - def __init__(self, value = 0): - """ - @param value: Initial color value in RGB - """ - Form.NumericInput.__init__(self, tp=Form.FT_COLOR, value=value) - - - class StringInput(InputControl, StringArgument): - """ - Base string input control class. - This class also constructs a StringArgument - """ - def __init__(self, - tp=None, - width=1024, - swidth=40, - hlp=None, - value=None, - size=None): - """ - @param width: String size. But in some cases it has special meaning. For example in FileInput control. - If you want to define the string buffer size then pass the 'size' argument - @param swidth: Control width - @param value: Initial value - @param size: String size - """ - if tp is None: - tp = Form.FT_ASCII - if not size: - size = width - Form.InputControl.__init__(self, tp, width, swidth, hlp) - Form.StringArgument.__init__(self, size=size, value=value) - - - class FileInput(StringInput): - """ - File Open/Save input control - """ - def __init__(self, - width=512, - swidth=80, - save=False, open=False, - hlp=None, value=None): - - if save == open: - raise ValueError("Invalid mode. Choose either open or save") - if width < 512: - raise ValueError("Invalid width. Must be greater than 512.") - - # The width field is overloaded in this control and is used - # to denote the type of the FileInput dialog (save or load) - # On the other hand it is passed as is to the StringArgument part - Form.StringInput.__init__( - self, - tp=Form.FT_FILE, - width="1" if save else "0", - swidth=swidth, - hlp=hlp, - size=width, - value=value) - - - class DirInput(StringInput): - """ - Directory browsing control - """ - def __init__(self, - width=512, - swidth=80, - hlp=None, - value=None): - - if width < 512: - raise ValueError("Invalid width. Must be greater than 512.") - - Form.StringInput.__init__( - self, - tp=Form.FT_DIR, - width=width, - swidth=swidth, - hlp=hlp, - size=width, - value=value) - - - class ButtonInput(InputControl): - """ - Button control. - A handler along with a 'code' (numeric value) can be associated with the button. - This way one handler can handle many buttons based on the button code (or in other terms id or tag) - """ - def __init__(self, handler, code="", swidth="", hlp=None): - """ - @param handler: Button handler. A callback taking one argument which is the code. - @param code: A code associated with the button and that is later passed to the handler. - """ - Form.InputControl.__init__( - self, - Form.FT_BUTTON, - code, - swidth, - hlp) - self.arg = _FORMCB_T(lambda view, code, h=handler: h(code)) - - - class FormChangeCb(Control): - """ - Form change handler. - This can be thought of like a dialog procedure. - Everytime a form action occurs, this handler will be called along with the control id. - The programmer can then call various form actions accordingly: - - EnableField - - ShowField - - MoveField - - GetFieldValue - - etc... - - Special control IDs: -1 (The form is initialized) and -2 (Ok has been clicked) - - """ - def __init__(self, handler): - """ - Constructs the handler. - @param handler: The handler (preferrably a member function of a class derived from the Form class). - """ - Form.Control.__init__(self) - - # Save the handler - self.handler = handler - - # Create a callback stub - # We use this mechanism to create an intermediate step - # where we can create an 'fa' adapter for use by Python - self.arg = _FORMCHGCB_T(self.helper_cb) - - def helper_cb(self, fid, p_fa): - # Remember the pointer to the forms_action in the parent form - self.form.p_fa = p_fa - - # Call user's handler - r = self.handler(fid) - return 0 if r is None else r - - def get_tag(self): - return Form.FT_FORMCHG - - def free(self): - Form.Control.free(self) - # Remove reference to the handler - # (Normally the handler is a member function in the parent form) - self.handler = None - - - class EmbeddedChooserControl(InputControl): - """ - Embedded chooser control. - This control links to a Chooser2 control created with the 'embedded=True' - """ - def __init__(self, - chooser=None, - swidth=40, - hlp=None): - """ - Embedded chooser control - - @param chooser: A chooser2 instance (must be constructed with 'embedded=True') - """ - - # !! Make sure a chooser instance is passed !! - if chooser is None or not isinstance(chooser, Choose2): - raise ValueError("Invalid chooser passed.") - - # Create an embedded chooser structure from the Choose2 instance - if chooser.Embedded() != 1: - raise ValueError("Failed to create embedded chooser instance.") - - # Construct input control - Form.InputControl.__init__(self, Form.FT_ECHOOSER, "", swidth) - - # Get a pointer to the chooser_info_t and the selection vector - # (These two parameters are the needed arguments for the AskUsingForm()) - emb, sel = _idaapi.choose2_get_embedded(chooser) - - # Get a pointer to a c_void_p constructed from an address - p_embedded = pointer(c_void_p.from_address(emb)) - p_sel = pointer(c_void_p.from_address(sel)) - - # - Create the embedded chooser info on control creation - # - Do not free the embeded chooser because after we get the args - # via Compile() the user can still call Execute() which relies - # on the already computed args - self.arg = (p_embedded, p_sel) - - # Save chooser instance - self.chooser = chooser - - # Add a bogus 'size' attribute - self.size = 0 - - - value = property(lambda self: self.chooser) - """Returns the embedded chooser instance""" - - - def AddCommand(self, - caption, - flags = _idaapi.CHOOSER_POPUP_MENU, - menu_index = -1, - icon = -1): - """ - Adds a new embedded chooser command - Save the returned value and later use it in the OnCommand handler - - @return: Returns a negative value on failure or the command index - """ - if not self.form.title: - raise ValueError("Form title is not set!") - - # Encode all information for the AddCommand() in the 'caption' parameter - caption = "%s:%d:%s" % (self.form.title, self.id, caption) - return self.chooser.AddCommand(caption, flags=flags, menu_index=menu_index, icon=icon, emb=2002) - - - def free(self): - """ - Frees the embedded chooser data - """ - self.chooser.Close() - self.chooser = None - Form.Control.free(self) - - - class DropdownListControl(InputControl, _qstrvec_t): - """ - Dropdown control - This control allows manipulating a dropdown control - """ - def __init__(self, items=[], readonly=True, selval=0, width=50, swidth=50, hlp = None): - """ - @param items: A string list of items used to prepopulate the control - @param readonly: Specifies whether the dropdown list is editable or not - @param selval: The preselected item index (when readonly) or text value (when editable) - @param width: the control width (n/a if the dropdown list is readonly) - @param swidth: string width - """ - - # Ignore the width if readonly was set - if readonly: - width = 0 - - # Init the input control base class - Form.InputControl.__init__( - self, - Form.FT_DROPDOWN_LIST, - width, - swidth, - hlp) - - # Init the associated qstrvec - _qstrvec_t.__init__(self, items) - - # Remember if readonly or not - self.readonly = readonly - - if readonly: - # Create a C integer and remember it - self.__selval = c_int(selval) - val_addr = addressof(self.__selval) - else: - # Create an strvec with one qstring - self.__selval = _qstrvec_t([selval]) - # Get address of the first element - val_addr = self.__selval.addressof(0) - - # Two arguments: - # - argument #1: a pointer to the qstrvec containing the items - # - argument #2: an integer to hold the selection - # or - # #2: a qstring to hold the dropdown text control value - self.arg = ( - pointer(c_void_p.from_address(self.clink_ptr)), - pointer(c_void_p.from_address(val_addr)) - ) - - - def __set_selval(self, val): - if self.readonly: - self.__selval.value = val - else: - self.__selval[0] = val - - def __get_selval(self): - # Return the selection index - # or the entered text value - return self.__selval.value if self.readonly else self.__selval[0] - - value = property(__get_selval, __set_selval) - selval = property(__get_selval, __set_selval) - """ - Read/write the selection value. - The value is used as an item index in readonly mode or text value in editable mode - This value can be used only after the form has been closed. - """ - - def free(self): - self._free() - - - def set_items(self, items): - """Sets the dropdown list items""" - self.from_list(items) - - - class MultiLineTextControl(InputControl, textctrl_info_t): - """ - Multi line text control. - This class inherits from textctrl_info_t. Thus the attributes are also inherited - This control allows manipulating a multilinetext control - """ - def __init__(self, text="", flags=0, tabsize=0, width=50, swidth=50, hlp = None): - """ - @param text: Initial text value - @param flags: One of textctrl_info_t.TXTF_.... values - @param tabsize: Tab size - @param width: Display width - @param swidth: String width - """ - # Init the input control base class - Form.InputControl.__init__(self, Form.FT_MULTI_LINE_TEXT, width, swidth, hlp) - - # Init the associated textctrl_info base class - textctrl_info_t.__init__(self, text=text, flags=flags, tabsize=tabsize) - - # Get the argument as a pointer from the embedded ti - self.arg = pointer(c_void_p.from_address(self.clink_ptr)) - - - def free(self): - self._free() - - - # - # Form class - # - def __init__(self, form, controls): - """ - Contruct a Form class. - This class wraps around AskUsingForm() or OpenForm() and provides an easier / alternative syntax for describing forms. - The form control names are wrapped inside the opening and closing curly braces and the control themselves are - defined and instantiated via various form controls (subclasses of Form). - - @param form: The form string - @param controls: A dictionary containing the control name as a _key_ and control object as _value_ - """ - self._reset() - self.form = form - """Form string""" - self.controls = controls - """Dictionary of controls""" - self.__args = None - - self.title = None - """The Form title. It will be filled when the form is compiled""" - - self.modal = True - """By default, forms are modal""" - - self.openform_flags = 0 - """ - If non-modal, these flags will be passed to OpenForm. - This is an OR'ed combination of the PluginForm.FORM_* values. - """ - - - def Free(self): - """ - Frees all resources associated with a compiled form. - Make sure you call this function when you finish using the form. - """ - - # Free all the controls - for ctrl in self.__controls.values(): - ctrl.free() - - # Reset the controls - # (Note that we are not removing the form control attributes, no need) - self._reset() - - # Unregister, so we don't try and free it again at closing-time. - _idaapi.py_unregister_compiled_form(self) - - - def _reset(self): - """ - Resets the Form class state variables - """ - self.__controls = {} - self.__ctrl_id = 1 - - - def __getitem__(self, name): - """Returns a control object by name""" - return self.__controls[name] - - - def Add(self, name, ctrl, mkattr = True): - """ - Low level function. Prefer AddControls() to this function. - This function adds one control to the form. - - @param name: Control name - @param ctrl: Control object - @param mkattr: Create control name / control object as a form attribute - """ - # Assign a unique ID - ctrl.id = self.__ctrl_id - self.__ctrl_id += 1 - - # Create attribute with control name - if mkattr: - setattr(self, name, ctrl) - - # Remember the control - self.__controls[name] = ctrl - - # Link the form to the control via its form attribute - ctrl.form = self - - # Is it a group? Add each child - if isinstance(ctrl, Form.GroupControl): - self._AddGroup(ctrl, mkattr) - - - def FindControlById(self, id): - """ - Finds a control instance given its id - """ - for ctrl in self.__controls.values(): - if ctrl.id == id: - return ctrl - return None - - - @staticmethod - def _ParseFormTitle(form): - """ - Parses the form's title from the form text - """ - help_state = 0 - for i, line in enumerate(form.split("\n")): - if line.startswith("STARTITEM ") or line.startswith("BUTTON "): - continue - # Skip "HELP" and remember state - elif help_state == 0 and line == "HELP": - help_state = 1 # Mark inside HELP - continue - elif help_state == 1 and line == "ENDHELP": - help_state = 2 # Mark end of HELP - continue - return line.strip() - - return None - - - def _AddGroup(self, Group, mkattr=True): - """ - Internal function. - This function expands the group item names and creates individual group item controls - - @param Group: The group class (checkbox or radio group class) - """ - - # Create group item controls for each child - for child_name in Group.children_names: - self.Add( - child_name, - # Use the class factory - Group.ItemClass(Group.tag, Group), - mkattr) - - - def AddControls(self, controls, mkattr=True): - """ - Adds controls from a dictionary. - The dictionary key is the control name and the value is a Form.Control object - @param controls: The control dictionary - """ - for name, ctrl in controls.items(): - # Add the control - self.Add(name, ctrl, mkattr) - - - def CompileEx(self, form): - """ - Low level function. - Compiles (parses the form syntax and adds the control) the form string and - returns the argument list to be passed the argument list to AskUsingForm(). - - The form controls are wrapped inside curly braces: {ControlName}. - - A special operator can be used to return the ID of a given control by its name: {id:ControlName}. - This is useful when you use the STARTITEM form keyword to set the initially focused control. - - @param form: Compiles the form and returns the arguments needed to be passed to AskUsingForm() - """ - # First argument is the form string - args = [None] - - # Second argument, if form is not modal, is the set of flags - if not self.modal: - args.append(self.openform_flags | 0x80) # Add FORM_QWIDGET - - ctrlcnt = 1 - - # Reset all group control internal flags - for ctrl in self.__controls.values(): - if isinstance(ctrl, Form.GroupControl): - ctrl._reset() - - p = 0 - while True: - i1 = form.find("{", p) - # No more items? - if i1 == -1: - break - - # Check if escaped - if (i1 != 0) and form[i1-1] == "\\": - # Remove escape sequence and restart search - form = form[:i1-1] + form[i1:] - - # Skip current marker - p = i1 - - # Continue search - continue - - i2 = form.find("}", i1) - if i2 == -1: - raise SyntaxError("No matching closing brace '}'") - - # Parse control name - ctrlname = form[i1+1:i2] - if not ctrlname: - raise ValueError("Control %d has an invalid name!" % ctrlcnt) - - # Is it the IDOF operator? - if ctrlname.startswith("id:"): - idfunc = True - # Take actual ctrlname - ctrlname = ctrlname[3:] - else: - idfunc = False - - # Find the control - ctrl = self.__controls.get(ctrlname, None) - if ctrl is None: - raise ValueError("No matching control '%s'" % ctrlname) - - # Replace control name by tag - if idfunc: - tag = str(ctrl.id) - else: - tag = ctrl.get_tag() - taglen = len(tag) - form = form[:i1] + tag + form[i2+1:] - - # Set new position - p = i1 + taglen - - # Was it an IDOF() ? No need to push parameters - # Just ID substitution is fine - if idfunc: - continue - - - # For GroupItem controls, there are no individual arguments - # The argument is assigned for the group itself - if isinstance(ctrl, Form.GroupItemControl): - # GroupItem controls will have their position dynamically set - ctrl.assign_pos() - else: - # Push argument(s) - # (Some controls need more than one argument) - arg = ctrl.get_arg() - if isinstance(arg, (types.ListType, types.TupleType)): - # Push all args - args.extend(arg) - else: - # Push one arg - args.append(arg) - - ctrlcnt += 1 - - # If no FormChangeCb instance was passed, and thus there's no '%/' - # in the resulting form string, let's provide a minimal one, so that - # we will retrieve 'p_fa', and thus actions that rely on it will work. - if form.find(Form.FT_FORMCHG) < 0: - form = form + Form.FT_FORMCHG - fccb = Form.FormChangeCb(lambda *args: 1) - self.Add("___dummyfchgcb", fccb) - # Regardless of the actual position of '%/' in the form - # string, a formchange callback _must_ be right after - # the form string. - if self.modal: - inspos = 1 - else: - inspos = 2 - args.insert(inspos, fccb.get_arg()) - - # Patch in the final form string - args[0] = form - - self.title = self._ParseFormTitle(form) - return args - - - def Compile(self): - """ - Compiles a form and returns the form object (self) and the argument list. - The form object will contain object names corresponding to the form elements - - @return: It will raise an exception on failure. Otherwise the return value is ignored - """ - - # Reset controls - self._reset() - - # Insert controls - self.AddControls(self.controls) - - # Compile form and get args - self.__args = self.CompileEx(self.form) - - # Register this form, to make sure it will be freed at closing-time. - _idaapi.py_register_compiled_form(self) - - return (self, self.__args) - - - def Compiled(self): - """ - Checks if the form has already been compiled - - @return: Boolean - """ - return self.__args is not None - - - def _ChkCompiled(self): - if not self.Compiled(): - raise SyntaxError("Form is not compiled") - - - def Execute(self): - """ - Displays a modal dialog containing the compiled form. - @return: 1 - ok ; 0 - cancel - """ - self._ChkCompiled() - if not self.modal: - raise SyntaxError("Form is not modal. Open() should be instead") - - return AskUsingForm(*self.__args) - - - def Open(self): - """ - Opens a widget containing the compiled form. - """ - self._ChkCompiled() - if self.modal: - raise SyntaxError("Form is modal. Execute() should be instead") - - OpenForm(*self.__args) - - - def EnableField(self, ctrl, enable): - """ - Enable or disable an input field - @return: False - no such control - """ - return _idaapi.formchgcbfa_enable_field(self.p_fa, ctrl.id, enable) - - - def ShowField(self, ctrl, show): - """ - Show or hide an input field - @return: False - no such control - """ - return _idaapi.formchgcbfa_show_field(self.p_fa, ctrl.id, show) - - - def MoveField(self, ctrl, x, y, w, h): - """ - Move/resize an input field - - @return: False - no such fiel - """ - return _idaapi.formchgcbfa_move_field(self.p_fa, ctrl.id, x, y, w, h) - - - def GetFocusedField(self): - """ - Get currently focused input field. - @return: None if no field is selected otherwise the control ID - """ - id = _idaapi.formchgcbfa_get_focused_field(self.p_fa) - return self.FindControlById(id) - - - def SetFocusedField(self, ctrl): - """ - Set currently focused input field - @return: False - no such control - """ - return _idaapi.formchgcbfa_set_focused_field(self.p_fa, ctrl.id) - - - def RefreshField(self, ctrl): - """ - Refresh a field - @return: False - no such control - """ - return _idaapi.formchgcbfa_refresh_field(self.p_fa, ctrl.id) - - - def Close(self, close_normally): - """ - Close the form - @param close_normally: - 1: form is closed normally as if the user pressed Enter - 0: form is closed abnormally as if the user pressed Esc - @return: None - """ - return _idaapi.formchgcbfa_close(self.p_fa, close_normally) - - - def GetControlValue(self, ctrl): - """ - Returns the control's value depending on its type - @param ctrl: Form control instance - @return: - - color button, radio controls: integer - - file/dir input, string input and string label: string - - embedded chooser control (0-based indices of selected items): integer list - - for multilinetext control: textctrl_info_t - - dropdown list controls: string (when editable) or index (when readonly) - - None: on failure - """ - tid, sz = self.ControlToFieldTypeIdAndSize(ctrl) - r = _idaapi.formchgcbfa_get_field_value( - self.p_fa, - ctrl.id, - tid, - sz) - # Multilinetext? Unpack the tuple into a new textctrl_info_t instance - if r is not None and tid == 7: - return textctrl_info_t(text=r[0], flags=r[1], tabsize=r[2]) - else: - return r - - - def SetControlValue(self, ctrl, value): - """ - Set the control's value depending on its type - @param ctrl: Form control instance - @param value: - - embedded chooser: a 0-base indices list to select embedded chooser items - - multilinetext: a textctrl_info_t - - dropdown list: an integer designating the selection index if readonly - a string designating the edit control value if not readonly - @return: Boolean true on success - """ - tid, _ = self.ControlToFieldTypeIdAndSize(ctrl) - return _idaapi.formchgcbfa_set_field_value( - self.p_fa, - ctrl.id, - tid, - value) - - - @staticmethod - def ControlToFieldTypeIdAndSize(ctrl): - """ - Converts a control object to a tuple containing the field id - and the associated buffer size - """ - # Input control depend on the associated buffer size (supplied by the user) - - # Make sure you check instances types taking into account inheritance - if isinstance(ctrl, Form.DropdownListControl): - return (8, 1 if ctrl.readonly else 0) - elif isinstance(ctrl, Form.MultiLineTextControl): - return (7, 0) - elif isinstance(ctrl, Form.EmbeddedChooserControl): - return (5, 0) - # Group items or controls - elif isinstance(ctrl, (Form.GroupItemControl, Form.GroupControl)): - return (2, 0) - elif isinstance(ctrl, Form.StringLabel): - return (3, min(_idaapi.MAXSTR, ctrl.size)) - elif isinstance(ctrl, Form.ColorInput): - return (4, 0) - elif isinstance(ctrl, Form.NumericInput): - # Pass the numeric control type - return (6, ord(ctrl.tp[0])) - elif isinstance(ctrl, Form.InputControl): - return (1, ctrl.size) - else: - raise NotImplementedError, "Not yet implemented" - -# -------------------------------------------------------------------------- -# Instantiate AskUsingForm function pointer -try: - import ctypes - # Setup the numeric argument size - Form.NumericArgument.DefI64 = _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL - AskUsingForm__ = ctypes.CFUNCTYPE(ctypes.c_long)(_idaapi.py_get_AskUsingForm()) - OpenForm__ = ctypes.CFUNCTYPE(ctypes.c_long)(_idaapi.py_get_OpenForm()) -except: - def AskUsingForm__(*args): - warning("AskUsingForm() needs ctypes library in order to work") - return 0 - def OpenForm__(*args): - warning("OpenForm() needs ctypes library in order to work") - - -def AskUsingForm(*args): - """ - Calls AskUsingForm() - @param: Compiled Arguments obtain through the Form.Compile() function - @return: 1 = ok, 0 = cancel - """ - old = set_script_timeout(0) - r = AskUsingForm__(*args) - set_script_timeout(old) - return r - -def OpenForm(*args): - """ - Calls OpenForm() - @param: Compiled Arguments obtain through the Form.Compile() function - """ - old = set_script_timeout(0) - r = OpenForm__(*args) - set_script_timeout(old) - - # - -# -class PluginForm(object): - """ - PluginForm class. - - This form can be used to host additional controls. Please check the PyQt example. - """ - - FORM_MDI = 0x01 - """start by default as MDI (obsolete)""" - FORM_TAB = 0x02 - """attached by default to a tab""" - FORM_RESTORE = 0x04 - """restore state from desktop config""" - FORM_ONTOP = 0x08 - """form should be "ontop""" - FORM_MENU = 0x10 - """form must be listed in the windows menu (automatically set for all plugins)""" - FORM_CENTERED = 0x20 - """form will be centered on the screen""" - FORM_PERSIST = 0x40 - """form will persist until explicitly closed with Close()""" - - - def __init__(self): - """ - """ - self.__clink__ = _idaapi.plgform_new() - - - - 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.FORM_ constants - """ - options |= PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE - return _idaapi.plgform_show(self.__clink__, self, caption, options) - - - @staticmethod - def FormToPyQtWidget(form, ctx = sys.modules['__main__']): - """ - Use this method to convert a TForm* to a QWidget to be used by PyQt - - @param ctx: Context. Reference to a module that already imported SIP and QtGui modules - """ - return ctx.sip.wrapinstance(ctx.sip.voidptr(form).__int__(), ctx.QtGui.QWidget) - - - @staticmethod - def FormToPySideWidget(form, ctx = sys.modules['__main__']): - """ - Use this method to convert a TForm* to a QWidget to be used by PySide - - @param ctx: Context. Reference to a module that already imported QtGui module - """ - if form is None: - return None - if type(form).__name__ == "SwigPyObject": - # Since 'form' is a SwigPyObject, we first need to convert it to a PyCObject. - # However, there's no easy way of doing it, so we'll use a rather brutal approach: - # converting the SwigPyObject to a 'long' (will go through 'SwigPyObject_long', - # that will return the pointer's value as a long), and then convert that value - # back to a pointer into a PyCObject. - ptr_l = long(form) - from ctypes import pythonapi, c_void_p, py_object - pythonapi.PyCObject_FromVoidPtr.restype = py_object - pythonapi.PyCObject_AsVoidPtr.argtypes = [c_void_p, c_void_p] - form = pythonapi.PyCObject_FromVoidPtr(ptr_l, 0) - return ctx.QtGui.QWidget.FromCObject(form) - - - def OnCreate(self, form): - """ - This event is called when the plugin form is created. - The programmer should populate the form when this event is triggered. - - @return: None - """ - pass - - - def OnClose(self, form): - """ - Called when the plugin form is closed - - @return: None - """ - pass - - - def Close(self, options): - """ - Closes the form. - - @param options: Close options (FORM_SAVE, FORM_NO_CONTEXT, ...) - - @return: None - """ - return _idaapi.plgform_close(self.__clink__, options) - - FORM_SAVE = 0x1 - """Save state in desktop config""" - - FORM_NO_CONTEXT = 0x2 - """Don't change the current context (useful for toolbars)""" - - FORM_DONT_SAVE_SIZE = 0x4 - """Don't save size of the window""" - - FORM_CLOSE_LATER = 0x8 - """This flag should be used when Close() is called from an event handler""" -# - -class Choose: - """ - Choose - class for choose() with callbacks - """ - def __init__(self, list, title, flags=0, deflt=1, icon=37): - self.list = list - self.title = title - - self.flags = flags - self.x0 = -1 - self.x1 = -1 - self.y0 = -1 - self.y1 = -1 - - self.width = -1 - self.deflt = deflt - self.icon = icon - - # HACK: Add a circular reference for non-modal choosers. This prevents the GC - # from collecting the class object the callbacks need. Unfortunately this means - # that the class will never be collected, unless refhack is set to None explicitly. - if (flags & Choose2.CH_MODAL) == 0: - self.refhack = self - - def sizer(self): - """ - Callback: sizer - returns the length of the list - """ - return len(self.list) - - def getl(self, n): - """ - Callback: getl - get one item from the list - """ - if n == 0: - return self.title - if n <= self.sizer(): - return str(self.list[n-1]) - else: - return "" - - - def ins(self): - pass - - - def update(self, n): - pass - - - def edit(self, n): - pass - - - def enter(self, n): - print "enter(%d) called" % n - - - def destroy(self): - pass - - - def get_icon(self, n): - pass - - - def choose(self): - """ - choose - Display the choose dialogue - """ - old = set_script_timeout(0) - n = _idaapi.choose_choose( - self, - self.flags, - self.x0, - self.y0, - self.x1, - self.y1, - self.width, - self.deflt, - self.icon) - set_script_timeout(old) - return n -%} - -%pythoncode %{ -# -class cli_t(pyidc_opaque_object_t): - """ - cli_t wrapper class. - - This class allows you to implement your own command line interface handlers. - """ - - def __init__(self): - self.__cli_idx = -1 - self.__clink__ = None - - - def register(self, flags = 0, sname = None, lname = None, hint = None): - """ - Registers the CLI. - - @param flags: Feature bits. No bits are defined yet, must be 0 - @param sname: Short name (displayed on the button) - @param lname: Long name (displayed in the menu) - @param hint: Hint for the input line - - @return Boolean: True-Success, False-Failed - """ - - # Already registered? - if self.__cli_idx >= 0: - return True - - if sname is not None: self.sname = sname - if lname is not None: self.lname = lname - if hint is not None: self.hint = hint - - # Register - self.__cli_idx = _idaapi.install_command_interpreter(self) - return False if self.__cli_idx < 0 else True - - - def unregister(self): - """ - Unregisters the CLI (if it was registered) - """ - if self.__cli_idx < 0: - return False - - _idaapi.remove_command_interpreter(self.__cli_idx) - self.__cli_idx = -1 - return True - - - def __del__(self): - self.unregister() - - # - # Implement these methods in the subclass: - # -# -# def OnExecuteLine(self, line): -# """ -# The user pressed Enter. The CLI is free to execute the line immediately or ask for more lines. -# -# This callback is mandatory. -# -# @param line: typed line(s) -# @return Boolean: True-executed line, False-ask for more lines -# """ -# return True -# -# def OnKeydown(self, line, x, sellen, vkey, shift): -# """ -# A keyboard key has been pressed -# This is a generic callback and the CLI is free to do whatever it wants. -# -# This callback is optional. -# -# @param line: current input line -# @param x: current x coordinate of the cursor -# @param sellen: current selection length (usually 0) -# @param vkey: virtual key code. if the key has been handled, it should be returned as zero -# @param shift: shift state -# -# @return: -# None - Nothing was changed -# tuple(line, x, sellen, vkey): if either of the input line or the x coordinate or the selection length has been modified. -# It is possible to return a tuple with None elements to preserve old values. Example: tuple(new_line, None, None, None) or tuple(new_line) -# """ -# return None -# -# def OnCompleteLine(self, prefix, n, line, prefix_start): -# """ -# The user pressed Tab. Find a completion number N for prefix PREFIX -# -# This callback is optional. -# -# @param prefix: Line prefix at prefix_start (string) -# @param n: completion number (int) -# @param line: the current line (string) -# @param prefix_start: the index where PREFIX starts in LINE (int) -# -# @return: None if no completion could be generated otherwise a String with the completion suggestion -# """ -# return None -# - -# -# -class simplecustviewer_t(object): - """The base class for implementing simple custom viewers""" - def __init__(self): - self.__this = None - - def __del__(self): - """Destructor. It also frees the associated C++ object""" - try: - _idaapi.pyscv_delete(self.__this) - except: - pass - - @staticmethod - def __make_sl_arg(line, fgcolor=None, bgcolor=None): - return line if (fgcolor is None and bgcolor is None) else (line, fgcolor, bgcolor) - - def Create(self, title): - """ - Creates the custom view. This should be the first method called after instantiation - - @param title: The title of the view - @return: Boolean whether it succeeds or fails. It may fail if a window with the same title is already open. - In this case better close existing windows - """ - self.title = title - self.__this = _idaapi.pyscv_init(self, title) - return True if self.__this else False - - def Close(self): - """ - Destroys the view. - One has to call Create() afterwards. - Show() can be called and it will call Create() internally. - @return: Boolean - """ - return _idaapi.pyscv_close(self.__this) - - def Show(self): - """ - Shows an already created view. It the view was close, then it will call Create() for you - @return: Boolean - """ - return _idaapi.pyscv_show(self.__this) - - def Refresh(self): - return _idaapi.pyscv_refresh(self.__this) - - def RefreshCurrent(self): - """Refreshes the current line only""" - return _idaapi.pyscv_refresh_current(self.__this) - - def Count(self): - """Returns the number of lines in the view""" - return _idaapi.pyscv_count(self.__this) - - def GetSelection(self): - """ - Returns the selected area or None - @return: - - tuple(x1, y1, x2, y2) - - None if no selection - """ - return _idaapi.pyscv_get_selection(self.__this) - - def ClearLines(self): - """Clears all the lines""" - _idaapi.pyscv_clear_lines(self.__this) - - def AddLine(self, line, fgcolor=None, bgcolor=None): - """ - Adds a colored line to the view - @return: Boolean - """ - return _idaapi.pyscv_add_line(self.__this, self.__make_sl_arg(line, fgcolor, bgcolor)) - - def InsertLine(self, lineno, line, fgcolor=None, bgcolor=None): - """ - Inserts a line in the given position - @return: Boolean - """ - return _idaapi.pyscv_insert_line(self.__this, lineno, self.__make_sl_arg(line, fgcolor, bgcolor)) - - def EditLine(self, lineno, line, fgcolor=None, bgcolor=None): - """ - Edits an existing line. - @return: Boolean - """ - return _idaapi.pyscv_edit_line(self.__this, lineno, self.__make_sl_arg(line, fgcolor, bgcolor)) - - def PatchLine(self, lineno, offs, value): - """Patches an existing line character at the given offset. This is a low level function. You must know what you're doing""" - return _idaapi.pyscv_patch_line(self.__this, lineno, offs, value) - - def DelLine(self, lineno): - """ - Deletes an existing line - @return: Boolean - """ - return _idaapi.pyscv_del_line(self.__this, lineno) - - def GetLine(self, lineno): - """ - Returns a line - @param lineno: The line number - @return: - Returns a tuple (colored_line, fgcolor, bgcolor) or None - """ - return _idaapi.pyscv_get_line(self.__this, lineno) - - def GetCurrentWord(self, mouse = 0): - """ - Returns the current word - @param mouse: Use mouse position or cursor position - @return: None if failed or a String containing the current word at mouse or cursor - """ - return _idaapi.pyscv_get_current_word(self.__this, mouse) - - def GetCurrentLine(self, mouse = 0, notags = 0): - """ - Returns the current line. - @param mouse: Current line at mouse pos - @param notags: If True then tag_remove() will be called before returning the line - @return: Returns the current line (colored or uncolored) or None on failure - """ - return _idaapi.pyscv_get_current_line(self.__this, mouse, notags) - - def GetPos(self, mouse = 0): - """ - Returns the current cursor or mouse position. - @param mouse: return mouse position - @return: Returns a tuple (lineno, x, y) - """ - return _idaapi.pyscv_get_pos(self.__this, mouse) - - def GetLineNo(self, mouse = 0): - """Calls GetPos() and returns the current line number or -1 on failure""" - r = self.GetPos(mouse) - return -1 if not r else r[0] - - def Jump(self, lineno, x=0, y=0): - return _idaapi.pyscv_jumpto(self.__this, lineno, x, y) - - def AddPopupMenu(self, title, hotkey=""): - """ - Adds a popup menu item - @param title: The name of the menu item - @param hotkey: Hotkey of the item or just empty - @return: Returns the - """ - return _idaapi.pyscv_add_popup_menu(self.__this, title, hotkey) - - def ClearPopupMenu(self): - """ - Clears all previously installed popup menu items. - Use this function if you're generating menu items on the fly (in the OnPopup() callback), - and before adding new items - """ - _idaapi.pyscv_clear_popup_menu(self.__this) - - def IsFocused(self): - """Returns True if the current view is the focused view""" - return _idaapi.pyscv_is_focused(self.__this) - - def GetTForm(self): - """ - Return the TForm hosting this view. - - @return: The TForm that hosts this view, or None. - """ - return _idaapi.pyscv_get_tform(self.__this) - - def GetTCustomControl(self): - """ - Return the TCustomControl underlying this view. - - @return: The TCustomControl underlying this view, or None. - """ - return _idaapi.pyscv_get_tcustom_control(self.__this) - - - - # Here are all the supported events -# -# def OnClick(self, shift): -# """ -# User clicked in the view -# @param shift: Shift flag -# @return: Boolean. True if you handled the event -# """ -# print "OnClick, shift=%d" % shift -# return True -# -# def OnDblClick(self, shift): -# """ -# User dbl-clicked in the view -# @param shift: Shift flag -# @return: Boolean. True if you handled the event -# """ -# print "OnDblClick, shift=%d" % shift -# return True -# -# def OnCursorPosChanged(self): -# """ -# Cursor position changed. -# @return: Nothing -# """ -# print "OnCurposChanged" -# -# def OnClose(self): -# """ -# The view is closing. Use this event to cleanup. -# @return: Nothing -# """ -# print "OnClose" -# -# def OnKeydown(self, vkey, shift): -# """ -# User pressed a key -# @param vkey: Virtual key code -# @param shift: Shift flag -# @return: Boolean. True if you handled the event -# """ -# 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. -# @param lineno: The line number (zero based) -# @return: -# - tuple(number of important lines, hint string) -# - None: if no hint available -# """ -# return (1, "OnHint, line=%d" % lineno) -# -# def OnPopupMenu(self, menu_id): -# """ -# A context (or popup) menu item was executed. -# @param menu_id: ID previously registered with add_popup_menu() -# @return: Boolean -# """ -# print "OnPopupMenu, menu_id=" % menu_id -# return True -# -# %} diff --git a/swig/lines.i b/swig/lines.i index eb282f7..56e74c7 100644 --- a/swig/lines.i +++ b/swig/lines.i @@ -79,252 +79,15 @@ %{ // -//------------------------------------------------------------------------ -static PyObject *py_get_user_defined_prefix = NULL; -static void idaapi s_py_get_user_defined_prefix( - ea_t ea, - int lnnum, - int indent, - const char *line, - char *buf, - size_t bufsize) -{ - PYW_GIL_GET; - newref_t py_ret( - PyObject_CallFunction( - py_get_user_defined_prefix, - PY_FMT64 "iis" PY_FMT64, - ea, lnnum, indent, line, bufsize)); - - // Error? Display it - // No error? Copy the buffer - if ( !PyW_ShowCbErr("py_get_user_defined_prefix") ) - { - Py_ssize_t py_len; - char *py_str; - if ( PyString_AsStringAndSize(py_ret.o, &py_str, &py_len) != -1 ) - { - memcpy(buf, py_str, qmin(bufsize, py_len)); - if ( py_len < bufsize ) - buf[py_len] = '\0'; - } - } -} // %} %inline %{ // - -//------------------------------------------------------------------------ -/* -# -def set_user_defined_prefix(width, callback): - """ - User-defined line-prefixes are displayed just after the autogenerated - line prefixes. In order to use them, the plugin should call the - following function to specify its width and contents. - @param width: the width of the user-defined prefix - @param callback: a get_user_defined_prefix callback to get the contents of the prefix. - Its arguments: - ea - linear address - lnnum - line number - indent - indent of the line contents (-1 means the default instruction) - indent and is used for instruction itself. see explanations for printf_line() - line - the line to be generated. the line usually contains color tags this argument - can be examined to decide whether to generated the prefix - bufsize- the maximum allowed size of the output buffer - It returns a buffer of size < bufsize - - In order to remove the callback before unloading the plugin, specify the width = 0 or the callback = None - """ - pass -# -*/ -static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( width == 0 || pycb == Py_None ) - { - // Release old callback reference - Py_XDECREF(py_get_user_defined_prefix); - - // ...and clear it - py_get_user_defined_prefix = NULL; - - // Uninstall user defind prefix - set_user_defined_prefix(0, NULL); - } - else if ( PyCallable_Check(pycb) ) - { - // Release old callback reference - Py_XDECREF(py_get_user_defined_prefix); - - // Copy new callback and hold a reference - py_get_user_defined_prefix = pycb; - Py_INCREF(py_get_user_defined_prefix); - - set_user_defined_prefix(width, s_py_get_user_defined_prefix); - } - else - { - Py_RETURN_FALSE; - } - Py_RETURN_TRUE; -} - -//------------------------------------------------------------------------- -/* -# -def tag_remove(colstr): - """ - Remove color escape sequences from a string - @param colstr: the colored string with embedded tags - @return: - None on failure - or a new string w/o the tags - """ - pass -# -*/ -PyObject *py_tag_remove(const char *instr) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - size_t sz = strlen(instr); - char *buf = new char[sz + 5]; - if ( buf == NULL ) - Py_RETURN_NONE; - - ssize_t r = tag_remove(instr, buf, sz); - PyObject *res; - if ( r < 0 ) - { - Py_INCREF(Py_None); - res = Py_None; - } - else - { - res = PyString_FromString(buf); - } - delete [] buf; - return res; -} - -//------------------------------------------------------------------------- -PyObject *py_tag_addr(ea_t ea) -{ - char buf[100]; - tag_addr(buf, buf + sizeof(buf), ea); - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyString_FromString(buf); -} - -//------------------------------------------------------------------------- -int py_tag_skipcode(const char *line) -{ - return tag_skipcode(line)-line; -} - -//------------------------------------------------------------------------- -int py_tag_skipcodes(const char *line) -{ - return tag_skipcodes(line)-line; -} - -//------------------------------------------------------------------------- -int py_tag_advance(const char *line, int cnt) -{ - return tag_advance(line, cnt)-line; -} - -//------------------------------------------------------------------------- -/* -# -def generate_disassembly(ea, max_lines, as_stack, notags): - """ - Generate disassembly lines (many lines) and put them into a buffer - - @param ea: address to generate disassembly for - @param max_lines: how many lines max to generate - @param as_stack: Display undefined items as 2/4/8 bytes - @return: - - None on failure - - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing - the most important line number and a tuple of generated lines - """ - pass -# -*/ -PyObject *py_generate_disassembly( - ea_t ea, - int max_lines, - bool as_stack, - bool notags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( max_lines <= 0 ) - Py_RETURN_NONE; - - qstring qbuf; - char **lines = new char *[max_lines]; - int lnnum; - int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack); - - newref_t py_tuple(PyTuple_New(nlines)); - for ( int i=0; i - %} %pythoncode %{ # - -# ---------------- Color escape sequence defitions ------------------------- -COLOR_ADDR_SIZE = 16 if _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL else 8 -SCOLOR_FG_MAX = '\x28' # Max color number -SCOLOR_OPND1 = chr(cvar.COLOR_ADDR+1) # Instruction operand 1 -SCOLOR_OPND2 = chr(cvar.COLOR_ADDR+2) # Instruction operand 2 -SCOLOR_OPND3 = chr(cvar.COLOR_ADDR+3) # Instruction operand 3 -SCOLOR_OPND4 = chr(cvar.COLOR_ADDR+4) # Instruction operand 4 -SCOLOR_OPND5 = chr(cvar.COLOR_ADDR+5) # Instruction operand 5 -SCOLOR_OPND6 = chr(cvar.COLOR_ADDR+6) # Instruction operand 6 -SCOLOR_UTF8 = chr(cvar.COLOR_ADDR+10) # Following text is UTF-8 encoded - -# ---------------- Line prefix colors -------------------------------------- -PALETTE_SIZE = (cvar.COLOR_FG_MAX+_idaapi.COLOR_BG_MAX) - -def requires_color_esc(c): - """ - Checks if the given character requires escaping - @param c: character (string of one char) - @return: Boolean - """ - t = ord(c[0]) - return c >= COLOR_ON and c <= COLOR_INV - -def COLSTR(str, tag): - """ - Utility function to create a colored line - @param str: The string - @param tag: Color tag constant. One of SCOLOR_XXXX - """ - return SCOLOR_ON + tag + str + SCOLOR_OFF + tag - # - %} diff --git a/swig/linput.i b/swig/linput.i new file mode 100644 index 0000000..373c5b6 --- /dev/null +++ b/swig/linput.i @@ -0,0 +1,4 @@ +%inline %{ +// +// +%} diff --git a/swig/loader.i b/swig/loader.i index c49f7da..19f4ff8 100644 --- a/swig/loader.i +++ b/swig/loader.i @@ -12,7 +12,7 @@ // TODO: These could be wrapped if needed %ignore load_info_t; %ignore add_plugin_option; -%ignore get_plugins_path; +%ignore get_plugins_paths; %ignore build_loaders_list; %ignore free_loaders_list; %ignore get_loader_name_from_dll; @@ -21,7 +21,6 @@ %ignore load_nonbinary_file; %ignore impinfo_t; %ignore import_module; -%ignore plugin_info_t; %ignore get_plugins; %ignore invoke_plugin; %ignore dbg_info_t; @@ -116,10 +115,7 @@ %ignore mem2base; %rename (mem2base) py_mem2base; %ignore update_snapshot_attributes; -%ignore build_snapshot_tree; %ignore visit_snapshot_tree; -%ignore snapshot_t; -%ignore snapshots_t; %ignore load_plugin; %rename (load_plugin) py_load_plugin; %ignore run_plugin; @@ -129,93 +125,5 @@ %inline %{ // - -//------------------------------------------------------------------------ -/* -# -def mem2base(mem, ea, fpos): - """ - Load database from the memory. - @param mem: the buffer - @param ea: start linear addresses - @param fpos: position in the input file the data is taken from. - if == -1, then no file position correspond to the data. - @return: - - Returns zero if the passed buffer was not a string - - Otherwise 1 is returned - """ - pass -# -*/ -static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1) -{ - Py_ssize_t len; - char *buf; - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 ) - return 0; - } - - return mem2base((void *)buf, ea, ea+len, fpos); -} - -//------------------------------------------------------------------------ -/* -# -def load_plugin(name): - """ - Loads a plugin - @return: - - None if plugin could not be loaded - - An opaque object representing the loaded plugin - """ - pass -# -*/ -static PyObject *py_load_plugin(const char *name) -{ - plugin_t *r = load_plugin(name); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( r == NULL ) - Py_RETURN_NONE; - else - return PyCObject_FromVoidPtr(r, NULL); -} - -//------------------------------------------------------------------------ -/* -# -def run_plugin(plg): - """ - Runs a plugin - @param plg: A plugin object (returned by load_plugin()) - @return: Boolean - """ - pass -# -*/ -static bool py_run_plugin(PyObject *plg, int arg) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(plg) ) - { - return false; - } - else - { - plugin_t *p = (plugin_t *)PyCObject_AsVoidPtr(plg); - bool rc; - Py_BEGIN_ALLOW_THREADS; - rc = run_plugin(p, arg); - Py_END_ALLOW_THREADS; - return rc; - } -} - // - %} - - - diff --git a/swig/moves.i b/swig/moves.i index 3a2a190..3413a0c 100644 --- a/swig/moves.i +++ b/swig/moves.i @@ -7,7 +7,16 @@ %ignore curloc_after_segments_moved; %ignore curloc::rebase_stack; %ignore loc_gtag; +%ignore write_gli; +%ignore read_gli; %ignore DEFINE_CURLOC_HELPERS; %ignore DEFINE_LOCATION_HELPERS; +%ignore histories_after_segments_moved; +%ignore lochist_t::rebase_stack; +%ignore location_t::location_t(bool); +%ignore lochist_t::is_hexrays68_compat; +%ignore lochist_entry_t::set_place(const place_t &); + +%template(segm_move_info_vec_t) qvector; %include "moves.hpp" diff --git a/swig/nalt.i b/swig/nalt.i index 618f1c5..3b945de 100644 --- a/swig/nalt.i +++ b/swig/nalt.i @@ -136,55 +136,6 @@ %{ // - -//------------------------------------------------------------------------- -// callback for enumerating imports -// ea: import address -// name: import name (NULL if imported by ordinal) -// ord: import ordinal (0 for imports by name) -// param: user parameter passed to enum_import_names() -// return: 1-ok, 0-stop enumeration -static int idaapi py_import_enum_cb( - ea_t ea, - const char *name, - uval_t ord, - void *param) -{ - // If no name, try to get the name associated with the 'ea'. It may be coming from IDS - char name_buf[MAXSTR]; - if ( name == NULL ) - name = get_true_name(BADADDR, ea, name_buf, sizeof(name_buf)); - - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t py_name; - if ( name == NULL ) - py_name = borref_t(Py_None); - else - py_name = newref_t(PyString_FromString(name)); - - newref_t py_ord(Py_BuildValue(PY_FMT64, pyul_t(ord))); - newref_t py_ea(Py_BuildValue(PY_FMT64, pyul_t(ea))); - newref_t py_result( - PyObject_CallFunctionObjArgs( - (PyObject *)param, - py_ea.o, - py_name.o, - py_ord.o, - NULL)); - return py_result != NULL && PyObject_IsTrue(py_result.o) ? 1 : 0; -} - -//------------------------------------------------------------------------- -switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyObject_HasAttrString(self, S_CLINK_NAME) ) - return NULL; - - switch_info_ex_t *r; - newref_t attr(PyObject_GetAttrString(self, S_CLINK_NAME)); - return PyCObject_Check(attr.o) ? ((switch_info_ex_t *) PyCObject_AsVoidPtr(attr.o)) : NULL; -} // %} @@ -197,686 +148,10 @@ switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self) %inline %{ // - -//------------------------------------------------------------------------- -/* -# -def get_import_module_name(path, fname, callback): - """ - Returns the name of an imported module given its index - @return: None or the module name - """ - pass -# -*/ -static PyObject *py_get_import_module_name(int mod_index) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - char buf[MAXSTR]; - if ( !get_import_module_name(mod_index, buf, sizeof(buf)) ) - Py_RETURN_NONE; - - return PyString_FromString(buf); -} - -//------------------------------------------------------------------------- -/* -# -def get_switch_info_ex(ea): - """ - Returns the a switch_info_ex_t structure containing the information about the switch. - Please refer to the SDK sample 'uiswitch' - @return: None or switch_info_ex_t instance - """ - pass -# -*/ -PyObject *py_get_switch_info_ex(ea_t ea) -{ - switch_info_ex_t *ex = new switch_info_ex_t(); - ref_t py_obj; - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0 - || (py_obj = create_idaapi_linked_class_instance(S_PY_SWIEX_CLSNAME, ex)) == NULL ) - { - delete ex; - Py_RETURN_NONE; - } - py_obj.incref(); - return py_obj.o; -} - -//------------------------------------------------------------------------- -/* -# -def create_switch_xrefs(insn_ea, si): - """ - This function creates xrefs from the indirect jump. - - Usually there is no need to call this function directly because the kernel - will call it for switch tables - - Note: Custom switch information are not supported yet. - - @param insn_ea: address of the 'indirect jump' instruction - @param si: switch information - - @return: Boolean - """ - pass -# -*/ -idaman bool ida_export py_create_switch_xrefs( - ea_t insn_ea, - PyObject *py_swi) -{ - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); - if ( swi == NULL ) - return false; - - create_switch_xrefs(insn_ea, swi); - return true; -} - -//------------------------------------------------------------------------- -struct cases_and_targets_t -{ - casevec_t cases; - eavec_t targets; -}; - -//------------------------------------------------------------------------- -/* -# -def calc_switch_cases(insn_ea, si): - """ - Get information about a switch's cases. - - The returned information can be used as follows: - - for idx in xrange(len(results.cases)): - cur_case = results.cases[idx] - for cidx in xrange(len(cur_case)): - print "case: %d" % cur_case[cidx] - print " goto 0x%x" % results.targets[idx] - - @param insn_ea: address of the 'indirect jump' instruction - @param si: switch information - - @return: a structure with 2 members: 'cases', and 'targets'. - """ - pass -# -*/ -idaman cases_and_targets_t *ida_export py_calc_switch_cases( - ea_t insn_ea, - PyObject *py_swi) -{ - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); - if ( swi == NULL ) - return NULL; - - cases_and_targets_t *ct = new cases_and_targets_t; - if ( !calc_switch_cases(insn_ea, swi, &ct->cases, &ct->targets) ) - { - delete ct; - return NULL; - } - - return ct; -} - - -//------------------------------------------------------------------------- -/* -# -def create_switch_table(insn_ea, si): - """ - Create switch table from the switch information - - @param insn_ea: address of the 'indirect jump' instruction - @param si: switch information - - @return: Boolean - """ - pass -# -*/ -idaman bool ida_export py_create_switch_table( - ea_t insn_ea, - PyObject *py_swi) -{ - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); - if ( swi == NULL ) - return false; - - create_switch_table(insn_ea, swi); - return true; -} - -//------------------------------------------------------------------------- -/* -# -def set_switch_info_ex(ea, switch_info_ex): - """ - Saves the switch information in the database - Please refer to the SDK sample 'uiswitch' - @return: Boolean - """ - pass -# -*/ -bool py_set_switch_info_ex(ea_t ea, PyObject *py_swi) -{ - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); - if ( swi == NULL ) - return false; - - set_switch_info_ex(ea, swi); - return true; -} - -//------------------------------------------------------------------------- -/* -# -def del_switch_info_ex(ea): - """ - Deletes stored switch information - """ - pass -# -*/ -void py_del_switch_info_ex(ea_t ea) -{ - del_switch_info_ex(ea); -} - -//------------------------------------------------------------------------- -/* -# -def enum_import_names(mod_index, callback): - """ - Enumerate imports from a specific module. - Please refer to ex_imports.py example. - - @param mod_index: The module index - @param callback: A callable object that will be invoked with an ea, name (could be None) and ordinal. - @return: 1-finished ok, -1 on error, otherwise callback return value (<=0) - """ - pass -# -*/ -static int py_enum_import_names(int mod_index, PyObject *py_cb) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCallable_Check(py_cb) ) - return -1; - return enum_import_names(mod_index, py_import_enum_cb, py_cb); -} - -//------------------------------------------------------------------------- -static PyObject *switch_info_ex_t_create() -{ - switch_info_ex_t *inst = new switch_info_ex_t(); - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(inst, NULL); -} - -//--------------------------------------------------------------------------- -static bool switch_info_ex_t_destroy(PyObject *py_obj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_obj) ) - return false; - switch_info_ex_t *inst = (switch_info_ex_t *) PyCObject_AsVoidPtr(py_obj); - delete inst; - return true; -} - -static bool switch_info_ex_t_assign(PyObject *self, PyObject *other) -{ - switch_info_ex_t *lhs = switch_info_ex_t_get_clink(self); - switch_info_ex_t *rhs = switch_info_ex_t_get_clink(other); - if (lhs == NULL || rhs == NULL) - return false; - - *lhs = *rhs; - return true; -} - -//------------------------------------------------------------------------- -// Auto generated - begin -// - -static PyObject *switch_info_ex_t_get_regdtyp(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", (char)link->regdtyp); -} -static void switch_info_ex_t_set_regdtyp(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->regdtyp = (char)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_flags2(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("i", link->flags2); -} -static void switch_info_ex_t_set_flags2(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->flags2 = (int)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_jcases(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("i", link->jcases); -} -static void switch_info_ex_t_set_jcases(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->jcases = (int)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_regnum(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("i", (int)link->regnum); -} -static void switch_info_ex_t_set_regnum(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->regnum = (int)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_flags(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", (ushort)link->flags); -} -static void switch_info_ex_t_set_flags(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->flags = (uint16)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_ncases(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", (uint16)link->ncases); -} -static void switch_info_ex_t_set_ncases(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->ncases = (ushort)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_defjump(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->defjump); -} -static void switch_info_ex_t_set_defjump(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - uint64 v(0); PyW_GetNumber(value, &v); - link->defjump = (pyul_t)v; -} - -static PyObject *switch_info_ex_t_get_jumps(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->jumps); -} -static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - uint64 v(0); PyW_GetNumber(value, &v); - link->jumps = (pyul_t)v; -} - -static PyObject *switch_info_ex_t_get_elbase(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->elbase); -} -static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyW_GetNumber(value, &v); - link->elbase = (pyul_t)v; -} - -static PyObject *switch_info_ex_t_get_startea(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->startea); -} -static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyW_GetNumber(value, &v); - link->startea = (pyul_t)v; -} - -static PyObject *switch_info_ex_t_get_custom(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->custom); -} -static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyW_GetNumber(value, &v); - link->custom = (pyul_t)v; -} - -static PyObject *switch_info_ex_t_get_ind_lowcase(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->ind_lowcase); -} -static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyW_GetNumber(value, &v); - link->ind_lowcase = (pyul_t)v; -} - -static PyObject *switch_info_ex_t_get_values_lowcase(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->values); -} -static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyW_GetNumber(value, &v); - link->values = (pyul_t)v; -} - -// -// Auto generated - end -// -//------------------------------------------------------------------------- // %} %pythoncode %{ # -SWI_SPARSE = 0x1 -"""sparse switch ( value table present ) otherwise lowcase present""" -SWI_V32 = 0x2 -"""32-bit values in table""" -SWI_J32 = 0x4 -"""32-bit jump offsets""" -SWI_VSPLIT = 0x8 -"""value table is split (only for 32-bit values)""" -SWI_DEFAULT = 0x10 -"""default case is present""" -SWI_END_IN_TBL = 0x20 -"""switchend in table (default entry)""" -SWI_JMP_INV = 0x40 -"""jumptable is inversed (last entry is for first entry in values table)""" -SWI_SHIFT_MASK = 0x180 -"""use formula (element*shift + elbase) to find jump targets""" - -SWI_ELBASE = 0x200 -"""elbase is present (if not and shift!=0, endof(jumpea) is used)""" -SWI_JSIZE = 0x400 -"""jump offset expansion bit""" - -SWI_VSIZE = 0x800 -"""value table element size expansion bit""" - -SWI_SEPARATE = 0x1000 -"""do not create an array of individual dwords""" - -SWI_SIGNED = 0x2000 -"""jump table entries are signed""" - -SWI_CUSTOM = 0x4000 -"""custom jump table - ph.create_switch_xrefs will be called to create code xrefs for the table. it must return 2. custom jump table must be created by the module""" - -SWI_EXTENDED = 0x8000 -"""this is switch_info_ex_t""" - -SWI2_INDIRECT = 0x0001 -"""value table elements are used as indexes into the jump table""" -SWI2_SUBTRACT = 0x0002 -"""table values are subtracted from the elbase instead of being addded""" - -# -------------------------------------------------------------------------- -class switch_info_ex_t(py_clinked_object_t): - def __init__(self, lnk = None): - py_clinked_object_t.__init__(self, lnk) - - def _create_clink(self): - return _idaapi.switch_info_ex_t_create() - - def _del_clink(self, lnk): - return _idaapi.switch_info_ex_t_destroy(lnk) - - def assign(self, other): - return _idaapi.switch_info_ex_t_assign(self, other) - - def is_indirect(self): - return (self.flags & SWI_EXTENDED) != 0 and (self.flags2 & SWI2_INDIRECT) != 0 - - def is_subtract(self): - return (self.flags & SWI_EXTENDED) != 0 and (self.flags2 & SWI2_SUBTRACT) != 0 - - def get_jtable_size(self): - return self.jcases if self.is_indirect() else self.ncases - - def get_lowcase(self): - return self.ind_lowcase if self.is_indirect() else self.lowcase - - def set_expr(self, r, dt): - self.regnum = r - self.regdtyp = dt - - def get_shift(self): - return (self.flags & SWI_SHIFT_MASK) >> 7 - - def set_shift(self, shift): - self.flags &= ~SWI_SHIFT_MASK - self.flags |= ((shift & 3) << 7) - - def get_jtable_element_size(self): - code = self.flags & (SWI_J32|SWI_JSIZE) - if code == 0: return 2 - elif code == SWI_J32: return 4 - elif code == SWI_JSIZE: return 1 - else: return 8 - - def set_jtable_element_size(self, size): - self.flags &= ~(SWI_J32|SWI_JSIZE) - if size == 4: self.flags |= SWI_J32 - elif size == 1: self.flags |= SWI_JSIZE - elif size == 8: self.flags |= SWI_J32|SWI_JSIZE - elif size != 2: return False - return True - - def get_vtable_element_size(self): - code = self.flags & (SWI_V32|SWI_VSIZE) - if code == 0: return 2 - elif code == SWI_V32: return 4 - elif code == SWI_VSIZE: return 1 - return 8 - - def set_vtable_element_size(self, size): - self.flags &= ~SWI_V32|SWI_VSIZE - if size == 4: self.flags |= SWI_V32 - elif size == 1: self.flags |= SWI_VSIZE - elif size == 8: self.flags |= SWI_V32|SWI_VSIZE - elif size != 2: return False - return True - - # - # Autogenerated - # - def __get_regdtyp__(self): - return _idaapi.switch_info_ex_t_get_regdtyp(self) - def __set_regdtyp__(self, v): - _idaapi.switch_info_ex_t_set_regdtyp(self, v) - def __get_flags2__(self): - return _idaapi.switch_info_ex_t_get_flags2(self) - def __set_flags2__(self, v): - _idaapi.switch_info_ex_t_set_flags2(self, v) - def __get_jcases__(self): - return _idaapi.switch_info_ex_t_get_jcases(self) - def __set_jcases__(self, v): - _idaapi.switch_info_ex_t_set_jcases(self, v) - def __get_regnum__(self): - return _idaapi.switch_info_ex_t_get_regnum(self) - def __set_regnum__(self, v): - _idaapi.switch_info_ex_t_set_regnum(self, v) - def __get_flags__(self): - return _idaapi.switch_info_ex_t_get_flags(self) - def __set_flags__(self, v): - _idaapi.switch_info_ex_t_set_flags(self, v) - def __get_ncases__(self): - return _idaapi.switch_info_ex_t_get_ncases(self) - def __set_ncases__(self, v): - _idaapi.switch_info_ex_t_set_ncases(self, v) - def __get_defjump__(self): - return _idaapi.switch_info_ex_t_get_defjump(self) - def __set_defjump__(self, v): - _idaapi.switch_info_ex_t_set_defjump(self, v) - def __get_jumps__(self): - return _idaapi.switch_info_ex_t_get_jumps(self) - def __set_jumps__(self, v): - _idaapi.switch_info_ex_t_set_jumps(self, v) - def __get_elbase__(self): - return _idaapi.switch_info_ex_t_get_elbase(self) - def __set_elbase__(self, v): - _idaapi.switch_info_ex_t_set_elbase(self, v) - def __get_startea__(self): - return _idaapi.switch_info_ex_t_get_startea(self) - def __set_startea__(self, v): - _idaapi.switch_info_ex_t_set_startea(self, v) - def __get_custom__(self): - return _idaapi.switch_info_ex_t_get_custom(self) - def __set_custom__(self, v): - _idaapi.switch_info_ex_t_set_custom(self, v) - def __get_ind_lowcase__(self): - return _idaapi.switch_info_ex_t_get_ind_lowcase(self) - def __set_ind_lowcase__(self, v): - _idaapi.switch_info_ex_t_set_ind_lowcase(self, v) - def __get_values_lowcase__(self): - return _idaapi.switch_info_ex_t_get_values_lowcase(self) - def __set_values_lowcase__(self, v): - _idaapi.switch_info_ex_t_set_values_lowcase(self, v) - regdtyp = property(__get_regdtyp__, __set_regdtyp__) - """size of the switch expression register as dtyp""" - flags2 = property(__get_flags2__, __set_flags2__) - jcases = property(__get_jcases__, __set_jcases__) - """number of entries in the jump table (SWI2_INDIRECT)""" - regnum = property(__get_regnum__, __set_regnum__) - """the switch expression as a register number""" - flags = property(__get_flags__, __set_flags__) - """the switch expression as a register number""" - ncases = property(__get_ncases__, __set_ncases__) - """number of cases (excluding default)""" - defjump = property(__get_defjump__, __set_defjump__) - """default jump address""" - jumps = property(__get_jumps__, __set_jumps__) - """jump table address""" - elbase = property(__get_elbase__, __set_elbase__) - """element base""" - startea = property(__get_startea__, __set_startea__) - """start of switch idiom""" - custom = property(__get_custom__, __set_custom__) - """information for custom tables (filled and used by modules)""" - ind_lowcase = property(__get_ind_lowcase__, __set_ind_lowcase__) - values = property(__get_values_lowcase__, __set_values_lowcase__) - lowcase = property(__get_values_lowcase__, __set_values_lowcase__) - # %} diff --git a/swig/name.i b/swig/name.i index d005877..d7bce0a 100644 --- a/swig/name.i +++ b/swig/name.i @@ -29,6 +29,7 @@ %ignore get_ea_name; %rename (get_ea_name) py_get_ea_name; +%ignore get_name_value2; %ignore make_visible_name2; @@ -77,91 +78,11 @@ inline qstring py_## FNAME(ea_t ea) { return FNAME(ea); } %inline %{ // -//------------------------------------------------------------------------ -PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) -{ - // Get debug names - ea_name_vec_t names; - PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_BEGIN_ALLOW_THREADS; - get_debug_names(ea1, ea2, names); - Py_END_ALLOW_THREADS; - PyObject *dict = Py_BuildValue("{}"); - if (dict != NULL) - { - for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it) - { - PyDict_SetItem(dict, - Py_BuildValue(PY_FMT64, it->ea), - PyString_FromString(it->name.c_str())); - } - } - return dict; -} - -//------------------------------------------------------------------------- -inline qstring py_get_ea_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, gtn_flags); - return out; -} -//------------------------------------------------------------------------ // %} %pythoncode %{ # - -class NearestName: - """ - Utility class to help find the nearest name in a given ea/name dictionary - """ - def __init__(self, ea_names): - self.update(ea_names) - - - def update(self, ea_names): - """Updates the ea/names map""" - self._names = ea_names - self._addrs = ea_names.keys() - self._addrs.sort() - - - def find(self, ea): - """ - Returns a tupple (ea, name, pos) that is the nearest to the passed ea - If no name is matched then None is returned - """ - pos = bisect.bisect_left(self._addrs, ea) - # no match - if pos >= len(self._addrs): - return None - # exact match? - if self._addrs[pos] != ea: - pos -= 1 # go to previous element - if pos < 0: - return None - return self[pos] - - - def _get_item(self, index): - ea = self._addrs[index] - return (ea, self._names[ea], index) - - - def __iter__(self): - return (self._get_item(index) for index in xrange(0, len(self._addrs))) - - - def __getitem__(self, index): - """Returns the tupple (ea, name, index)""" - if index > len(self._addrs): - raise StopIteration - return self._get_item(index) - -extract_name = extract_name2 - # %} diff --git a/swig/plgform.i b/swig/plgform.i new file mode 100644 index 0000000..931aa15 --- /dev/null +++ b/swig/plgform.i @@ -0,0 +1,17 @@ + +// relies on kernwin.i to include kernwin.hpp + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/pro.i b/swig/pro.i index 025260b..2f7e05a 100644 --- a/swig/pro.i +++ b/swig/pro.i @@ -115,6 +115,10 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1); void qvector::grow(const unsigned int &x=0); %ignore qvector::grow; + +void qvector::grow(const long long &x=0); +%ignore qvector::grow; + %ignore qvector::at(size_t); // simpleline_t doesn't implement '=='. Therefore, all these cannot be present in the instantiated template. @@ -140,33 +144,39 @@ void qvector::grow(const unsigned int &x=0); // resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_unsigned_int, 0 | 0 ); // instead of that: // resultobj = SWIG_From_unsigned_SS_int(static_cast< unsigned int >(*result)); - inline const T& __getitem__(size_t i) const throw(std::out_of_range) { + inline const T& __getitem__(size_t i) const { if (i >= $self->size() || i < 0) throw std::out_of_range("out of bounds access"); return $self->at(i); } - inline void __setitem__(size_t i, const T& v) throw(std::out_of_range) { + inline void __setitem__(size_t i, const T& v) { if (i >= $self->size() || i < 0) throw std::out_of_range("out of bounds access"); $self->at(i) = v; } + inline const T&at(size_t i) { + return __getitem__(i); + } + %pythoncode { __iter__ = _bounded_getitem_iterator } } //--------------------------------------------------------------------- -%template(uvalvec_t) qvector; // unsigned values -%template(intvec_t) qvector; -%template(boolvec_t) qvector; -%template(casevec_t) qvector >; // signed values -%template(strvec_t) qvector; +%template(uvalvec_t) qvector; // unsigned values +%template(intvec_t) qvector; +%template(int64vec_t) qvector; // for EA64 svalvec_t objects +%template(boolvec_t) qvector; +%template(casevec_t) qvector >; // signed values +%template(strvec_t) qvector; %pythoncode %{ _listify_types(uvalvec_t, intvec_t, + int64vec_t, boolvec_t, casevec_t, strvec_t) diff --git a/swig/registry.i b/swig/registry.i index e71bf93..45b150d 100644 --- a/swig/registry.i +++ b/swig/registry.i @@ -35,110 +35,11 @@ %{ // -//------------------------------------------------------------------------- -static PyObject *_py_reg_subkey_children(const char *name, bool subkeys) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *result = NULL; - qstrvec_t children; - Py_BEGIN_ALLOW_THREADS; - if ( reg_subkey_children(&children, name, subkeys) ) - { - result = PyList_New(children.size()); - if ( result != NULL ) - for ( size_t i = 0, n = children.size(); i < n; ++i ) - PyList_SET_ITEM(result, i, PyString_FromString(children[i].c_str())); - } - Py_END_ALLOW_THREADS; - if ( result == NULL ) - Py_RETURN_NONE; - else - return result; -} // %} %inline %{ // -//------------------------------------------------------------------------- -PyObject *py_reg_read_string(const char *name, const char *subkey = NULL, const char *def = NULL) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - char utf8[MAXSTR * 10]; - bool ok; - Py_BEGIN_ALLOW_THREADS; - if ( def == NULL ) - { - ok = reg_read_string(name, utf8, sizeof(utf8), subkey); - } - else - { - reg_read_string(name, sizeof(utf8), utf8, def, subkey); - ok = true; - } - Py_END_ALLOW_THREADS; - return PyString_FromString(ok ? utf8 : ""); -} - -//------------------------------------------------------------------------- -regval_type_t py_reg_data_type(const char *name, const char *subkey = NULL) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - regval_type_t rt = reg_unknown; - Py_BEGIN_ALLOW_THREADS; - reg_data_type(&rt, name, subkey); - Py_END_ALLOW_THREADS; - return rt; -} - -//------------------------------------------------------------------------- -PyObject *py_reg_read_binary(const char *name, const char *subkey = NULL) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bytevec_t bytes; - bool ok; - Py_BEGIN_ALLOW_THREADS; - ok = reg_read_binary(name, &bytes, subkey); - Py_END_ALLOW_THREADS; - if ( ok ) - return PyString_FromStringAndSize((const char *) bytes.begin(), bytes.size()); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -void py_reg_write_binary(const char *name, PyObject *py_bytes, const char *subkey = NULL) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( PyString_Check(py_bytes) ) - { - char *py_bytes_raw = NULL; - Py_ssize_t py_size = 0; - PyString_AsStringAndSize(py_bytes, &py_bytes_raw, &py_size); - bytevec_t bytes; - bytes.append(py_bytes_raw, py_size); - Py_BEGIN_ALLOW_THREADS; - reg_write_binary(name, bytes.begin(), bytes.size(), subkey); - Py_END_ALLOW_THREADS; - } - else - { - PyErr_SetString(PyExc_ValueError, "Bytes string expected!"); - } -} - -//------------------------------------------------------------------------- -PyObject *py_reg_subkey_subkeys(const char *name) -{ - return _py_reg_subkey_children(name, true); -} - -//------------------------------------------------------------------------- -PyObject *py_reg_subkey_values(const char *name) -{ - return _py_reg_subkey_children(name, false); -} - // %} diff --git a/swig/segment.i b/swig/segment.i index 9e8f416..beb54fc 100644 --- a/swig/segment.i +++ b/swig/segment.i @@ -20,55 +20,19 @@ %ignore correct_address; %{ -void segment_t_startEA_set(segment_t *segm, ea_t newea) -{ - if ( getseg(segm->startEA) == segm ) - { - PyErr_SetString(PyExc_AttributeError, "Can't modify startEA, please use set_segm_start() instead"); - } - else - { - segm->startEA = newea; - } -} - -ea_t segment_t_startEA_get(segment_t *segm) -{ - return segm->startEA; -} - -void segment_t_endEA_set(segment_t *segm, ea_t newea) -{ - if ( getseg(segm->startEA) == segm ) - { - PyErr_SetString(PyExc_AttributeError, "Can't modify endEA, please use set_segm_end() instead"); - } - else - { - segm->endEA = newea; - } -} - -ea_t segment_t_endEA_get(segment_t *segm) -{ - return segm->endEA; -} +// +// %} + %extend segment_t { ea_t startEA; - ea_t endEA; + ea_t endEA; } %include "segment.hpp" %inline %{ -sel_t get_defsr(segment_t *s, int reg) -{ - return s->defsr[reg]; -} -void set_defsr(segment_t *s, int reg, sel_t value) -{ - s->defsr[reg] = value; -} +// +// %} diff --git a/swig/struct.i b/swig/struct.i index cd790c2..0e822f9 100644 --- a/swig/struct.i +++ b/swig/struct.i @@ -4,13 +4,58 @@ %ignore term_structs; %ignore get_struc_name(tid_t); %ignore get_member_name2(tid_t); - %ignore sync_from_struc; +%ignore get_member_by_id(tid_t, struc_t **); // allow version w/ qstring* only +//------------------------------------------------------------------------- +// For 'get_member_by_id()' +%typemap(in,numinputs=0) qstring *out_mname (qstring temp) { + $1 = &temp; +} +%typemap(argout) qstring *out_mname { + if (result) + { + %append_output(PyString_FromStringAndSize($1->begin(), $1->length())); + } + else + { + Py_XDECREF(resultobj); + Py_INCREF(Py_None); + resultobj = Py_None; + } +} +%typemap(freearg) qstring* out_mname +{ + // Nothing. We certainly don't want 'temp' to be deleted. +} + +//------------------------------------------------------------------------- +// For 'get_member_by_fullname()' and 'get_member_by_id()' +%typemap(in,numinputs=0) struc_t **sptr_place (struc_t *temp) { + $1 = &temp; +} +%typemap(argout) struc_t **sptr_place { + if ( result ) + { + %append_output(SWIG_NewPointerObj(SWIG_as_voidptr($1), SWIGTYPE_p_struc_t, 0 | 0 )); + } + else + { + Py_XDECREF(resultobj); + Py_INCREF(Py_None); + resultobj = Py_None; + } +} + +//------------------------------------------------------------------------- %include "struct.hpp" // Add a get_member() member function to struc_t. // This helps to access the members array in the class. %extend struc_t { - member_t *get_member(int index) { return &(self->members[index]); } + member_t *get_member(int index) { return &(self->members[index]); } } +%inline %{ +// +// +%} diff --git a/swig/typeconv.i b/swig/typeconv.i index 679578f..a9d71bf 100644 --- a/swig/typeconv.i +++ b/swig/typeconv.i @@ -41,20 +41,48 @@ for (i =0; i < len; i++) { - PyObject *o = PySequence_GetItem($input,i); - if (!PyLong_Check(o)) + newref_t item(PySequence_GetItem($input,i)); + if (!PyLong_Check(item.o)) { - Py_XDECREF(o); PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers"); return NULL; } - temp[i] = PyLong_AsUnsignedLong(o); - Py_DECREF(o); + temp[i] = PyLong_AsUnsignedLong(item.o); } $1 = &temp[0]; } +//------------------------------------------------------------------------- +// Same, but with non-fixed sized arrays. +%typemap(in) (const tid_t *path, int plen) (qvector temp) { + if (!PySequence_Check($input)) + { + PyErr_SetString(PyExc_TypeError,"Expecting a sequence"); + return NULL; + } + int plen = PySequence_Length($input); + if ( plen <= 0 ) + { + PyErr_SetString(PyExc_TypeError, "Sequence must have at least 1 item"); + return NULL; + } + temp.resize(plen); + for ( int i =0; i < plen; ++i ) + { + newref_t item(PySequence_GetItem($input,i)); + if (!PyLong_Check(item.o)) + { + PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers"); + return NULL; + } + + temp[i] = PyLong_AsUnsignedLong(item.o); + } + $1 = temp.begin(); + $2 = int(temp.size()); +} + //--------------------------------------------------------------------- %define %cstring_output_maxstr_none(TYPEMAP, SIZE) @@ -174,6 +202,28 @@ } //--------------------------------------------------------------------- +// md5/sha256 hash retrieval +%typemap(in, numinputs=0) uchar hash[ANY] (uchar temp[$1_dim0]) +{ + $1 = temp; +} + +%typemap(argout) uchar hash[ANY] +{ + Py_XDECREF(resultobj); + if (result) + { + char buf[2*$1_dim0 + 1]; + get_hex_string(buf, sizeof(buf), $1, $1_dim0); + resultobj = PyString_FromString(buf); + } + else + { + Py_INCREF(Py_None); + resultobj = Py_None; + } +} + // Check that the argument is a callable Python object //--------------------------------------------------------------------- %typemap(in) PyObject *pyfunc { @@ -183,6 +233,24 @@ } $1 = $input; } +// Check that the argument is None or a callable Python object +//--------------------------------------------------------------------- +%typemap(in) PyObject *pyfunc_or_none { + if ($input != Py_None && !PyCallable_Check($input)) { + PyErr_SetString(PyExc_TypeError, "Expected None or a callable object"); + return NULL; + } + $1 = $input; +} +// Check that the argument is None or a tuple +//--------------------------------------------------------------------- +%typemap(in) PyObject *tuple_or_none { + if ($input != Py_None && !PyTuple_Check($input)) { + PyErr_SetString(PyExc_TypeError, "Expected None or a tuple"); + return NULL; + } + $1 = $input; +} %typemap(in) ea_t { uint64 $1_temp; @@ -198,6 +266,9 @@ // PyLong_FromUnsignedLong(unsigned int) call time. %typemap(out) ea_t "$result = PyLong_FromUnsignedLongLong($1);" +%typemap(in) qtime64_t "$1 = PyLong_AsUnsignedLongLong($input);" +%typemap(out) qtime64_t "$result = PyLong_FromUnsignedLongLong($1);" + //--------------------------------------------------------------------- // IN qstring //--------------------------------------------------------------------- @@ -238,14 +309,16 @@ }; #ifdef __EA64__ -%apply longlong *INOUT { sval_t *value }; -%apply ulonglong *INOUT { ea_t *addr }; -%apply ulonglong *INOUT { sel_t *sel }; +%apply longlong *INOUT { sval_t *value }; +%apply longlong *INOUT { adiff_t *disp }; +%apply ulonglong *INOUT { ea_t *addr }; +%apply ulonglong *INOUT { sel_t *sel }; %apply ulonglong *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection() #else -%apply int *INOUT { sval_t *value }; -%apply unsigned int *INOUT { ea_t *addr }; -%apply unsigned int *INOUT { sel_t *sel }; +%apply int *INOUT { sval_t *value }; +%apply int *INOUT { adiff_t *disp }; +%apply unsigned int *INOUT { ea_t *addr }; +%apply unsigned int *INOUT { sel_t *sel }; %apply unsigned int *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection() #endif diff --git a/swig/typeinf.i b/swig/typeinf.i index d13ce87..9fabf8b 100644 --- a/swig/typeinf.i +++ b/swig/typeinf.i @@ -112,6 +112,8 @@ %ignore get_default_align; %ignore align_size; %ignore align_size; +%ignore get_arg_align; +%ignore align_stkarg_up; %ignore get_default_enum_size; %ignore max_ptr_size; %ignore based_ptr_name_and_size; @@ -154,6 +156,8 @@ %ignore type_pair_vec_t::add_names; +%ignore callregs_t::findreg; + %ignore format_data_info_t; %ignore valinfo_t; %ignore print_c_data; @@ -174,6 +178,7 @@ %ignore func_type_data_t::serialize; %ignore func_type_data_t::deserialize; %ignore enum_type_data_t::get_enum_base_type; +%ignore enum_type_data_t::serialize_enum; %ignore enum_type_data_t::deserialize_enum; %ignore valstr_deprecated_t; %ignore valinfo_deprecated_t; @@ -187,80 +192,6 @@ %{ // -//------------------------------------------------------------------------- -// A set of tinfo_t & details objects that were created from IDAPython. -// This is necessary in order to clear all the "type details" that are -// associated, in the kernel, with the tinfo_t instances. -// -// Unfortunately the IDAPython plugin has to terminate _after_ the IDB is -// closed, but the "type details" must be cleared _before_ the IDB is closed. -static qvector py_tinfo_t_vec; -static qvector py_ptr_type_data_t_vec; -static qvector py_array_type_data_t_vec; -static qvector py_func_type_data_t_vec; -static qvector py_udt_type_data_t_vec; - -static void __clear(tinfo_t *inst) { inst->clear(); } -static void __clear(ptr_type_data_t *inst) { inst->obj_type.clear(); inst->closure.clear(); } -static void __clear(array_type_data_t *inst) { inst->elem_type.clear(); } -static void __clear(func_type_data_t *inst) { inst->clear(); inst->rettype.clear(); } -static void __clear(udt_type_data_t *inst) { inst->clear(); } - -void til_clear_python_tinfo_t_instances(void) -{ - // Pre-emptive strike: clear all the python-exposed tinfo_t - // (& related types) instances: if that were not done here, - // ~tinfo_t() calls happening as part of the python shutdown - // process will try and clear() their details. ..but the kernel's - // til-related functions will already have deleted those details - // at that point. - // - // NOTE: Don't clear() the arrays of pointers. All the python-exposed - // instances will be deleted through the python shutdown/ref-decrementing - // process anyway (which will cause til_deregister_..() calls), and the - // entries will be properly pulled out of the vector when that happens. -#define BATCH_CLEAR(Type) \ - do \ - { \ - for ( size_t i = 0, n = py_##Type##_vec.size(); i < n; ++i ) \ - __clear(py_##Type##_vec[i]); \ - } while ( false ) - - BATCH_CLEAR(tinfo_t); - BATCH_CLEAR(ptr_type_data_t); - BATCH_CLEAR(array_type_data_t); - BATCH_CLEAR(func_type_data_t); - BATCH_CLEAR(udt_type_data_t); -#undef BATCH_CLEAR -} - -#define DEF_REG_UNREG_REFCOUNTED(Type) \ - void til_register_python_##Type##_instance(Type *inst) \ - { \ - /* Let's add_unique() it, because in the case of tinfo_t, every reference*/ \ - /* to an object's tinfo_t property will end up trying to register it. */ \ - py_##Type##_vec.add_unique(inst); \ - } \ - \ - void til_deregister_python_##Type##_instance(Type *inst) \ - { \ - qvector::iterator found = py_##Type##_vec.find(inst); \ - if ( found != py_##Type##_vec.end() ) \ - { \ - __clear(inst); \ - /* tif->clear();*/ \ - py_##Type##_vec.erase(found); \ - } \ - } - -DEF_REG_UNREG_REFCOUNTED(tinfo_t); -DEF_REG_UNREG_REFCOUNTED(ptr_type_data_t); -DEF_REG_UNREG_REFCOUNTED(array_type_data_t); -DEF_REG_UNREG_REFCOUNTED(func_type_data_t); -DEF_REG_UNREG_REFCOUNTED(udt_type_data_t); - -#undef DEF_REG_UNREG_REFCOUNTED - // %} @@ -272,7 +203,6 @@ DEF_REG_UNREG_REFCOUNTED(udt_type_data_t); } } - %extend tinfo_t { bool deserialize( @@ -306,6 +236,12 @@ DEF_REG_UNREG_REFCOUNTED(udt_type_data_t); til_deregister_python_tinfo_t_instance($self); delete $self; } + + qstring __str__() const { + qstring qs; + $self->print(&qs); + return qs; + } } %ignore tinfo_t::~tinfo_t(void); @@ -337,14 +273,12 @@ DEF_REG_UNREG_REFCOUNTED(udt_type_data_t); %template(funcargvec_t) qvector; %template(udtmembervec_t) qvector; -%feature("director") text_sink_t; -%warnfilter(514) text_sink_t; // Director base class 'x' has no virtual destructor. - %include "typeinf.hpp" // Custom wrappers %rename (load_til) load_til_wrap; +%rename (load_til_header) load_til_header_wrap; %rename (get_type_size0) py_get_type_size0; %rename (idc_get_type_raw) py_idc_get_type_raw; %rename (idc_get_local_type_raw) py_idc_get_local_type_raw; @@ -354,694 +288,12 @@ DEF_REG_UNREG_REFCOUNTED(udt_type_data_t); %rename (pack_object_to_bv) py_pack_object_to_bv; %inline %{ // -//------------------------------------------------------------------------- -PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags) -{ - tinfo_t tif; - qstring name; - qtype fields, type; - bool ok = parse_decl2(ti, decl, &name, &tif, flags); - if ( ok ) - ok = tif.serialize(&type, &fields, NULL, SUDT_FAST); - - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return Py_BuildValue("(sss)", - name.c_str(), - (char *)type.c_str(), - (char *)fields.c_str()); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -/* -# -def calc_type_size(ti, tp): - """ - Returns the size of a type - @param ti: Type info. 'idaapi.cvar.idati' can be passed. - @param tp: type string - @return: - - None on failure - - The size of the type - """ - pass -# -*/ -PyObject *py_calc_type_size(const til_t *ti, PyObject *tp) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( PyString_Check(tp) ) - { - // To avoid release of 'data' during Py_BEGIN|END_ALLOW_THREADS section. - borref_t tpref(tp); - const type_t *data = (type_t *)PyString_AsString(tp); - size_t sz; - Py_BEGIN_ALLOW_THREADS; - tinfo_t tif; - tif.deserialize(ti, &data, NULL, NULL); - sz = tif.get_size(); - Py_END_ALLOW_THREADS; - if ( sz != BADSIZE ) - return PyInt_FromLong(sz); - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_ValueError, "String expected!"); - return NULL; - } -} - -//------------------------------------------------------------------------- -/* -# -def apply_type(ti, ea, tp_name, py_type, py_fields, flags) - """ - Apply the specified type to the address - @param ti: Type info library. 'idaapi.cvar.idati' can be used. - @param py_type: type string - @param py_fields: fields string (may be empty or None) - @param ea: the address of the object - @param flags: combination of TINFO_... constants or 0 - @return: Boolean - """ - pass -# -*/ -static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_t ea, int flags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) - { - PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); - return NULL; - } - const type_t *type = (const type_t *) PyString_AsString(py_type); - const p_list *fields = PyW_Fields(py_fields); - bool rc; - Py_BEGIN_ALLOW_THREADS; - struc_t *sptr; - member_t *mptr = get_member_by_id(ea, &sptr); - if ( type[0] == '\0' ) - { - if ( mptr != NULL ) - { - rc = mptr->has_ti(); - if ( rc ) - del_member_tinfo(sptr, mptr); - } - else - { - rc = has_ti(ea); - if ( rc ) - del_tinfo2(ea); - } - } - else - { - tinfo_t tif; - rc = tif.deserialize(ti, &type, &fields, NULL); - if ( rc ) - { - if ( mptr != NULL ) - rc = set_member_tinfo2(sptr, mptr, 0, tif, 0); - else - rc = apply_tinfo2(ea, tif, flags); - } - } - Py_END_ALLOW_THREADS; - return rc; -} - -//------------------------------------------------------------------------- -/* -# -def print_type(ea, one_line): - """ - Returns the type of an item - @return: - - None on failure - - The type string with a semicolon. Can be used directly with idc.SetType() - """ - pass -# -*/ -static PyObject *py_print_type(ea_t ea, bool one_line) -{ - char buf[64*MAXSTR]; - int flags = PRTYPE_SEMI | (one_line ? PRTYPE_1LINE : PRTYPE_MULTI); - bool ok = print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return PyString_FromString(buf); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -/* -# -def py_unpack_object_from_idb(ti, tp, fields, ea, pio_flags = 0): - """ - Unpacks from the database at 'ea' to an object. - Please refer to unpack_object_from_bv() - """ - pass -# -*/ -PyObject *py_unpack_object_from_idb( - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - ea_t ea, - int pio_flags = 0) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) - { - PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); - return NULL; - } - - // To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section. - borref_t py_type_ref(py_type); - borref_t py_fields_ref(py_fields); - - // Unpack - type_t *type = (type_t *) PyString_AsString(py_type); - const p_list *fields = PyW_Fields(py_fields); - idc_value_t idc_obj; - error_t err; - Py_BEGIN_ALLOW_THREADS; - err = unpack_object_from_idb( - &idc_obj, - ti, - type, - fields, - ea, - NULL, - pio_flags); - Py_END_ALLOW_THREADS; - - // Unpacking failed? - if ( err != eOk ) - return Py_BuildValue("(ii)", 0, err); - - // Convert - ref_t py_ret; - err = idcvar_to_pyvar(idc_obj, &py_ret); - - // Conversion failed? - if ( err != CIP_OK ) - return Py_BuildValue("(ii)", 0, err); - else - return Py_BuildValue("(iO)", 1, py_ret.o); -} - -//------------------------------------------------------------------------- -/* -# -def unpack_object_from_bv(ti, tp, fields, bytes, pio_flags = 0): - """ - Unpacks a buffer into an object. - Returns the error_t returned by idaapi.pack_object_to_idb - @param ti: Type info. 'idaapi.cvar.idati' can be passed. - @param tp: type string - @param fields: fields string (may be empty or None) - @param bytes: the bytes to unpack - @param pio_flags: flags used while unpacking - @return: - - tuple(0, err) on failure - - tuple(1, obj) on success - """ - pass -# -*/ -PyObject *py_unpack_object_from_bv( - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - PyObject *py_bytes, - int pio_flags = 0) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) || !PyString_Check(py_bytes) ) - { - PyErr_SetString(PyExc_ValueError, "Incorrect argument type!"); - return NULL; - } - - // To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section. - borref_t py_type_ref(py_type); - borref_t py_fields_ref(py_fields); - - // Get type strings - type_t *type = (type_t *) PyString_AsString(py_type); - const p_list *fields = PyW_Fields(py_fields); - - // Make a byte vector - bytevec_t bytes; - bytes.resize(PyString_Size(py_bytes)); - memcpy(bytes.begin(), PyString_AsString(py_bytes), bytes.size()); - - idc_value_t idc_obj; - error_t err; - Py_BEGIN_ALLOW_THREADS; - err = unpack_object_from_bv( - &idc_obj, - ti, - type, - fields, - bytes, - pio_flags); - Py_END_ALLOW_THREADS; - - // Unpacking failed? - if ( err != eOk ) - return Py_BuildValue("(ii)", 0, err); - - // Convert - ref_t py_ret; - err = idcvar_to_pyvar(idc_obj, &py_ret); - - // Conversion failed? - if ( err != CIP_OK ) - return Py_BuildValue("(ii)", 0, err); - - return Py_BuildValue("(iO)", 1, py_ret.o); -} - -//------------------------------------------------------------------------- -/* -# -def pack_object_to_idb(obj, ti, tp, fields, ea, pio_flags = 0): - """ - Write a typed object to the database. - Raises an exception if wrong parameters were passed or conversion fails - Returns the error_t returned by idaapi.pack_object_to_idb - @param ti: Type info. 'idaapi.cvar.idati' can be passed. - @param tp: type string - @param fields: fields string (may be empty or None) - @param ea: ea to be used while packing - @param pio_flags: flags used while unpacking - """ - pass -# -*/ -PyObject *py_pack_object_to_idb( - PyObject *py_obj, - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - ea_t ea, - int pio_flags = 0) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) - { - PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); - return NULL; - } - - // Convert Python object to IDC object - idc_value_t idc_obj; - borref_t py_obj_ref(py_obj); - if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) ) - return NULL; - - // To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section. - borref_t py_type_ref(py_type); - borref_t py_fields_ref(py_fields); - - // Get type strings - type_t *type = (type_t *)PyString_AsString(py_type); - const p_list *fields = PyW_Fields(py_fields); - - // Pack - // error_t err; - error_t err; - Py_BEGIN_ALLOW_THREADS; - err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags); - Py_END_ALLOW_THREADS; - return PyInt_FromLong(err); -} - -//------------------------------------------------------------------------- -/* -# -def pack_object_to_bv(obj, ti, tp, fields, base_ea, pio_flags = 0): - """ - Packs a typed object to a string - @param ti: Type info. 'idaapi.cvar.idati' can be passed. - @param tp: type string - @param fields: fields string (may be empty or None) - @param base_ea: base ea used to relocate the pointers in the packed object - @param pio_flags: flags used while unpacking - @return: - tuple(0, err_code) on failure - tuple(1, packed_buf) on success - """ - pass -# -*/ -// Returns a tuple(Boolean, PackedBuffer or Error Code) -PyObject *py_pack_object_to_bv( - PyObject *py_obj, - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - ea_t base_ea, - int pio_flags=0) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) - { - PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); - return NULL; - } - - // Convert Python object to IDC object - idc_value_t idc_obj; - borref_t py_obj_ref(py_obj); - if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) ) - return NULL; - - // To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section. - borref_t py_type_ref(py_type); - borref_t py_fields_ref(py_fields); - - // Get type strings - type_t *type = (type_t *)PyString_AsString(py_type); - const p_list *fields = PyW_Fields(py_fields); - - // Pack - relobj_t bytes; - error_t err; - Py_BEGIN_ALLOW_THREADS; - err = pack_object_to_bv( - &idc_obj, - ti, - type, - fields, - &bytes, - NULL, - pio_flags); - if ( err == eOk && !bytes.relocate(base_ea, inf.mf) ) - err = -1; - Py_END_ALLOW_THREADS; - if ( err == eOk ) - return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size()); - else - return Py_BuildValue("(ii)", 0, err); -} - -//------------------------------------------------------------------------- -/* Parse types from a string or file. See ParseTypes() in idc.py */ -int idc_parse_types(const char *input, int flags) -{ - int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT; - - if ((flags & 1) != 0) - hti |= HTI_FIL; - - return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti); -} - -//------------------------------------------------------------------------- -PyObject *py_idc_get_type_raw(ea_t ea) -{ - qtype type, fields; - bool ok = get_tinfo(ea, &type, &fields); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str()); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -PyObject *py_idc_get_local_type_raw(int ordinal) -{ - const type_t *type; - const p_list *fields; - bool ok = get_numbered_type(idati, ordinal, &type, &fields); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return Py_BuildValue("(ss)", (char *)type, (char *)fields); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -char *idc_guess_type(ea_t ea, char *buf, size_t bufsize) -{ - tinfo_t tif; - if ( guess_tinfo2(ea, &tif) ) - { - qstring out; - if ( tif.print(&out) ) - return qstrncpy(buf, out.begin(), bufsize); - } - return NULL; -} - -//------------------------------------------------------------------------- -char *idc_get_type(ea_t ea, char *buf, size_t bufsize) -{ - tinfo_t tif; - if ( get_tinfo2(ea, &tif) ) - { - qstring out; - if ( tif.print(&out) ) - { - qstrncpy(buf, out.c_str(), bufsize); - return buf; - } - } - return NULL; -} - -//------------------------------------------------------------------------- -int idc_set_local_type(int ordinal, const char *dcl, int flags) -{ - if (dcl == NULL || dcl[0] == '\0') - { - if ( !del_numbered_type(idati, ordinal) ) - return 0; - } - else - { - tinfo_t tif; - qstring name; - if ( !parse_decl2(idati, dcl, &name, &tif, flags) ) - return 0; - - if ( ordinal <= 0 ) - { - if ( !name.empty() ) - ordinal = get_type_ordinal(idati, name.begin()); - - if ( ordinal <= 0 ) - ordinal = alloc_type_ordinal(idati); - } - - if ( tif.set_numbered_type(idati, ordinal, 0, name.c_str()) != TERR_OK ) - return 0; - } - return ordinal; -} - -//------------------------------------------------------------------------- -int idc_get_local_type(int ordinal, int flags, char *buf, size_t maxsize) -{ - tinfo_t tif; - if ( !tif.get_numbered_type(idati, ordinal) ) - { - buf[0] = 0; - return false; - } - - qstring res; - const char *name = get_numbered_type_name(idati, ordinal); - if ( !tif.print(&res, name, flags, 2, 40) ) - { - buf[0] = 0; - return false; - } - - qstrncpy(buf, res.begin(), maxsize); - return true; -} - -//------------------------------------------------------------------------- -PyObject *idc_print_type(PyObject *py_type, PyObject *py_fields, const char *name, int flags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) - { - PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); - return NULL; - } - - // To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section. - borref_t py_type_ref(py_type); - borref_t py_fields_ref(py_fields); - - qstring res; - const type_t *type = (type_t *)PyString_AsString(py_type); - const p_list *fields = PyW_Fields(py_fields); - bool ok; - Py_BEGIN_ALLOW_THREADS; - tinfo_t tif; - ok = tif.deserialize(idati, &type, &fields, NULL) - && tif.print(&res, name, flags, 2, 40); - Py_END_ALLOW_THREADS; - if ( ok ) - return PyString_FromString(res.begin()); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize) -{ - const char *name = get_numbered_type_name(idati, ordinal); - if ( name == NULL ) - return false; - - qstrncpy(buf, name, bufsize); - return true; -} - -//------------------------------------------------------------------------- -/* -# -def get_named_type(til, name, ntf_flags): - """ - Get a type data by its name. - @param til: the type library - @param name: the type name - @param ntf_flags: a combination of NTF_* constants - @return: - None on failure - tuple(code, type_str, fields_str, cmt, field_cmts, sclass, value) on success - """ - pass -# -*/ -PyObject *py_get_named_type(const til_t *til, const char *name, int ntf_flags) -{ - const type_t *type = NULL; - const p_list *fields = NULL, *field_cmts = NULL; - const char *cmt = NULL; - sclass_t sclass = sc_unk; - uint32 value = 0; - int code = get_named_type(til, name, ntf_flags, &type, &fields, &cmt, &field_cmts, &sclass, &value); - if ( code == 0 ) - Py_RETURN_NONE; - PyObject *tuple = PyTuple_New(7); - int idx = 0; -#define ADD(Expr) PyTuple_SetItem(tuple, idx++, (Expr)) -#define ADD_OR_NONE(Cond, Expr) \ - do \ - { \ - if ( Cond ) \ - { \ - ADD(Expr); \ - } \ - else \ - { \ - Py_INCREF(Py_None); \ - ADD(Py_None); \ - } \ - } while ( false ) - - ADD(PyInt_FromLong(long(code))); - ADD(PyString_FromString((const char *) type)); - ADD_OR_NONE(fields != NULL, PyString_FromString((const char *) fields)); - ADD_OR_NONE(cmt != NULL, PyString_FromString(cmt)); - ADD_OR_NONE(field_cmts != NULL, PyString_FromString((const char *) field_cmts)); - ADD(PyInt_FromLong(long(sclass))); - ADD(PyLong_FromUnsignedLong(long(value))); -#undef ADD_OR_NONE -#undef ADD - return tuple; -} - -//------------------------------------------------------------------------- -PyObject *py_get_named_type64(const til_t *til, const char *name, int ntf_flags) -{ - return py_get_named_type(til, name, ntf_flags | NTF_64BIT); -} - -//------------------------------------------------------------------------- -int py_print_decls(text_sink_t &printer, til_t *til, PyObject *py_ordinals, uint32 flags) -{ - if ( !PyList_Check(py_ordinals) ) - { - PyErr_SetString(PyExc_ValueError, "'ordinals' must be a list"); - return 0; - } - - Py_ssize_t nords = PyList_Size(py_ordinals); - ordvec_t ordinals; - ordinals.reserve(size_t(nords)); - for ( Py_ssize_t i = 0; i < nords; ++i ) - { - borref_t item(PyList_GetItem(py_ordinals, i)); - if ( item == NULL - || (!PyInt_Check(item.o) && !PyLong_Check(item.o)) ) - { - qstring msg; - msg.sprnt("ordinals[%d] is not a valid value", int(i)); - PyErr_SetString(PyExc_ValueError, msg.begin()); - return 0; - } - uint32 ord = PyInt_Check(item.o) ? PyInt_AsLong(item.o) : PyLong_AsLong(item.o); - ordinals.push_back(ord); - } - return print_decls(printer, til, ordinals.empty() ? NULL : &ordinals, flags); -} - // -til_t *load_til(const char *tildir, const char *name) -{ - char errbuf[MAXSTR]; - til_t *res = load_til(tildir, name, errbuf, sizeof(errbuf)); - if ( res == NULL ) - PyErr_SetString(PyExc_RuntimeError, errbuf); - return res; -} -%} - -%rename (load_til_header) load_til_header_wrap; -%inline %{ -til_t *load_til_header_wrap(const char *tildir, const char *name) -{ - char errbuf[MAXSTR]; - til_t *res = load_til_header(tildir, name, errbuf, sizeof(errbuf));; - if ( res == NULL ) - PyErr_SetString(PyExc_RuntimeError, errbuf); - return res; -} %} %cstring_output_maxsize(char *buf, size_t maxsize); %pythoncode %{ # - -def get_type_size0(ti, tp): - """ - DEPRECATED. Please use calc_type_size instead - Returns the size of a type - @param ti: Type info. 'idaapi.cvar.idati' can be passed. - @param tp: type string - @return: - - None on failure - - The size of the type - """ - return calc_type_size(ti, tp) - # - %} diff --git a/swig/ua.i b/swig/ua.i index 0f4ef0d..b3c6915 100644 --- a/swig/ua.i +++ b/swig/ua.i @@ -46,1429 +46,15 @@ %inline %{ // - -//------------------------------------------------------------------------- -/* -# -def init_output_buffer(size = MAXSTR): - """ - This function initialize an output buffer with the given size. - It should be called before using any out_xxxx() functions. - @return: It returns a string. This string should then be passed to MakeLine(). - This function could return None if it failed to create a buffer with the given size. - """ - pass -# -*/ -PyObject *py_init_output_buffer(size_t size = MAXSTR) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Let Python allocate a writable string buffer for us - PyObject *py_str = PyString_FromStringAndSize(NULL, size); - if ( py_str == NULL ) - Py_RETURN_NONE; - - init_output_buffer(PyString_AsString(py_str), size); - return py_str; -} - -//------------------------------------------------------------------------- -/* -# -def term_output_buffer(): - """Use this function to terminate an output buffer.""" - pass -# -*/ -void py_term_output_buffer() -{ - term_output_buffer(); -} - -//------------------------------------------------------------------------- -/* -# -def decode_preceding_insn(ea): - """ - Decodes the preceding instruction. Please check ua.hpp / decode_preceding_insn() - @param ea: current ea - @return: tuple(preceeding_ea or BADADDR, farref = Boolean) - """ - pass -# -*/ -PyObject *py_decode_preceding_insn(ea_t ea) -{ - bool farref; - ea_t r = decode_preceding_insn(ea, &farref); - PYW_GIL_CHECK_LOCKED_SCOPE(); - return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0); -} - -//------------------------------------------------------------------------- -/* -# -def OutValue(op, outflags = 0): - """ - Output immediate value - @param op: operand (of type op_t) - @return: flags of the output value - -1: value is output with COLOR_ERROR - 0: value is output as a number or character or segment - """ - pass -# -*/ -flags_t py_OutValue(PyObject *x, int outflags=0) -{ - op_t *op = op_t_get_clink(x); - if ( op == NULL ) - return 0; - - return OutValue(*op, outflags); -} - -//------------------------------------------------------------------------- -/* -# -def get_stkvar(op, v): - """ - Get pointer to stack variable - @param op: reference to instruction operand - @param v: immediate value in the operand (usually op.addr) - @return: - - None on failure - - tuple(member_t, actval) - where actval: actual value used to fetch stack variable - """ - pass -# -*/ -PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - uint64 v; - if ( op == NULL || !PyW_GetNumber(py_v, &v) ) - Py_RETURN_NONE; - - sval_t actval; - member_t *member = get_stkvar(*op, sval_t(v), &actval); - if ( member == NULL ) - Py_RETURN_NONE; - - return Py_BuildValue("(O" PY_SFMT64 ")", - SWIG_NewPointerObj(SWIG_as_voidptr(member), SWIGTYPE_p_member_t, 0), - pyl_t(actval)); -} - -//------------------------------------------------------------------------- -/* -header: frame.hpp -# -def add_stkvar3(op, v, flags): - """ - Automatically add stack variable if doesn't exist - Processor modules should use ua_stkvar2() - @param op: reference to instruction operand - @param v: immediate value in the operand (usually op.addr) - @param flags: combination of STKVAR_... constants - @return: Boolean - """ - pass -# -*/ -bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - uint64 v; - return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true; -} - -//------------------------------------------------------------------------- -/* -header: typeinf.hpp -# -def apply_type_to_stkarg(op, v, type, name): - """ - Apply type information to a stack variable - - @param op: reference to instruction operand - @param v: immediate value in the operand (usually op.addr) - @param type: type string. Retrieve from idc.ParseType("type string", flags)[1] - @param name: stack variable name - - @return: Boolean - """ - pass -# -*/ -bool py_apply_type_to_stkarg( - PyObject *py_op, - PyObject *py_uv, - PyObject *py_type, - const char *name) -{ - uint64 v; - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type)) - { - return false; - } - else - { - const type_t *t = (type_t *) PyString_AsString(py_type); - tinfo_t tif; - tif.deserialize(idati, &t); - borref_t br(py_op); - bool rc; - Py_BEGIN_ALLOW_THREADS; - rc = apply_tinfo_to_stkarg(*op, uval_t(v), tif, name); - Py_END_ALLOW_THREADS; - return rc; - } -} - -//------------------------------------------------------------------------- -/* -# -def OutImmChar(op, outflags = 0): - """ - Output operand value as a commented character constant - @param op: operand (of type op_t) - @return: None - """ - pass -# -*/ -static void py_OutImmChar(PyObject *x) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(x); - if ( op != NULL ) - OutImmChar(*op); -} - -//------------------------------------------------------------------------- -/* -# -def ua_stkvar2(op, outflags = 0): - """ - Create or modify a stack variable in the function frame. - Please check ua.hpp / ua_stkvar2() - @param op: operand (of type op_t) - @return: None - """ - pass -# -*/ -static bool py_ua_stkvar2(PyObject *x, adiff_t v, int flags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(x); - return op == NULL ? false : ua_stkvar2(*op, v, flags); -} - -//------------------------------------------------------------------------- -/* -# -def ua_add_off_drefs(op, type): - """ - Add xrefs for offset operand of the current instruction - Please check ua.hpp / ua_add_off_drefs() - @param op: operand (of type op_t) - @return: None - """ - pass -# -*/ -ea_t py_ua_add_off_drefs(PyObject *py_op, dref_t type) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - return op == NULL ? BADADDR : ua_add_off_drefs(*op, type); -} - -//------------------------------------------------------------------------- -/* -# -def ua_add_off_drefs2(op, type, outf): - """ - Add xrefs for offset operand of the current instruction - Please check ua.hpp / ua_add_off_drefs2() - @return: ea_t - """ - pass -# -*/ -ea_t py_ua_add_off_drefs2(PyObject *py_op, dref_t type, int outf) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - return op == NULL ? BADADDR : ua_add_off_drefs2(*op, type, outf); -} - -//------------------------------------------------------------------------- -/* -# -def out_name_expr(op, ea, off): - """ - Output a name expression - @param op: operand (of type op_t) - @param ea: address of expression - @param off: the value of name expression. this parameter is used only to - check that the name expression will have the wanted value. - You may pass BADADDR for this parameter. - @return: true if the name expression has been produced - """ - pass -# -*/ -bool py_out_name_expr( - PyObject *py_op, - ea_t ea, - PyObject *py_off) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - uint64 v(0); - adiff_t off; - if ( PyW_GetNumber(py_off, &v) ) - off = adiff_t(v); - else - off = BADADDR; - - return op == NULL ? false : out_name_expr(*op, ea, off); -} - -//------------------------------------------------------------------------- -/* -# -def construct_macro(insn): - """ - See ua.hpp's construct_macro(). - """ - pass -# -*/ -bool py_construct_macro(bool enable, PyObject *build_macro) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( !PyCallable_Check(build_macro) ) - return false; - - static qstack macro_builders; - - macro_builders.push(newref_t(build_macro)); - struct ida_local lambda_t - { - static bool idaapi call_build_macro(insn_t &s, bool may_go_forward) - { - PyObject *py_builder = macro_builders.top().o; - newref_t pyres = PyObject_CallFunction( - py_builder, "O", - may_go_forward ? Py_True : Py_False); - PyW_ShowCbErr("build_macro"); - if ( pyres.o == NULL || pyres.o == Py_None ) - return false; - insn_t *_s = insn_t_get_clink(pyres.o); - if ( _s == NULL ) - return false; - s = *_s; - return true; - } - }; - bool res = construct_macro(enable, lambda_t::call_build_macro); - macro_builders.pop(); - return res; -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( i < 0 || i >= UA_MAXOP || !PyCObject_Check(py_insn_lnk) ) - Py_RETURN_NONE; - - // Extract C link - insn_t *insn = (insn_t *)PyCObject_AsVoidPtr(py_insn_lnk); - - // Return a link to the operand - return PyCObject_FromVoidPtr(&insn->Operands[i], NULL); -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_create() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(new insn_t(), NULL); -} - -//------------------------------------------------------------------------- -static PyObject *op_t_create() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(new op_t(), NULL); -} - -//------------------------------------------------------------------------- -static bool op_t_assign(PyObject *self, PyObject *other) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *lhs = op_t_get_clink(self); - op_t *rhs = op_t_get_clink(other); - if (lhs == NULL || rhs == NULL) - return false; - - *lhs = *rhs; - return true; -} - -//------------------------------------------------------------------------- -static bool insn_t_assign(PyObject *self, PyObject *other) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *lhs = insn_t_get_clink(self); - insn_t *rhs = insn_t_get_clink(other); - if (lhs == NULL || rhs == NULL) - return false; - - *lhs = *rhs; - return true; -} - -//------------------------------------------------------------------------- -static bool op_t_destroy(PyObject *py_obj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_obj) ) - return false; - - op_t *op = (op_t *)PyCObject_AsVoidPtr(py_obj); - delete op; - - return true; -} - -//------------------------------------------------------------------------- -static bool insn_t_destroy(PyObject *py_obj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_obj) ) - return false; - - delete (insn_t *)PyCObject_AsVoidPtr(py_obj); - return true; -} - -//------------------------------------------------------------------------- -// Returns a C link to the global 'cmd' variable -static PyObject *py_get_global_cmd_link() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(&::cmd, NULL); -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_is_canon_insn(int itype) -{ - bool ok = ph.is_canon_insn(itype); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_canon_feature(int itype) -{ - uint32 v = ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0; - PYW_GIL_CHECK_LOCKED_SCOPE(); - return Py_BuildValue("I", v); -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_canon_mnem(int itype) -{ - bool ok = ph.is_canon_insn(itype); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_cs(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->cs); -} - -static void insn_t_set_cs(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - - uint64 v(0); - PyW_GetNumber(value, &v); - link->cs = ea_t(v); -} - -static PyObject *insn_t_get_ip(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->ip); -} - -static void insn_t_set_ip(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->ip = ea_t(v); -} - -static PyObject *insn_t_get_ea(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->ea); -} - -static void insn_t_set_ea(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->ea = ea_t(v); -} - -static PyObject *insn_t_get_itype(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->itype); -} - -static void insn_t_set_itype(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->itype = (uint16)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_size(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->size); -} - -static void insn_t_set_size(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->size = (uint16)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_auxpref(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->auxpref); -} - -static void insn_t_set_auxpref(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->auxpref = (uint16)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_segpref(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->segpref); -} - -static void insn_t_set_segpref(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->segpref = (char)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_insnpref(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->insnpref); -} - -static void insn_t_set_insnpref(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->insnpref = (char)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_flags(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->flags); -} - -static void insn_t_set_flags(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->flags = (char)PyInt_AsLong(value); -} - -//------------------------------------------------------------------------- -static PyObject *op_t_get_n(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->n); -} - -static void op_t_set_n(PyObject *self, PyObject *value) -{ - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->n = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_type(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("B", link->type); -} - -static void op_t_set_type(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->type = (optype_t)PyInt_AsLong(value); -} - -static PyObject *op_t_get_offb(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->offb); -} - -static void op_t_set_offb(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->offb = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_offo(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->offo); -} - -static void op_t_set_offo(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->offo = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_flags(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("B", link->flags); -} - -static void op_t_set_flags(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->flags = (uchar)PyInt_AsLong(value); -} - -static PyObject *op_t_get_dtyp(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->dtyp); -} - -static void op_t_set_dtyp(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->dtyp = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_reg_phrase(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->reg); -} -static void op_t_set_reg_phrase(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->reg = (uint16)PyInt_AsLong(value); -} - -static PyObject *op_t_get_value(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->value); -} - -static void op_t_set_value(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->value = uval_t(v); -} - -static PyObject *op_t_get_addr(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->addr); -} - -static void op_t_set_addr(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->addr = ea_t(v); -} - -static PyObject *op_t_get_specval(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->specval); -} - -static void op_t_set_specval(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->specval = ea_t(v); -} - -static PyObject *op_t_get_specflag1(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag1); -} - -static void op_t_set_specflag1(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag1 = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_specflag2(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag2); -} - -static void op_t_set_specflag2(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag2 = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_specflag3(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag3); -} - -static void op_t_set_specflag3(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag3 = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_specflag4(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag4); -} - -static void op_t_set_specflag4(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag4 = (char)PyInt_AsLong(value); -} - // %} %{ // -//------------------------------------------------------------------------- -insn_t *insn_t_get_clink(PyObject *self) -{ - return (insn_t *)pyobj_get_clink(self); -} - -//------------------------------------------------------------------------- -op_t *op_t_get_clink(PyObject *self) -{ - return (op_t *)pyobj_get_clink(self); -} // %} %pythoncode %{ # - -# ----------------------------------------------------------------------- -class op_t(py_clinked_object_t): - """Class representing operands""" - def __init__(self, lnk = None): - py_clinked_object_t.__init__(self, lnk) - - def _create_clink(self): - return _idaapi.op_t_create() - - def _del_clink(self, lnk): - return _idaapi.op_t_destroy(lnk) - - def assign(self, other): - """Copies the contents of 'other' to 'self'""" - return _idaapi.op_t_assign(self, other) - - def __eq__(self, other): - """Checks if two register operands are equal by checking the register number and its dtype""" - return (self.reg == other.reg) and (self.dtyp == other.dtyp) - - def is_reg(self, r): - """Checks if the register operand is the given processor register""" - return self.type == o_reg and self.reg == r - - def has_reg(self, r): - """Checks if the operand accesses the given processor register""" - return self.reg == r.reg - - # - # Autogenerated - # - def __get_n__(self): - return _idaapi.op_t_get_n(self) - def __set_n__(self, v): - _idaapi.op_t_set_n(self, v) - def __get_type__(self): - return _idaapi.op_t_get_type(self) - def __set_type__(self, v): - _idaapi.op_t_set_type(self, v) - def __get_offb__(self): - return _idaapi.op_t_get_offb(self) - def __set_offb__(self, v): - _idaapi.op_t_set_offb(self, v) - def __get_offo__(self): - return _idaapi.op_t_get_offo(self) - def __set_offo__(self, v): - _idaapi.op_t_set_offo(self, v) - def __get_flags__(self): - return _idaapi.op_t_get_flags(self) - def __set_flags__(self, v): - _idaapi.op_t_set_flags(self, v) - def __get_dtyp__(self): - return _idaapi.op_t_get_dtyp(self) - def __set_dtyp__(self, v): - _idaapi.op_t_set_dtyp(self, v) - def __get_reg_phrase__(self): - return _idaapi.op_t_get_reg_phrase(self) - def __set_reg_phrase__(self, v): - _idaapi.op_t_set_reg_phrase(self, v) - def __get_value__(self): - return _idaapi.op_t_get_value(self) - def __set_value__(self, v): - _idaapi.op_t_set_value(self, v) - def __get_addr__(self): - return _idaapi.op_t_get_addr(self) - def __set_addr__(self, v): - _idaapi.op_t_set_addr(self, v) - def __get_specval__(self): - return _idaapi.op_t_get_specval(self) - def __set_specval__(self, v): - _idaapi.op_t_set_specval(self, v) - def __get_specflag1__(self): - return _idaapi.op_t_get_specflag1(self) - def __set_specflag1__(self, v): - _idaapi.op_t_set_specflag1(self, v) - def __get_specflag2__(self): - return _idaapi.op_t_get_specflag2(self) - def __set_specflag2__(self, v): - _idaapi.op_t_set_specflag2(self, v) - def __get_specflag3__(self): - return _idaapi.op_t_get_specflag3(self) - def __set_specflag3__(self, v): - _idaapi.op_t_set_specflag3(self, v) - def __get_specflag4__(self): - return _idaapi.op_t_get_specflag4(self) - def __set_specflag4__(self, v): - _idaapi.op_t_set_specflag4(self, v) - - n = property(__get_n__, __set_n__) - type = property(__get_type__, __set_type__) - offb = property(__get_offb__, __set_offb__) - offo = property(__get_offo__, __set_offo__) - flags = property(__get_flags__, __set_flags__) - dtyp = property(__get_dtyp__, __set_dtyp__) - reg = property(__get_reg_phrase__, __set_reg_phrase__) - phrase = property(__get_reg_phrase__, __set_reg_phrase__) - value = property(__get_value__, __set_value__) - addr = property(__get_addr__, __set_addr__) - specval = property(__get_specval__, __set_specval__) - specflag1 = property(__get_specflag1__, __set_specflag1__) - specflag2 = property(__get_specflag2__, __set_specflag2__) - specflag3 = property(__get_specflag3__, __set_specflag3__) - specflag4 = property(__get_specflag4__, __set_specflag4__) - -# ----------------------------------------------------------------------- -class insn_t(py_clinked_object_t): - """Class representing instructions""" - def __init__(self, lnk = None): - py_clinked_object_t.__init__(self, lnk) - - # Create linked operands - self.Operands = [] - for i in xrange(0, UA_MAXOP): - self.Operands.append(op_t(insn_t_get_op_link(self.clink, i))) - - # Convenience operand reference objects - self.Op1 = self.Operands[0] - self.Op2 = self.Operands[1] - self.Op3 = self.Operands[2] - self.Op4 = self.Operands[3] - self.Op5 = self.Operands[4] - self.Op6 = self.Operands[5] - - def assign(self, other): - """Copies the contents of 'other' to 'self'""" - return _idaapi.insn_t_assign(self, other) - -# -# def copy(self): -# """Returns a new copy of this class""" -# pass -# - - def _create_clink(self): - return _idaapi.insn_t_create() - - - def _del_clink(self, lnk): - return _idaapi.insn_t_destroy(lnk) - - - def __iter__(self): - return (self.Operands[idx] for idx in xrange(0, UA_MAXOP)) - - - def __getitem__(self, idx): - """ - Operands can be accessed directly as indexes - @return op_t: Returns an operand of type op_t - """ - if idx >= UA_MAXOP: - raise KeyError - else: - return self.Operands[idx] - - def is_macro(self): - return self.flags & INSN_MACRO != 0 - - def is_canon_insn(self): - return _idaapi.insn_t_is_canon_insn(self.itype) - - def get_canon_feature(self): - return _idaapi.insn_t_get_canon_feature(self.itype) - - def get_canon_mnem(self): - return _idaapi.insn_t_get_canon_mnem(self.itype) - - # - # Autogenerated - # - def __get_cs__(self): - return _idaapi.insn_t_get_cs(self) - def __set_cs__(self, v): - _idaapi.insn_t_set_cs(self, v) - def __get_ip__(self): - return _idaapi.insn_t_get_ip(self) - def __set_ip__(self, v): - _idaapi.insn_t_set_ip(self, v) - def __get_ea__(self): - return _idaapi.insn_t_get_ea(self) - def __set_ea__(self, v): - _idaapi.insn_t_set_ea(self, v) - def __get_itype__(self): - return _idaapi.insn_t_get_itype(self) - def __set_itype__(self, v): - _idaapi.insn_t_set_itype(self, v) - def __get_size__(self): - return _idaapi.insn_t_get_size(self) - def __set_size__(self, v): - _idaapi.insn_t_set_size(self, v) - def __get_auxpref__(self): - return _idaapi.insn_t_get_auxpref(self) - def __set_auxpref__(self, v): - _idaapi.insn_t_set_auxpref(self, v) - def __get_segpref__(self): - return _idaapi.insn_t_get_segpref(self) - def __set_segpref__(self, v): - _idaapi.insn_t_set_segpref(self, v) - def __get_insnpref__(self): - return _idaapi.insn_t_get_insnpref(self) - def __set_insnpref__(self, v): - _idaapi.insn_t_set_insnpref(self, v) - def __get_flags__(self): - return _idaapi.insn_t_get_flags(self) - def __set_flags__(self, v): - _idaapi.insn_t_set_flags(self, v) - - cs = property(__get_cs__, __set_cs__) - ip = property(__get_ip__, __set_ip__) - ea = property(__get_ea__, __set_ea__) - itype = property(__get_itype__, __set_itype__) - size = property(__get_size__, __set_size__) - auxpref = property(__get_auxpref__, __set_auxpref__) - segpref = property(__get_segpref__, __set_segpref__) - insnpref = property(__get_insnpref__, __set_insnpref__) - flags = property(__get_flags__, __set_flags__) - - -#---------------------------------------------------------------------------- -# P R O C E S S O R M O D U L E S C O N S T A N T S -#---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------- -# processor_t related constants - -CUSTOM_CMD_ITYPE = 0x8000 -REG_SPOIL = 0x80000000 - -REAL_ERROR_FORMAT = -1 # not supported format for current .idp -REAL_ERROR_RANGE = -2 # number too big (small) for store (mem NOT modifyed) -REAL_ERROR_BADDATA = -3 # illegal real data for load (IEEE data not filled) - -# -# Check whether the operand is relative to stack pointer or frame pointer. -# This function is used to determine how to output a stack variable -# This function may be absent. If it is absent, then all operands -# are sp based by default. -# Define this function only if some stack references use frame pointer -# instead of stack pointer. -# returns flags: -OP_FP_BASED = 0x00000000 # operand is FP based -OP_SP_BASED = 0x00000001 # operand is SP based -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 - -# -# processor_t.flag -# -PR_SEGS = 0x000001 # has segment registers? -PR_USE32 = 0x000002 # supports 32-bit addressing? -PR_DEFSEG32 = 0x000004 # segments are 32-bit by default -PR_RNAMESOK = 0x000008 # allow to user register names for location names -PR_ADJSEGS = 0x000020 # IDA may adjust segments moving their starting/ending addresses. -PR_DEFNUM = 0x0000C0 # default number representation: -PRN_HEX = 0x000000 # hex -PRN_OCT = 0x000040 # octal -PRN_DEC = 0x000080 # decimal -PRN_BIN = 0x0000C0 # binary -PR_WORD_INS = 0x000100 # instruction codes are grouped 2bytes in binrary line prefix -PR_NOCHANGE = 0x000200 # The user can't change segments and code/data attributes (display only) -PR_ASSEMBLE = 0x000400 # Module has a built-in assembler and understands IDP_ASSEMBLE -PR_ALIGN = 0x000800 # All data items should be aligned properly -PR_TYPEINFO = 0x001000 # the processor module supports - # type information callbacks - # ALL OF THEM SHOULD BE IMPLEMENTED! - # (the ones >= decorate_name) -PR_USE64 = 0x002000 # supports 64-bit addressing? -PR_SGROTHER = 0x004000 # the segment registers don't contain - # the segment selectors, something else -PR_STACK_UP = 0x008000 # the stack grows up -PR_BINMEM = 0x010000 # the processor module provides correct - # segmentation for binary files - # (i.e. it creates additional segments) - # The kernel will not ask the user - # to specify the RAM/ROM sizes -PR_SEGTRANS = 0x020000 # the processor module supports - # the segment translation feature - # (it means it calculates the code - # addresses using the codeSeg() function) -PR_CHK_XREF = 0x040000 # don't allow near xrefs between segments - # with different bases -PR_NO_SEGMOVE = 0x080000 # the processor module doesn't support move_segm() - # (i.e. the user can't move segments) -PR_FULL_HIFXP = 0x100000 # REF_VHIGH operand value contains full operand - # not only the high bits. Meaningful if ph.high_fixup_bits -PR_USE_ARG_TYPES = 0x200000 # use ph.use_arg_types callback -PR_SCALE_STKVARS = 0x400000 # use ph.get_stkvar_scale callback -PR_DELAYED = 0x800000 # has delayed jumps and calls -PR_ALIGN_INSN = 0x1000000 # allow ida to create alignment instructions - # arbirtrarily. Since these instructions - # might lead to other wrong instructions - # and spoil the listing, IDA does not create - # them by default anymore -PR_PURGING = 0x2000000 # there are calling conventions which may - # purge bytes from the stack -PR_CNDINSNS = 0x4000000 # has conditional instructions -PR_USE_TBYTE = 0x8000000 # BTMT_SPECFLT means _TBYTE type -PR_DEFSEG64 = 0x10000000 # segments are 64-bit by default - - -# ---------------------------------------------------------------------- -# -# Misc constants -# -UA_MAXOP = 6 -"""The maximum number of operands in the insn_t structure""" - -# Create 'cmd' into the global scope -cmd = insn_t(_idaapi.py_get_global_cmd_link()) -"""cmd is a global variable of type insn_t. It is contains information about the last decoded instruction. -This variable is also filled by processor modules when they decode instructions.""" - -# ---------------------------------------------------------------------- -# instruc_t related constants - -# -# instruc_t.feature -# -CF_STOP = 0x00001 # Instruction doesn't pass execution to the next instruction -CF_CALL = 0x00002 # CALL instruction (should make a procedure here) -CF_CHG1 = 0x00004 # The instruction modifies the first operand -CF_CHG2 = 0x00008 # The instruction modifies the second operand -CF_CHG3 = 0x00010 # The instruction modifies the third operand -CF_CHG4 = 0x00020 # The instruction modifies 4 operand -CF_CHG5 = 0x00040 # The instruction modifies 5 operand -CF_CHG6 = 0x00080 # The instruction modifies 6 operand -CF_USE1 = 0x00100 # The instruction uses value of the first operand -CF_USE2 = 0x00200 # The instruction uses value of the second operand -CF_USE3 = 0x00400 # The instruction uses value of the third operand -CF_USE4 = 0x00800 # The instruction uses value of the 4 operand -CF_USE5 = 0x01000 # The instruction uses value of the 5 operand -CF_USE6 = 0x02000 # The instruction uses value of the 6 operand -CF_JUMP = 0x04000 # The instruction passes execution using indirect jump or call (thus needs additional analysis) -CF_SHFT = 0x08000 # Bit-shift instruction (shl,shr...) -CF_HLL = 0x10000 # Instruction may be present in a high level language function. - -# ---------------------------------------------------------------------- -# op_t related constants - -# -# op_t.type -# Description Data field -o_void = 0 # No Operand ---------- -o_reg = 1 # General Register (al,ax,es,ds...) reg -o_mem = 2 # Direct Memory Reference (DATA) addr -o_phrase = 3 # Memory Ref [Base Reg + Index Reg] phrase -o_displ = 4 # Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr -o_imm = 5 # Immediate Value value -o_far = 6 # Immediate Far Address (CODE) addr -o_near = 7 # Immediate Near Address (CODE) addr -o_idpspec0 = 8 # Processor specific type -o_idpspec1 = 9 # Processor specific type -o_idpspec2 = 10 # Processor specific type -o_idpspec3 = 11 # Processor specific type -o_idpspec4 = 12 # Processor specific type -o_idpspec5 = 13 # Processor specific type - # There can be more processor specific types - -# -# op_t.dtyp -# -dt_byte = 0 # 8 bit -dt_word = 1 # 16 bit -dt_dword = 2 # 32 bit -dt_float = 3 # 4 byte -dt_double = 4 # 8 byte -dt_tbyte = 5 # variable size (ph.tbyte_size) -dt_packreal = 6 # packed real format for mc68040 -dt_qword = 7 # 64 bit -dt_byte16 = 8 # 128 bit -dt_code = 9 # ptr to code (not used?) -dt_void = 10 # none -dt_fword = 11 # 48 bit -dt_bitfild = 12 # bit field (mc680x0) -dt_string = 13 # pointer to asciiz string -dt_unicode = 14 # pointer to unicode string -dt_3byte = 15 # 3-byte data -dt_ldbl = 16 # long double (which may be different from tbyte) -dt_byte32 = 17 # 256 bit -dt_byte64 = 18 # 512 bit - -# -# op_t.flags -# -OF_NO_BASE_DISP = 0x80 # o_displ: base displacement doesn't exist meaningful only for o_displ type if set, base displacement (x.addr) doesn't exist. -OF_OUTER_DISP = 0x40 # o_displ: outer displacement exists meaningful only for o_displ type if set, outer displacement (x.value) exists. -PACK_FORM_DEF = 0x20 # !o_reg + dt_packreal: packed factor defined -OF_NUMBER = 0x10 # can be output as number only if set, the operand can be converted to a number only -OF_SHOW = 0x08 # should the operand be displayed? if clear, the operand is hidden and should not be displayed - -# -# insn_t.flags -# -INSN_MACRO = 0x01 # macro instruction -INSN_MODMAC = 0x02 # macros: may modify the database to make room for the macro insn - -# -# Set IDP options constants -# -IDPOPT_STR = 1 # string constant -IDPOPT_NUM = 2 # number -IDPOPT_BIT = 3 # bit, yes/no -IDPOPT_FLT = 4 # float -IDPOPT_I64 = 5 # 64bit number - -IDPOPT_OK = 0 # ok -IDPOPT_BADKEY = 1 # illegal keyword -IDPOPT_BADTYPE = 2 # illegal type of value -IDPOPT_BADVALUE = 3 # illegal value (bad range, for example) - -# ---------------------------------------------------------------------- -class processor_t(pyidc_opaque_object_t): - """Base class for all processor module scripts""" - def __init__(self): - # Take a reference to 'cmd' - self.cmd = cmd - - def get_idpdesc(self): - """ - This function must be present and should return the list of - short processor names similar to the one in ph.psnames. - This method can be overridden to return to the kernel a different IDP description. - """ - return '\x01'.join(map(lambda t: '\x01'.join(t), zip(self.plnames, self.psnames))) - - def get_uFlag(self): - """Use this utility function to retrieve the 'uFlag' global variable""" - return _idaapi.cvar.uFlag - - def get_auxpref(self): - """This function returns cmd.auxpref value""" - return self.cmd.auxpref - - -# ---------------------------------------------------------------------- -class __ph(object): - id = property(lambda self: ph_get_id()) - cnbits = property(lambda self: ph_get_cnbits()) - dnbits = property(lambda self: ph_get_dnbits()) - flag = property(lambda self: ph_get_flag()) - high_fixup_bits = property(lambda self: ph_get_high_fixup_bits()) - icode_return = property(lambda self: ph_get_icode_return()) - instruc = property(lambda self: ph_get_instruc()) - instruc_end = property(lambda self: ph_get_instruc_end()) - instruc_start = property(lambda self: ph_get_instruc_start()) - regCodeSreg = property(lambda self: ph_get_regCodeSreg()) - regDataSreg = property(lambda self: ph_get_regDataSreg()) - regFirstSreg = property(lambda self: ph_get_regFirstSreg()) - regLastSreg = property(lambda self: ph_get_regLastSreg()) - regnames = property(lambda self: ph_get_regnames()) - segreg_size = property(lambda self: ph_get_segreg_size()) - tbyte_size = property(lambda self: ph_get_tbyte_size()) - version = property(lambda self: ph_get_version()) - -ph = __ph() - # %} diff --git a/swig/view.i b/swig/view.i index 6dddf83..7ea2f11 100644 --- a/swig/view.i +++ b/swig/view.i @@ -1,1221 +1,16 @@ %{ -// - -//------------------------------------------------------------------------- -class py_customidamemo_t; -class lookup_info_t -{ -public: - struct entry_t - { - entry_t() : form(NULL), view(NULL), py_view(NULL) {} - private: - TForm *form; - TCustomControl *view; - py_customidamemo_t *py_view; - friend class lookup_info_t; - }; - - entry_t &new_entry(py_customidamemo_t *py_view) - { - QASSERT(30454, py_view != NULL && !find_by_py_view(NULL, NULL, py_view)); - entry_t &e = entries.push_back(); - e.py_view = py_view; - return e; - } - - void commit(entry_t &e, TForm *form, TCustomControl *view) - { - QASSERT(30455, &e >= entries.begin() && &e < entries.end()); - QASSERT(30456, form != NULL && view != NULL && e.py_view != NULL - && !find_by_form(NULL, NULL, form) - && !find_by_view(NULL, NULL, view) - && find_by_py_view(NULL, NULL, e.py_view)); - e.form = form; - e.view = view; - } - -#define FIND_BY__BODY(crit, res1, res2) \ - { \ - for ( entries_t::const_iterator it = entries.begin(); it != entries.end(); ++it ) \ - { \ - const entry_t &e = *it; \ - if ( e.crit == crit ) \ - { \ - if ( out_##res1 != NULL ) \ - *out_##res1 = e.res1; \ - if ( out_##res2 != NULL ) \ - *out_##res2 = e.res2; \ - return true; \ - } \ - } \ - return false; \ - } - bool find_by_form(TCustomControl **out_view, py_customidamemo_t **out_py_view, const TForm *form) const FIND_BY__BODY(form, view, py_view); - bool find_by_view(TForm **out_form, py_customidamemo_t **out_py_view, const TCustomControl *view) const FIND_BY__BODY(view, form, py_view); - bool find_by_py_view(TForm **out_form, TCustomControl **out_view, const py_customidamemo_t *py_view) const FIND_BY__BODY(py_view, view, form); -#undef FIND_BY__BODY - - bool del_by_py_view(const py_customidamemo_t *py_view) - { - for ( entries_t::iterator it = entries.begin(); it != entries.end(); ++it ) - { - if ( it->py_view == py_view ) - { - entries.erase(it); - return true; - } - } - return false; - } - -private: - typedef qvector entries_t; - entries_t entries; -}; - -//------------------------------------------------------------------------- -template -T *view_extract_this(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - ref_t py_this(PyW_TryGetAttrString(self, S_M_THIS)); - if ( py_this == NULL || !PyCObject_Check(py_this.o) ) - return NULL; - return (T*) PyCObject_AsVoidPtr(py_this.o); -} - -//------------------------------------------------------------------------- -class py_customidamemo_t -{ - void convert_node_info( - node_info_t *out, - uint32 *out_flags, - ref_t py_nodeinfo) - { - if ( out_flags != NULL ) - *out_flags = 0; -#define COPY_PROP(checker, converter, pname, flag) \ - do \ - { \ - newref_t pname(PyObject_GetAttrString(py_nodeinfo.o, #pname)); \ - if ( pname != NULL && checker(pname.o) ) \ - { \ - out->pname = converter(pname.o); \ - if ( out_flags != NULL ) \ - *out_flags |= flag; \ - } \ - } while ( false ) -#define COPY_ULONG_PROP(pname, flag) COPY_PROP(PyNumber_Check, PyLong_AsUnsignedLong, pname, flag) -#define COPY_STRING_PROP(pname, flag) COPY_PROP(PyString_Check, PyString_AsString, pname, flag) - COPY_ULONG_PROP(bg_color, NIF_BG_COLOR); - COPY_ULONG_PROP(frame_color, NIF_FRAME_COLOR); - COPY_ULONG_PROP(ea, NIF_EA); - COPY_STRING_PROP(text, NIF_TEXT); -#undef COPY_STRING_PROP -#undef COPY_ULONG_PROP -#undef COPY_PROP - } - - enum - { - GRBASE_HAVE_VIEW_ACTIVATED = 0x001, - GRBASE_HAVE_VIEW_DEACTIVATED = 0x002, - GRBASE_HAVE_KEYDOWN = 0x004, - GRBASE_HAVE_POPUP = 0x008, - GRBASE_HAVE_VIEW_CLICK = 0x010, - GRBASE_HAVE_VIEW_DBLCLICK = 0x020, - GRBASE_HAVE_VIEW_CURPOS = 0x040, - GRBASE_HAVE_CLOSE = 0x080, - GRBASE_HAVE_VIEW_SWITCHED = 0x100, - GRBASE_HAVE_VIEW_MOUSE_OVER = 0x200, - GRBASE_HAVE_VIEW_MOUSE_MOVED = 0x400, - }; - - static void ensure_view_callbacks_installed(); - int cb_flags; - // number of arguments for: - int ovc_num_args; // OnViewClick implementation - int ovdc_num_args; // OnViewDblclick implementation - int ovmo_num_args; // OnViewMouseOver implementation - int ovmm_num_args; // OnViewMouseMoved implementation - -protected: - ref_t self; - TCustomControl *view; - // This is called after having modified the - // node properties in the IDB. In case an - // implementation is performing some caching, - // this is a chance to update that cache. - // If 'ni' is NULL, then the node info was deleted. - virtual void node_info_modified( - int /*n*/, - const node_info_t * /*ni*/, - uint32 /*flags*/) {} - - struct callback_id_t - { - qstring name; - int have; - }; - struct callbacks_ids_t : public qvector - { - void add(const char *_n, int _h) - { - callback_id_t &o = push_back(); - o.name = _n; - o.have = _h; - } - }; - callbacks_ids_t cbids; - - bool collect_pyobject_callbacks(PyObject *self); - virtual void collect_class_callbacks_ids(callbacks_ids_t *out); - - void install_custom_viewer_handlers(); - - // Bi-directionally bind/unbind the Python object and this controller. - bool bind(PyObject *_self, TCustomControl *view); - void unbind(bool clear_view); - - static lookup_info_t lookup_info; - friend TForm *pycim_get_tform(PyObject *self); - friend TCustomControl *pycim_get_tcustom_control(PyObject *self); - -public: - py_customidamemo_t(); - virtual ~py_customidamemo_t(); - virtual void refresh() - { - refresh_viewer(view); - } - void set_node_info(PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags); - void set_nodes_infos(PyObject *dict); - PyObject *get_node_info(PyObject *py_node_idx); - void del_nodes_infos(PyObject *py_nodes); - PyObject *get_current_renderer_type(); - void set_current_renderer_type(PyObject *py_rto); - PyObject *create_groups(PyObject *groups_infos); - PyObject *delete_groups(PyObject *groups, PyObject *new_current); - PyObject *set_groups_visibility(PyObject *groups, PyObject *expand, PyObject *new_current); - - // View events - void on_view_activated(); - void on_view_deactivated(); - void on_view_keydown(int key, int state); - void on_view_popup(); - void on_view_click(const view_mouse_event_t *event); - void on_view_dblclick(const view_mouse_event_t *event); - void on_view_curpos(); - void on_view_close(); - void on_view_switched(tcc_renderer_type_t rt); - void on_view_mouse_over(const view_mouse_event_t *event); - void on_view_mouse_moved(const view_mouse_event_t *event); - inline bool has_callback(int flag) { return (cb_flags & flag) != 0; } - 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( - TCustomControl *cv, - int shift, - view_mouse_event_t *e, - void *ud); -}; - -//------------------------------------------------------------------------- -py_customidamemo_t::py_customidamemo_t() - : self(newref_t(NULL)), - view(NULL) -{ - PYGLOG("%p: py_customidamemo_t()\n", this); - ensure_view_callbacks_installed(); - ovc_num_args = -1; - ovdc_num_args = -1; - ovmo_num_args = -1; - ovmm_num_args = -1; -} - -//------------------------------------------------------------------------- -py_customidamemo_t::~py_customidamemo_t() -{ - PYGLOG("%p: ~py_customidamemo_t()\n", this); - unbind(true); - lookup_info.del_by_py_view(this); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::ensure_view_callbacks_installed() -{ - static bool installed = false; - if ( !installed ) - { - struct ida_local lambda_t - { - static int idaapi callback(void * /*ud*/, int code, va_list va) - { - py_customidamemo_t *py_view; - if ( lookup_info.find_by_view(NULL, &py_view, va_arg(va, TCustomControl *)) ) - { - PYW_GIL_GET; - switch ( code ) - { - case view_activated: - py_view->on_view_activated(); - break; - case view_deactivated: - py_view->on_view_deactivated(); - break; - case view_keydown: - { - int key = va_arg(va, int); - int state = va_arg(va, int); - py_view->on_view_keydown(key, state); - } - break; - case obsolete_view_popup: - py_view->on_view_popup(); - break; - case view_click: - case view_dblclick: - { - const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*); - if ( code == view_click ) - py_view->on_view_click(event); - else - py_view->on_view_dblclick(event); - } - break; - case view_curpos: - py_view->on_view_curpos(); - break; - case view_close: - py_view->on_view_close(); - delete py_view; - break; - case view_switched: - { - tcc_renderer_type_t rt = (tcc_renderer_type_t) va_arg(va, int); - py_view->on_view_switched(rt); - } - break; - case view_mouse_over: - { - const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*); - py_view->on_view_mouse_over(event); - } - break; - } - } - return 0; - } - }; - hook_to_notification_point(HT_VIEW, lambda_t::callback, NULL); - installed = true; - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::set_node_info( - PyObject *py_node_idx, - PyObject *py_node_info, - PyObject *py_flags) -{ - if ( !PyNumber_Check(py_node_idx) || !PyNumber_Check(py_flags) ) - return; - borref_t py_idx(py_node_idx); - borref_t py_ni(py_node_info); - borref_t py_fl(py_flags); - node_info_t ni; - convert_node_info(&ni, NULL, py_ni); - int idx = PyInt_AsLong(py_idx.o); - uint32 flgs = PyLong_AsLong(py_fl.o); - viewer_set_node_info(view, idx, ni, flgs); - node_info_modified(idx, &ni, flgs); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::set_nodes_infos(PyObject *dict) -{ - if ( !PyDict_Check(dict) ) - return; - Py_ssize_t pos = 0; - PyObject *o_key, *o_value; - while ( PyDict_Next(dict, &pos, &o_key, &o_value) ) - { - borref_t key(o_key); - borref_t value(o_value); - if ( !PyNumber_Check(key.o) ) - continue; - uint32 flags; - node_info_t ni; - convert_node_info(&ni, &flags, value); - int idx = PyInt_AsLong(key.o); - viewer_set_node_info(view, idx, ni, flags); - node_info_modified(idx, &ni, flags); - } -} - -//------------------------------------------------------------------------- -PyObject *py_customidamemo_t::get_node_info(PyObject *py_node_idx) -{ - if ( !PyNumber_Check(py_node_idx) ) - Py_RETURN_NONE; - node_info_t ni; - if ( !viewer_get_node_info(view, &ni, PyInt_AsLong(py_node_idx)) ) - Py_RETURN_NONE; - return Py_BuildValue("(kkks)", ni.bg_color, ni.frame_color, ni.ea, ni.text.c_str()); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::del_nodes_infos(PyObject *py_nodes) -{ - if ( !PySequence_Check(py_nodes) ) - return; - Py_ssize_t sz = PySequence_Size(py_nodes); - for ( Py_ssize_t i = 0; i < sz; ++i ) - { - newref_t item(PySequence_GetItem(py_nodes, i)); - if ( !PyNumber_Check(item.o) ) - continue; - int idx = PyInt_AsLong(item.o); - viewer_del_node_info(view, idx); - node_info_modified(idx, NULL, 0); - } -} - -//------------------------------------------------------------------------- -PyObject *py_customidamemo_t::get_current_renderer_type() -{ - tcc_renderer_type_t rt = get_view_renderer_type(view); - return PyLong_FromLong(long(rt)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::set_current_renderer_type(PyObject *py_rto) -{ - tcc_renderer_type_t rt = TCCRT_INVALID; - borref_t py_rt(py_rto); - if ( PyNumber_Check(py_rt.o) ) - { - rt = tcc_renderer_type_t(PyLong_AsLong(py_rt.o)); - set_view_renderer_type(view, rt); - } -} - -//------------------------------------------------------------------------- -PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos) -{ - if ( !PySequence_Check(_groups_infos) ) - Py_RETURN_NONE; - borref_t groups_infos(_groups_infos); - groups_crinfos_t gis; - Py_ssize_t sz = PySequence_Size(groups_infos.o); - for ( Py_ssize_t i = 0; i < sz; ++i ) - { - newref_t item(PySequence_GetItem(groups_infos.o, i)); - if ( !PyDict_Check(item.o) ) - continue; - borref_t nodes(PyDict_GetItemString(item.o, "nodes")); - if ( nodes.o == NULL || !PySequence_Check(nodes.o) ) - continue; - borref_t text(PyDict_GetItemString(item.o, "text")); - if ( text.o == NULL || !PyString_Check(text.o) ) - continue; - group_crinfo_t gi; - Py_ssize_t nodes_cnt = PySequence_Size(nodes.o); - for ( Py_ssize_t k = 0; k < nodes_cnt; ++k ) - { - newref_t node(PySequence_GetItem(nodes.o, k)); - if ( PyInt_Check(node.o) ) - gi.nodes.add_unique(PyInt_AsLong(node.o)); - } - if ( !gi.nodes.empty() ) - { - gi.text = PyString_AsString(text.o); - gis.push_back(gi); - } - } - intvec_t groups; - if ( gis.empty() || !viewer_create_groups(view, &groups, gis) || groups.empty() ) - Py_RETURN_NONE; - - PyObject *py_groups = PyList_New(0); - for ( intvec_t::const_iterator it = groups.begin(); it != groups.end(); ++it ) - PyList_Append(py_groups, PyInt_FromLong(long(*it))); - return py_groups; -} - -//------------------------------------------------------------------------- -static void pynodes_to_idanodes(intvec_t *idanodes, ref_t pynodes) -{ - Py_ssize_t sz = PySequence_Size(pynodes.o); - for ( Py_ssize_t i = 0; i < sz; ++i ) - { - newref_t item(PySequence_GetItem(pynodes.o, i)); - if ( !PyInt_Check(item.o) ) - continue; - idanodes->add_unique(PyInt_AsLong(item.o)); - } -} - -//------------------------------------------------------------------------- -PyObject *py_customidamemo_t::delete_groups(PyObject *_groups, PyObject *_new_current) -{ - if ( !PySequence_Check(_groups) || !PyNumber_Check(_new_current) ) - Py_RETURN_NONE; - borref_t groups(_groups); - borref_t new_current(_new_current); - intvec_t ida_groups; - pynodes_to_idanodes(&ida_groups, groups); - if ( ida_groups.empty() ) - Py_RETURN_NONE; - if ( viewer_delete_groups(view, ida_groups, int(PyInt_AsLong(new_current.o))) ) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -//------------------------------------------------------------------------- -PyObject *py_customidamemo_t::set_groups_visibility(PyObject *_groups, PyObject *_expand, PyObject *_new_current) -{ - if ( !PySequence_Check(_groups) - || !PyBool_Check(_expand) - || !PyNumber_Check(_new_current) ) - Py_RETURN_NONE; - borref_t groups(_groups); - borref_t expand(_expand); - borref_t new_current(_new_current); - intvec_t ida_groups; - pynodes_to_idanodes(&ida_groups, groups); - if ( ida_groups.empty() ) - Py_RETURN_NONE; - if ( viewer_set_groups_visibility(view, ida_groups, expand.o == Py_True, int(PyInt_AsLong(new_current.o))) ) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -//------------------------------------------------------------------------- -bool py_customidamemo_t::bind(PyObject *_self, TCustomControl *view) -{ - if ( this->self != NULL || this->view != NULL ) - return false; - PYGLOG("%p: py_customidamemo_t::bind(_self=%p, view=%p)\n", this, _self, view); - PYW_GIL_CHECK_LOCKED_SCOPE(); - - newref_t py_cobj(PyCObject_FromVoidPtr(this, NULL)); - PyObject_SetAttrString(_self, S_M_THIS, py_cobj.o); - - this->self = borref_t(_self); - this->view = view; - return true; -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::unbind(bool clear_view) -{ - if ( self == NULL ) - return; - PYGLOG("%p: py_customidamemo_t::unbind(); self.o=%p, view=%p\n", this, self.o, view); - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_cobj(PyCObject_FromVoidPtr(NULL, NULL)); - PyObject_SetAttrString(self.o, S_M_THIS, py_cobj.o); - self = newref_t(NULL); - if ( clear_view ) - view = NULL; -} - -//------------------------------------------------------------------------- -void idaapi py_customidamemo_t::s_on_view_mouse_moved( - TCustomControl *cv, - int shift, - view_mouse_event_t *e, - void *ud) -{ - PYW_GIL_GET; - py_customidamemo_t *_this = (py_customidamemo_t *) ud; - _this->on_view_mouse_moved(e); -} - -//------------------------------------------------------------------------- -int py_customidamemo_t::get_py_method_arg_count(char *method_name) -{ - newref_t method(PyObject_GetAttrString(self.o, method_name)); - if ( method != NULL && PyCallable_Check(method.o) ) - { - newref_t fc(PyObject_GetAttrString(method.o, "func_code")); - if ( fc != NULL ) - { - newref_t ac(PyObject_GetAttrString(fc.o, "co_argcount")); - if ( ac != NULL ) - return PyInt_AsLong(ac.o); - } - } - return -1; -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::collect_class_callbacks_ids(callbacks_ids_t *out) -{ - out->add(S_ON_VIEW_ACTIVATED, GRBASE_HAVE_VIEW_ACTIVATED); - out->add(S_ON_VIEW_DEACTIVATED, GRBASE_HAVE_VIEW_DEACTIVATED); - out->add(S_ON_VIEW_KEYDOWN, GRBASE_HAVE_KEYDOWN); - out->add(S_ON_POPUP, GRBASE_HAVE_POPUP); - out->add(S_ON_VIEW_CLICK, GRBASE_HAVE_VIEW_CLICK); - out->add(S_ON_VIEW_DBLCLICK, GRBASE_HAVE_VIEW_DBLCLICK); - out->add(S_ON_VIEW_CURPOS, GRBASE_HAVE_VIEW_CURPOS); - out->add(S_ON_CLOSE, GRBASE_HAVE_CLOSE); - out->add(S_ON_VIEW_SWITCHED, GRBASE_HAVE_VIEW_SWITCHED); - out->add(S_ON_VIEW_MOUSE_OVER, GRBASE_HAVE_VIEW_MOUSE_OVER); - out->add(S_ON_VIEW_MOUSE_MOVED, GRBASE_HAVE_VIEW_MOUSE_MOVED); -} - -//------------------------------------------------------------------------- -bool py_customidamemo_t::collect_pyobject_callbacks(PyObject *o) -{ - callbacks_ids_t cbids; - collect_class_callbacks_ids(&cbids); - cb_flags = 0; - for ( callbacks_ids_t::const_iterator it = cbids.begin(); it != cbids.end(); ++it ) - { - const callback_id_t &cbid = *it; - ref_t attr(PyW_TryGetAttrString(o, cbid.name.c_str())); - int have = cbid.have; - // Mandatory fields not present? - if ( (attr == NULL && have <= 0 ) - // Mandatory callback fields present but not callable? - || (attr != NULL && have >= 0 && PyCallable_Check(attr.o) == 0)) - { - return false; - } - if ( have > 0 && attr != NULL ) - cb_flags |= have; - } - - return true; -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::install_custom_viewer_handlers() -{ - if ( has_callback(GRBASE_HAVE_VIEW_MOUSE_MOVED) ) - { - // Set user-data - set_custom_viewer_handler(view, CVH_USERDATA, (void *)this); - - // - set_custom_viewer_handler(view, CVH_MOUSEMOVE, (void *)s_on_view_mouse_moved); - } -} - -//------------------------------------------------------------------------- -#define CHK_EVT(flag_needed) \ - if ( self == NULL || !has_callback(flag_needed) ) \ - return; \ - PYW_GIL_CHECK_LOCKED_SCOPE() - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_activated() -{ - CHK_EVT(GRBASE_HAVE_VIEW_ACTIVATED); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_ACTIVATED, - NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_deactivated() -{ - CHK_EVT(GRBASE_HAVE_VIEW_DEACTIVATED); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_DEACTIVATED, - NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_keydown(int key, int state) -{ - CHK_EVT(GRBASE_HAVE_KEYDOWN); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_KEYDOWN, - "ii", - key, state)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_popup() -{ - CHK_EVT(GRBASE_HAVE_POPUP); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_POPUP, - NULL)); -} - -//------------------------------------------------------------------------- -static PyObject *build_renderer_pos_swig_proxy(const view_mouse_event_t *event) -{ - return SWIG_NewPointerObj( - SWIG_as_voidptr(&event->renderer_pos), - SWIGTYPE_p_renderer_pos_info_t, - 0); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_click(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_CLICK); - if ( ovc_num_args < 0 ) - ovc_num_args = get_py_method_arg_count((char*)S_ON_VIEW_CLICK); - if ( ovc_num_args == 6 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CLICK, - "iiiiO", - event->x, event->y, event->state, event->button, rpos)); - } - else if ( ovc_num_args == 5 ) - { - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CLICK, - "iiii", - event->x, event->y, event->state, event->button)); - } - else - { - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CLICK, - "iii", - event->x, event->y, event->state)); - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_dblclick(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_DBLCLICK); - if ( ovdc_num_args < 0 ) - ovdc_num_args = get_py_method_arg_count((char*)S_ON_VIEW_DBLCLICK); - if ( ovdc_num_args == 5 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_DBLCLICK, - "iiiO", - event->x, event->y, event->state, rpos)); - } - else - { - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_DBLCLICK, - "iii", - event->x, event->y, event->state)); - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_curpos() -{ - CHK_EVT(GRBASE_HAVE_VIEW_CURPOS); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CURPOS, - NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_close() -{ - CHK_EVT(GRBASE_HAVE_CLOSE); - pycall_res_t result(PyObject_CallMethod(self.o, (char *)S_ON_CLOSE, NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_switched(tcc_renderer_type_t rt) -{ - CHK_EVT(GRBASE_HAVE_VIEW_SWITCHED); - pycall_res_t result(PyObject_CallMethod(self.o, (char *)S_ON_VIEW_SWITCHED, "i", int(rt))); -} - -//------------------------------------------------------------------------- -static ref_t build_current_graph_item_tuple(int *out_icode, const view_mouse_event_t *event) -{ - const selection_item_t *item = event->location.item; - ref_t tuple; - if ( (event->rtype == TCCRT_GRAPH || event->rtype == TCCRT_PROXIMITY) - && item != NULL ) - { - if ( item->is_node ) - { - *out_icode = 1; - tuple = newref_t(Py_BuildValue("(i)", item->node)); - } - else - { - *out_icode = 2; - tuple = newref_t(Py_BuildValue("(ii)", item->elp.e.src, item->elp.e.dst)); - } - } - else - { - *out_icode = 0; - tuple = newref_t(Py_BuildValue("()")); - } - return tuple; -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_mouse_over(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_MOUSE_OVER); - if ( ovmo_num_args < 0 ) - ovmo_num_args = get_py_method_arg_count((char*)S_ON_VIEW_MOUSE_OVER); - if ( event->rtype != TCCRT_GRAPH && event->rtype != TCCRT_PROXIMITY ) - return; - - int icode; - ref_t tuple = build_current_graph_item_tuple(&icode, event); - if ( ovmo_num_args == 7 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result(PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_MOUSE_OVER, - "iiiiOO", - event->x, event->y, event->state, icode, tuple.o, rpos)); - } - else - { - pycall_res_t result(PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_MOUSE_OVER, - "iiiiO", - event->x, event->y, event->state, icode, tuple.o)); - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_mouse_moved(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_MOUSE_MOVED); - if ( ovmm_num_args < 0 ) - ovmm_num_args = get_py_method_arg_count((char*)S_ON_VIEW_MOUSE_MOVED); - - int icode; - ref_t tuple = build_current_graph_item_tuple(&icode, event); - if ( ovmm_num_args == 7 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result(PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_MOUSE_MOVED, - "iiiiOO", - event->x, event->y, event->state, icode, tuple.o, rpos)); - } -} - - -#undef CHK_EVT - -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- - -#define GET_THIS() py_customidamemo_t *_this = view_extract_this(self) -#define CHK_THIS() \ - GET_THIS(); \ - if ( _this == NULL ) \ - return -#define CHK_THIS_OR_NULL() \ - GET_THIS(); \ - if ( _this == NULL ) \ - return NULL; -#define CHK_THIS_OR_NONE() \ - GET_THIS(); \ - if ( _this == NULL ) \ - Py_RETURN_NONE - -//------------------------------------------------------------------------- -void pygc_refresh(PyObject *self) -{ - CHK_THIS(); - _this->refresh(); -} - -//------------------------------------------------------------------------- -void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags) -{ - CHK_THIS(); - _this->set_node_info(py_node_idx, py_node_info, py_flags); -} - -//------------------------------------------------------------------------- -void pygc_set_nodes_infos(PyObject *self, PyObject *values) -{ - CHK_THIS(); - _this->set_nodes_infos(values); -} - -//------------------------------------------------------------------------- -PyObject *pygc_get_node_info(PyObject *self, PyObject *py_node_idx) -{ - GET_THIS(); - if ( _this != NULL ) - return _this->get_node_info(py_node_idx); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -void pygc_del_nodes_infos(PyObject *self, PyObject *py_nodes) -{ - CHK_THIS(); - _this->del_nodes_infos(py_nodes); -} - -//------------------------------------------------------------------------- -PyObject *pygc_get_current_renderer_type(PyObject *self) -{ - GET_THIS(); - if ( _this != NULL ) - return _this->get_current_renderer_type(); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt) -{ - CHK_THIS(); - _this->set_current_renderer_type(py_rt); -} - -//------------------------------------------------------------------------- -PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos) -{ - CHK_THIS_OR_NONE(); - return _this->create_groups(groups_infos); -} - -//------------------------------------------------------------------------- -PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current) -{ - CHK_THIS_OR_NONE(); - return _this->delete_groups(groups, new_current); -} - -//------------------------------------------------------------------------- -PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current) -{ - CHK_THIS_OR_NONE(); - return _this->set_groups_visibility(groups, expand, new_current); -} - -//------------------------------------------------------------------------- -TForm *pycim_get_tform(PyObject *self) -{ - CHK_THIS_OR_NULL(); - TForm *form = NULL; - if ( !py_customidamemo_t::lookup_info.find_by_py_view(&form, NULL, _this) ) - return NULL; - return form; -} - -//------------------------------------------------------------------------- -TCustomControl *pycim_get_tcustom_control(PyObject *self) -{ - CHK_THIS_OR_NULL(); - TCustomControl *tcc = NULL; - if ( !py_customidamemo_t::lookup_info.find_by_py_view(NULL, &tcc, _this) ) - return NULL; - return tcc; -} - -#undef CHK_THIS_OR_NONE -#undef CHK_THIS_OR_NULL -#undef CHK_THIS -#undef GET_THIS - -//------------------------------------------------------------------------- -lookup_info_t py_customidamemo_t::lookup_info; -// +// +// %} %inline %{ -// -void pygc_refresh(PyObject *self); -void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags); -void pygc_set_nodes_infos(PyObject *self, PyObject *values); -PyObject *pygc_get_node_info(PyObject *self, PyObject *py_node_idx); -void pygc_del_nodes_infos(PyObject *self, PyObject *py_nodes); -PyObject *pygc_get_current_renderer_type(PyObject *self); -void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt); -PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos); -PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current); -PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current); -TForm *pycim_get_tform(PyObject *self); -TCustomControl *pycim_get_tcustom_control(PyObject *self); -// +// +// %} %pythoncode %{ -# -class CustomIDAMemo(object): - def Refresh(self): - """ - Refreshes the graph. This causes the OnRefresh() to be called - """ - _idaapi.pygc_refresh(self) - - def GetCurrentRendererType(self): - return _idaapi.pygc_get_current_renderer_type(self) - - def SetCurrentRendererType(self, rtype): - """ - Set the current view's renderer. - - @param rtype: The renderer type. Should be one of the idaapi.TCCRT_* values. - """ - _idaapi.pygc_set_current_renderer_type(self, rtype) - - def SetNodeInfo(self, node_index, node_info, flags): - """ - Set the properties for the given node. - - Example usage (set second nodes's bg color to red): - inst = ... - p = idaapi.node_info_t() - p.bg_color = 0x00ff0000 - inst.SetNodeInfo(1, p, idaapi.NIF_BG_COLOR) - - @param node_index: The node index. - @param node_info: An idaapi.node_info_t instance. - @param flags: An OR'ed value of NIF_* values. - """ - _idaapi.pygc_set_node_info(self, node_index, node_info, flags) - - def SetNodesInfos(self, values): - """ - Set the properties for the given nodes. - - Example usage (set first three nodes's bg color to purple): - inst = ... - p = idaapi.node_info_t() - p.bg_color = 0x00ff00ff - inst.SetNodesInfos({0 : p, 1 : p, 2 : p}) - - @param values: A dictionary of 'int -> node_info_t' objects. - """ - _idaapi.pygc_set_nodes_infos(self, values) - - def GetNodeInfo(self, node): - """ - Get the properties for the given node. - - @param node: The index of the node. - @return: A tuple (bg_color, frame_color, ea, text), or None. - """ - return _idaapi.pygc_get_node_info(self, node) - - def DelNodesInfos(self, *nodes): - """ - Delete the properties for the given node(s). - - @param nodes: A list of node IDs - """ - return _idaapi.pygc_del_nodes_infos(self, nodes) - - def CreateGroups(self, groups_infos): - """ - Send a request to modify the graph by creating a - (set of) group(s), and perform an animation. - - Each object in the 'groups_infos' list must be of the format: - { - "nodes" : [, , , ...] # The list of nodes to group - "text" : # The synthetic text for that group - } - - @param groups_infos: A list of objects that describe those groups. - @return: A [, , ...] list of group nodes, or None (failure). - """ - return _idaapi.pygc_create_groups(self, groups_infos) - - def DeleteGroups(self, groups, new_current = -1): - """ - Send a request to delete the specified groups in the graph, - and perform an animation. - - @param groups: A list of group node numbers. - @param new_current: A node to focus on after the groups have been deleted - @return: True on success, False otherwise. - """ - return _idaapi.pygc_delete_groups(self, groups, new_current) - - def SetGroupsVisibility(self, groups, expand, new_current = -1): - """ - Send a request to expand/collapse the specified groups in the graph, - and perform an animation. - - @param groups: A list of group node numbers. - @param expand: True to expand the group, False otherwise. - @param new_current: A node to focus on after the groups have been expanded/collapsed. - @return: True on success, False otherwise. - """ - return _idaapi.pygc_set_groups_visibility(self, groups, expand, new_current) - - def GetTForm(self): - """ - Return the TForm hosting this view. - - @return: The TForm that hosts this view, or None. - """ - return _idaapi.pycim_get_tform(self) - - def GetTCustomControl(self): - """ - Return the TCustomControl underlying this view. - - @return: The TCustomControl underlying this view, or None. - """ - return _idaapi.pycim_get_tcustom_control(self) - - -# -%} - -%{ -// -class py_idaview_t : public py_customidamemo_t -{ - typedef py_customidamemo_t inherited; - -public: - static bool Bind(PyObject *self); - static bool Unbind(PyObject *self); -}; - -//------------------------------------------------------------------------- -bool py_idaview_t::Bind(PyObject *self) -{ - // Already a py_idaview_t associated to this object? - py_idaview_t *_this = view_extract_this(self); - if ( _this != NULL ) - return false; - - qstring title; - if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) ) - return false; - - // Get the IDAView associated to this TForm - TForm *tform = find_tform(title.c_str()); - if ( tform == NULL ) - return false; - TCustomControl *v = get_tform_idaview(tform); - if ( v == NULL ) - return false; - - // Get unique py_idaview_t associated to that tform - py_idaview_t *py_view; - TCustomControl *found_view; - if ( lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) ) - { - // If we have a py_idaview_t for that form, ensure it has - // the expected view. - QASSERT(30451, found_view == v); - } - else - { - py_view = new py_idaview_t(); - lookup_info_t::entry_t &e = lookup_info.new_entry(py_view); - lookup_info.commit(e, tform, v); - } - - // Finally, bind: - // py_idaview_t <=> IDAViewWrapper - // py_idaview_t => TCustomControl - bool ok = py_view->bind(self, v); - if ( ok ) - { - ok = py_view->collect_pyobject_callbacks(self); - if ( ok ) - py_view->install_custom_viewer_handlers(); - else - delete py_view; - } - return ok; -} - -//------------------------------------------------------------------------- -bool py_idaview_t::Unbind(PyObject *self) -{ - py_idaview_t *_this = view_extract_this(self); - if ( _this == NULL ) - return false; - _this->unbind(true); - return true; -} - -//------------------------------------------------------------------------- -bool pyidag_bind(PyObject *self) -{ - return py_idaview_t::Bind(self); -} - -//------------------------------------------------------------------------- -bool pyidag_unbind(PyObject *self) -{ - return py_idaview_t::Unbind(self); -} - -// -%} - -%inline %{ -// -bool pyidag_bind(PyObject *self); -bool pyidag_unbind(PyObject *self); -// -%} - -%pythoncode %{ -# -class IDAViewWrapper(CustomIDAMemo): - """This class wraps access to native IDA views. See kernwin.hpp file""" - def __init__(self, title): - """ - Constructs the IDAViewWrapper object around the view - whose title is 'title'. - - @param title: The title of the existing IDA view. E.g., 'IDA View-A' - """ - self._title = title - - def Bind(self): - return _idaapi.pyidag_bind(self) - - def Unbind(self): - return _idaapi.pyidag_unbind(self) - -# +# +# %} diff --git a/tools/deploy.py b/tools/deploy.py new file mode 100644 index 0000000..624d01e --- /dev/null +++ b/tools/deploy.py @@ -0,0 +1,83 @@ +""" +Deploy code snips into swig interface files + +(c) Hex-Rays +""" + +import sys +import re +import os + +major, minor, micro, _, _ = sys.version_info + +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("-t", "--template", required=True) +parser.add_argument("-o", "--output", required=True) +parser.add_argument("-m", "--module", required=True) +parser.add_argument("-w", "--pywraps", required=True) +parser.add_argument("-v", "--verbose", default=False, action="store_true") +args = parser.parse_args() + +# creates a regular expression +def make_re(tag, module, prefix): + module = "py_%s" % module + s = '%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s' % {'m': module, 'tag': tag, 'p': prefix} + return (s, re.compile(s, re.DOTALL)) + +def convert_path(path_in): + parts = path_in.split('/') + return os.sep.join(parts) + +def deploy(module, template, output, pywraps, verbose): + template = convert_path(template) + output = convert_path(output) + # create regular expressions + tags = ( + ('pycode', make_re('pycode', module, '#')), + ('code', make_re('code', module, '//')), + ('inline', make_re('inline', module, '//')) + ) + + # read dest file + template_str = "".join(file(template, "r").readlines()) + + # read input file(s) + input_parts = [] + for fname in ["py_%s.%s" % (module, ext) for ext in ["hpp", "py"]]: + path = os.path.join(pywraps, fname) + if os.path.isfile(path): + input_parts.append("".join(file(path, "r").readlines())) + input_str = "".join(input_parts) + + pcount = 0 + for desc, (expr_str, expr) in tags: + # find source pattern + matches = expr.findall(input_str) + if not matches: + if verbose: + print("Failed to match <%s> source expression against '%s', skipping...!" % (desc, expr_str)) + continue + + # find pattern in destination + dest = expr.search(template_str) + if not dest: + raise Exception("Found <%s> for module '%s' in input, but failed to match in destination" % (desc, module)) + + # accumulate all the strings to be replaced + replaces = [] + for src in matches: + replaces.append(src) + + template_str = template_str[:dest.start(1)] + "\n".join(replaces) + template_str[dest.end(1):] + pcount += 1 + + with open(output, 'w') as f: + f.write(template_str) + +deploy(args.module, args.template, args.output, args.pywraps, args.verbose) diff --git a/tools/genhooks/doxy_gen_notifs.cfg b/tools/genhooks/doxy_gen_notifs.cfg new file mode 100644 index 0000000..9f6891f --- /dev/null +++ b/tools/genhooks/doxy_gen_notifs.cfg @@ -0,0 +1,2372 @@ +# Doxyfile 1.8.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "parsed_notifications" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = "staging/parsed_notifications" + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = NO + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = NO + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = NO + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../../include/idp.hpp ../../include/dbg.hpp ../../include/kernwin.hpp + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /