IDAPython 1.4.3:

- IDA 6.0 support
- Python CLI now prints expression evaluation result (no need to use print())
- Changed Alt-8 to Ctrl-F3 (because it conflicts with window switching key Alt+n)
- Added get_highlighted_identifier()
- Added PluginForm class to allow UI development with either PyQt4 or PySide
- Added idautils.Entries() to enumerate entrypoints
- idc / AddConst() was broken
- Minor fixes
This commit is contained in:
elias.bachaalany 2010-11-10 13:58:08 +00:00
parent 1d2f1d1f07
commit ac5d88a83b
15 changed files with 520 additions and 136 deletions

View File

@ -9,13 +9,14 @@ REQUIREMENTS
[Tested versions are in brackets] [Tested versions are in brackets]
- IDA and IDA SDK [5.6]
- IDA and IDA SDK [> 5.6]
http://www.hex-rays.com/idapro/ http://www.hex-rays.com/idapro/
- Python [2.5.1, 2.6.1] - Python [2.5.1, 2.6.1, 2.7]
http://www.python.org/ http://www.python.org/
- Simplified Wrapper Interface Generator (SWIG) [1.3.36] - Simplified Wrapper Interface Generator (SWIG) [2.0]
http://www.swig.org/ http://www.swig.org/
- Unix utilities (GNU patch on Windows): - Unix utilities (GNU patch on Windows):
@ -35,18 +36,18 @@ BUILDING
Make sure all the needed tools (compiler, swig) are on the PATH. Make sure all the needed tools (compiler, swig) are on the PATH.
1, Unpack the IDAPython source and IDA Pro SDK into the following 1. Unpack the IDAPython source and IDA Pro SDK into the following
directory structure: directory structure:
swigsdk-versions/5.6/ - version 5.6 of the IDA Pro SDK swigsdk-versions/x.y/ - A supported version of the IDA Pro SDK
idapython/ - IDAPython source code idapython/ - IDAPython source code
2, On Mac OS X copy libida.dylib from the IDA install directory to 2. On Mac OS X copy libida.dylib from the IDA install directory to
swigsdk-versions/5.6/lib/gcc32.mac/ swigsdk-versions/x.y/lib/gcc32.mac/
and libida64.dylib to and libida64.dylib to
swigsdk-versions/5.6/lib/gcc64.mac/ swigsdk-versions/x.y/lib/gcc64.mac/
3, Build the plugin 3. Build the plugin
python build.py python build.py
@ -55,6 +56,18 @@ Make sure all the needed tools (compiler, swig) are on the PATH.
Run 'build.py --help' for more information. Run 'build.py --help' for more information.
4, Install the components as described in README.txt 4. Install the components as described in README.txt
See build.py for build details and possible tweaks. See build.py for build details and possible tweaks.
On 64 bits distributions, you may need to compile Python to generate a 32bit
version of the interpreter:
1. tar xvf Python-2.6.6.tar.bz2
2. cd Python-2.6.6
3. CC="gcc -m32" CXX="c++ -m32" ./configure --prefix=/path/to/py32 --enable-shared
4. make
5. make install
6. cd /path/to/py32/lib
7. ln -s libpython2.6.so.1.0 libpython2.6.so.1
8. PYTHONHOME=/path/to/py32 LD_LIBRARY_PATH=/path/to/py32/lib idaq

View File

@ -1,5 +1,14 @@
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes. Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
Changes from version 1.4.2 to 1.4.3
------------------------------------
- IDA 6.0 support
- Python CLI now prints expression evaluation result (no need to use print())
- Changed Alt-8 to Ctrl-F3 (because it conflicts with window switching key Alt+n)
- Added get_highlighted_identifier()
- Added PluginForm class to allow UI development with either PyQt4 or PySide
- Added idautils.Entries() to enum entrypoints
Changes from version 1.4.1 to 1.4.2 Changes from version 1.4.1 to 1.4.2
------------------------------------ ------------------------------------
- Added command completion - Added command completion
@ -127,4 +136,3 @@ Changes from version 0.5.0 to 0.6.0
- Bunch of misc small cleanups and fixes - Bunch of misc small cleanups and fixes
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt - For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt

View File

