mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-24 01:59:18 +01:00
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:
parent
1d2f1d1f07
commit
ac5d88a83b
33
BUILDING.txt
33
BUILDING.txt
@ -9,13 +9,14 @@ REQUIREMENTS
|
||||
|
||||
[Tested versions are in brackets]
|
||||
|
||||
- IDA and IDA SDK [5.6]
|
||||
|
||||
- IDA and IDA SDK [> 5.6]
|
||||
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/
|
||||
|
||||
- Simplified Wrapper Interface Generator (SWIG) [1.3.36]
|
||||
- Simplified Wrapper Interface Generator (SWIG) [2.0]
|
||||
http://www.swig.org/
|
||||
|
||||
- Unix utilities (GNU patch on Windows):
|
||||
@ -35,18 +36,18 @@ BUILDING
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
|
||||
2, On Mac OS X copy libida.dylib from the IDA install directory to
|
||||
swigsdk-versions/5.6/lib/gcc32.mac/
|
||||
2. On Mac OS X copy libida.dylib from the IDA install directory to
|
||||
swigsdk-versions/x.y/lib/gcc32.mac/
|
||||
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
|
||||
|
||||
@ -55,6 +56,18 @@ Make sure all the needed tools (compiler, swig) are on the PATH.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
10
CHANGES.txt
10
CHANGES.txt
@ -1,5 +1,14 @@
|
||||
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
|
||||
------------------------------------
|
||||
- Added command completion
|
||||
@ -127,4 +136,3 @@ Changes from version 0.5.0 to 0.6.0
|
||||
- Bunch of misc small cleanups and fixes
|
||||
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
|
||||
|
||||
|
||||
|
22
README.txt
22
README.txt
@ -16,7 +16,7 @@ AVAILABILITY
|
||||
------------
|
||||
|
||||
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
|
||||
http://code.google.com/p/idapython/
|
||||
@ -26,7 +26,7 @@ RESOURCES
|
||||
---------
|
||||
|
||||
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
|
||||
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
|
||||
--------------------------
|
||||
|
||||
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
|
||||
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
|
||||
3. Copy the plugins to the %IDADIR%\plugins\
|
||||
|
||||
|
||||
USAGE
|
||||
-----
|
||||
|
||||
The plugin has three hotkeys:
|
||||
|
||||
- Run script (Alt-9)
|
||||
- Execute Python statement(s) (Alt-8)
|
||||
- Run previously executed script again (Alt-7)
|
||||
- Run script: File / Script file (Alt-F7)
|
||||
- Execute Python statement(s) (Ctrl-F3)
|
||||
- Run previously executed script again: View / Recent Scripts (Alt+F9)
|
||||
|
||||
Batch mode execution:
|
||||
|
||||
Start IDA with the following command line options:
|
||||
|
||||
-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
|
||||
exits with a qexit() call.
|
||||
|
8
build.py
8
build.py
@ -23,8 +23,8 @@ from distutils import sysconfig
|
||||
# Start of user configurable options
|
||||
VERBOSE = True
|
||||
|
||||
IDA_MAJOR_VERSION = 5
|
||||
IDA_MINOR_VERSION = 7
|
||||
IDA_MAJOR_VERSION = 6
|
||||
IDA_MINOR_VERSION = 0
|
||||
|
||||
if 'IDA' in os.environ:
|
||||
IDA_SDK = os.environ['IDA']
|
||||
@ -36,7 +36,7 @@ else:
|
||||
# IDAPython version
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 4
|
||||
VERSION_PATCH = 2
|
||||
VERSION_PATCH = 3
|
||||
|
||||
# Determine Python version
|
||||
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
|
||||
@ -89,6 +89,8 @@ BINDIST_MANIFEST = [
|
||||
"examples/ex_dbg.py",
|
||||
"examples/ex_custview.py",
|
||||
"examples/ex_prefix_plugin.py",
|
||||
"examples/ex_pyside.py",
|
||||
"examples/ex_pyqt.py",
|
||||
"examples/ex_imports.py"
|
||||
]
|
||||
|
||||
|
@ -3,30 +3,38 @@ import idaapi
|
||||
# -----------------------------------------------------------------------
|
||||
# Using raw IDAAPI
|
||||
def raw_main(p=True):
|
||||
global q
|
||||
f = idaapi.get_func(here())
|
||||
if not f:
|
||||
return
|
||||
|
||||
q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS)
|
||||
for n in xrange(0, q.size()):
|
||||
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)):
|
||||
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)):
|
||||
if p: print " %d->%d" % (n, q.pred(n, ns))
|
||||
if p:
|
||||
print " %d->%d" % (n, q.pred(n, ns))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Using the class
|
||||
def cls_main(p=True):
|
||||
global f
|
||||
f = idaapi.FlowChart(idaapi.get_func(here()))
|
||||
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():
|
||||
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():
|
||||
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
|
||||
f = None
|
||||
|
70
python.cpp
70
python.cpp
@ -52,7 +52,7 @@
|
||||
static const char S_IDC_ARGS_VARNAME[] = "ARGV";
|
||||
static const char S_MAIN[] = "__main__";
|
||||
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";
|
||||
|
||||
#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
|
||||
// Note: The references are borrowed. No need to free them.
|
||||
PyObject *GetMainGlobals()
|
||||
static PyObject *GetMainGlobals()
|
||||
{
|
||||
PyObject *module = PyImport_AddModule(S_MAIN);
|
||||
if ( module == NULL )
|
||||
@ -328,6 +328,42 @@ PyObject *GetMainGlobals()
|
||||
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
|
||||
static const char idc_runpythonstatement_args[] = { VT_STR2, 0 };
|
||||
@ -654,11 +690,14 @@ bool idaapi IDAPython_extlang_run(
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(func);
|
||||
PyObject *pres = PyEval_EvalCodeEx(
|
||||
code,
|
||||
globals, NULL, &pargs[0], nargs,
|
||||
globals, NULL,
|
||||
&pargs[0], nargs,
|
||||
NULL, 0, NULL, 0, NULL);
|
||||
|
||||
ok = return_python_result(result, pres, errbuf, errbufsize);
|
||||
} while ( false );
|
||||
|
||||
@ -666,6 +705,7 @@ bool idaapi IDAPython_extlang_run(
|
||||
|
||||
if ( imported_module )
|
||||
Py_XDECREF(module);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -1002,29 +1042,27 @@ void enable_extlang_python(bool enable)
|
||||
// Execute a line in the Python CLI
|
||||
bool idaapi IDAPython_cli_execute_line(const char *line)
|
||||
{
|
||||
const char *first_line = strrchr(line, '\n');
|
||||
if ( first_line == NULL )
|
||||
first_line = line;
|
||||
// do not process empty lines
|
||||
if ( line[0] == '\0' )
|
||||
return true;
|
||||
|
||||
const char *last_line = strrchr(line, '\n');
|
||||
if ( last_line == NULL )
|
||||
last_line = line;
|
||||
else
|
||||
first_line += 1;
|
||||
last_line += 1;
|
||||
|
||||
// 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?
|
||||
bool more = tline[qstrlen(tline)-1] == ':' || isspace(first_line[0]);
|
||||
qfree(tline);
|
||||
|
||||
bool more = last_line[qstrlen(last_line)-1] == ':' || isspace(last_line[0]);
|
||||
if ( more )
|
||||
return false;
|
||||
}
|
||||
|
||||
begin_execution();
|
||||
PyRun_SimpleString(line);
|
||||
PythonEvalOrExec(line);
|
||||
end_execution();
|
||||
|
||||
return true;
|
||||
|
@ -16,6 +16,7 @@ import idc
|
||||
import types
|
||||
import os
|
||||
|
||||
|
||||
def refs(ea, funcfirst, funcnext):
|
||||
"""
|
||||
Generic reference collector - INTERNAL USE ONLY.
|
||||
@ -241,6 +242,7 @@ def Chunks(start):
|
||||
yield (chunk.startEA, chunk.endEA)
|
||||
status = func_iter.next()
|
||||
|
||||
|
||||
def Modules():
|
||||
"""
|
||||
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)
|
||||
result = idaapi.get_next_module(mod)
|
||||
|
||||
|
||||
def Names():
|
||||
"""
|
||||
Returns a list of names
|
||||
|
||||
@return: tuple(ea, name)
|
||||
@return: List of tuples (ea, name)
|
||||
"""
|
||||
for i in xrange(idaapi.get_nlist_size()):
|
||||
ea = idaapi.get_nlist_ea(i)
|
||||
name = idaapi.get_nlist_name(i)
|
||||
yield (ea, name)
|
||||
|
||||
|
||||
def Segments():
|
||||
"""
|
||||
Get list of segments (sections) in the binary image
|
||||
@ -274,6 +278,20 @@ def Segments():
|
||||
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):
|
||||
"""
|
||||
Get a list of function items
|
||||
@ -475,11 +493,6 @@ class Strings(object):
|
||||
|
||||
return None
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetRegisterList():
|
||||
"""Returns the register list"""
|
||||
return idaapi.ph_get_regnames()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetIdbDir():
|
||||
"""
|
||||
@ -489,6 +502,11 @@ def GetIdbDir():
|
||||
"""
|
||||
return os.path.dirname(idaapi.cvar.database_idb) + os.sep
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetRegisterList():
|
||||
"""Returns the register list"""
|
||||
return idaapi.ph_get_regnames()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def GetInstructionList():
|
||||
"""Returns the instruction list of the current processor module"""
|
||||
|
@ -7530,7 +7530,7 @@ def WriteTxt(filepath, ea1, ea2):
|
||||
def WriteExe(filepath):
|
||||
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 AddUnion(index,name): return AddStrucEx(index,name,1)
|
||||
def OpStroff(ea,n,strid): return OpStroffEx(ea,n,strid,0)
|
||||
|
@ -2,7 +2,7 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# 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.
|
||||
#
|
||||
|
@ -48,6 +48,9 @@
|
||||
%ignore shuffle_tribytes;
|
||||
%ignore set_enum_id;
|
||||
%ignore validate_tofs;
|
||||
%ignore set_flags_nomark;
|
||||
%ignore set_flbits_nomark;
|
||||
%ignore clr_flbits_nomark;
|
||||
%ignore ida_vpagesize;
|
||||
%ignore ida_vpages;
|
||||
%ignore ida_npagesize;
|
||||
|
27
swig/gdl.i
27
swig/gdl.i
@ -1,25 +1,10 @@
|
||||
%ignore cancellable_graph_t::check_cancel;
|
||||
%ignore gdl_graph_t::gen_gdl;
|
||||
%ignore gdl_graph_t::gen_gdl;
|
||||
%ignore gdl_graph_t::path;
|
||||
%ignore gdl_graph_t::path_exists;
|
||||
%ignore gdl_graph_t::gen_dot;
|
||||
%ignore cancellable_graph_t;
|
||||
%ignore gdl_graph_t;
|
||||
|
||||
%ignore intmap_t::dstr;
|
||||
%ignore intmap_t::print;
|
||||
%ignore intseq_t::add_block;
|
||||
%ignore intseq_t::add_unique;
|
||||
%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 intmap_t;
|
||||
%ignore intset_t;
|
||||
%ignore intseq_t;
|
||||
%ignore node_set_t;
|
||||
%ignore qflow_chart_t::blocks;
|
||||
%ignore flow_chart_t;
|
||||
%ignore default_graph_format;
|
||||
|
28
swig/graph.i
28
swig/graph.i
@ -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)>
|
||||
class py_graph_t
|
||||
@ -726,9 +749,7 @@ void pyg_select_node(PyObject *self, int nid)
|
||||
}
|
||||
//</code(py_graph)>
|
||||
%}
|
||||
#endif // __NT__
|
||||
|
||||
#ifdef __NT__
|
||||
%inline %{
|
||||
//<inline(py_graph)>
|
||||
void pyg_refresh(PyObject *self);
|
||||
@ -739,7 +760,6 @@ void pyg_select_node(PyObject *self, int nid);
|
||||
bool pyg_show(PyObject *self);
|
||||
//</inline(py_graph)>
|
||||
%}
|
||||
#endif // __NT__
|
||||
|
||||
%pythoncode %{
|
||||
#<pycode(py_graph)>
|
||||
|
@ -76,9 +76,7 @@
|
||||
#include "err.h"
|
||||
#include "fpro.h"
|
||||
#include <map>
|
||||
#ifdef __NT__
|
||||
#include "graph.hpp"
|
||||
#endif
|
||||
#include "graph.hpp"
|
||||
|
||||
//<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_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";
|
||||
|
386
swig/kernwin.i
386
swig/kernwin.i
@ -16,12 +16,26 @@
|
||||
%ignore askfile_cv;
|
||||
%ignore askyn_cv;
|
||||
%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 addblanks;
|
||||
%ignore trim;
|
||||
%ignore skipSpaces;
|
||||
%ignore stristr;
|
||||
|
||||
%ignore get_highlighted_identifier;
|
||||
%rename (get_highlighted_identifier) py_get_highlighted_identifier;
|
||||
|
||||
// CLI
|
||||
%ignore cli_t;
|
||||
%ignore install_command_interpreter;
|
||||
@ -119,49 +133,6 @@ bool idaapi py_menu_item_callback(void *userdata)
|
||||
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 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)>
|
||||
|
||||
%}
|
||||
|
||||
#ifdef __NT__
|
||||
%{
|
||||
//<code(py_cli)>
|
||||
//--------------------------------------------------------------------------
|
||||
@ -778,7 +863,7 @@ struct py_cli_cbs_t
|
||||
qstring *line,
|
||||
int *p_x,
|
||||
int *p_sellen,
|
||||
uint16 *vk_key,
|
||||
int *vk_key,
|
||||
int shift);
|
||||
};
|
||||
|
||||
@ -796,7 +881,7 @@ private:
|
||||
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, 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); \
|
||||
} \
|
||||
@ -843,7 +928,7 @@ private:
|
||||
qstring *line,
|
||||
int *p_x,
|
||||
int *p_sellen,
|
||||
uint16 *vk_key,
|
||||
int *vk_key,
|
||||
int shift)
|
||||
{
|
||||
PyObject *result = PyObject_CallMethod(
|
||||
@ -1875,9 +1960,7 @@ public:
|
||||
|
||||
//</code(py_custviewer)>
|
||||
%}
|
||||
#endif
|
||||
|
||||
#ifdef __NT__
|
||||
%inline %{
|
||||
//<inline(py_cli)>
|
||||
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
|
||||
//</inline(py_custviewer)>
|
||||
%}
|
||||
#endif // __NT__
|
||||
|
||||
%inline %{
|
||||
uint32 idaapi choose_sizer(void *self)
|
||||
@ -2179,7 +2261,28 @@ uint32 choose_choose(void *self,
|
||||
//<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
|
||||
#</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);
|
||||
int choose2_show(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)>
|
||||
%}
|
||||
|
||||
@ -2617,6 +2800,107 @@ class Choose2(object):
|
||||
# """Return list [bgcolor, flags=CHITEM_XXXX] or None; check chooser_item_attrs_t"""
|
||||
# return [0x0, CHITEM_BOLD]
|
||||
#</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)>
|
||||
%}
|
||||
|
||||
|
@ -37,6 +37,8 @@
|
||||
%ignore wchar2char;
|
||||
%ignore u2cstr;
|
||||
%ignore c2ustr;
|
||||
%ignore base64_encode;
|
||||
%ignore base64_decode;
|
||||
%ignore utf8_unicode;
|
||||
%ignore win_utf2idb;
|
||||
%ignore char2oem;
|
||||
|
Loading…
Reference in New Issue
Block a user