diff --git a/build.py b/build.py index 3a9abfb..b491d07 100644 --- a/build.py +++ b/build.py @@ -126,6 +126,7 @@ SRCDIST_MANIFEST = [ "swig/ua.i", "swig/xref.i", "swig/graph.i", + "swig/fpro.i", "tools/gendocs.py", ] @@ -325,6 +326,9 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64): if ea64: platform_macros.append("__EA64__") + if '--early-load' in sys.argv: + platform_macros.append("PLUGINFIX") + # Build the wrapper from the interface files ea64flag = ea64 and "-D__EA64__" or "" swigcmd = "swig %s -Iswig -o idaapi.cpp %s -I%s idaapi.i" % (SWIG_OPTIONS, ea64flag, ida_include_directory) diff --git a/python.cpp b/python.cpp index eab3309..65688b1 100644 --- a/python.cpp +++ b/python.cpp @@ -560,13 +560,57 @@ void enable_python_cli(bool enable) } #endif +/* Install python menu items */ +static void install_python_menus() +{ + /* Add menu items for all the functions */ + /* Different paths are used for the GUI version */ + add_menu_item("File/IDC command...", "P~y~thon command...", + "Alt-8", SETMENU_APP, + (menu_item_callback_t *)IDAPython_Menu_Callback, + (void *)IDAPYTHON_RUNSTATEMENT); + + /* Add Load Python file menu item*/ + bool result = add_menu_item("File/Load file/IDC file...", "P~y~thon file...", + "Alt-9", SETMENU_APP, + (menu_item_callback_t *)IDAPython_Menu_Callback, + (void *)IDAPYTHON_RUNFILE); + if (!result) + add_menu_item("File/IDC command...", "P~y~thon file...", + "Alt-9", SETMENU_APP, + (menu_item_callback_t *)IDAPython_Menu_Callback, + (void *)IDAPYTHON_RUNFILE); + + /* Add View Python Scripts menu item*/ + result = add_menu_item("View/Open subviews/Show strings", "Python S~c~ripts", + "Alt-7", SETMENU_APP, + (menu_item_callback_t *)IDAPython_Menu_Callback, + (void *)IDAPYTHON_SCRIPTBOX); + if (!result) + add_menu_item("View/Open subviews/Problems", "Python S~c~ripts", + "Alt-7", SETMENU_APP, + (menu_item_callback_t *)IDAPython_Menu_Callback, + (void *)IDAPYTHON_SCRIPTBOX); +} + +/* we install the menu later because the text version crashes if +add_menu_item is called too early */ +static int idaapi menu_installer_cb(void *, int code, va_list) +{ + if ( code != ui_ready_to_run ) + return 0; + + install_python_menus(); + unhook_from_notification_point(HT_UI, menu_installer_cb, NULL); + return 0; +} + /* Initialize the Python environment */ bool IDAPython_Init(void) { char *options; char tmp[MAXSTR+64]; - char *initpath; - bool result = 1; + bool result = true; /* Already initialized? */ if (initialized == 1) @@ -634,35 +678,11 @@ bool IDAPython_Init(void) if (options) IDAPython_RunScript(options); - /* Add menu items for all the functions */ - /* Different paths are used for the GUI version */ - add_menu_item("File/IDC command...", "P~y~thon command...", - "Alt-8", SETMENU_APP, - (menu_item_callback_t *)IDAPython_Menu_Callback, - (void *)IDAPYTHON_RUNSTATEMENT); - - /* Add Load Python file menu item*/ - result = add_menu_item("File/Load file/IDC file...", "P~y~thon file...", - "Alt-9", SETMENU_APP, - (menu_item_callback_t *)IDAPython_Menu_Callback, - (void *)IDAPYTHON_RUNFILE); - if (!result) - add_menu_item("File/IDC command...", "P~y~thon file...", - "Alt-9", SETMENU_APP, - (menu_item_callback_t *)IDAPython_Menu_Callback, - (void *)IDAPYTHON_RUNFILE); - - /* Add View Python Scripts menu item*/ - result = add_menu_item("View/Open subviews/Show strings", "Python S~c~ripts", - "Alt-7", SETMENU_APP, - (menu_item_callback_t *)IDAPython_Menu_Callback, - (void *)IDAPYTHON_SCRIPTBOX); - if (!result) - add_menu_item("View/Open subviews/Problems", "Python S~c~ripts", - "Alt-7", SETMENU_APP, - (menu_item_callback_t *)IDAPython_Menu_Callback, - (void *)IDAPYTHON_SCRIPTBOX); - +#ifdef PLUGINFIX + hook_to_notification_point(HT_UI, menu_installer_cb, NULL); +#else + install_python_menus(); +#endif /* Register a RunPythonStatement() function for IDC */ set_idc_func("RunPythonStatement", idc_runpythonstatement, idc_runpythonstatement_args); @@ -679,6 +699,9 @@ bool IDAPython_Init(void) /* Cleaning up Python */ void IDAPython_Term(void) { +#ifdef PLUGINFIX + unhook_from_notification_point(HT_UI, menu_installer_cb, NULL); +#endif /* Remove the menu items before termination */ del_menu_item("File/Load file/Python file..."); del_menu_item("File/Python file..."); @@ -767,7 +790,11 @@ extern "C" { plugin_t PLUGIN = { IDP_INTERFACE_VERSION, +#ifdef PLUGINFIX + PLUGIN_FIX, // plugin flags +#else 0, // plugin flags +#endif init, // initialize term, // terminate. this pointer may be NULL. run, // invoke plugin diff --git a/python/idautils.py b/python/idautils.py index 28d7ba2..b8d110e 100644 --- a/python/idautils.py +++ b/python/idautils.py @@ -178,7 +178,7 @@ def Threads(): yield idc.GetThreadId(i) -def Heads(start=idaapi.cvar.inf.minEA, end=idaapi.cvar.inf.maxEA): +def Heads(start=None, end=None): """ Get a list of heads (instructions or data) @@ -187,6 +187,9 @@ def Heads(start=idaapi.cvar.inf.minEA, end=idaapi.cvar.inf.maxEA): @return: list of heads between start and end """ + if not start: start = idaapi.cvar.inf.minEA + if not end: end = idaapi.cvar.inf.maxEA + ea = start if not idc.isHead(idc.GetFlags(ea)): ea = idaapi.next_head(ea, end) @@ -195,7 +198,7 @@ def Heads(start=idaapi.cvar.inf.minEA, end=idaapi.cvar.inf.maxEA): ea = idaapi.next_head(ea, end) -def Functions(start=idaapi.cvar.inf.minEA, end=idaapi.cvar.inf.maxEA): +def Functions(start=None, end=None): """ Get a list of functions @@ -209,6 +212,9 @@ def Functions(start=idaapi.cvar.inf.minEA, end=idaapi.cvar.inf.maxEA): in multiple segments will be reported multiple times, once in each segment as they are listed. """ + if not start: start = idaapi.cvar.inf.minEA + if not end: end = idaapi.cvar.inf.maxEA + func = idaapi.get_func(start) if not func: func = idaapi.get_next_func(start) @@ -414,13 +420,17 @@ class Strings(object): self._si = idaapi.string_info_t() self.size = 0 - def refresh(self, ea1=idaapi.cvar.inf.minEA, ea2=idaapi.cvar.inf.maxEA): + def refresh(self, ea1=None, ea2=None): """Refreshes the strings list""" + if not ea1: ea1 = idaapi.cvar.inf.minEA + if not ea2: ea2 = idaapi.cvar.inf.maxEA idaapi.refresh_strlist(ea1, ea2) self.size = idaapi.get_strlist_qty() def setup(self, strtypes=STR_C, minlen=5, only_7bit=True, ignore_instructions=False, - ea1=idaapi.cvar.inf.minEA, ea2=idaapi.cvar.inf.maxEA, display_only_existing_strings=False): + ea1=None, ea2=None, display_only_existing_strings=False): + if not ea1: ea1 = idaapi.cvar.inf.minEA + if not ea2: ea2 = idaapi.cvar.inf.maxEA t = idaapi.strwinsetup_t() t.strtypes = strtypes t.minlen = minlen