@ -16,7 +16,7 @@ AVAILABILITY
------------ ------------
Latest stable versions of IDAPython are available from Latest stable versions of IDAPython are available from
http://www.d-dome.net/idapython/ http://code.google.com/p/idapython/downloads/list
Development builds are available from Development builds are available from
http://code.google.com/p/idapython/ http://code.google.com/p/idapython/
@ -26,7 +26,7 @@ RESOURCES
--------- ---------
The full function cross-reference is readable online at The full function cross-reference is readable online at
http://www.d-dome.net/idapython/reference/ http://www.hex-rays.com/idapro/idapython_docs/
Bugs and enhancement requests should be submitted to Bugs and enhancement requests should be submitted to
http://code.google.com/p/idapython/issues/list http://code.google.com/p/idapython/issues/list
@ -38,25 +38,29 @@ Mailing list for the project is hosted by Google Groups at
INSTALLATION FROM BINARIES INSTALLATION FROM BINARIES
-------------------------- --------------------------
1, Install Python 2.5 or 2.6 from http://www.python.org/ 1. Install Python 2.5 or 2.6 from http://www.python.org/
2, Copy the python and python64 directories to the IDA install directory 2. Copy the python and python64 directories to the IDA install directory
3. Copy the plugins to the %IDADIR%\plugins\ 3. Copy the plugins to the %IDADIR%\plugins\
USAGE USAGE
----- -----
The plugin has three hotkeys: - Run script: File / Script file (Alt-F7)
- Execute Python statement(s) (Ctrl-F3)
- Run script (Alt-9) - Run previously executed script again: View / Recent Scripts (Alt+F9)
- Execute Python statement(s) (Alt-8)
- Run previously executed script again (Alt-7)
Batch mode execution: Batch mode execution:
Start IDA with the following command line options: Start IDA with the following command line options:
-A -OIDAPython:yourscript.py file_to_work_on -A -OIDAPython:yourscript.py file_to_work_on
or
-Syourscript.py
or
-S"yourscript.py arg1 arg2 arg3"
(Please see http://www.hexblog.com/?p=128)
If you want fully unattended execution mode, make sure your script If you want fully unattended execution mode, make sure your script
exits with a qexit() call. exits with a qexit() call.
@ -74,11 +78,11 @@ Where N can be:
User init file: User init file:
You can place your custom settings to a file called 'idapythonrc.py' You can place your custom settings to a file called 'idapythonrc.py'
that should be placed to that should be placed to
${HOME}/.idapro/ ${HOME}/.idapro/
or or
%AppData%\Hex-Rays\IDA Pro %AppData%\Hex-Rays\IDA Pro

View File

@ -23,8 +23,8 @@ from distutils import sysconfig
# Start of user configurable options # Start of user configurable options
VERBOSE = True VERBOSE = True
IDA_MAJOR_VERSION = 5 IDA_MAJOR_VERSION = 6
IDA_MINOR_VERSION = 7 IDA_MINOR_VERSION = 0
if 'IDA' in os.environ: if 'IDA' in os.environ:
IDA_SDK = os.environ['IDA'] IDA_SDK = os.environ['IDA']
@ -36,7 +36,7 @@ else:
# IDAPython version # IDAPython version
VERSION_MAJOR = 1 VERSION_MAJOR = 1
VERSION_MINOR = 4 VERSION_MINOR = 4
VERSION_PATCH = 2 VERSION_PATCH = 3
# Determine Python version # Determine Python version
PYTHON_MAJOR_VERSION = int(platform.python_version()[0]) PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@ -89,6 +89,8 @@ BINDIST_MANIFEST = [
"examples/ex_dbg.py", "examples/ex_dbg.py",
"examples/ex_custview.py", "examples/ex_custview.py",
"examples/ex_prefix_plugin.py", "examples/ex_prefix_plugin.py",
"examples/ex_pyside.py",
"examples/ex_pyqt.py",
"examples/ex_imports.py" "examples/ex_imports.py"
] ]

View File

@ -3,30 +3,38 @@ import idaapi
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Using raw IDAAPI # Using raw IDAAPI
def raw_main(p=True): def raw_main(p=True):
global q
f = idaapi.get_func(here()) f = idaapi.get_func(here())
if not f: if not f:
return return
q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS) q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS)
for n in xrange(0, q.size()): for n in xrange(0, q.size()):
b = q[n] b = q[n]
if p: print "%x - %x [%d]:" % (b.startEA, b.endEA, n) if p:
print "%x - %x [%d]:" % (b.startEA, b.endEA, n)
for ns in xrange(0, q.nsucc(n)): for ns in xrange(0, q.nsucc(n)):
if p: print " %d->%d" % (n, q.succ(n, ns)) if p:
print " %d->%d" % (n, q.succ(n, ns))
for ns in xrange(0, q.npred(n)): for ns in xrange(0, q.npred(n)):
if p: print " %d->%d" % (n, q.pred(n, ns)) if p:
print " %d->%d" % (n, q.pred(n, ns))
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Using the class # Using the class
def cls_main(p=True): def cls_main(p=True):
global f
f = idaapi.FlowChart(idaapi.get_func(here())) f = idaapi.FlowChart(idaapi.get_func(here()))
for block in f: for block in f:
if p: print "%x - %x [%d]:" % (block.startEA, block.endEA, block.id) if p:
print "%x - %x [%d]:" % (block.startEA, block.endEA, block.id)
for succ_block in block.succs(): for succ_block in block.succs():
if p: print " %x - %x [%d]:" % (succ_block.startEA, succ_block.endEA, succ_block.id) if p:
print " %x - %x [%d]:" % (succ_block.startEA, succ_block.endEA, succ_block.id)
for pred_block in block.preds(): for pred_block in block.preds():
if p: print " %x - %x [%d]:" % (pred_block.startEA, pred_block.endEA, pred_block.id) if p:
print " %x - %x [%d]:" % (pred_block.startEA, pred_block.endEA, pred_block.id)
q = None q = None
f = None f = None

View File

@ -52,7 +52,7 @@
static const char S_IDC_ARGS_VARNAME[] = "ARGV"; static const char S_IDC_ARGS_VARNAME[] = "ARGV";
static const char S_MAIN[] = "__main__"; static const char S_MAIN[] = "__main__";
static const char S_IDC_RUNPYTHON_STATEMENT[] = "RunPythonStatement"; static const char S_IDC_RUNPYTHON_STATEMENT[] = "RunPythonStatement";
static const char S_HOTKEY_RUNSTATEMENT[] = "Alt-8"; static const char S_HOTKEY_RUNSTATEMENT[] = "Ctrl-F3";
static const char S_IDAPYTHON_DATA_NODE[] = "IDAPython_Data"; static const char S_IDAPYTHON_DATA_NODE[] = "IDAPython_Data";
#ifdef PLUGINFIX #ifdef PLUGINFIX
@ -320,7 +320,7 @@ static void handle_python_error(char *errbuf, size_t errbufsize)
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Helper function to get globals for the __main__ module // Helper function to get globals for the __main__ module
// Note: The references are borrowed. No need to free them. // Note: The references are borrowed. No need to free them.
PyObject *GetMainGlobals() static PyObject *GetMainGlobals()
{ {
PyObject *module = PyImport_AddModule(S_MAIN); PyObject *module = PyImport_AddModule(S_MAIN);
if ( module == NULL ) if ( module == NULL )
@ -328,6 +328,42 @@ PyObject *GetMainGlobals()
return PyModule_GetDict(module); return PyModule_GetDict(module);
} }
//------------------------------------------------------------------------
static void PythonEvalOrExec(const char *str, const char *filename = "<string>")
{
// Compile as an expression
PyCompilerFlags cf = {0};
PyObject *py_code = Py_CompileStringFlags(str, filename, Py_eval_input, &cf);
if ( py_code == NULL || PyErr_Occurred() )
{
// Not an expression?
PyErr_Clear();
// Run as a string
PyRun_SimpleString(str);
return;
}
PyObject *py_globals = GetMainGlobals();
PyObject *py_result = PyEval_EvalCode(
(PyCodeObject *) py_code,
py_globals,
py_globals);
Py_DECREF(py_code);
if ( py_result == NULL || PyErr_Occurred() )
{
PyErr_Print();
return;
}
qstring result_str;
if ( py_result != Py_None && PyW_ObjectToString(py_result, &result_str) )
msg("%s\n", result_str.c_str());
Py_DECREF(py_result);
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Simple Python statement runner function for IDC // Simple Python statement runner function for IDC
static const char idc_runpythonstatement_args[] = { VT_STR2, 0 }; static const char idc_runpythonstatement_args[] = { VT_STR2, 0 };
@ -654,11 +690,14 @@ bool idaapi IDAPython_extlang_run(
ok = false; ok = false;
break; break;
} }
PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(func); PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(func);
PyObject *pres = PyEval_EvalCodeEx( PyObject *pres = PyEval_EvalCodeEx(
code, code,
globals, NULL, &pargs[0], nargs, globals, NULL,
&pargs[0], nargs,
NULL, 0, NULL, 0, NULL); NULL, 0, NULL, 0, NULL);
ok = return_python_result(result, pres, errbuf, errbufsize); ok = return_python_result(result, pres, errbuf, errbufsize);
} while ( false ); } while ( false );
@ -666,6 +705,7 @@ bool idaapi IDAPython_extlang_run(
if ( imported_module ) if ( imported_module )
Py_XDECREF(module); Py_XDECREF(module);
return ok; return ok;
} }
@ -1002,29 +1042,27 @@ void enable_extlang_python(bool enable)
// Execute a line in the Python CLI // Execute a line in the Python CLI
bool idaapi IDAPython_cli_execute_line(const char *line) bool idaapi IDAPython_cli_execute_line(const char *line)
{ {
const char *first_line = strrchr(line, '\n'); // do not process empty lines
if ( first_line == NULL ) if ( line[0] == '\0' )
first_line = line; return true;
const char *last_line = strrchr(line, '\n');
if ( last_line == NULL )
last_line = line;
else else
first_line += 1; last_line += 1;
// skip empty lines // skip empty lines
if ( first_line[0] != '\0' ) if ( last_line[0] != '\0' )
{ {
// take a copy of the line so we r-trim it
char *tline = qstrdup(first_line);
trim(tline);
// line ends with ":" or begins with a space character? // line ends with ":" or begins with a space character?
bool more = tline[qstrlen(tline)-1] == ':' || isspace(first_line[0]); bool more = last_line[qstrlen(last_line)-1] == ':' || isspace(last_line[0]);
qfree(tline);
if ( more ) if ( more )
return false; return false;
} }
begin_execution(); begin_execution();
PyRun_SimpleString(line); PythonEvalOrExec(line);
end_execution(); end_execution();
return true; return true;

View File

@ -16,6 +16,7 @@ import idc
import types import types
import os import os
def refs(ea, funcfirst, funcnext): def refs(ea, funcfirst, funcnext):
""" """
Generic reference collector - INTERNAL USE ONLY. Generic reference collector - INTERNAL USE ONLY.
@ -241,6 +242,7 @@ def Chunks(start):
yield (chunk.startEA, chunk.endEA) yield (chunk.startEA, chunk.endEA)
status = func_iter.next() status = func_iter.next()
def Modules(): def Modules():
""" """
Returns a list of module objects with name,size,base and the rebase_to attributes Returns a list of module objects with name,size,base and the rebase_to attributes
@ -251,17 +253,19 @@ def Modules():
yield idaapi.object_t(name=mod.name, size=mod.size, base=mod.base, rebase_to=mod.rebase_to) yield idaapi.object_t(name=mod.name, size=mod.size, base=mod.base, rebase_to=mod.rebase_to)
result = idaapi.get_next_module(mod) result = idaapi.get_next_module(mod)
def Names(): def Names():
""" """
Returns a list of names Returns a list of names
@return: tuple(ea, name) @return: List of tuples (ea, name)
""" """
for i in xrange(idaapi.get_nlist_size()): for i in xrange(idaapi.get_nlist_size()):
ea = idaapi.get_nlist_ea(i) ea = idaapi.get_nlist_ea(i)
name = idaapi.get_nlist_name(i) name = idaapi.get_nlist_name(i)
yield (ea, name) yield (ea, name)
def Segments(): def Segments():
""" """
Get list of segments (sections) in the binary image Get list of segments (sections) in the binary image
@ -274,6 +278,20 @@ def Segments():
yield seg.startEA yield seg.startEA
def Entries():
"""
Returns a list of entry points
@return: List of tuples (index, ordinal, ea, name)
"""
n = idaapi.get_entry_qty()
for i in xrange(0, n):
ordinal = idaapi.get_entry_ordinal(i)
ea = idaapi.get_entry(ordinal)
name = idaapi.get_entry_name(ordinal)
yield (i, ordinal, ea, name)
def FuncItems(start): def FuncItems(start):
""" """
Get a list of function items Get a list of function items
@ -475,11 +493,6 @@ class Strings(object):
return None return None
# -----------------------------------------------------------------------
def GetRegisterList():
"""Returns the register list"""
return idaapi.ph_get_regnames()
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
def GetIdbDir(): def GetIdbDir():
""" """
@ -489,6 +502,11 @@ def GetIdbDir():
""" """
return os.path.dirname(idaapi.cvar.database_idb) + os.sep return os.path.dirname(idaapi.cvar.database_idb) + os.sep
# -----------------------------------------------------------------------
def GetRegisterList():
"""Returns the register list"""
return idaapi.ph_get_regnames()
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
def GetInstructionList(): def GetInstructionList():
"""Returns the instruction list of the current processor module""" """Returns the instruction list of the current processor module"""

View File

@ -7530,7 +7530,7 @@ def WriteTxt(filepath, ea1, ea2):
def WriteExe(filepath): def WriteExe(filepath):
return GenerateFile(OFILE_EXE, filepath, 0, BADADDR, 0) return GenerateFile(OFILE_EXE, filepath, 0, BADADDR, 0)
def AddConst(enum_id,name,value): return AddConstEx(enum_id,name,value,-1) def AddConst(enum_id,name,value): return AddConstEx(enum_id,name,value, idaapi.BADADDR)
def AddStruc(index,name): return AddStrucEx(index,name,0) def AddStruc(index,name): return AddStrucEx(index,name,0)
def AddUnion(index,name): return AddStrucEx(index,name,1) def AddUnion(index,name): return AddStrucEx(index,name,1)
def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0) def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0)

View File

@ -2,7 +2,7 @@
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# IDAPython - Python plugin for Interactive Disassembler Pro # IDAPython - Python plugin for Interactive Disassembler Pro
# #
# Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net> # Copyright (c) The IDAPython Team <idapython@googlegroups.com>
# #
# All rights reserved. # All rights reserved.
# #

View File

@ -48,6 +48,9 @@
%ignore shuffle_tribytes; %ignore shuffle_tribytes;
%ignore set_enum_id; %ignore set_enum_id;
%ignore validate_tofs; %ignore validate_tofs;
%ignore set_flags_nomark;
%ignore set_flbits_nomark;
%ignore clr_flbits_nomark;
%ignore ida_vpagesize; %ignore ida_vpagesize;
%ignore ida_vpages; %ignore ida_vpages;
%ignore ida_npagesize; %ignore ida_npagesize;

View File

@ -1,25 +1,10 @@
%ignore cancellable_graph_t::check_cancel; %ignore cancellable_graph_t;
%ignore gdl_graph_t::gen_gdl; %ignore gdl_graph_t;
%ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::path;
%ignore gdl_graph_t::path_exists;
%ignore gdl_graph_t::gen_dot;
%ignore intmap_t::dstr; %ignore intmap_t;
%ignore intmap_t::print; %ignore intset_t;
%ignore intseq_t::add_block; %ignore intseq_t;
%ignore intseq_t::add_unique; %ignore node_set_t;
%ignore intseq_t::del;
%ignore intseq_t::dstr;
%ignore intseq_t::print;
%ignore intseq_t::remove_block;
%ignore intset_t::dstr;
%ignore intset_t::print;
%ignore node_set_t::add;
%ignore node_set_t::extract;
%ignore node_set_t::intersect;
%ignore node_set_t::node_set_t;
%ignore node_set_t::sub;
%ignore qflow_chart_t::blocks; %ignore qflow_chart_t::blocks;
%ignore flow_chart_t; %ignore flow_chart_t;
%ignore default_graph_format; %ignore default_graph_format;

View File

@ -1,4 +1,27 @@
#ifdef __NT__ %ignore mutable_graph_t;
%ignore graph_visitor_t;
%ignore abstract_graph_t;
%{
#ifdef __GNUC__
// for some reason GCC insists on putting the vtable into the object file,
// even though we only use mutable_graph_t by pointer
// so we define these methods here to make the linker happy
edge_info_t *idaapi mutable_graph_t::get_edge(edge_t e) { INTERR(); };
mutable_graph_t *idaapi mutable_graph_t::clone(void) const { INTERR(); };
bool idaapi mutable_graph_t::redo_layout(void) { INTERR(); };
void idaapi mutable_graph_t::resize(int n) { INTERR(); };
int idaapi mutable_graph_t::add_node(const rect_t *r) { INTERR(); };
ssize_t idaapi mutable_graph_t::del_node(int n) { INTERR(); };
bool idaapi mutable_graph_t::add_edge(int i, int j, const edge_info_t *ei) { INTERR(); };
bool idaapi mutable_graph_t::del_edge(int i, int j) { INTERR(); };
bool idaapi mutable_graph_t::replace_edge(int i, int j, int x, int y) { INTERR(); };
bool idaapi mutable_graph_t::refresh(void) { INTERR(); };
bool idaapi mutable_graph_t::set_nrect(int n, const rect_t &r) { INTERR(); };
#endif
%}
%{ %{
//<code(py_graph)> //<code(py_graph)>
class py_graph_t class py_graph_t
@ -726,9 +749,7 @@ void pyg_select_node(PyObject *self, int nid)
} }
//</code(py_graph)> //</code(py_graph)>
%} %}
#endif // __NT__
#ifdef __NT__
%inline %{ %inline %{
//<inline(py_graph)> //<inline(py_graph)>
void pyg_refresh(PyObject *self); void pyg_refresh(PyObject *self);
@ -739,7 +760,6 @@ void pyg_select_node(PyObject *self, int nid);
bool pyg_show(PyObject *self); bool pyg_show(PyObject *self);
//</inline(py_graph)> //</inline(py_graph)>
%} %}
#endif // __NT__
%pythoncode %{ %pythoncode %{
#<pycode(py_graph)> #<pycode(py_graph)>

View File

@ -76,9 +76,7 @@
#include "err.h" #include "err.h"
#include "fpro.h" #include "fpro.h"
#include <map> #include <map>
#ifdef __NT__ #include "graph.hpp"
#include "graph.hpp"
#endif
//<code(py_idaapi)> //<code(py_idaapi)>
@ -114,6 +112,7 @@ static const char S_ON_DBL_CLICK[] = "OnDblClick";
static const char S_ON_CURSOR_POS_CHANGED[] = "OnCursorPosChanged"; static const char S_ON_CURSOR_POS_CHANGED[] = "OnCursorPosChanged";
static const char S_ON_KEYDOWN[] = "OnKeydown"; static const char S_ON_KEYDOWN[] = "OnKeydown";
static const char S_ON_COMPLETE_LINE[] = "OnCompleteLine"; 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_POPUP[] = "OnPopup";
static const char S_ON_HINT[] = "OnHint"; static const char S_ON_HINT[] = "OnHint";
static const char S_ON_POPUP_MENU[] = "OnPopupMenu"; static const char S_ON_POPUP_MENU[] = "OnPopupMenu";

View File

@ -16,12 +16,26 @@
%ignore askfile_cv; %ignore askfile_cv;
%ignore askyn_cv; %ignore askyn_cv;
%ignore askyn_v; %ignore askyn_v;
%ignore add_custom_viewer_popup_item;
%ignore create_custom_viewer;
%ignore destroy_custom_viewer;
%ignore destroy_custom_viewerdestroy_custom_viewer;
%ignore get_custom_viewer_place;
%ignore set_custom_viewer_popup_menu;
%ignore set_custom_viewer_handler;
%ignore set_custom_viewer_range;
%ignore is_idaview;
%ignore refresh_custom_viewer;
%ignore set_custom_viewer_handlers;
// Ignore these string functions. There are trivial replacements in Python. // Ignore these string functions. There are trivial replacements in Python.
%ignore addblanks; %ignore addblanks;
%ignore trim; %ignore trim;
%ignore skipSpaces; %ignore skipSpaces;
%ignore stristr; %ignore stristr;
%ignore get_highlighted_identifier;
%rename (get_highlighted_identifier) py_get_highlighted_identifier;
// CLI // CLI
%ignore cli_t; %ignore cli_t;
%ignore install_command_interpreter; %ignore install_command_interpreter;
@ -119,49 +133,6 @@ bool idaapi py_menu_item_callback(void *userdata)
return ret; return ret;
} }
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
//------------------------------------------------------------------------
/*
int py_execute_sync(PyObject *py_callable, int reqf)
{
if ( !PyCallable_Check(py_callable) )
return -1;
struct py_exec_request_t: exec_request_t
{
PyObject *py_callable;
virtual int idaapi execute(void)
{
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callable, NULL);
int r = py_result == NULL || !PyInt_Check(py_result) ? -1 : PyInt_AsLong(py_result);
Py_XDECREF(py_result);
return r;
}
py_exec_request_t(PyObject *pyc): py_callable(pyc) { }
};
py_exec_request_t req(py_callable);
return execute_sync(req, reqf);
}
*/
@ -753,11 +724,125 @@ PyObject *choose2_find(const char *title)
return NULL; return NULL;
return c2->get_self(); return c2->get_self();
} }
class plgform_t
{
private:
PyObject *py_obj;
TForm *form;
static int idaapi s_callback(void *ud, int notification_code, va_list va)
{
plgform_t *_this = (plgform_t *)ud;
if ( notification_code == ui_tform_visible )
{
TForm *form = va_arg(va, TForm *);
if ( form == _this->form )
{
PyObject *py_result = PyObject_CallMethod(
_this->py_obj,
(char *)S_ON_CREATE, "O",
PyCObject_FromVoidPtr(form, NULL));
PyW_ShowErr(S_ON_CREATE);
Py_XDECREF(py_result);
}
}
else if ( notification_code == ui_tform_invisible )
{
TForm *form = va_arg(va, TForm *);
if ( form == _this->form )
{
PyObject *py_result = PyObject_CallMethod(
_this->py_obj,
(char *)S_ON_CLOSE, "O",
PyCObject_FromVoidPtr(form, NULL));
PyW_ShowErr(S_ON_CLOSE);
Py_XDECREF(py_result);
_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__
Py_XDECREF(py_obj);
}
public:
plgform_t(): py_obj(NULL), 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 = obj;
Py_INCREF(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 *__new__()
{
return PyCObject_FromVoidPtr(new plgform_t(), __del__);
}
static void __del__(void *obj)
{
delete (plgform_t *)obj;
}
};
//</code(py_kernwin)> //</code(py_kernwin)>
%} %}
#ifdef __NT__
%{ %{
//<code(py_cli)> //<code(py_cli)>
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -778,7 +863,7 @@ struct py_cli_cbs_t
qstring *line, qstring *line,
int *p_x, int *p_x,
int *p_sellen, int *p_sellen,
uint16 *vk_key, int *vk_key,
int shift); int shift);
}; };
@ -796,7 +881,7 @@ private:
static const py_cli_cbs_t py_cli_cbs[MAX_PY_CLI]; static const py_cli_cbs_t py_cli_cbs[MAX_PY_CLI];
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
#define IMPL_PY_CLI_CB(CBN) \ #define IMPL_PY_CLI_CB(CBN) \
static bool idaapi s_keydown##CBN(qstring *line, int *p_x, int *p_sellen, uint16 *vk_key, int shift) \ 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); \ return py_clis[CBN]->on_keydown(line, p_x, p_sellen, vk_key, shift); \
} \ } \
@ -843,7 +928,7 @@ private:
qstring *line, qstring *line,
int *p_x, int *p_x,
int *p_sellen, int *p_sellen,
uint16 *vk_key, int *vk_key,
int shift) int shift)
{ {
PyObject *result = PyObject_CallMethod( PyObject *result = PyObject_CallMethod(
@ -1875,9 +1960,7 @@ public:
//</code(py_custviewer)> //</code(py_custviewer)>
%} %}
#endif
#ifdef __NT__
%inline %{ %inline %{
//<inline(py_cli)> //<inline(py_cli)>
static int py_install_command_interpreter(PyObject *py_obj) static int py_install_command_interpreter(PyObject *py_obj)
@ -2085,7 +2168,6 @@ bool pyscv_edit_line(PyObject *py_this, size_t nline, PyObject *py_sl)
#undef DECL_THIS #undef DECL_THIS
//</inline(py_custviewer)> //</inline(py_custviewer)>
%} %}
#endif // __NT__
%inline %{ %inline %{
uint32 idaapi choose_sizer(void *self) uint32 idaapi choose_sizer(void *self)
@ -2179,7 +2261,28 @@ uint32 choose_choose(void *self,
//<inline(py_kernwin)> //<inline(py_kernwin)>
//------------------------------------------------------------------------ //------------------------------------------------------------------------
//------------------------------------------------------------------------
/*
#<pydoc>
def get_highlighted_identifier(flags = 0):
"""
Returns the currently highlighted identifier
@param flags: reserved (pass 0)
@return: None or the highlighted identifier
"""
pass
#</pydoc>
*/
static PyObject *py_get_highlighted_identifier(int flags = 0)
{
char buf[MAXSTR];
bool ok = get_highlighted_identifier(buf, sizeof(buf), flags);
if ( !ok )
Py_RETURN_NONE;
else
return PyString_FromString(buf);
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
/* /*
@ -2374,8 +2477,62 @@ def py_execute_sync(callable, reqf)
""" """
pass pass
#</pyd0c> #</pyd0c>
//------------------------------------------------------------------------
static int py_execute_sync(PyObject *py_callable, int reqf)
{
if ( !PyCallable_Check(py_callable) )
return -1;
struct py_exec_request_t: exec_request_t
{
PyObject *py_callable;
virtual int idaapi execute(void)
{
PyGILState_STATE state = PyGILState_Ensure();
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callable, NULL);
int r = py_result == NULL || !PyInt_Check(py_result) ? -1 : PyInt_AsLong(py_result);
Py_XDECREF(py_result);
PyGILState_Release(state);
return r;
}
py_exec_request_t(PyObject *pyc): py_callable(pyc)
{
}
};
py_exec_request_t req(py_callable);
return execute_sync(req, reqf);
}
*/
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
//------------------------------------------------------------------------
/*
#<pydoc>
def is_idaq():
"""
Returns True or False depending if IDAPython is hosted by IDAQ
"""
#</pydoc>
*/ */
//int py_execute_sync(PyObject *py_callable, int reqf);
@ -2385,6 +2542,32 @@ void choose2_refresh(PyObject *self);
void choose2_close(PyObject *self); void choose2_close(PyObject *self);
int choose2_show(PyObject *self); int choose2_show(PyObject *self);
void choose2_activate(PyObject *self); void choose2_activate(PyObject *self);
#define DECL_PLGFORM plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link);
static PyObject *plgform_new()
{
return plgform_t::__new__();
}
static bool plgform_show(
PyObject *py_link,
PyObject *py_obj,
const char *caption,
int options = FORM_MDI|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
//</inline(py_kernwin)> //</inline(py_kernwin)>
%} %}
@ -2617,6 +2800,107 @@ class Choose2(object):
# """Return list [bgcolor, flags=CHITEM_XXXX] or None; check chooser_item_attrs_t""" # """Return list [bgcolor, flags=CHITEM_XXXX] or None; check chooser_item_attrs_t"""
# return [0x0, CHITEM_BOLD] # return [0x0, CHITEM_BOLD]
#</pydoc> #</pydoc>
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"""
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_MDI|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
"""
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__)
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"""
#</pycode(py_kernwin)> #</pycode(py_kernwin)>
%} %}

View File

@ -37,6 +37,8 @@
%ignore wchar2char; %ignore wchar2char;
%ignore u2cstr; %ignore u2cstr;
%ignore c2ustr; %ignore c2ustr;
%ignore base64_encode;
%ignore base64_decode;
%ignore utf8_unicode; %ignore utf8_unicode;
%ignore win_utf2idb; %ignore win_utf2idb;
%ignore char2oem; %ignore char2oem;