added PyWraps sources. This will facilitate deployment, development and debugging of IDAPython additions

This commit is contained in:
elias.bachaalany@gmail.com 2011-12-02 15:40:11 +00:00
parent 1258fab948
commit 930d7cbcd4
69 changed files with 24434 additions and 0 deletions

125
pywraps/deploy.bat Normal file
View File

@ -0,0 +1,125 @@
@echo off
rem Please use the same tag for the same .i file
rem That means if many insertions are going to happen in one given .i file then don't use more than code marking tag
set PY=c:\python26\python.exe
echo.
echo -------- DEPLOY started --------------------------------------------------
echo.
rem --------------------------------------------------------------------------
echo Deploying idaapi (common functions, notifywhen)
%PY% deploy.py py_idaapi py_cvt.hpp,py_idaapi.hpp,py_idaapi.py,py_notifywhen.hpp,py_notifywhen.py ..\swig\idaapi.i
rem --------------------------------------------------------------------------
echo Deploying Graph
%PY% deploy.py py_graph py_graph.hpp,py_graph.py ..\swig\graph.i
rem --------------------------------------------------------------------------
echo Deploying custview
%PY% deploy.py py_custviewer py_custview.py,py_custview.hpp ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying plgform
%PY% deploy.py py_plgform py_plgform.hpp,py_plgform.py ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying expr
%PY% deploy.py py_expr py_expr.hpp,py_expr.py ..\swig\expr.i
rem --------------------------------------------------------------------------
echo Deploying cli
%PY% deploy.py py_cli py_cli.py,py_cli.hpp ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying Loader
%PY% deploy.py py_loader py_loader.hpp ..\swig\loader.i
rem --------------------------------------------------------------------------
echo Deploying kernwin, choose2, askusingform
%PY% deploy.py py_kernwin py_kernwin.hpp,py_kernwin.py,py_choose.hpp,py_choose2.hpp,py_choose2.py,py_askusingform.hpp,py_askusingform.py ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying idd
%PY% deploy.py py_idd py_dbg.hpp,py_appcall.py ..\swig\idd.i
rem --------------------------------------------------------------------------
echo Deploying nalt
%PY% deploy.py py_nalt py_nalt.hpp,py_nalt.py ..\swig\nalt.i
rem --------------------------------------------------------------------------
echo Deploying dbg
%PY% deploy.py py_dbg py_dbg.hpp ..\swig\dbg.i
rem --------------------------------------------------------------------------
echo Deploying linput/diskio
%PY% deploy.py py_diskio py_linput.hpp,py_diskio.hpp,py_diskio.py ..\swig\diskio.i
rem --------------------------------------------------------------------------
echo Deploying name
%PY% deploy.py py_name py_name.hpp,py_name.py ..\swig\name.i
rem --------------------------------------------------------------------------
echo Deploying qfile
%PY% deploy.py py_qfile py_qfile.hpp ..\swig\fpro.i
rem --------------------------------------------------------------------------
echo Deploying bytes
%PY% deploy.py py_bytes py_bytes.hpp,py_custdata.py,py_custdata.hpp ..\swig\bytes.i
rem --------------------------------------------------------------------------
echo Deploying typeinf
%PY% deploy.py py_typeinf py_typeinf.hpp ..\swig\typeinf.i
rem --------------------------------------------------------------------------
echo Deploying gdl
%PY% deploy.py py_gdl py_gdl.py ..\swig\gdl.i
rem --------------------------------------------------------------------------
echo Deploying ua
%PY% deploy.py py_ua py_ua.hpp,py_ua.py ..\swig\ua.i
rem --------------------------------------------------------------------------
echo Deploying idp
%PY% deploy.py py_idp py_idp.hpp ..\swig\idp.i
rem --------------------------------------------------------------------------
echo Deploying lines
%PY% deploy.py py_lines py_lines.hpp,py_lines.py ..\swig\lines.i
rem --------------------------------------------------------------------------
echo Deploying pc_win32_appcall
%PY% deploy.py appcalltest py_appcall.py ..\..\..\ida\tests\input\pc_win32_appcall.pe.hints
rem --------------------------------------------------------------------------
echo Deploying ex_custdata example
%PY% deploy.py ex_custdata ..\examples\ex_custdata.py ..\..\..\ida\tests\input\pc_win32_custdata1.pe.hints
rem --------------------------------------------------------------------------
echo Deploying ex_formchooser
%PY% deploy.py ex_formchooser py_askusingform.py ..\..\formchooser\formchooser.py
rem --------------------------------------------------------------------------
echo Deploying ex_askusingform
%PY% deploy.py ex_askusingform py_askusingform.py ..\examples\ex_askusingform.py
rem --------------------------------------------------------------------------
echo Deploying ex_cli example
%PY% deploy.py ex_cli_ex1 py_cli.py ..\examples\ex_cli.py
rem --------------------------------------------------------------------------
echo Deploying ex_expr example
%PY% deploy.py ex_expr py_expr.py ..\examples\ex_expr.py
rem --------------------------------------------------------------------------
echo Deploying ex_custview.py example
%PY% deploy.py py_custviewerex1 py_custview.py ..\examples\ex_custview.py
rem --------------------------------------------------------------------------
echo.
echo -------- DEPLOY finished -------------------------------------------------
echo.
:end

91
pywraps/deploy.py Normal file
View File

@ -0,0 +1,91 @@
"""
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</%(tag)s\(%(m)s\)>' % {'m': mod_name, 'tag': tag, 'p': prefix}
return (s, re.compile(s, re.DOTALL))
def deploy(mod_name, src_files, dest_file, silent = True):
# 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'])
main()

172
pywraps/driver.cpp Normal file
View File

@ -0,0 +1,172 @@
//--------------------------------------------------------------------------
// IDA includes
#include <windows.h>
#include <pro.h>
#include <ida.hpp>
#include <idp.hpp>
#include <loader.hpp>
#include <bytes.hpp>
#include <enum.hpp>
#include <kernwin.hpp>
#include <diskio.hpp>
#include <bytes.hpp>
#include <graph.hpp>
#include <map>
#include <idd.hpp>
#include <dbg.hpp>
#include <ieee.h>
#include <err.h>
#include <expr.hpp>
#include <typeinf.hpp>
#include <struct.hpp>
#include <nalt.hpp>
#include <frame.hpp>
//--------------------------------------------------------------------------
// PyWraps
#include <Python.h>
#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<PyMethodDef> 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
"Alt-0" // the preferred hotkey to run the plugin
};

19
pywraps/driver_bytes.cpp Normal file
View File

@ -0,0 +1,19 @@
#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);

109
pywraps/driver_chooser.cpp Normal file
View File

@ -0,0 +1,109 @@
#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);

29
pywraps/driver_cli.cpp Normal file
View File

@ -0,0 +1,29 @@
#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);

View File

@ -0,0 +1,77 @@
#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;

384
pywraps/driver_custview.cpp Normal file
View File

@ -0,0 +1,384 @@
#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; i<qnumber(sample_lines); i++ )
{
lines.push_back(simpleline_t("")); // add empty line
lines.push_back(simpleline_t(sample_lines[i].text));
lines.back().bgcolor = sample_lines[i].color;
}
}
my_custviewer()
{
id_n = 0;
init_sample_lines();
data.set_minmax();
}
bool init(const char *title)
{
if ( id_n != 0 )
return true;
if ( !create(title, HAVE_HINT | HAVE_CLICK | HAVE_KEYDOWN | HAVE_CURPOS, &data) )
return false;
id_n = add_popup_menu("Do this", "N");
return true;
}
};
my_custviewer *g_cv;
//-------------------------------------------------------------------------
static PyObject *ex_pyscv_init(PyObject *self, PyObject *args)
{
const char *title;
PyObject *py_link;
if ( !PyArg_ParseTuple(args, "Os", &py_link, &title) )
return NULL;
return pyscv_init(py_link, title);
}
static PyObject *ex_pyscv_add_line(PyObject *self, PyObject *args)
{
PyObject *py_this, *py_sl;
if ( !PyArg_ParseTuple(args, "OO", &py_this, &py_sl) )
return NULL;
return Py_BuildValue("i", pyscv_add_line(py_this, py_sl));
}
static PyObject *ex_pyscv_delete(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return Py_BuildValue("i", pyscv_delete(py_this));
}
static PyObject *ex_pyscv_show(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return Py_BuildValue("i", pyscv_show(py_this));
}
static PyObject *ex_pyscv_refresh(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return Py_BuildValue("i", pyscv_refresh(py_this));
}
static PyObject *ex_pyscv_close(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
pyscv_close(py_this);
Py_RETURN_NONE;
}
static PyObject *ex_pyscv_clear_popup_menu(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
pyscv_clear_popup_menu(py_this);
Py_RETURN_NONE;
}
static PyObject *ex_pyscv_del_line(PyObject *self, PyObject *args)
{
PyObject *py_this;
size_t nline;
if ( !PyArg_ParseTuple(args, "O" PY_FMT64, &py_this, &nline) )
return NULL;
return Py_BuildValue("i", pyscv_del_line(py_this, nline));
}
static PyObject *ex_pyscv_get_pos(PyObject *self, PyObject *args)
{
PyObject *py_this;
int mouse;
if ( !PyArg_ParseTuple(args, "Oi", &py_this, &mouse) )
return NULL;
return pyscv_get_pos(py_this, mouse == 0 ? false : true);
}
static PyObject *ex_pyscv_refresh_current(PyObject *self, PyObject *args)
{
PyObject *py_this;
int mouse;
if ( !PyArg_ParseTuple(args, "Oi", &py_this, &mouse) )
return NULL;
return Py_BuildValue("i", pyscv_refresh_current(py_this));
}
static PyObject *ex_pyscv_get_current_line(PyObject *self, PyObject *args)
{
PyObject *py_this;
int mouse, notags;
if ( !PyArg_ParseTuple(args, "Oii", &py_this, &mouse, &notags) )
return NULL;
return pyscv_get_current_line(py_this, mouse == 0 ? false : true, notags == 0 ? false : true);
}
static PyObject *ex_pyscv_is_focused(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return Py_BuildValue("i", pyscv_is_focused(py_this));
}
static PyObject *ex_pyscv_add_popup_menu(PyObject *self, PyObject *args)
{
PyObject *py_this;
const char *title, *hotkey;
if ( !PyArg_ParseTuple(args, "Oss", &py_this, &title, &hotkey) )
return NULL;
return Py_BuildValue("i", pyscv_add_popup_menu(py_this, title, hotkey));
}
static PyObject *ex_pyscv_get_line(PyObject *self, PyObject *args)
{
PyObject *py_this;
size_t nline;
if ( !PyArg_ParseTuple(args, "O" PY_FMT64, &py_this, &nline) )
return NULL;
return pyscv_get_line(py_this, nline);
}
static PyObject *ex_pyscv_jumpto(PyObject *self, PyObject *args)
{
PyObject *py_this;
int x, y;
size_t lineno;
if ( !PyArg_ParseTuple(args, "O" PY_FMT64 "ii", &py_this, &lineno, &x, &y) )
return NULL;
return Py_BuildValue("i", pyscv_jumpto(py_this, lineno, x, y));
}
static PyObject *ex_pyscv_edit_line(PyObject *self, PyObject *args)
{
PyObject *py_this, *py_sl;
size_t lineno;
if ( !PyArg_ParseTuple(args, "O" PY_FMT64 "O", &py_this, &lineno, &py_sl) )
return NULL;
return Py_BuildValue("i", pyscv_edit_line(py_this, lineno, py_sl));
}
static PyObject *ex_pyscv_insert_line(PyObject *self, PyObject *args)
{
PyObject *py_this, *py_sl;
size_t lineno;
if ( !PyArg_ParseTuple(args, "O" PY_FMT64 "O", &py_this, &lineno, &py_sl) )
return NULL;
return Py_BuildValue("i", pyscv_insert_line(py_this, lineno, py_sl));
}
static PyObject *ex_pyscv_patch_line(PyObject *self, PyObject *args)
{
PyObject *py_this;
size_t lineno, offs;
int value;
if ( !PyArg_ParseTuple(args, "O" PY_FMT64 PY_FMT64 "i", &py_this, &lineno, &offs, &value) )
return NULL;
return Py_BuildValue("i", pyscv_patch_line(py_this, lineno, offs, value));
}
static PyObject *ex_pyscv_count(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return Py_BuildValue(PY_FMT64, pyscv_count(py_this));
}
static PyObject *ex_pyscv_get_selection(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return pyscv_get_selection(py_this);
}
static PyObject *ex_pyscv_get_current_word(PyObject *self, PyObject *args)
{
PyObject *py_this;
int mouse;
if ( !PyArg_ParseTuple(args, "Oi", &py_this, &mouse) )
return NULL;
return pyscv_get_current_word(py_this, mouse != 0);
}
static PyObject *ex_pyscv_clear_lines(PyObject *self, PyObject *args)
{
PyObject *py_this;
if ( !PyArg_ParseTuple(args, "O", &py_this) )
return NULL;
return pyscv_clear_lines(py_this);
}
//-------------------------------------------------------------------------
static PyMethodDef py_methods_custview[] =
{
{"pyscv_init", ex_pyscv_init, METH_VARARGS, ""},
{"pyscv_close", ex_pyscv_close, METH_VARARGS, ""},
{"pyscv_add_line", ex_pyscv_add_line, METH_VARARGS, ""},
{"pyscv_delete", ex_pyscv_delete, METH_VARARGS, ""},
{"pyscv_refresh", ex_pyscv_refresh, METH_VARARGS, ""},
{"pyscv_clear_lines", ex_pyscv_clear_lines, METH_VARARGS, ""},
{"pyscv_show", ex_pyscv_show, METH_VARARGS, ""},
{"pyscv_clear_popup_menu", ex_pyscv_clear_popup_menu, METH_VARARGS, ""},
{"pyscv_del_line", ex_pyscv_del_line, METH_VARARGS, ""},
{"pyscv_get_pos", ex_pyscv_get_pos, METH_VARARGS, ""},
{"pyscv_refresh_current", ex_pyscv_refresh_current, METH_VARARGS, ""},
{"pyscv_get_current_line", ex_pyscv_get_current_line, METH_VARARGS, ""},
{"pyscv_is_focused", ex_pyscv_is_focused, METH_VARARGS, ""},
{"pyscv_add_popup_menu", ex_pyscv_add_popup_menu, METH_VARARGS, ""},
{"pyscv_get_line", ex_pyscv_get_line, METH_VARARGS, ""},
{"pyscv_jumpto", ex_pyscv_jumpto, METH_VARARGS, ""},
{"pyscv_edit_line", ex_pyscv_edit_line, METH_VARARGS, ""},
{"pyscv_insert_line", ex_pyscv_insert_line, METH_VARARGS, ""},
{"pyscv_count", ex_pyscv_count, METH_VARARGS, ""},
{"pyscv_patch_line", ex_pyscv_patch_line, METH_VARARGS, ""},
{"pyscv_get_selection", ex_pyscv_get_selection, METH_VARARGS, ""},
{"pyscv_get_current_word", ex_pyscv_get_current_word, METH_VARARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */
};
DRIVER_INIT_METHODS(custview);
#define DRIVER_RUN
void driver_run(int)
{
if ( !g_cv->init("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;
}

78
pywraps/driver_dbg.cpp Normal file
View File

@ -0,0 +1,78 @@
#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;
if ( pyvar_to_idcvar(self, &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);

47
pywraps/driver_diskio.cpp Normal file
View File

@ -0,0 +1,47 @@
#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);

56
pywraps/driver_expr.cpp Normal file
View File

@ -0,0 +1,56 @@
#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);

44
pywraps/driver_graph.cpp Normal file
View File

@ -0,0 +1,44 @@
#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);

View File

@ -0,0 +1,78 @@
#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);

18
pywraps/driver_nalt.cpp Normal file
View File

@ -0,0 +1,18 @@
#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);

View File

@ -0,0 +1,36 @@
#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();
}

336
pywraps/link_gen.py Normal file
View File

@ -0,0 +1,336 @@
import types
C_TO_PY_CAST = {
'b' : 'char',
'i' : 'int',
'H' : 'uint16',
'h' : 'int16',
'B' : 'uchar',
}
# --------------------------------------------------------------------------------------------
class gen_fmt(object):
def __init__(self, fields, tp = None, bv = None, cast=None, cmt = None):
self.fields = fields
self.tp = tp
# Format to be passed to Py_BuildValue
if not bv:
self.bv = "XXX"
else:
if bv == "K":
self.bv = "PY_FMT64"
else:
self.bv = '"%s"' % bv
if not cast:
if bv == "K":
cast = "pyul_t"
elif bv in C_TO_PY_CAST:
cast = C_TO_PY_CAST[bv]
self.cast = "" if not cast else "(%s)" % cast
self.cmt = cmt
if bv == "K":
self.setcvt = "uint64 v(0); PyGetNumber(value, &v);"
elif bv == 'i':
self.setcvt = "int v = PyInt_AsLong(value);"
else:
self.setcvt = "uint64 v = %sPyInt_AsLong(value);" % self.cast
# --------------------------------------------------------------------------------------------
switch_info_ex_t_gen = [
gen_fmt('regdtyp', bv = 'b', cmt = 'size of the switch expression register as dtyp'),
gen_fmt('flags2', bv = 'i'),
gen_fmt('jcases', bv = 'i', cmt = 'number of entries in the jump table (SWI2_INDIRECT)'),
gen_fmt('regnum', bv = 'i', cmt = 'the switch expression as a register number'),
gen_fmt('flags', bv = 'H', cmt = 'the switch expression as a register number'),
gen_fmt('ncases', bv = 'H', cmt = 'number of cases (excluding default)'),
gen_fmt('defjump', bv = 'K', cmt = 'default jump address'),
gen_fmt('jumps', bv = 'K', cmt = 'jump table address'),
gen_fmt('elbase', bv = 'K', cmt = 'element base'),
gen_fmt('startea', bv = 'K', cmt = 'start of switch idiom'),
gen_fmt('custom', bv = 'K', cmt = 'information for custom tables (filled and used by modules)'),
gen_fmt('ind_lowcase', bv = 'K'),
gen_fmt(['values', 'lowcase'], bv = 'K'),
]
op_t_gen = [
gen_fmt('n', bv = 'b'),
gen_fmt('type', bv = 'B'),
gen_fmt('offb', bv = 'b'),
gen_fmt('offo', bv = 'b'),
gen_fmt('flags', bv = 'B'),
gen_fmt('dtyp', bv = 'b'),
gen_fmt(['reg', 'phrase'], bv = 'H'),
gen_fmt('value', bv = 'K'),
gen_fmt('addr', bv = 'K'),
gen_fmt('specval', bv = 'K'),
gen_fmt('specflag1', bv = 'b'),
gen_fmt('specflag2', bv = 'b'),
gen_fmt('specflag3', bv = 'b'),
gen_fmt('specflag4', bv = 'b')
]
insn_t_gen = [
gen_fmt('cs', bv = 'K'),
gen_fmt('ip', bv = 'K'),
gen_fmt('ea', bv = 'K'),
gen_fmt('itype', bv = 'H'),
gen_fmt('size', bv = 'H'),
gen_fmt('auxpref', bv = 'H'),
gen_fmt('segpref', bv = 'b'),
gen_fmt('insnpref', bv = 'b'),
gen_fmt('Op1', tp = 'op_t'),
gen_fmt('Op2', tp = 'op_t'),
gen_fmt('Op3', tp = 'op_t'),
gen_fmt('Op4', tp = 'op_t'),
gen_fmt('Op5', tp = 'op_t'),
gen_fmt('Op6', tp = 'op_t'),
gen_fmt('flags', bv = 'b')
]
regval_t_gen = [
gen_fmt('rvtype', bv = 'i'),
gen_fmt('ival', bv = 'K'),
gen_fmt('fval', bv = 'd'),
gen_fmt('bytes', bv = 's'),
]
# --------------------------------------------------------------------------------------------
S_LINK_ATTR = 'S_CLINK_NAME' # If the name is a literal, make sure you specify double quotations
S_CMOD_NAME = '_idaapi'
# --------------------------------------------------------------------------------------------
def gen_stub(gen, name, cname = None, tabs=4, gen_py_file = False, gen_c_file = False):
# Assume C type name same as python type name
if not cname:
cname = name
# Python property lines
prop_body = []
# Python get/set bodies
getset_body = []
# C get/set bodies
cgetset_body = []
# some spacing constants
spc = ' ' * tabs
spc2 = spc * 2
nspc = '\n' + spc
nspc2 = '\n' + spc2
cget_link = '%s_get_clink' % cname
#
# Process fields
#
for g in gen:
# a union will be represented by a list
if type(g.fields) != types.ListType:
fields = [g.fields]
else:
fields = g.fields
# join all field names (in case of a union)
flds_name = '_'.join(fields)
# form the method and variable names
set_method = '__set_%s__' % flds_name
get_method = '__get_%s__' % flds_name
cset_method = '%s_set_%s' % (name, flds_name)
cget_method = '%s_get_%s' % (name, flds_name)
fld_name = '__%s__' % flds_name
basic_type = not g.tp
vars = {
'get': get_method,
'set': set_method,
'l': S_LINK_ATTR,
'fld' : fld_name,
'cmod' : S_CMOD_NAME,
'cget': cget_method,
'cset': cset_method,
'csetcvt': g.setcvt,
'cname': cname,
'cgetlink': cget_link,
'cfield1': fields[0],
'bv': g.bv,
'bvcast': g.cast
}
#
# Python code
#
# basic type?
# For basic types we need to create property and get/set methods
if basic_type:
for fld in fields:
prop_body.append('%s = property(%s, %s)' % (fld, get_method, set_method))
if g.cmt:
prop_body.append('"""%s"""' % g.cmt)
#
code = '\n'.join([
# get method
'def %(get)s(self):',
spc2 + 'return %(cmod)s.%(cget)s(self)',
# set method
spc + 'def %(set)s(self, v):',
spc2 + '%(cmod)s.%(cset)s(self, v)',
]) % vars
getset_body.append(code)
#
# C code
#
if basic_type:
code = '\n'.join([
"""static PyObject *%(cget)s(PyObject *self)
{
%(cname)s *link = %(cgetlink)s(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(%(bv)s, %(bvcast)slink->%(cfield1)s);
}
static void %(cset)s(PyObject *self, PyObject *value)
{
%(cname)s *link = %(cgetlink)s(self);
if ( link == NULL )
return;
%(csetcvt)s
link->%(cfield1)s = %(bvcast)sv;
}
"""
]) % vars
cgetset_body.append(code)
# print 'prop_body->\n\t', '\n\t'.join(prop_body), '\n<'
# print 'getset_body->\n', '\n'.join(getset_body), '\n<'
# print 'cgetset_body->\n', '\n'.join(cgetset_body), '\n<'
vars = {
'name': name,
'cname': cname,
'getlink': cget_link,
'l': S_LINK_ATTR,
'cmod' : S_CMOD_NAME
}
#
# Form the complete Python code
#
py = '\n'.join([
'class %(name)s(py_clinked_object_t):',
# init() code
spc + 'def __init__(self, lnk = None):',
spc2 + 'py_clinked_object_t.__init__(self, lnk)',
'',
spc + 'def _create_clink(self):',
spc2 + 'return _idaapi.%(name)s_create()',
'',
spc + 'def _del_clink(self, lnk):',
spc2 + 'return _idaapi.%(name)s_destroy(lnk)',
'',
spc + 'def assign(self, other):',
spc2 + 'return _idaapi.%(name)s_assign(self, other)',
'',
'',
spc + '#',
spc + '# Autogenerated',
spc + '#',
# get/set code
spc + nspc.join(getset_body),
# props code
spc + nspc.join(prop_body),
]) % vars
#
# Form the Python to C conversion function
#
#
# Form the complete C code
#
ccode = '\n'.join([
# Form the C get link code
"""%(cname)s *%(getlink)s(PyObject *self)
{
if ( !PyObject_HasAttrString(self, %(l)s) )
return NULL;
%(cname)s *r;
PyObject *attr = PyObject_GetAttrString(self, %(l)s);
if ( PyCObject_Check(attr) )
r = (%(cname)s *) PyCObject_AsVoidPtr(attr);
else
r = NULL;
Py_DECREF(attr);
return r;
}
static PyObject *%(cname)s_create()
{
%(cname)s *inst = new %(cname)s();
return PyCObject_FromVoidPtr(inst, NULL);
}
static bool %(cname)s_destroy(PyObject *py_obj)
{
if ( !PyCObject_Check(py_obj) )
return false;
%(cname)s *inst = (%(cname)s *) PyCObject_AsVoidPtr(py_obj);
delete inst;
return true;
}
static bool %(cname)s_assign(PyObject *self, PyObject *other)
{
%(cname)s *lhs = %(cname)s_get_clink(self);
%(cname)s *rhs = %(cname)s_get_clink(other);
if (lhs == NULL || rhs == NULL)
return false;
*lhs = *rhs;
return true;
}
//-------------------------------------------------------------------------
// Auto generated - begin
//
""",
# Form C get/set functions
''.join(cgetset_body),
"""//
// Auto generated - end
//
//-------------------------------------------------------------------------"""
]) % vars
# write the Python file
if gen_py_file:
f = open(name + '.py', 'w')
f.write(py)
f.close()
# write C file
if gen_c_file:
f = open(name + '.cpp', 'w')
f.write(ccode)
f.close()
# --------------------------------------------------------------------------------------------
def main():
files = [
('switch_info_ex_t', switch_info_ex_t_gen),
]
for (n, g) in files:
gen_stub(g, n, gen_py_file = True, gen_c_file = True)
main()

978
pywraps/py_appcall.py Normal file
View File

@ -0,0 +1,978 @@
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 *
# ----------------------------------------------------------------------------------------------------------------------------------------------
#<pycode(py_idd)>
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.get_type_size0(_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__()
#</pycode(py_idd)>
# ----------------------------------------------------------------------------------------------------------------------------------------------
#<pycode(appcalltest)>
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
# -----------------------------------------------------------------------
# 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
# -----------------------------------------------------------------------
# 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_enum_files, test2, test_exec_throw)
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<eax>(int a<esi>, int b<edi>);")
asm2 = a.proto("_asm2", "int __usercall asm2<eax>(int a, int b, int c<ecx>);")
asm3 = a.proto("_asm3", "int __usercall asm3<edx>(int f<eax>, int a, int b, int c<ecx>);")
asm4 = a.proto("_asm4", "unsigned __int16 __usercall asm4<al:ah>(unsigned __int8 a<bl>, unsigned __int8 b<cl>);")
asm5 = a.proto("_asm5", "unsigned int __usercall asm5<si:bx>(unsigned __int8 a<al>, unsigned __int8 b<cl>, unsigned __int8 c<dl>, int d<ebx>);")
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
#</pycode(appcalltest)>
# initialize the test
#test_init()

355
pywraps/py_askusingform.hpp Normal file
View File

@ -0,0 +1,355 @@
#ifndef __PY_ASKUSINGFORM__
#define __PY_ASKUSINGFORM__
//<code(py_kernwin)>
//</code(py_kernwin)>
//---------------------------------------------------------------------------
//<inline(py_kernwin)>
#define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa;
//---------------------------------------------------------------------------
DECLARE_PY_CLINKED_OBJECT(textctrl_info_t);
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 fid, 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;
switch ( ft )
{
case 8:
{
// Readonly? Then return the selected index
if ( sz == 1 )
{
int sel_idx;
if ( fa->get_field_value(fid, &sel_idx) )
return PyLong_FromLong(sel_idx);
}
// Not readonly? Then return the qstring
else
{
qstring val;
if ( fa->get_field_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_field_value(fid, &ti) )
return Py_BuildValue("(sII)", ti.text.c_str(), ti.flags, ti.tabsize);
break;
}
// button - uint32
case 4:
{
uint32 val;
if ( fa->get_field_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_field_value(fid, val) )
return PyString_FromString(val);
break;
}
// string input
case 3:
{
qstring val;
val.resize(sz + 1);
if ( fa->get_field_value(fid, val.begin()) )
return PyString_FromString(val.begin());
break;
}
case 5:
{
intvec_t intvec;
// Returned as 1-base
if (fa->get_field_value(fid, &intvec))
{
// Make 0-based
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
(*it)--;
return PyW_IntVecToPyList(intvec);
}
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_field_value(fid, &u.sel) )
return Py_BuildValue(PY_FMT64, u.sel);
break;
}
// sval_t
case 'n':
case 'N':
case 'D':
case 'O':
case 'Y':
case 'H':
{
if ( fa->get_field_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(sz == 'L' ? "K" : "L", u.ull);
break;
}
case 'M': // uval_t
case '$': // ea_t
{
if ( fa->get_field_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;
switch ( ft )
{
// dropdown list
case 8:
{
// Editable dropdown list
if ( PyString_Check(py_val) )
{
qstring val(PyString_AsString(py_val));
return fa->set_field_value(fid, &val);
}
// Readonly dropdown list
else
{
int sel_idx = PyLong_AsLong(py_val);
return fa->set_field_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_field_value(fid, ti);
}
// button - uint32
case 4:
{
uint32 val = PyLong_AsUnsignedLong(py_val);
return fa->set_field_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_field_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_field_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 (size_t)AskUsingForm_c;
}
//</inline(py_kernwin)>
#endif // __PY_ASKUSINGFORM__

1876
pywraps/py_askusingform.py Normal file

File diff suppressed because it is too large Load Diff

218
pywraps/py_bytes.hpp Normal file
View File

@ -0,0 +1,218 @@
#ifndef __PY_IDA_BYTES__
#define __PY_IDA_BYTES__
//<code(py_bytes)>
//------------------------------------------------------------------------
static bool idaapi py_testf_cb(flags_t flags, void *ud)
{
PyObject *py_flags = PyLong_FromUnsignedLong(flags);
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags, NULL);
PYW_GIL_RELEASE;
bool ret = result != NULL && PyObject_IsTrue(result);
Py_XDECREF(result);
Py_XDECREF(py_flags);
return ret;
}
//------------------------------------------------------------------------
// Wraps the (next|prev)that()
static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next)
{
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_ENSURE;
PyObject *py_result = PyObject_CallFunction(
(PyObject *)ud,
PY_FMT64 "iII",
pyul_t(ea),
fpos,
o,
v);
PYW_GIL_RELEASE;
PyW_ShowCbErr("visit_patched_bytes");
int ret = (py_result != NULL && PyInt_Check(py_result)) ? PyInt_AsLong(py_result) : 0;
Py_XDECREF(py_result);
return ret;
}
//</code(py_bytes)>
//------------------------------------------------------------------------
//<inline(py_bytes)>
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable)
{
if ( !PyCallable_Check(py_callable) )
return 0;
else
return visit_patched_bytes(ea1, ea2, py_visit_patched_bytes_cb, py_callable);
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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);
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
{
do
{
if ( size <= 0 )
break;
// Allocate memory via Python
PyObject *py_buf = PyString_FromStringAndSize(NULL, Py_ssize_t(size));
if ( py_buf == NULL )
break;
// Read bytes
bool ok = get_many_bytes(ea, PyString_AsString(py_buf), size);
// If failed, dispose the Python string
if ( !ok )
{
Py_DECREF(py_buf);
py_buf = Py_None;
Py_INCREF(py_buf);
}
return py_buf;
} while ( false );
Py_RETURN_NONE;
}
//---------------------------------------------------------------------------
/*
#<pydoc>
def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII):
"""
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
@param flags: combination of ACFOPT_...
@return: string contents (not including terminating 0) or None
"""
pass
#</pydoc>
*/
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) )
{
qfree(buf);
Py_RETURN_NONE;
}
if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' )
used_size--;
PyObject *py_buf = PyString_FromStringAndSize((const char *)buf, used_size);
qfree(buf);
return py_buf;
}
//---------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_get_ascii_contents(
ea_t ea,
size_t len,
int32 type)
{
return py_get_ascii_contents2(ea, len, type);
}
//</inline(py_bytes)>
#endif

87
pywraps/py_choose.hpp Normal file
View File

@ -0,0 +1,87 @@
#ifndef __PY_CHOOSE__
#define __PY_CHOOSE__
//---------------------------------------------------------------------------
//<inline(py_kernwin)>
//---------------------------------------------------------------------------
uint32 idaapi choose_sizer(void *self)
{
PyObject *pyres;
uint32 res;
PYW_GIL_ENSURE;
pyres = PyObject_CallMethod((PyObject *)self, "sizer", "");
PYW_GIL_RELEASE;
res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
}
//---------------------------------------------------------------------------
char *idaapi choose_getl(void *self, uint32 n, char *buf)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
(PyObject *)self,
"getl",
"l",
n);
PYW_GIL_RELEASE;
const char *res;
if (pyres == NULL || (res = PyString_AsString(pyres)) == NULL )
qstrncpy(buf, "<Empty>", MAXSTR);
else
qstrncpy(buf, res, MAXSTR);
Py_XDECREF(pyres);
return buf;
}
//---------------------------------------------------------------------------
void idaapi choose_enter(void *self, uint32 n)
{
PYW_GIL_ENSURE;
Py_XDECREF(PyObject_CallMethod((PyObject *)self, "enter", "l", n));
PYW_GIL_RELEASE;
}
//---------------------------------------------------------------------------
uint32 choose_choose(
void *self,
int flags,
int x0,int y0,
int x1,int y1,
int width,
int deflt,
int icon)
{
PyObject *pytitle = PyObject_GetAttrString((PyObject *)self, "title");
const char *title = pytitle != NULL ? PyString_AsString(pytitle) : "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 */
Py_XDECREF(pytitle);
return r;
}
//</inline(py_kernwin)>
#endif // __PY_CHOOSE__

956
pywraps/py_choose2.hpp Normal file
View File

@ -0,0 +1,956 @@
#ifndef __PY_CHOOSE2__
#define __PY_CHOOSE2__
//<code(py_kernwin)>
//------------------------------------------------------------------------
// 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<PyObject *, py_choose2_t *> 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)
{
// 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<POPUP_NAMES_COUNT; i++ )
qfree((void *)popup_names[i]);
delete [] popup_names;
popup_names = NULL;
}
void install_hooks(bool install)
{
if ( install )
{
if ( (flags & CH_ATTRS) != 0 )
{
if ( !hook_to_notification_point(HT_UI, ui_cb, this) )
flags &= ~CH_ATTRS;
else
ui_cb_hooked = true;
}
}
else
{
if ( (flags & CH_ATTRS) != 0 )
{
unhook_from_notification_point(HT_UI, ui_cb, this);
ui_cb_hooked = false;
}
}
}
void on_get_line(int lineno, char * const *line_arr)
{
// Get headers?
if ( lineno == 0 )
{
// Copy the pre-parsed columns
for ( size_t i=0; i < cols.size(); i++ )
qstrncpy(line_arr[i], cols[i].c_str(), MAXSTR);
return;
}
// Clear buffer
int ncols = int(cols.size());
for ( int i=ncols-1; i>=0; i-- )
line_arr[i][0] = '\0';
// Call Python
PYW_GIL_ENSURE;
PyObject *list = PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1);
PYW_GIL_RELEASE;
if ( list == NULL )
return;
// Go over the List returned by Python and convert to C strings
for ( int i=ncols-1; i>=0; i-- )
{
PyObject *item = PyList_GetItem(list, Py_ssize_t(i));
if ( item == NULL )
continue;
const char *str = PyString_AsString(item);
if ( str != NULL )
qstrncpy(line_arr[i], str, MAXSTR);
}
Py_DECREF(list);
}
size_t on_get_size()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return 0;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
}
void on_refreshed()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
}
void on_select(const intvec_t &intvec)
{
PYW_GIL_ENSURE;
PyObject *py_list = PyW_IntVecToPyList(intvec);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_SELECT, "O", py_list);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
Py_XDECREF(py_list);
}
void on_close()
{
// Call Python
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
// 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_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_DELETE_LINE,
"i",
lineno - 1);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res + 1;
}
int on_refresh(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_REFRESH,
"i",
lineno - 1);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res + 1;
}
void on_insert_line()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_INSERT_LINE, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
}
void on_enter(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_SELECT_LINE,
"i",
lineno - 1);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
}
void on_edit_line(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_EDIT_LINE,
"i",
lineno - 1);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
}
int on_command(int cmd_id, int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_COMMAND,
"ii",
lineno - 1,
cmd_id);
PYW_GIL_RELEASE;
if ( pyres==NULL )
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_XDECREF(pyres);
return res;
}
int on_get_icon(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_GET_ICON,
"i",
lineno - 1);
PYW_GIL_RELEASE;
size_t res = PyInt_AsLong(pyres);
Py_XDECREF(pyres);
return res;
}
void on_get_line_attr(int lineno, chooser_item_attrs_t *attr)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return;
if ( PyList_Check(pyres) )
{
PyObject *item;
if ( (item = PyList_GetItem(pyres, 0)) != NULL )
attr->color = PyInt_AsLong(item);
if ( (item = PyList_GetItem(pyres, 1)) != NULL )
attr->flags = PyInt_AsLong(item);
}
Py_XDECREF(pyres);
}
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;
// 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;
// Embedded chooser?
if ( get_embedded() != NULL )
{
static const char delimiter[] = ":";
char temp[MAXSTR];
qstrncpy(temp, caption, sizeof(temp));
char *p = strtok(temp, delimiter);
if ( p == NULL )
return -1;
// Copy the title
char title_str[MAXSTR];
qstrncpy(title_str, p, sizeof(title_str));
// Copy the echooser ID
p = strtok(NULL, delimiter);
if ( p == NULL )
return -1;
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
ptitle = title_buf;
// Adjust the caption
p = strtok(NULL, delimiter);
caption += (p - temp);
}
else
{
ptitle = title.c_str();
}
if ( !add_chooser_command(
ptitle,
caption,
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)
{
PyObject *attr;
// Get flags
attr = PyW_TryGetAttrString(self, S_FLAGS);
if ( attr == NULL )
return -1;
flags = PyInt_Check(attr) != 0 ? PyInt_AsLong(attr) : 0;
Py_DECREF(attr);
// Get the title
if ( !PyW_GetStringAttr(self, S_TITLE, &title) )
return -1;
// Get columns
attr = PyW_TryGetAttrString(self, "cols");
if ( attr == NULL )
return -1;
// Get col count
int ncols = int(PyList_Size(attr));
// Get cols caption and widthes
cols.qclear();
for ( int i=0; i<ncols; i++ )
{
// get list item: [name, width]
PyObject *list = PyList_GetItem(attr, i);
PyObject *v = PyList_GetItem(list, 0);
// Extract string
const char *str = v == NULL ? "" : PyString_AsString(v);
cols.push_back(str);
// Extract width
int width;
v = PyList_GetItem(list, 1);
// No width? Guess width from column title
if ( v == NULL )
width = strlen(str);
else
width = PyInt_AsLong(v);
widths.push_back(width);
}
Py_DECREF(attr);
// Get *deflt
int deflt = -1;
attr = PyW_TryGetAttrString(self, "deflt");
if ( attr != NULL )
{
deflt = PyInt_AsLong(attr);
Py_DECREF(attr);
}
// Get *icon
int icon = -1;
if ( (attr = PyW_TryGetAttrString(self, "icon")) != NULL )
{
icon = PyInt_AsLong(attr);
Py_DECREF(attr);
}
// Get *x1,y1,x2,y2
int pts[4];
static const char *pt_attrs[qnumber(pts)] = {"x1", "y1", "x2", "y2"};
for ( size_t i=0; i < qnumber(pts); i++ )
{
if ( (attr = PyW_TryGetAttrString(self, pt_attrs[i])) == NULL )
{
pts[i] = -1;
}
else
{
pts[i] = PyInt_AsLong(attr);
Py_DECREF(attr);
}
}
// Check what callbacks we have
static const struct
{
const char *name;
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},
};
cb_flags = 0;
for ( int i=0; i<qnumber(callbacks); i++ )
{
attr = attr = PyW_TryGetAttrString(self, callbacks[i].name);
bool have_cb = attr != NULL && PyCallable_Check(attr) != 0;
Py_XDECREF(attr);
if ( have_cb )
{
cb_flags |= callbacks[i].have;
}
else
{
// Mandatory field?
if ( callbacks[i].have == 0 )
return -1;
}
}
// Get *popup names
// An array of 4 strings: ("Insert", "Delete", "Edit", "Refresh"
attr = PyW_TryGetAttrString(self, S_POPUP_NAMES);
if ( (attr != NULL)
&& PyList_Check(attr)
&& PyList_Size(attr) == POPUP_NAMES_COUNT )
{
popup_names = new const char *[POPUP_NAMES_COUNT];
for ( int i=0; i<POPUP_NAMES_COUNT; i++ )
{
const char *str = PyString_AsString(PyList_GetItem(attr, i));
popup_names[i] = qstrdup(str);
}
}
Py_XDECREF(attr);
// Adjust flags (if needed)
if ( (cb_flags & CHOOSE2_HAVE_GETATTR) != 0 )
flags |= CH_ATTRS;
// Increase object reference
Py_INCREF(self);
this->self = self;
// Hook to notification point (to handle chooser item attributes)
install_hooks(true);
// Check if *embedded
attr = PyW_TryGetAttrString(self, S_EMBEDDED);
if ( attr != NULL && PyObject_IsTrue(attr) == 1 )
{
// Create an embedded chooser structure
embedded = new chooser_info_t();
embedded->obj = this;
embedded->cb = sizeof(chooser_info_t);
embedded->title = title.c_str();
embedded->columns = ncols;
embedded->deflt = deflt;
embedded->flags = flags;
embedded->width = pts[0]; // Take x1
embedded->height = pts[1]; // Take y1
embedded->icon = icon;
embedded->popup_names = popup_names;
embedded->widths = widths.begin();
embedded->destroyer = s_destroy;
embedded->getl = s_getl;
embedded->sizer = s_sizer;
embedded->del = (cb_flags & CHOOSE2_HAVE_DEL) != 0 ? s_del : NULL;
embedded->edit = (cb_flags & CHOOSE2_HAVE_EDIT) != 0 ? s_edit : NULL;
embedded->enter = (cb_flags & CHOOSE2_HAVE_ENTER) != 0 ? s_enter : NULL;
embedded->get_icon = (cb_flags & CHOOSE2_HAVE_GETICON) != 0 ? s_get_icon : NULL;
embedded->ins = (cb_flags & CHOOSE2_HAVE_INS) != 0 ? s_ins : NULL;
embedded->update = (cb_flags & CHOOSE2_HAVE_UPDATE) != 0 ? s_update : NULL;
embedded->get_attrs = NULL;
// Fill callbacks that are only present in idaq
if ( is_idaq() )
{
embedded->select = (cb_flags & CHOOSE2_HAVE_SELECT) != 0 ? s_select : NULL;
embedded->refresh = (cb_flags & CHOOSE2_HAVE_REFRESHED)!= 0 ? s_refreshed : NULL;
}
else
{
embedded->select = NULL;
embedded->refresh = NULL;
}
}
Py_XDECREF(attr);
// Create the chooser (if not embedded)
int r;
if ( embedded == NULL )
{
r = ::choose2(
flags,
pts[0], pts[1], pts[2], pts[3],
this,
ncols,
&widths[0],
s_sizer,
s_getl,
title.c_str(),
icon,
deflt,
(cb_flags & CHOOSE2_HAVE_DEL) != 0 ? s_del : NULL,
(cb_flags & CHOOSE2_HAVE_INS) != 0 ? s_ins : NULL,
(cb_flags & CHOOSE2_HAVE_UPDATE) != 0 ? s_update : NULL,
(cb_flags & CHOOSE2_HAVE_EDIT) != 0 ? s_edit : NULL,
(cb_flags & CHOOSE2_HAVE_ENTER) != 0 ? s_enter : NULL,
s_destroy,
popup_names,
(cb_flags & CHOOSE2_HAVE_GETICON) != 0 ? s_get_icon : NULL);
clear_popup_names();
// Modal chooser return the index of the selected item
if ( is_modal() )
r--;
}
// Embedded chooser?
else
{
// Return success
r = 1;
}
return r;
}
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)
{
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)--;
return PyW_IntVecToPyList(intvec);
}
//------------------------------------------------------------------------
// Return the C instances as 64bit numbers
PyObject *choose2_get_embedded(PyObject *self)
{
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);
if ( c2 != NULL )
return c2->add_command(caption, flags, menu_index, icon);
else
return -2;
}
//------------------------------------------------------------------------
PyObject *choose2_find(const char *title)
{
py_choose2_t *c2 = py_choose2_t::find_chooser(title);
return c2 == NULL ? NULL : c2->get_self();
}
//</code(py_kernwin)>
//---------------------------------------------------------------------------
//<inline(py_kernwin)>
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);
//</inline(py_kernwin)>
//---------------------------------------------------------------------------
// Testing functions. They belong to PyWraps and won't be copied to IDAPython
//---------------------------------------------------------------------------
static void NT_CDECL choose2_test_embedded(chooser_info_t *embedded)
{
msg("cb=%d -> looks %valid\n",
embedded->cb,
embedded->cb == sizeof(chooser_info_t) ? "" : "in");
}
static size_t choose2_get_test_embedded()
{
return (size_t)choose2_test_embedded;
}
#endif // __PY_CHOOSE2__

390
pywraps/py_choose2.py Normal file
View File

@ -0,0 +1,390 @@
# -----------------------------------------------------------------------
# Standalone and testing code
from ctypes import *
try:
import _idaapi
except:
print("Please try me from inside IDA")
sys.exit(0)
try:
import pywraps
pywraps_there = True
print("Choose2: using pywraps")
_idaapi.choose2_create = pywraps.py_choose2_create
_idaapi.choose2_activate = pywraps.py_choose2_activate
_idaapi.choose2_refresh = pywraps.py_choose2_refresh
_idaapi.choose2_close = pywraps.py_choose2_close
_idaapi.choose2_add_command = pywraps.py_choose2_add_command
_idaapi.choose2_get_embedded = pywraps.py_choose2_get_embedded
_idaapi.choose2_get_embedded_selection = pywraps.py_choose2_get_embedded_selection
try:
# Get function address
# void test_embedded(chooser_info_t *)
TEST_EMBEDDED = CFUNCTYPE(c_void_p, c_void_p)
test_embedded = TEST_EMBEDDED(pywraps.py_choose2_get_test_embedded())
except Exception as e:
test_embedded = None
print("Choose2: Exception: %s" % str(e))
except Exception as e:
pywraps_there = False
print("Choose2: Not using pywraps: %s" % str(e))
# -----------------------------------------------------------------------
#<pycode(py_kernwin)>
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_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):
"""
Adds a new 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
"""
# 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:
#
#<pydoc>
# 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]
#</pydoc>
#</pycode(py_kernwin)>
# -----------------------------------------------------------------------
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 OnCommand(self, n, cmd_id):
if cmd_id == self.cmd_a:
print "command A selected @", n
elif cmd_id == self.cmd_b:
print "command B selected @", n
else:
print "Unknown command:", cmd_id, "@", n
return 1
def OnGetIcon(self, n):
r = self.items[n]
t = self.icon + r[1].count("*")
print "geticon", n, t
return t
def show(self):
t = self.Show(self.modal)
if t < 0:
return False
if not self.modal:
self.cmd_a = self.AddCommand("command A")
self.cmd_b = self.AddCommand("command B")
print("Show() returned: %d\n" % t)
return True
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()
# -----------------------------------------------------------------------
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__':
#test_choose2_embedded()
test_choose2(False)

293
pywraps/py_cli.hpp Normal file
View File

@ -0,0 +1,293 @@
#ifndef __PYWRAPS_CLI__
#define __PYWRAPS_CLI__
//<code(py_cli)>
//--------------------------------------------------------------------------
#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_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_EXECUTE_LINE,
"s",
line);
PYW_GIL_RELEASE;
bool ok = result != NULL && PyObject_IsTrue(result);
PyW_ShowCbErr(S_ON_EXECUTE_LINE);
Py_XDECREF(result);
return ok;
}
//--------------------------------------------------------------------------
// 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_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_KEYDOWN,
"siiHi",
line->c_str(),
*p_x,
*p_sellen,
*vk_key,
shift);
PYW_GIL_RELEASE;
bool ok = result != NULL && PyTuple_Check(result);
PyW_ShowCbErr(S_ON_KEYDOWN);
if ( ok )
{
Py_ssize_t sz = PyTuple_Size(result);
PyObject *item;
if ( sz > 0 && (item = PyTuple_GetItem(result, 0)) != NULL && PyString_Check(item) )
*line = PyString_AsString(item);
if ( sz > 1 && (item = PyTuple_GetItem(result, 1)) != NULL && PyInt_Check(item) )
*p_x = PyInt_AsLong(item);
if ( sz > 2 && (item = PyTuple_GetItem(result, 2)) != NULL && PyInt_Check(item) )
*p_sellen = PyInt_AsLong(item);
if ( sz > 3 && (item = PyTuple_GetItem(result, 3)) != NULL && PyInt_Check(item) )
*vk_key = PyInt_AsLong(item) & 0xffff;
}
Py_XDECREF(result);
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_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_COMPLETE_LINE,
"sisi",
prefix,
n,
line,
x);
PYW_GIL_RELEASE;
bool ok = result != NULL && PyString_Check(result);
PyW_ShowCbErr(S_ON_COMPLETE_LINE);
if ( ok )
*completion = PyString_AsString(result);
Py_XDECREF(result);
return ok;
}
// Private ctor (use bind())
py_cli_t()
{
}
public:
//---------------------------------------------------------------------------
static int bind(PyObject *py_obj)
{
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'
if ( (attr = PyW_TryGetAttrString(py_obj, S_FLAGS)) == NULL )
{
py_cli->cli.flags = 0;
}
else
{
py_cli->cli.flags = PyLong_AsLong(attr);
Py_DECREF(attr);
}
// 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);
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
//</code(py_cli)>
//--------------------------------------------------------------------------
//<inline(py_cli)>
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);
}
//</inline(py_cli)>
//---------------------------------------------------------------------------
#endif // __PYWRAPS_CLI__

187
pywraps/py_cli.py Normal file
View File

@ -0,0 +1,187 @@
# -----------------------------------------------------------------------
# Standalone and testing code
import sys
try:
import pywraps
pywraps_there = True
print "Using pywraps"
except:
pywraps_there = False
print "Using IDAPython"
try:
import _idaapi
from idaapi import pyidc_opaque_object_t
except:
print "Please run this script from inside IDA"
sys.exit(0)
if pywraps_there:
_idaapi.install_command_interpreter = pywraps.install_command_interpreter
_idaapi.remove_command_interpreter = pywraps.remove_command_interpreter
# -----------------------------------------------------------------------
#<pycode(py_cli)>
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:
#
#<pydoc>
# 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
#</pydoc>
#</pycode(py_cli)>
# -----------------------------------------------------------------------
#<pycode(ex_cli_ex1)>
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
#</pycode(ex_cli_ex1)>
# -----------------------------------------------------------------------

699
pywraps/py_custdata.hpp Normal file
View File

@ -0,0 +1,699 @@
#ifndef __PY_IDA_CUSTDATA__
#define __PY_IDA_CUSTDATA__
//<code(py_bytes)>
//------------------------------------------------------------------------
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_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_MAY_CREATE_AT,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(nbytes));
PYW_GIL_RELEASE;
PyW_ShowCbErr(S_MAY_CREATE_AT);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
}
// !=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
{
// 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;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_CALC_ITEM_SIZE,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(maxsize));
PYW_GIL_RELEASE;
if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL )
return 0;
uint64 num = 0;
PyW_GetNumber(py_result, &num);
Py_XDECREF(py_result);
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)
{
// Already registered?
if ( dtid >= 0 )
return dtid;
memset(&dt, 0, sizeof(dt));
dt.cbsize = sizeof(dt);
dt.ud = this;
PyObject *py_attr = NULL;
do
{
// 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) )
dt.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// props
py_attr = PyW_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL && PyInt_Check(py_attr) )
dt.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// may_create_at
py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
dt.may_create_at = s_may_create_at;
Py_XDECREF(py_attr);
// calc_item_size
py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
dt.calc_item_size = s_calc_item_size;
Py_XDECREF(py_attr);
// Clear attribute
py_attr = NULL;
// 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 = PyInt_FromLong(dtid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
// Done with attribute
py_attr = NULL;
} while ( false );
Py_XDECREF(py_attr);
return dtid;
}
bool unregister_dt()
{
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<int, py_custom_data_type_t *> 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
{
// Build a string from the buffer
PyObject *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;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value,
pyul_t(current_ea),
operand_num,
dtid);
PYW_GIL_RELEASE;
// Done with the string
Py_DECREF(py_value);
// Error while calling the function?
if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL )
return false;
bool ok = false;
if ( PyString_Check(py_result) )
{
Py_ssize_t len;
char *buf;
if ( out != NULL && PyString_AsStringAndSize(py_result, &buf, &len) != -1 )
{
out->qclear();
out->append(buf, len);
}
ok = true;
}
Py_DECREF(py_result);
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
{
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num);
PYW_GIL_RELEASE;
// 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) || PyTuple_Size(py_result) != 2 )
break;
// Borrow references
PyObject *py_bool = PyTuple_GetItem(py_result, 0);
PyObject *py_val = PyTuple_GetItem(py_result, 1);
// Get return code from Python
ok = PyObject_IsTrue(py_bool);
// 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, &buf, &len) != -1 )
{
value->qclear();
value->append(buf, len);
}
}
// An error occured?
else
{
// Make sure the user returned (False, String)
if ( py_bool != Py_False || !PyString_Check(py_val) )
{
*errstr = "Invalid return value returned from the Python callback!";
break;
}
// Get the error message
*errstr = PyString_AsString(py_val);
}
} while ( false );
Py_DECREF(py_result);
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.
{
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_ANALYZE,
PY_FMT64 "i",
pyul_t(current_ea),
operand_num);
PYW_GIL_RELEASE;
PyW_ShowCbErr(S_ANALYZE);
Py_XDECREF(py_result);
}
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;
PyObject *py_attr = NULL;
do
{
// 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) )
df.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// 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) )
df.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// text_width
py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.text_width = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// print cb
py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
df.print = s_print;
Py_XDECREF(py_attr);
// scan cb
py_attr = PyW_TryGetAttrString(py_obj, S_SCAN);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
df.scan = s_scan;
Py_XDECREF(py_attr);
// analyze cb
py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
df.analyze = s_analyze;
Py_XDECREF(py_attr);
// Done with attribute
py_attr = NULL;
// 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 = PyInt_FromLong(dfid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
py_attr = NULL;
} while ( false );
Py_XDECREF(py_attr);
return dfid;
}
bool unregister_df(int dtid)
{
// 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 <dtid, dfid> 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<py_custom_data_format_entry_t> 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)
{
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)
{
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);
}
//</code(py_bytes)>
//------------------------------------------------------------------------
//<inline(py_bytes)>
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
// 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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def unregister_custom_data_type(dtid):
"""
Unregisters a custom data type.
@param dtid: the data type id
@return: Boolean
"""
pass
#</pydoc>
*/
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_format(int dtid, int fid)
{
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);
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_type(int dtid)
{
const data_type_t *dt = get_custom_data_type(dtid);
if ( dt == NULL )
Py_RETURN_NONE;
return py_data_type_to_py_dict(dt);
}
//</inline(py_bytes)>
#endif

241
pywraps/py_custdata.py Normal file
View File

@ -0,0 +1,241 @@
# -----------------------------------------------------------------------
# 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.register_custom_data_type = pywraps.register_custom_data_type
_idaapi.unregister_custom_data_type = pywraps.unregister_custom_data_type
_idaapi.register_custom_data_format = pywraps.register_custom_data_format
_idaapi.unregister_custom_data_format = pywraps.unregister_custom_data_format
_idaapi.get_custom_data_format = pywraps.get_custom_data_format
_idaapi.get_custom_data_type = pywraps.get_custom_data_type
# -----------------------------------------------------------------------
#<pycode(py_bytes)>
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
#<pydoc>
# 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
#</pydoc>
# -----------------------------------------------------------------------
# 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
#<pydoc>
# 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
#</pydoc>
# -----------------------------------------------------------------------
def __walk_types_and_formats(formats, type_action, format_action):
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:]
if not type_action(dt):
broken = True
break
for df in dfs:
if not format_action(df, dt.id):
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 "Registering format '%s' with built-in types, ID=%d" % (df.name, df.id)
else:
print " Registering format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid)
return df.id != -1
def __reg_type(dt):
dt.register()
print "Registering type '%s', ID=%d" % (dt.name, dt.id)
return dt.id != -1
ok = __walk_types_and_formats(formats, __reg_type, __reg_format)
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):
df.unregister(dtid)
print "%snregistering format '%s'" % ("U" if dtid == 0 else " u", df.name)
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)
return 1 if ok else -1
#</pycode(py_bytes)>
# -----------------------------------------------------------------------

1110
pywraps/py_custview.hpp Normal file

File diff suppressed because it is too large Load Diff

458
pywraps/py_custview.py Normal file
View File

@ -0,0 +1,458 @@
# -----------------------------------------------------------------------
# Standalone and testing code
import sys, struct
try:
import _idaapi
except:
print "Please try me from inside IDA"
sys.exit(0)
try:
import pywraps
pywraps_there = True
print "Using pywraps"
_idaapi.pyscv_init = pywraps.pyscv_init
_idaapi.pyscv_close = pywraps.pyscv_close
_idaapi.pyscv_add_line = pywraps.pyscv_add_line
_idaapi.pyscv_delete = pywraps.pyscv_delete
_idaapi.pyscv_refresh = pywraps.pyscv_refresh
_idaapi.pyscv_show = pywraps.pyscv_show
_idaapi.pyscv_clear_popup_menu = pywraps.pyscv_clear_popup_menu
_idaapi.pyscv_del_line = pywraps.pyscv_del_line
_idaapi.pyscv_get_pos = pywraps.pyscv_get_pos
_idaapi.pyscv_refresh_current = pywraps.pyscv_refresh_current
_idaapi.pyscv_get_current_line = pywraps.pyscv_get_current_line
_idaapi.pyscv_is_focused = pywraps.pyscv_is_focused
_idaapi.pyscv_add_popup_menu = pywraps.pyscv_add_popup_menu
_idaapi.pyscv_get_line = pywraps.pyscv_get_line
_idaapi.pyscv_jumpto = pywraps.pyscv_jumpto
_idaapi.pyscv_edit_line = pywraps.pyscv_edit_line
_idaapi.pyscv_patch_line = pywraps.pyscv_patch_line
_idaapi.pyscv_insert_line = pywraps.pyscv_insert_line
_idaapi.pyscv_count = pywraps.pyscv_count
_idaapi.pyscv_get_selection = pywraps.pyscv_get_selection
_idaapi.pyscv_clear_lines = pywraps.pyscv_clear_lines
_idaapi.pyscv_get_current_word = pywraps.pyscv_get_current_word
except:
pywraps_there = False
print "Not using pywraps"
# -----------------------------------------------------------------------
#<pycode(py_custviewer)>
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)
# Here are all the supported events
#<pydoc>
# 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
#</pydoc>
#</pycode(py_custviewer)>
#<pycode(py_custviewerex1)>
# -----------------------------------------------------------------------
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
self.menu_hello = self.AddPopupMenu("Hello")
self.menu_world = self.AddPopupMenu("World")
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 = "<None>"
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 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 AddPopupMenu()
@return: Boolean
"""
print "OnPopupMenu, menu_id=%d" % menu_id
if menu_id == self.menu_hello:
print "Hello"
elif menu_id == self.menu_world:
print "World"
else:
# Unhandled
return False
return True
# -----------------------------------------------------------------------
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()
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
#</pycode(py_custviewerex1)>

1095
pywraps/py_cvt.hpp Normal file

File diff suppressed because it is too large Load Diff

699
pywraps/py_dbg.hpp Normal file
View File

@ -0,0 +1,699 @@
#ifndef __PYDBG__
#define __PYDBG__
//<code(py_idd)>
//-------------------------------------------------------------------------
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)
{
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)
{
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_value_t> 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<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
qstring s;
PyW_ObjectToString(py_item, &s);
msg("obj[%d]->%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;
}
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("input variables:\n"
"----------------\n");
qstring s;
for ( Py_ssize_t i=0; i<nargs; i++ )
{
VarPrint(&s, &idc_args[i]);
msg("%d]\n%s\n-----------\n", int(i), s.c_str());
s.qclear();
}
}
// Do Appcall
idc_value_t idc_result;
error_t ret = appcall(
func_ea,
tid,
(type_t *)type,
(p_list *)fields,
idc_args.size(),
idc_args.begin(),
&idc_result);
if ( ret != eOk )
{
// An exception was thrown?
if ( ret == eExecThrow )
{
// Convert the result (which is a debug_event) into a Python object
PyObject *py_appcall_exc(NULL);
idcvar_to_pyvar(idc_result, &py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc);
Py_DECREF(py_appcall_exc);
return NULL;
}
// An error in the Appcall? (or an exception but AppCallOptions/DEBEV is not set)
else
{
char err_str[MAXSTR];
qstrerror(ret, err_str, sizeof(err_str));
PyErr_SetString(PyExc_Exception, err_str);
return NULL;
}
}
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("return variables:\n"
"-----------------\n");
qstring s;
for ( Py_ssize_t i=0; i<nargs; i++ )
{
VarPrint(&s, &idc_args[i]);
msg("%d]\n%s\n-----------\n", int(i), s.c_str());
s.qclear();
}
}
// Convert IDC values back to Python values
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
// We convert arguments but fail only on fatal errors
// (we ignore failure because of immutable objects)
if ( idcvar_to_pyvar(idc_args[i], &py_item) == CIP_FAILED )
{
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC values to Python values");
return NULL;
}
}
// Convert the result from IDC back to Python
PyObject *py_result(NULL);
if ( idcvar_to_pyvar(idc_result, &py_result) <= CIP_IMMUTABLE )
{
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC return value to Python return value");
return NULL;
}
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("return var:\n"
"-----------\n");
qstring s;
VarPrint(&s, &idc_result);
msg("%s\n-----------\n", s.c_str());
}
return py_result;
}
//</code(py_idd)>
//<inline(py_idd)>
//-------------------------------------------------------------------------
/*
#<pydoc>
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, bit_strings_default_mask)
The bit_strings can be a tuple of strings or None (if the register does not have bit_strings)
"""
pass
#</pydoc>
*/
static PyObject *dbg_get_registers()
{
if ( dbg == NULL )
Py_RETURN_NONE;
PyObject *py_list = PyList_New(dbg->registers_size);
for ( int i=0; i<dbg->registers_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<nbits; i++ )
{
const char *s = ri.bit_strings[i];
PyList_SetItem(py_bits, i, PyString_FromString(s == NULL ? "" : s));
}
}
else
{
Py_INCREF(Py_None);
py_bits = Py_None;
}
// name, flags, class, dtyp, bit_strings, bit_strings_default_mask
PyList_SetItem(py_list, i,
Py_BuildValue("(sIIINI)",
ri.name,
ri.flags,
(unsigned int)ri.register_class,
(unsigned int)ri.dtyp,
py_bits,
(unsigned int)ri.bit_strings_default));
}
return py_list;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value)
{
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));
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_write_memory(ea, buffer):
"""
Writes a buffer to the debugee's memory
@return: Boolean
"""
pass
#</pydoc>
*/
static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
{
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_get_name():
"""
This function returns the current debugger's name.
@return: Debugger name or None if no debugger is active
"""
pass
#</pydoc>
*/
static PyObject *dbg_get_name()
{
if ( dbg == NULL )
Py_RETURN_NONE;
else
return PyString_FromString(dbg->name);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *dbg_get_memory_info()
{
if ( !dbg_can_query() )
Py_RETURN_NONE;
// Invalidate memory
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
meminfo_vec_t areas;
get_dbg_memory_info(&areas);
return meminfo_vec_t_to_py(areas);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static bool dbg_can_query();
PyObject *py_appcall(
ea_t func_ea,
thid_t tid,
PyObject *py_type,
PyObject *py_fields,
PyObject *arg_list);
//</inline(py_idd)>
//<code(py_dbg)>
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
//</code(py_dbg)>
//<inline(py_dbg)>
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_manual_regions():
"""
Returns the manual memory regions
@return: list(startEA, endEA, name, sclass, sbase, bitness, perm)
"""
pass
#</pydoc>
*/
static PyObject *py_get_manual_regions()
{
meminfo_vec_t areas;
get_manual_regions(&areas);
return meminfo_vec_t_to_py(areas);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_is_loaded():
"""
Checks if a debugger is loaded
@return: Boolean
"""
pass
#</pydoc>
*/
static bool dbg_is_loaded()
{
return dbg != NULL;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def refresh_debugger_memory():
"""
Refreshes the debugger memory
@return: Nothing
"""
pass
#</pydoc>
*/
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);
Py_RETURN_NONE;
}
int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
public:
virtual ~DBG_Hooks() {};
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)
{
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;
}
//</inline(py_dbg)>
#endif

62
pywraps/py_diskio.hpp Normal file
View File

@ -0,0 +1,62 @@
#ifndef __PY_IDA_DISKIO__
#define __PY_IDA_DISKIO__
//<code(py_diskio)>
//--------------------------------------------------------------------------
int idaapi py_enumerate_files_cb(const char *file, void *ud)
{
PyObject *py_file = PyString_FromString(file);
PYW_GIL_ENSURE;
PyObject *py_ret = PyObject_CallFunctionObjArgs(
(PyObject *)ud,
py_file,
NULL);
PYW_GIL_RELEASE;
int r = (py_ret == NULL || !PyNumber_Check(py_ret)) ? 1 /* stop enumeration on failure */ : PyInt_AsLong(py_ret);
Py_XDECREF(py_file);
Py_XDECREF(py_ret);
return r;
}
//</code(py_diskio)>
//<inline(py_diskio)>
//--------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback)
{
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;
}
//</inline(py_diskio)>
#endif

5
pywraps/py_diskio.py Normal file
View File

@ -0,0 +1,5 @@
#<pycode(py_diskio)>
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)
#</pycode(py_diskio)>

156
pywraps/py_expr.hpp Normal file
View File

@ -0,0 +1,156 @@
#ifndef __PY_EXPR__
#define __PY_EXPR__
//<code(py_expr)>
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)
{
Py_INCREF(py_func);
}
~py_idcfunc_ctx_t()
{
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;
ppyobject_vec_t pargs;
char errbuf[MAXSTR];
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, NULL, errbuf, sizeof(errbuf)) )
{
// Error during conversion? Create an IDC exception
return PyW_CreateIdcException(r, errbuf);
}
// Call the Python function
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallObject(
ctx->py_func,
pargs.empty() ? NULL : pargs[0]);
error_t err;
if ( PyW_GetError(errbuf, sizeof(errbuf)) )
{
err = PyW_CreateIdcException(r, errbuf);
Py_XDECREF(py_result);
}
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;
if ( cvt != CIP_OK_NODECREF )
Py_XDECREF(py_result);
}
PYW_GIL_RELEASE;
// Free the converted args
pyw_free_idc_args(pargs);
return err;
}
//</code(py_expr)>
//<inline(py_expr)>
//---------------------------------------------------------------------------
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);
}
//</inline(py_expr)>
#endif

169
pywraps/py_expr.py Normal file
View File

@ -0,0 +1,169 @@
# --------------------------------------------------------------------------
import os
import sys
import idaapi
import _idaapi
from sys import getrefcount
import gc
try:
import pywraps
pywraps_there = True
_idaapi.pyw_register_idc_func = pywraps.pyw_register_idc_func
_idaapi.pyw_unregister_idc_func = pywraps.pyw_unregister_idc_func
_idaapi.py_get_call_idc_func = pywraps.py_get_call_idc_func
_idaapi.py_set_idc_func_ex = pywraps.py_set_idc_func_ex
except Exception as e:
pywraps_there = False
print("exception: %s" % str(e))
print("Using PyWraps: %s" % pywraps_there)
# --------------------------------------------------------------------------
#<pycode(py_expr)>
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)
#</pycode(py_expr)>
# --------------------------------------------------------------------------
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
#</pycode(ex_expr)>
# --------------------------------------------------------------------------
#<pycode(ex_expr)>
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")
#</pycode(ex_expr)>

88
pywraps/py_gdl.py Normal file
View File

@ -0,0 +1,88 @@
#<pycode(py_gdl)>
# -----------------------------------------------------------------------
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)
#</pycode(py_gdl)>

816
pywraps/py_graph.hpp Normal file
View File

@ -0,0 +1,816 @@
#ifndef __PY_IDA_GRAPH__
#define __PY_IDA_GRAPH__
//<code(py_graph)>
class py_graph_t
{
private:
enum
{
GR_HAVE_USER_HINT = 0x00000001,
GR_HAVE_CLICKED = 0x00000002,
GR_HAVE_DBL_CLICKED = 0x00000004,
GR_HAVE_GOTFOCUS = 0x00000008,
GR_HAVE_LOSTFOCUS = 0x00000010,
GR_HAVE_CHANGED_CURRENT = 0x00000020,
GR_HAVE_CLOSE = 0x00000040,
GR_HAVE_COMMAND = 0x00000080
};
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<int, nodetext_cache_t>
{
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 tform_pygraph_map_t: public std::map<TForm *, py_graph_t *>
{
public:
py_graph_t *get(TForm *form)
{
iterator it = find(form);
return it == end() ? NULL : it->second;
}
void add(TForm *form, py_graph_t *py)
{
(*this)[form] = py;
}
};
class cmdid_map_t: public std::map<Py_ssize_t, py_graph_t *>
{
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 tform_pygraph_map_t tform_pyg;
static cmdid_map_t cmdid_pyg;
int cb_flags;
TForm *form;
graph_viewer_t *gv;
bool refresh_needed;
PyObject *self;
nodetext_cache_map_t node_cache;
// static callback
static int idaapi s_callback(void *obj, int code, va_list va)
{
return ((py_graph_t *)obj)->gr_callback(code, va);
}
static bool idaapi s_menucb(void *ud)
{
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_ENSURE;
PyObject *ret = PyObject_CallMethod(self, (char *)S_ON_COMMAND, "n", id);
PYW_GIL_RELEASE;
Py_XDECREF(ret);
}
// 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)
{
if ( !refresh_needed )
return;
// Check return value to OnRefresh() call
PYW_GIL_ENSURE;
PyObject *ret = PyObject_CallMethod(self, (char *)S_ON_REFRESH, NULL);
PYW_GIL_RELEASE;
if ( ret == NULL || !PyObject_IsTrue(ret) )
{
Py_XDECREF(ret);
return;
}
// Refer to the nodes
PyObject *nodes = PyW_TryGetAttrString(self, S_M_NODES);
if ( ret == NULL || !PyList_Check(nodes) )
{
Py_XDECREF(nodes);
return;
}
// Refer to the edges
PyObject *edges = PyW_TryGetAttrString(self, S_M_EDGES);
if ( ret == NULL || !PyList_Check(edges) )
{
Py_DECREF(nodes);
Py_XDECREF(edges);
return;
}
// Resize the nodes
int max_nodes = abs(int(PyList_Size(nodes)));
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)-1; i>=0; i-- )
{
// Each list item is a sequence (id1, id2)
PyObject *item = PyList_GetItem(edges, i);
if ( !PySequence_Check(item) )
continue;
// Get and validate each of the two elements in the sequence
int edge_ids[2];
int j;
for ( j=0; j<qnumber(edge_ids); j++ )
{
PyObject *id = PySequence_GetItem(item, j);
if ( id == NULL || !PyInt_Check(id) )
{
Py_XDECREF(id);
break;
}
int v = int(PyInt_AS_LONG(id));
Py_DECREF(id);
if ( v > 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);
}
Py_DECREF(nodes);
Py_DECREF(edges);
}
// 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)
{
// 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_ENSURE;
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_GETTEXT, "i", node);
PYW_GIL_RELEASE;
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) )
{
s = PyString_AsString(result);
if ( s == NULL )
s = "";
c = node_cache.add(node, s, cl);
}
// User returned a sequence of text and bgcolor
else if ( PySequence_Check(result) && PySequence_Size(result) == 2 )
{
PyObject *py_str = PySequence_GetItem(result, 0);
PyObject *py_color = PySequence_GetItem(result, 1);
if ( py_str == NULL || !PyString_Check(py_str) || (s = PyString_AsString(py_str)) == NULL )
s = "";
if ( py_color != NULL && PyNumber_Check(py_color) )
cl = bgcolor_t(PyLong_AsUnsignedLong(py_color));
c = node_cache.add(node, s, cl);
Py_XDECREF(py_str);
Py_XDECREF(py_color);
}
Py_DECREF(result);
*str = c->text.c_str();
if ( bg_color != NULL )
*bg_color = c->bgcolor;
return true;
}
// 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)
{
// '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_ENSURE;
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_HINT, "i", mousenode);
PYW_GIL_RELEASE;
bool ok = result != NULL && PyString_Check(result);
if ( !ok )
{
Py_XDECREF(result);
return 0;
}
*hint = qstrdup(PyString_AsString(result));
Py_DECREF(result);
return 1; // use our hint
}
// graph is being destroyed
void on_destroy(mutable_graph_t * /*g*/ = NULL)
{
if ( self != NULL )
{
if ( (cb_flags & GR_HAVE_CLOSE) != 0 )
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(result);
}
unbind();
}
// Remove the TForm from list
if ( form != NULL )
tform_pyg.erase(form);
// Remove all associated commands from the list
cmdid_pyg.clear(this);
// Delete this instance
delete this;
}
// graph is being clicked
int on_clicked(
graph_viewer_t * /*gv*/,
selection_item_t * /*item1*/,
graph_item_t *item2)
{
// in: graph_viewer_t *gv
// 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_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_CLICK,
"i",
item2->n);
PYW_GIL_RELEASE;
if ( result == NULL || !PyObject_IsTrue(result) )
{
Py_XDECREF(result);
return 1;
}
Py_DECREF(result);
return 0;
}
// a graph node has been double clicked
int on_dblclicked(graph_viewer_t * /*gv*/, selection_item_t *item)
{
// in: graph_viewer_t *gv
// 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_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_DBL_CLICK,
"i",
item->node);
PYW_GIL_RELEASE;
if ( result == NULL || !PyObject_IsTrue(result) )
{
Py_XDECREF(result);
return 1;
}
Py_DECREF(result);
return 0;
}
// a graph viewer got focus
void on_gotfocus(graph_viewer_t * /*gv*/)
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_ACTIVATE,
NULL);
PYW_GIL_RELEASE;
Py_XDECREF(result);
}
// a graph viewer lost focus
void on_lostfocus(graph_viewer_t * /*gv*/)
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_DEACTIVATE,
NULL);
PYW_GIL_RELEASE;
Py_XDECREF(result);
}
// a new graph node became the current node
int on_changed_current(graph_viewer_t * /*gv*/, int curnode)
{
// in: graph_viewer_t *gv
// int curnode
// out: 0-ok, 1-forbid to change the current node
if ( curnode < 0 )
return 0;
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_SELECT,
"i",
curnode);
PYW_GIL_RELEASE;
bool allow = (result != NULL && PyObject_IsTrue(result));
Py_XDECREF(result);
return allow ? 0 : 1;
}
int 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_destroy(va_arg(va, mutable_graph_t *));
ret = 0;
break;
//
case grcode_clicked:
if ( cb_flags & GR_HAVE_CLICKED )
{
graph_viewer_t *gv = 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(gv, item, gitem);
}
else
{
// Ignore the click
ret = 1;
}
break;
//
case grcode_dblclicked:
if ( cb_flags & GR_HAVE_DBL_CLICKED )
{
graph_viewer_t *gv = va_arg(va, graph_viewer_t *);
selection_item_t *item = va_arg(va, selection_item_t *);
ret = on_dblclicked(gv, item);
}
else
ret = 1; // ignore
break;
//
case grcode_gotfocus:
if ( cb_flags & GR_HAVE_GOTFOCUS )
on_gotfocus(va_arg(va, graph_viewer_t *));
ret = 0;
break;
//
case grcode_lostfocus:
if ( cb_flags & GR_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 ( cb_flags & GR_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 ( cb_flags & GR_HAVE_CHANGED_CURRENT )
{
graph_viewer_t *gv = va_arg(va, graph_viewer_t *);
int cur_node = va_arg(va, int);
ret = on_changed_current(gv, cur_node);
}
else
ret = 0; // allow selection change
break;
//
default:
ret = 0;
break;
}
//grcode_changed_graph, // new graph has been set
//grcode_creating_group, // a group is being created
//grcode_deleting_group, // a group is being deleted
//grcode_group_visibility, // a group is being collapsed/uncollapsed
//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;
}
void unbind()
{
if ( self == NULL )
return;
// Unbind this object from the python object
PyObject *py_cobj = PyCObject_FromVoidPtr(NULL, NULL);
PyObject_SetAttrString(self, S_M_THIS, py_cobj);
Py_DECREF(py_cobj);
Py_XDECREF(self);
self = NULL;
}
void show()
{
open_tform(form, FORM_MDI|FORM_TAB|FORM_MENU);
}
static py_graph_t *extract_this(PyObject *self)
{
// Try to extract "this" from the python object
PyObject *py_this = PyW_TryGetAttrString(self, S_M_THIS);
if ( py_this == NULL || !PyCObject_Check(py_this) )
{
Py_XDECREF(py_this);
return NULL;
}
py_graph_t *ret = (py_graph_t *) PyCObject_AsVoidPtr(py_this);
Py_DECREF(py_this);
return ret;
}
void jump_to_node(int nid)
{
viewer_center_on(gv, nid);
int x, y;
// will return a place only when a node was previously selected
place_t *old_pl = get_custom_viewer_place(gv, 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(gv, new_pl, x, y);
delete new_pl;
}
}
void refresh()
{
refresh_needed = true;
refresh_viewer(gv);
}
int create(PyObject *self, const char *title)
{
// check what callbacks we have
static const struct
{
const char *name;
int have;
} callbacks[] =
{
{S_ON_REFRESH, 0}, // 0 = mandatory callback
{S_ON_GETTEXT, 0},
{S_M_EDGES, -1}, // -1 = mandatory attributes
{S_M_NODES, -1},
{S_ON_HINT, GR_HAVE_USER_HINT},
{S_ON_CLICK, GR_HAVE_CLICKED},
{S_ON_DBL_CLICK, GR_HAVE_DBL_CLICKED},
{S_ON_CLOSE, GR_HAVE_CLOSE},
{S_ON_COMMAND, GR_HAVE_COMMAND},
{S_ON_SELECT, GR_HAVE_CHANGED_CURRENT},
{S_ON_ACTIVATE, GR_HAVE_GOTFOCUS},
{S_ON_DEACTIVATE, GR_HAVE_LOSTFOCUS}
};
cb_flags = 0;
for ( int i=0; i<qnumber(callbacks); i++ )
{
PyObject *attr = PyW_TryGetAttrString(self, callbacks[i].name);
int have = callbacks[i].have;
// Mandatory fields not present?
if ( (attr == NULL && have <= 0 )
// Mandatory callback fields present but not callable?
|| (attr != NULL && have >= 0 && PyCallable_Check(attr) == 0))
{
Py_XDECREF(attr);
return -1;
}
if ( have > 0 && attr != NULL )
cb_flags |= have;
Py_XDECREF(attr);
}
// Keep a reference
this->self = self;
Py_INCREF(self);
// Bind py_graph_t to python object
PyObject *py_cobj = PyCObject_FromVoidPtr(this, NULL);
PyObject_SetAttrString(self, S_M_THIS, py_cobj);
Py_DECREF(py_cobj);
// Create form
HWND hwnd = NULL;
form = create_tform(title, &hwnd);
// Link "form" and "py_graph"
tform_pyg.add(form, this);
if ( hwnd != NULL )
{
// get a unique graph id
netnode id;
char grnode[MAXSTR];
qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title);
id.create(grnode);
gv = create_graph_viewer(form, id, s_callback, this, 0);
open_tform(form, FORM_MDI | FORM_TAB | FORM_MENU);
if ( gv != NULL )
viewer_fit_window(gv);
}
else
{
show();
}
viewer_fit_window(gv);
return 0;
}
Py_ssize_t add_command(const char *title, const char *hotkey)
{
if ( (cb_flags & GR_HAVE_COMMAND) == 0 || gv == NULL)
return 0;
Py_ssize_t cmd_id = cmdid_pyg.id();
bool ok = viewer_add_menu_item(gv, 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;
gv = NULL;
refresh_needed = true;
self = NULL;
}
static void SelectNode(PyObject *self, int /*nid*/)
{
py_graph_t *_this = extract_this(self);
if ( _this == NULL || _this->form == NULL )
return;
_this->jump_to_node(0);
}
static Py_ssize_t AddCommand(PyObject *self, const char *title, const char *hotkey)
{
py_graph_t *_this = extract_this(self);
if ( _this == NULL || _this->form == NULL )
return 0;
return _this->add_command(title, hotkey);
}
static void Close(PyObject *self)
{
py_graph_t *_this = extract_this(self);
if ( _this == NULL || _this->form == NULL )
return;
close_tform(_this->form, FORM_CLOSE_LATER);
}
static void Refresh(PyObject *self)
{
py_graph_t *_this = extract_this(self);
if ( _this == NULL )
return;
_this->refresh();
}
static py_graph_t *Show(PyObject *self)
{
py_graph_t *ret = extract_this(self);
// New instance?
if ( ret == 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
ret = tform_pyg.get(find_tform(title.c_str()));
// Instance not found? create a new one
if ( ret == NULL )
ret = new py_graph_t();
else
{
// unbind so we are rebound
ret->unbind();
ret->refresh_needed = true;
}
if ( ret->create(self, title.c_str()) < 0 )
{
delete ret;
ret = NULL;
}
}
else
{
ret->show();
}
return ret;
}
};
py_graph_t::tform_pygraph_map_t py_graph_t::tform_pyg;
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_refresh(PyObject *self)
{
py_graph_t::Refresh(self);
}
void pyg_close(PyObject *self)
{
py_graph_t::Close(self);
}
PyObject *pyg_add_command(PyObject *self, const char *title, const char *hotkey)
{
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);
}
//</code(py_graph)>
//--------------------------------------------------------------------------
//<inline(py_graph)>
void pyg_refresh(PyObject *self);
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);
//</inline(py_graph)>
#endif

169
pywraps/py_graph.py Normal file
View File

@ -0,0 +1,169 @@
#<pycode(py_graph)>
class GraphViewer(object):
"""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 Refresh(self):
"""
Refreshes the graph. This causes the OnRefresh() to be called
"""
_idaapi.pyg_refresh(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):
"""
Adds a menu command to the graph. Call this command after the graph is shown (with Show()).
Once a command is added, a command id is returned. The commands are handled inside the OnCommand() handler
@return: 0 on failure or the command id
"""
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
#<pydoc>
# 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):
# """
# Triggered when a menu command is selected through the menu or its hotkey
# @return: None
# """
# print "command:", cmd_id
#</pydoc>
#</pycode(py_graph)>

804
pywraps/py_idaapi.hpp Normal file
View File

@ -0,0 +1,804 @@
#ifndef __PY_IDAAPI__
#define __PY_IDAAPI__
//<code(py_idaapi)>
//------------------------------------------------------------------------
// 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_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__";
#ifdef __PYWRAPS__
static const char S_PY_IDAAPI_MODNAME[] = "__main__";
#else
static const char S_PY_IDAAPI_MODNAME[] = S_IDAAPI_MODNAME;
#endif
//------------------------------------------------------------------------
static PyObject *py_cvt_helper_module = NULL;
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;
};
//------------------------------------------------------------------------
const char *pywraps_check_autoscripts()
{
static const char *exts[] = {"py", "pyw", "pyc", "pyo"};
static const char *fns[] =
{
"swig_runtime_data" SWIG_RUNTIME_VERSION,
"sitecustomize",
"usercustomize"
};
for (size_t ifn=0; ifn < qnumber(fns); ++ifn )
{
for ( size_t iext=0; iext < qnumber(exts); ++iext )
{
static char fn[QMAXPATH];
qsnprintf(fn, sizeof(fn), "%s.%s", fns[ifn], exts[iext]);
if ( qfileexist(fn) )
return fn;
}
}
return NULL;
}
//------------------------------------------------------------------------
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)
{
PyObject *pyfunc = (PyObject *) argv[0].pvoid;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(pyfunc, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(py_result);
// Report Python error as IDC exception
qstring err;
if ( PyW_GetError(&err) )
return PyW_CreateIdcException(res, err.c_str());
return eOk;
}
//------------------------------------------------------------------------
// 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;
Py_XDECREF(py_cvt_helper_module);
py_cvt_helper_module = NULL;
// 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
PyObject *create_idaapi_class_instance0(const char *clsname)
{
PyObject *py_cls = get_idaapi_attr(clsname);
if ( py_cls == NULL )
return NULL;
PYW_GIL_ENSURE;
PyObject *py_obj = PyObject_CallFunctionObjArgs(py_cls, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_cls);
if ( PyW_GetError() || py_obj == NULL )
{
Py_XDECREF(py_obj);
Py_RETURN_NONE;
}
return py_obj;
}
//------------------------------------------------------------------------
// Utility function to create linked class instances
PyObject *create_idaapi_linked_class_instance(
const char *clsname,
void *lnk)
{
PyObject *py_cls = get_idaapi_attr(clsname);
if ( py_cls == NULL )
return NULL;
PyObject *py_lnk = PyCObject_FromVoidPtr(lnk, NULL);
PYW_GIL_ENSURE;
PyObject *py_obj = PyObject_CallFunctionObjArgs(py_cls, py_lnk, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_cls);
Py_DECREF(py_lnk);
if ( PyW_GetError() || py_obj == NULL )
{
Py_XDECREF(py_obj);
py_obj = NULL;
}
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
PyObject *get_idaapi_attr_by_id(const int class_id)
{
if ( class_id >= PY_CLSID_LAST || py_cvt_helper_module == NULL )
return NULL;
// 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__"
};
return PyObject_GetAttrString(py_cvt_helper_module, class_names[class_id]);
}
//------------------------------------------------------------------------
// Gets a class reference by name
PyObject *get_idaapi_attr(const char *attrname)
{
return py_cvt_helper_module == NULL
? NULL
: PyW_TryGetAttrString(py_cvt_helper_module, attrname);
}
//------------------------------------------------------------------------
// Returns a qstring from an object attribute
bool PyW_GetStringAttr(
PyObject *py_obj,
const char *attr_name,
qstring *str)
{
PyObject *py_attr = PyW_TryGetAttrString(py_obj, attr_name);
if ( py_attr == NULL )
return false;
bool ok = PyString_Check(py_attr) != 0;
if ( ok )
*str = PyString_AsString(py_attr);
Py_DECREF(py_attr);
return ok;
}
//------------------------------------------------------------------------
// Returns an attribute or NULL
// No errors will be set if the attribute did not exist
PyObject *PyW_TryGetAttrString(PyObject *py_obj, const char *attr)
{
if ( !PyObject_HasAttrString(py_obj, attr) )
return NULL;
else
return PyObject_GetAttrString(py_obj, attr);
}
//------------------------------------------------------------------------
// Tries to import a module and clears the exception on failure
PyObject *PyW_TryImportModule(const char *name)
{
PYW_GIL_ENSURE;
PyObject *result = PyImport_ImportModule(name);
PYW_GIL_RELEASE;
if ( result != NULL )
return result;
if ( PyErr_Occurred() )
PyErr_Clear();
return NULL;
}
//-------------------------------------------------------------------------
// 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)
{
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
return false;
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
idc_var->set_long(l);
return true;
}
// 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);
return true;
}
PyErr_Clear();
idc_var->set_int64(PyLong_AsLongLong(py_var));
return true;
}
//-------------------------------------------------------------------------
// Parses a Python object as a long or long long
bool PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64)
{
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
return false;
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
if ( num != NULL )
*num = uint64(l);
if ( is_64 != NULL )
*is_64 = false;
return true;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() )
{
if ( num != NULL )
*num = uint64(ul);
if ( is_64 != NULL )
*is_64 = false;
return true;
}
PyErr_Clear();
// Try to parse as int64
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if ( !PyErr_Occurred() )
{
if ( num != NULL )
*num = uint64(ll);
if ( is_64 != NULL )
*is_64 = true;
return true;
}
PyErr_Clear();
// Try to parse as uint64
unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var);
PyObject *err = PyErr_Occurred();
if ( err == NULL )
{
if ( num != NULL )
*num = uint64(ull);
if ( is_64 != NULL )
*is_64 = true;
return true;
}
// Negative number? _And_ it with uint64(-1)
bool ok = false;
if ( err == PyExc_TypeError )
{
PyObject *py_mask = Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull);
PyObject *py_num = PyNumber_And(py_var, py_mask);
if ( py_num != NULL && py_mask != NULL )
{
PyErr_Clear();
ull = PyLong_AsUnsignedLongLong(py_num);
if ( !PyErr_Occurred() )
{
if ( num != NULL )
*num = uint64(ull);
if ( is_64 != NULL )
*is_64 = true;
ok = true;
}
}
Py_XDECREF(py_num);
Py_XDECREF(py_mask);
}
PyErr_Clear();
return ok;
}
//-------------------------------------------------------------------------
// Checks if a given object is of sequence type
bool PyW_IsSequenceType(PyObject *obj)
{
if ( !PySequence_Check(obj) )
return false;
Py_ssize_t sz = PySequence_Size(obj);
if ( sz == -1 || PyErr_Occurred() != NULL )
{
PyErr_Clear();
return false;
}
return true;
}
//-------------------------------------------------------------------------
// Returns the string representation of an object
bool PyW_ObjectToString(PyObject *obj, qstring *out)
{
PyObject *py_str = PyObject_Str(obj);
if ( py_str != NULL )
{
*out = PyString_AsString(py_str);
Py_DECREF(py_str);
return true;
}
else
{
out->qclear();
return false;
}
}
//--------------------------------------------------------------------------
// Checks if a Python error occured and fills the out parameter with the
// exception string
bool PyW_GetError(qstring *out, bool clear_err)
{
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()
PyObject *py_fmtexc = get_idaapi_attr(S_IDAAPI_FORMATEXC);
// Helper there?
if ( py_fmtexc != NULL )
{
// Call helper
PYW_GIL_ENSURE;
py_ret = PyObject_CallFunctionObjArgs(
py_fmtexc,
err_type,
err_value,
err_traceback,
NULL);
PYW_GIL_RELEASE;
// Dispose helper reference
Py_DECREF(py_fmtexc);
}
// 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)
{
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)
{
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)
{
// Try to query the link attribute
PyObject *attr = PyW_TryGetAttrString(pyobj, S_CLINK_NAME);
void *t = attr != NULL && PyCObject_Check(attr) ? PyCObject_AsVoidPtr(attr) : NULL;
Py_XDECREF(attr);
return t;
}
//</code(py_idaapi)>
//<inline(py_idaapi)>
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_parse_command_line(const char *cmdline)
{
qstrvec_t args;
if ( parse_command_line(cmdline, &args) == 0 )
Py_RETURN_NONE;
PyObject *py_list = PyList_New(args.size());
for ( size_t i=0; i<args.size(); i++ )
PyList_SetItem(py_list, i, PyString_FromString(args[i].c_str()));
return py_list;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_inf_structure():
"""
Returns the global variable 'inf' (an instance of idainfo structure, see ida.hpp)
"""
pass
#</pydoc>
*/
idainfo *get_inf_structure(void)
{
return &inf;
}
//-------------------------------------------------------------------------
// Declarations from Python.cpp
/*
#<pydoc>
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
#</pydoc>
*/
int set_script_timeout(int timeout);
/*
#<pydoc>
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
#</pydoc>
*/
void disable_script_timeout();
/*
#<pydoc>
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
#</pydoc>
*/
void enable_extlang_python(bool enable);
void enable_python_cli(bool enable);
/*
#<pydoc>
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
#</pydoc>
*/
//---------------------------------------------------------------------------
// qstrvec_t wrapper
//---------------------------------------------------------------------------
DECLARE_PY_CLINKED_OBJECT(qstrvec_t);
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)
{
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)
{
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)
{
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;
}
//---------------------------------------------------------------------------
//</inline(py_idaapi)>
#endif

513
pywraps/py_idaapi.py Normal file
View File

@ -0,0 +1,513 @@
# -----------------------------------------------------------------------
try:
import pywraps
pywraps_there = True
except:
pywraps_there = False
import _idaapi
import random
import operator
import datetime
#<pycode(py_idaapi)>
import struct
import traceback
import os
import sys
import bisect
import __builtin__
# -----------------------------------------------------------------------
# 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)
# -----------------------------------------------------------------------
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):
"""Class representing an qstrvec_t"""
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)
# Save the argv, path, I/O and base modules for later cleanup
argv = sys.argv
path = sys.path
stdio = [sys.stdin, sys.stdout, sys.stderr]
basemodules = sys.modules.copy()
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 the globals to the state before the script was run
g['__file__'] = old__file__
sys.argv = argv
sys.path = path
sys.stdin, sys.stdout, sys.stderr = stdio
# Clean up the modules loaded by the script
for module in sys.modules.keys():
if not module in basemodules:
del sys.modules[module]
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 a completion object
IDAPython_Completion = __IDAPython_Completion_Util()
#</pycode(py_idaapi)>

1536
pywraps/py_idp.hpp Normal file

File diff suppressed because it is too large Load Diff

902
pywraps/py_kernwin.hpp Normal file
View File

@ -0,0 +1,902 @@
#ifndef __PY_KERNWIN__
#define __PY_KERNWIN__
//------------------------------------------------------------------------
//<inline(py_kernwin)>
//------------------------------------------------------------------------
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_register_timer(int interval, PyObject *py_callback)
{
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)
{
py_timer_ctx_t *ctx = (py_timer_ctx_t *)ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(ctx->pycallback, NULL);
int ret = py_result == NULL ? -1 : PyLong_AsLong(py_result);
Py_XDECREF(py_result);
PYW_GIL_RELEASE;
// Timer has been unregistered?
if ( ret == -1 )
{
// Fee 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);
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_unregister_timer(PyObject *py_timerctx)
{
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def choose_idasgn():
"""
Opens the signature chooser
@return: None or the selected signature name
"""
pass
#</pydoc>
*/
static PyObject *py_choose_idasgn()
{
char *name = choose_idasgn();
if ( name == NULL )
{
Py_RETURN_NONE;
}
else
{
PyObject *py_str = PyString_FromString(name);
qfree(name);
return py_str;
}
}
//------------------------------------------------------------------------
/*
#<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);
}
//------------------------------------------------------------------------
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;
if ( PyString_AsStringAndSize(data, &s, &len) == -1 )
return 0;
else
return load_custom_icon(s, len, format);
}
//------------------------------------------------------------------------
/*
#<pydoc>
def free_custom_icon(icon_id):
"""
Frees an icon loaded with load_custom_icon()
"""
pass
#</pydoc>
*/
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_asktext(int max_text, const char *defval, const char *prompt)
{
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def str2ea(addr):
"""
Converts a string express to EA. The expression evaluator may be called as well.
@return: BADADDR or address value
"""
pass
#</pydoc>
*/
ea_t py_str2ea(const char *str, ea_t screenEA = BADADDR)
{
ea_t ea;
bool ok = str2ea(str, &ea, screenEA);
return ok ? ea : BADADDR;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def process_ui_action(name, flags):
"""
Invokes an IDA UI action by name
@param name: action name
@param flags: Reserved. Must be zero
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_process_ui_action(const char *name, int flags)
{
return process_ui_action(name, flags, NULL);
}
//------------------------------------------------------------------------
/*
#<pydoc>
def del_menu_item(menu_ctx):
"""
Deletes a menu item previously added with add_menu_item()
@param menu_ctx: value returned by add_menu_item()
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_del_menu_item(PyObject *py_ctx)
{
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def del_hotkey(ctx):
"""
Deletes a previously registered function hotkey
@param ctx: Hotkey context previously returned by add_hotkey()
@return: Boolean.
"""
pass
#</pydoc>
*/
bool py_del_hotkey(PyObject *pyctx)
{
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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc)
{
// 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;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def add_menu_item(menupath, name, hotkey, flags, callback, args):
"""
Adds a menu item
@param menupath: path to the menu item after or before which the insertion will take place
@param name: name of the menu item (~x~ is used to denote Alt-x hot letter)
@param hotkey: hotkey for the menu item (may be empty)
@param flags: one of SETMENU_... consts
@param callback: function which gets called when the user selects the menu item.
The function callback is of the form:
def callback(*args):
pass
@param args: tuple containing the arguments
@return: None or a menu context (to be used by del_menu_item())
"""
pass
#</pydoc>
*/
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)
{
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);
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
//------------------------------------------------------------------------
static int py_execute_sync(PyObject *py_callable, int reqf)
{
// Not callable?
if ( !PyCallable_Check(py_callable) )
return -1;
struct py_exec_request_t: exec_request_t
{
PyObject *py_callable;
bool no_wait;
virtual int idaapi execute()
{
PYW_GIL_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);
PYW_GIL_RELEASE;
// Free this request
if ( no_wait )
delete this;
return r;
}
py_exec_request_t(PyObject *pyc, bool no_wait):
py_callable(pyc), no_wait(no_wait)
{
// Take reference to the callable
Py_INCREF(py_callable);
}
virtual ~py_exec_request_t()
{
// Release callable
Py_XDECREF(py_callable);
}
};
bool no_wait = (reqf & MFF_NOWAIT) != 0;
// Allocate a request
py_exec_request_t *req = new py_exec_request_t(py_callable, no_wait);
// Execute it
int r = execute_sync(*req, reqf);
// Delete only if NOWAIT was not specified
// (Otherwise the request will delete itself)
if ( !no_wait )
delete req;
return r;
}
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static bool py_execute_ui_requests(PyObject *py_list)
{
struct py_ui_request_t: public ui_request_t
{
private:
ppyobject_vec_t py_callables;
size_t py_callable_idx;
static int idaapi s_py_list_walk_cb(
PyObject *py_item,
Py_ssize_t index,
void *ud)
{
// Not callable? Terminate iteration
if ( !PyCallable_Check(py_item) )
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);
Py_INCREF(py_item);
return CIP_OK;
}
public:
py_ui_request_t(): py_callable_idx(0)
{
}
virtual bool idaapi run()
{
// Get callable
PyObject *py_callable = py_callables.at(py_callable_idx);
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callable, NULL);
bool reschedule = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
PYW_GIL_RELEASE;
// 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()
{
// Release all callables
for ( ppyobject_vec_t::const_iterator it=py_callables.begin();
it != py_callables.end();
++it )
{
Py_XDECREF(*it);
}
}
};
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;
}
//------------------------------------------------------------------------
/*
#<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>
*/
//---------------------------------------------------------------------------
// UI hooks
//---------------------------------------------------------------------------
int idaapi UI_Callback(void *ud, int notification_code, va_list va);
/*
#<pydoc>
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 term(self):
"""
IDA is terminated and the database is already closed.
The UI may close its windows in this callback.
"""
pass
#</pydoc>
*/
class UI_Hooks
{
public:
virtual ~UI_Hooks()
{
}
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*/)
{
Py_RETURN_NONE;
};
};
//</inline(py_kernwin)>
//---------------------------------------------------------------------------
//<code(py_kernwin)>
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
int idaapi UI_Callback(void *ud, int notification_code, va_list va)
{
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;
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;
}
}
}
catch (Swig::DirectorException &e)
{
msg("Exception in UI Hook function: %s\n", e.getMessage());
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
}
//------------------------------------------------------------------------
bool idaapi py_menu_item_callback(void *userdata)
{
// 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
PYW_GIL_ENSURE;
PyObject *result = PyEval_CallObject(func, args);
PYW_GIL_RELEASE;
// We cannot raise an exception in the callback, just print it.
if ( result == NULL )
{
PyErr_Print();
return false;
}
bool ret = PyObject_IsTrue(result) != 0;
Py_DECREF(result);
return ret;
}
//</code(py_kernwin)>
#endif

110
pywraps/py_kernwin.py Normal file
View File

@ -0,0 +1,110 @@
# -----------------------------------------------------------------------
# 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)
if pywraps_there:
_idaapi.execute_sync = pywraps.py_execute_sync
_idaapi.add_hotkey = pywraps.py_add_hotkey
_idaapi.del_hotkey = pywraps.py_del_hotkey
# -----------------------------------------------------------------------
#<pycode(py_kernwin)>
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_RAW = 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
#</pycode(py_kernwin)>
# ----------------------------------------------------------------------
from threading import Thread
import time
# ----------------------------------------------------------------------
def myfunction(cnt):
i = 1
while i <= cnt:
print "i=", i
i += 1
time.sleep(1)
print "done!"
def test_thread():
t = Thread(target=myfunction, args=(2,))
t.start()
t.join()
# ----------------------------------------------------------------------
def hotkey_func1():
print "Hello from hotkey handler in Python!"

211
pywraps/py_lines.hpp Normal file
View File

@ -0,0 +1,211 @@
#ifndef __PYWRAPS__LINES__
#define __PYWRAPS__LINES__
//<code(py_lines)>
//------------------------------------------------------------------------
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)
{
PyObject *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, &py_str, &py_len) != -1 )
{
memcpy(buf, py_str, qmin(bufsize, py_len));
if ( py_len < bufsize )
buf[py_len] = '\0';
}
}
Py_XDECREF(py_ret);
}
//</code(py_lines)>
//------------------------------------------------------------------------
//<inline(py_lines)>
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb)
{
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_tag_remove(const char *instr)
{
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);
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_generate_disassembly(
ea_t ea,
int max_lines,
bool as_stack,
bool notags)
{
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);
PyObject *py_tuple = PyTuple_New(nlines);
for ( int i=0; i<nlines; i++ )
{
const char *s = lines[i];
size_t line_len = strlen(s);
if ( notags )
{
qbuf.resize(line_len+5);
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0];
}
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
qfree(lines[i]);
}
delete [] lines;
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
Py_DECREF(py_tuple);
return py_result;
}
//</inline(py_lines)>
#endif

34
pywraps/py_lines.py Normal file
View File

@ -0,0 +1,34 @@
#<pycode(py_lines)>
# ---------------- 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
#</pycode(py_lines)>

361
pywraps/py_linput.hpp Normal file
View File

@ -0,0 +1,361 @@
#ifndef __PY_IDA_LINPUT__
#define __PY_IDA_LINPUT__
//--------------------------------------------------------------------------
//<inline(py_diskio)>
/*
#<pydoc>
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
#</pydoc>
*/
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)
{
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)
{
if ( pycobject != NULL && PyCObject_Check(pycobject) )
_from_cobject(pycobject);
}
//--------------------------------------------------------------------------
void close()
{
if ( li == NULL )
return;
if ( own == OWN_CREATE )
close_linput(li);
else if ( own == OWN_FROM_FP )
unmake_linput(li);
li = NULL;
own = OWN_NONE;
}
//--------------------------------------------------------------------------
~loader_input_t()
{
close();
}
//--------------------------------------------------------------------------
bool open(const char *filename, bool remote = false)
{
close();
li = open_linput(filename, remote);
if ( li == NULL )
return false;
// Save file name
fn = filename;
own = OWN_CREATE;
return true;
}
//--------------------------------------------------------------------------
void set_linput(linput_t *linput)
{
close();
own = OWN_FROM_LI;
li = linput;
fn.sprnt("<linput_t * %p>", 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)
{
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)
{
linput_t *fp_li = make_linput(fp);
if ( fp_li == NULL )
return NULL;
loader_input_t *l = new loader_input_t();
l->own = OWN_FROM_FP;
l->fn.sprnt("<FILE * %p>", fp);
l->li = fp_li;
return l;
}
//--------------------------------------------------------------------------
linput_t *get_linput()
{
return li;
}
//--------------------------------------------------------------------------
bool open_memory(ea_t start, asize_t size = 0)
{
linput_t *l = create_memory_linput(start, size);
if ( l == NULL )
return false;
close();
li = l;
fn = "<memory>";
own = OWN_CREATE;
return true;
}
//--------------------------------------------------------------------------
int32 seek(int32 pos, int whence = SEEK_SET)
{
return qlseek(li, pos, whence);
}
//--------------------------------------------------------------------------
int32 tell()
{
return qltell(li);
}
//--------------------------------------------------------------------------
PyObject *getz(size_t sz, int32 fpos = -1)
{
do
{
char *buf = (char *) malloc(sz + 5);
if ( buf == NULL )
break;
qlgetz(li, fpos, buf, sz);
PyObject *ret = PyString_FromString(buf);
free(buf);
return ret;
} while ( false );
Py_RETURN_NONE;
}
//--------------------------------------------------------------------------
PyObject *gets(size_t len)
{
do
{
char *buf = (char *) malloc(len + 5);
if ( buf == NULL )
break;
if ( qlgets(buf, len, li) == NULL )
{
free(buf);
break;
}
PyObject *ret = PyString_FromString(buf);
free(buf);
return ret;
} while ( false );
Py_RETURN_NONE;
}
//--------------------------------------------------------------------------
PyObject *read(size_t size)
{
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
ssize_t r = qlread(li, buf, size);
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)
{
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = lreadbytes(li, buf, size, big_endian);
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)
{
return ::file2base(li, pos, ea1, ea2, patchable);
}
//--------------------------------------------------------------------------
int32 size()
{
return qlsize(li);
}
//--------------------------------------------------------------------------
PyObject *filename()
{
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qlgetc(li);
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
}
};
//</inline(py_diskio)>
#endif

78
pywraps/py_loader.hpp Normal file
View File

@ -0,0 +1,78 @@
#ifndef __PY_LOADER___
#define __PY_LOADER___
//------------------------------------------------------------------------
//<inline(py_loader)>
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1)
{
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
return 0;
return mem2base((void *)buf, ea, ea+len, fpos);
}
//------------------------------------------------------------------------
/*
#<pydoc>
def load_plugin(name):
"""
Loads a plugin
@return:
- None if plugin could not be loaded
- An opaque object representing the loaded plugin
"""
pass
#</pydoc>
*/
static PyObject *py_load_plugin(const char *name)
{
plugin_t *r = load_plugin(name);
if ( r == NULL )
Py_RETURN_NONE;
else
return PyCObject_FromVoidPtr(r, NULL);
}
//------------------------------------------------------------------------
/*
#<pydoc>
def run_plugin(plg):
"""
Runs a plugin
@param plg: A plugin object (returned by load_plugin())
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_run_plugin(PyObject *plg, int arg)
{
if ( !PyCObject_Check(plg) )
return false;
else
return run_plugin((plugin_t *)PyCObject_AsVoidPtr(plg), arg);
}
//</inline(py_loader)>
#endif

486
pywraps/py_nalt.hpp Normal file
View File

@ -0,0 +1,486 @@
#ifndef __PY_IDA_NALT__
#define __PY_IDA_NALT__
//<code(py_nalt)>
//-------------------------------------------------------------------------
// 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));
PyObject *py_name;
if ( name == NULL )
{
py_name = Py_None;
Py_INCREF(Py_None);
}
else
{
py_name = PyString_FromString(name);
}
PyObject *py_ord = Py_BuildValue(PY_FMT64, pyul_t(ord));
PyObject *py_ea = Py_BuildValue(PY_FMT64, pyul_t(ea));
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(
(PyObject *)param,
py_ea,
py_name,
py_ord,
NULL);
PYW_GIL_RELEASE;
int r = py_result != NULL && PyObject_IsTrue(py_result) ? 1 : 0;
Py_DECREF(py_ea);
Py_DECREF(py_name);
Py_DECREF(py_ord);
Py_XDECREF(py_result);
return r;
}
//-------------------------------------------------------------------------
switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self)
{
if ( !PyObject_HasAttrString(self, S_CLINK_NAME) )
return NULL;
switch_info_ex_t *r;
PyObject *attr = PyObject_GetAttrString(self, S_CLINK_NAME);
if ( PyCObject_Check(attr) )
r = (switch_info_ex_t *) PyCObject_AsVoidPtr(attr);
else
r = NULL;
Py_DECREF(attr);
return r;
}
//</code(py_nalt)>
//<inline(py_nalt)>
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *py_get_import_module_name(int mod_index)
{
char buf[MAXSTR];
if ( !get_import_module_name(mod_index, buf, sizeof(buf)) )
Py_RETURN_NONE;
return PyString_FromString(buf);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_get_switch_info_ex(ea_t ea)
{
switch_info_ex_t *ex = new switch_info_ex_t();
PyObject *py_obj;
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;
}
return py_obj;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def del_switch_info_ex(ea):
"""
Deletes stored switch information
"""
pass
#</pydoc>
*/
void py_del_switch_info_ex(ea_t ea)
{
del_switch_info_ex(ea);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static int py_enum_import_names(int mod_index, PyObject *py_cb)
{
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();
return PyCObject_FromVoidPtr(inst, NULL);
}
//---------------------------------------------------------------------------
static bool switch_info_ex_t_destroy(PyObject *py_obj)
{
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);
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;
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);
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;
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);
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;
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);
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;
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);
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;
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);
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;
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);
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;
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;
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);
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_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);
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_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);
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_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);
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_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);
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_GetNumber(value, &v);
link->values = (pyul_t)v;
}
//
// Auto generated - end
//
//-------------------------------------------------------------------------
//</inline(py_nalt)>
#endif

191
pywraps/py_nalt.py Normal file
View File

@ -0,0 +1,191 @@
#<pycode(py_nalt)>
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__)
#</pycode(py_nalt)>

23
pywraps/py_name.hpp Normal file
View File

@ -0,0 +1,23 @@
//------------------------------------------------------------------------
//<inline(py_name)>
//------------------------------------------------------------------------
PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
{
// Get debug names
ea_name_vec_t names;
get_debug_names(ea1, ea2, names);
PyObject *dict = Py_BuildValue("{}");
if (dict == NULL)
return 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(py_name)>
//------------------------------------------------------------------------

52
pywraps/py_name.py Normal file
View File

@ -0,0 +1,52 @@
import bisect
#<pycode(py_name)>
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)
#</pycode(py_name)>

307
pywraps/py_notifywhen.hpp Normal file
View File

@ -0,0 +1,307 @@
#ifndef __PYWRAPS_NOTIFY_WHEN__
#define __PYWRAPS_NOTIFY_WHEN__
//------------------------------------------------------------------------
//<code(py_idaapi)>
//------------------------------------------------------------------------
//------------------------------------------------------------------------
class pywraps_notify_when_t
{
ppyobject_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_t> 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:
{
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<NW_EVENTSCNT; slot++ )
{
// convert index to flag and see
if ( ((1 << slot) & when) != 0 )
{
unregister_callback(slot, py_callable);
++cnt;
}
}
return cnt > 0;
}
//------------------------------------------------------------------------
void register_callback(int slot, PyObject *py_callable)
{
ppyobject_vec_t &tbl = table[slot];
ppyobject_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, py_callable);
// Already added
if ( it != it_end )
return;
// Increment reference
Py_INCREF(py_callable);
// Insert the element
tbl.push_back(py_callable);
}
//------------------------------------------------------------------------
void unregister_callback(int slot, PyObject *py_callable)
{
ppyobject_vec_t &tbl = table[slot];
ppyobject_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, py_callable);
// Not found?
if ( it == it_end )
return;
// Decrement reference
Py_DECREF(py_callable);
// Delete the element
tbl.erase(it);
}
public:
//------------------------------------------------------------------------
bool init()
{
return hook_to_notification_point(HT_IDP, idp_callback, this);
}
//------------------------------------------------------------------------
bool deinit()
{
// Uninstall all objects
ppyobject_vec_t::iterator it, it_end;
for ( int slot=0; slot<NW_EVENTSCNT; slot++ )
{
for ( it = table[slot].begin(), it_end = table[slot].end(); it!=it_end; ++it )
unregister_callback(slot, *it);
}
// ...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<NW_EVENTSCNT; slot++ )
{
// is this flag set?
if ( ((1 << slot) & when) != 0 )
{
register_callback(slot, py_callable);
++cnt;
}
}
return cnt > 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)
{
// 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 (ppyobject_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end();
it != it_end;
++it)
{
// Form the notification code
PyObject *py_code = PyInt_FromLong(1 << slot);
PyObject *py_result(NULL);
switch ( slot )
{
case NW_CLOSEIDB_SLOT:
case NW_INITIDA_SLOT:
case NW_TERMIDA_SLOT:
{
PYW_GIL_ENSURE;
py_result = PyObject_CallFunctionObjArgs(*it, py_code, NULL);
PYW_GIL_RELEASE;
break;
}
case NW_OPENIDB_SLOT:
{
PyObject *py_old = PyInt_FromLong(old);
PYW_GIL_ENSURE;
py_result = PyObject_CallFunctionObjArgs(*it, py_code, py_old, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_old);
}
break;
}
Py_DECREF(py_code);
if ( PyW_GetError(&err) || py_result == NULL )
{
PyErr_Clear();
warning("notify_when(): Error occured while notifying object.\n%s", err.c_str());
ok = false;
}
Py_XDECREF(py_result);
}
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;
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;
}
//</code(py_idaapi)>
//------------------------------------------------------------------------
//<inline(py_idaapi)>
//------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static bool notify_when(int when, PyObject *py_callable)
{
if ( g_nw == NULL || !PyCallable_Check(py_callable) )
return false;
return g_nw->notify_when(when, py_callable);
}
//</inline(py_idaapi)>
//------------------------------------------------------------------------
#endif

63
pywraps/py_notifywhen.py Normal file
View File

@ -0,0 +1,63 @@
# -----------------------------------------------------------------------
# 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
# -----------------------------------------------------------------------
#<pycode(py_idaapi)>
# 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"""
#</pycode(py_idaapi)>
# -----------------------------------------------------------------------
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)

158
pywraps/py_plgform.hpp Normal file
View File

@ -0,0 +1,158 @@
#ifndef __PY_PLGFORM__
#define __PY_PLGFORM__
//<code(py_plgform)>
//---------------------------------------------------------------------------
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 )
{
// 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
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_obj,
(char *)S_ON_CREATE, "O",
PyCObject_FromVoidPtr(form, NULL));
PYW_GIL_RELEASE;
PyW_ShowCbErr(S_ON_CREATE);
Py_XDECREF(py_result);
}
}
else if ( notification_code == ui_tform_invisible )
{
TForm *form = va_arg(va, TForm *);
if ( form == _this->form )
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_obj,
(char *)S_ON_CLOSE, "O",
PyCObject_FromVoidPtr(form, NULL));
PYW_GIL_RELEASE;
PyW_ShowCbErr(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 *create()
{
return PyCObject_FromVoidPtr(new plgform_t(), destroy);
}
static void destroy(void *obj)
{
delete (plgform_t *)obj;
}
};
//</code(py_plgform)>
//<inline(py_plgform)>
//---------------------------------------------------------------------------
#define DECL_PLGFORM 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_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_plgform)>
#endif // __PY_PLGFORM__

108
pywraps/py_plgform.py Normal file
View File

@ -0,0 +1,108 @@
import _idaapi
#<pycode(py_plgform)>
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"""
FORM_CLOSE_LATER = 0x8
"""This flag should be used when Close() is called from an event handler"""
#</pycode(py_plgform)>
plg = PluginForm()
plg.Show("This is it")

327
pywraps/py_qfile.hpp Normal file
View File

@ -0,0 +1,327 @@
#ifndef __PY_IDA_QFILE__
#define __PY_IDA_QFILE__
//<inline(py_qfile)>
/*
#<pydoc>
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
#</pydoc>
*/
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("<FILE * %p>", fp);
this->fp = fp;
return true;
}
inline void _from_cobject(PyObject *pycobject)
{
_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;
if ( pycobject != NULL && PyCObject_Check(pycobject) )
_from_cobject(pycobject);
}
//--------------------------------------------------------------------------
bool opened()
{
return fp != NULL;
}
//--------------------------------------------------------------------------
void close()
{
if ( fp == NULL )
return;
if ( own )
qfclose(fp);
fp = NULL;
own = true;
}
//--------------------------------------------------------------------------
~qfile_t()
{
close();
}
//--------------------------------------------------------------------------
bool open(const char *filename, const char *mode)
{
close();
fp = qfopen(filename, mode);
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("<FILE * %p>", 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()
{
return from_fp(qtmpfile());
}
//--------------------------------------------------------------------------
FILE *get_fp()
{
return fp;
}
//--------------------------------------------------------------------------
int seek(int32 offset, int whence = SEEK_SET)
{
return qfseek(fp, offset, whence);
}
//--------------------------------------------------------------------------
int32 tell()
{
return qftell(fp);
}
//--------------------------------------------------------------------------
PyObject *readbytes(int size, bool big_endian)
{
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = freadbytes(fp, buf, size, big_endian);
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;
int r = qfread(fp, buf, size);
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;
if ( qfgets(buf, size, fp) == 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)
{
int sz = PyString_GET_SIZE(py_buf);
void *buf = (void *)PyString_AS_STRING(py_buf);
return fwritebytes(fp, buf, sz, big_endian);
}
//--------------------------------------------------------------------------
int write(PyObject *py_buf)
{
if ( !PyString_Check(py_buf) )
return 0;
return qfwrite(fp, (void *)PyString_AS_STRING(py_buf), PyString_GET_SIZE(py_buf));
}
//--------------------------------------------------------------------------
int puts(const char *str)
{
return qfputs(str, fp);
}
//--------------------------------------------------------------------------
int32 size()
{
int pos = qfseek(fp, 0, SEEK_END);
int32 r = qftell(fp);
qfseek(fp, pos, SEEK_SET);
return r;
}
//--------------------------------------------------------------------------
int flush()
{
return qflush(fp);
}
//--------------------------------------------------------------------------
PyObject *filename()
{
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qfgetc(fp);
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
}
//--------------------------------------------------------------------------
int put_char(char chr)
{
return qfputc(chr, fp);
}
};
//</inline(py_qfile)>
#endif

308
pywraps/py_typeinf.hpp Normal file
View File

@ -0,0 +1,308 @@
#ifndef __PY_TYPEINF__
#define __PY_TYPEINF__
//<inline(py_typeinf)>
//-------------------------------------------------------------------------
PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
{
qtype fields, type;
qstring name;
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
if ( !ok )
Py_RETURN_NONE;
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_type_size0(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
#</pydoc>
*/
PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
{
if ( !PyString_Check(tp) )
{
PyErr_SetString(PyExc_ValueError, "String expected!");
return NULL;
}
size_t sz = get_type_size0(ti, (type_t *)PyString_AsString(tp));
if ( sz == BADSIZE )
Py_RETURN_NONE;
return PyInt_FromLong(sz);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def print_type(ea, on_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
#</pydoc>
*/
static PyObject *py_print_type(ea_t ea, bool one_line)
{
char buf[MAXSTR];
if ( print_type(ea, buf, sizeof(buf), one_line) )
{
qstrncat(buf, ";", sizeof(buf));
return PyString_FromString(buf);
}
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_unpack_object_from_idb(
til_t *ti,
PyObject *py_type,
PyObject *py_fields,
ea_t ea,
int pio_flags = 0)
{
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// Unpack
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
idc_value_t idc_obj;
error_t err = unpack_object_from_idb(
&idc_obj,
ti,
type,
fields,
ea,
NULL,
pio_flags);
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
err = idcvar_to_pyvar(idc_obj, &py_ret);
// Conversion failed?
if ( err != CIP_OK )
return Py_BuildValue("(ii)", 0, err);
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
Py_DECREF(py_ret);
return py_result;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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: type fields
@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
#</pydoc>
*/
PyObject *py_unpack_object_from_bv(
til_t *ti,
PyObject *py_type,
PyObject *py_fields,
PyObject *py_bytes,
int pio_flags = 0)
{
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) && !PyString_Check(py_bytes) )
{
PyErr_SetString(PyExc_ValueError, "Incorrect argument type!");
return NULL;
}
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(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 = unpack_object_from_bv(
&idc_obj,
ti,
type,
fields,
bytes,
pio_flags);
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
err = idcvar_to_pyvar(idc_obj, &py_ret);
// Conversion failed?
if ( err != CIP_OK )
return Py_BuildValue("(ii)", 0, err);
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
Py_DECREF(py_ret);
return py_result;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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: type fields
@param ea: ea to be used while packing
@param pio_flags: flags used while unpacking
"""
pass
#</pydoc>
*/
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)
{
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
return NULL;
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
// Pack
error_t err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags);
return PyInt_FromLong(err);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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: type fields
@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
#</pydoc>
*/
// 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)
{
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
return NULL;
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
// Pack
relobj_t bytes;
error_t err = pack_object_to_bv(
&idc_obj,
ti,
type,
fields,
&bytes,
NULL,
pio_flags);
do
{
if ( err != eOk )
break;
if ( !bytes.relocate(base_ea, inf.mf) )
{
err = -1;
break;
}
return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size());
} while ( false );
return Py_BuildValue("(ii)", 0, err);
}
//</inline(py_typeinf)>
#endif

793
pywraps/py_ua.hpp Normal file
View File

@ -0,0 +1,793 @@
#ifndef __PY_UA__
#define __PY_UA__
//-------------------------------------------------------------------------
//<code(py_ua)>
//-------------------------------------------------------------------------
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);
}
//</code(py_ua)>
//-------------------------------------------------------------------------
//<inline(py_ua)>
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_init_output_buffer(size_t size = MAXSTR)
{
// 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;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def term_output_buffer():
"""Use this function to terminate an output buffer."""
pass
#</pydoc>
*/
void py_term_output_buffer()
{
term_output_buffer();
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_decode_preceding_insn(ea_t ea)
{
bool farref;
ea_t r = decode_preceding_insn(ea, &farref);
return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
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);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v)
{
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
#<pydoc>
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
#</pydoc>
*/
bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags)
{
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: frame.hpp
// Calculate offset of stack variable in the frame structure
// pfn - pointer to function (can't be NULL!)
// x - reference to instruction operand
// v - value of variable offset in the instruction
// returns: offset of stack variable in the frame structure (0..n)
ea_t calc_frame_offset(func_t *pfn, const op_t *x, sval_t v);
*/
//-------------------------------------------------------------------------
/*
header: typeinf.hpp
#<pydoc>
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
#</pydoc>
*/
bool py_apply_type_to_stkarg(
PyObject *py_op,
PyObject *py_uv,
PyObject *py_type,
const char *name)
{
uint64 v;
op_t *op = op_t_get_clink(py_op);
if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type))
return false;
else
return apply_type_to_stkarg(*op, uval_t(v), (type_t *) PyString_AsString(py_type), name);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def OutImmChar(op, outflags = 0):
"""
Output operand value as a commented character constant
@param op: operand (of type op_t)
@return: None
"""
pass
#</pydoc>
*/
static void py_OutImmChar(PyObject *x)
{
op_t *op = op_t_get_clink(x);
if ( op != NULL )
OutImmChar(*op);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
static bool py_ua_stkvar2(PyObject *x, adiff_t v, int flags)
{
op_t *op = op_t_get_clink(x);
return op == NULL ? false : ua_stkvar2(*op, v, flags);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
ea_t py_ua_add_off_drefs(PyObject *py_op, dref_t type)
{
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs(*op, type);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
ea_t py_ua_add_off_drefs2(PyObject *py_op, dref_t type, int outf)
{
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs2(*op, type, outf);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
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
#</pydoc>
*/
bool py_out_name_expr(
PyObject *py_op,
ea_t ea,
PyObject *py_off)
{
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);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i)
{
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()
{
return PyCObject_FromVoidPtr(new insn_t(), NULL);
}
//-------------------------------------------------------------------------
static PyObject *op_t_create()
{
return PyCObject_FromVoidPtr(new op_t(), NULL);
}
//-------------------------------------------------------------------------
static bool op_t_assign(PyObject *self, PyObject *other)
{
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)
{
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)
{
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)
{
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()
{
return PyCObject_FromVoidPtr(&::cmd, NULL);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_is_canon_insn(int itype)
{
if ( ph.is_canon_insn(itype) )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_feature(int itype)
{
return Py_BuildValue("I", ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_mnem(int itype)
{
if ( ph.is_canon_insn(itype) )
return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_cs(PyObject *self)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("I", link->value);
}
static void op_t_set_value(PyObject *self, PyObject *value)
{
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
link->value = PyInt_AsLong(value);
}
static PyObject *op_t_get_addr(PyObject *self)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
link->specflag4 = (char)PyInt_AsLong(value);
}
//</inline(py_ua)>
#endif

519
pywraps/py_ua.py Normal file
View File

@ -0,0 +1,519 @@
#<pycode(py_ua)>
# -----------------------------------------------------------------------
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)
#<pydoc>
# def copy(self):
# """Returns a new copy of this class"""
# pass
#</pydoc>
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 # IDP specific type
o_idpspec1 = 9 # IDP specific type
o_idpspec2 = 10 # IDP specific type
o_idpspec3 = 11 # IDP specific type
o_idpspec4 = 12 # IDP specific type
o_idpspec5 = 13 # IDP specific type
o_last = 14 # first unused type
#
# 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)
#
# 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 self.plnames[0] + ':' + ':'.join(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()
#</pycode(py_ua)>

2
pywraps/pywraps.hpp Normal file
View File

@ -0,0 +1,2 @@
// Just a proxy header
#include "../pywraps.hpp"

32
pywraps/pywraps.sln Normal file
View File

@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pywraps", "pywraps.vcxproj", "{F43D6BB8-B7D6-486A-82E5-BABBA9848525}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Rel64|Win32 = Rel64|Win32
Release|Win32 = Release|Win32
Release64|Win32 = Release64|Win32
SemiDebug|Win32 = SemiDebug|Win32
SemiDebugx64|Win32 = SemiDebugx64|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.ActiveCfg = Debug|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Debug|Win32.Build.0 = Debug|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Rel64|Win32.ActiveCfg = Rel64|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Rel64|Win32.Build.0 = Rel64|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.ActiveCfg = Release|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release|Win32.Build.0 = Release|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release64|Win32.ActiveCfg = Release64|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.Release64|Win32.Build.0 = Release64|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.ActiveCfg = SemiDebug|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebug|Win32.Build.0 = SemiDebug|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebugx64|Win32.ActiveCfg = SemiDebugx64|Win32
{F43D6BB8-B7D6-486A-82E5-BABBA9848525}.SemiDebugx64|Win32.Build.0 = SemiDebugx64|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

1844
pywraps/pywraps.vcproj Normal file

File diff suppressed because it is too large Load Diff

663
pywraps/pywraps.vcxproj Normal file
View File

@ -0,0 +1,663 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Rel64|Win32">
<Configuration>Rel64</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release64|Win32">
<Configuration>Release64</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="SemiDebugx64|Win32">
<Configuration>SemiDebugx64</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="SemiDebug|Win32">
<Configuration>SemiDebug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F43D6BB8-B7D6-486A-82E5-BABBA9848525}</ProjectGuid>
<RootNamespace>pywraps</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Debug/pywraps.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\include;c:\python26\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;__PYWRAPS__;_PYWRAPS_DEBUG;NO_OBSOLETE_FUNCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderOutputFile>.\Debug/pywraps.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4005;4800;4018;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/export:PLUGIN %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>ida.lib;python26_d.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>../../../bin/x86_win_vc/plugins/pywraps.plw</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>..\..\..\lib\x86_win_vc_32;c:\python26\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/pywraps.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Debug/pywraps.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Debug/pywraps.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/pywraps.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\include;c:\python26\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NO_OBSOLETE_FUNCS;NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/pywraps.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/export:PLUGIN %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>ida.lib;python26.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>../../../bin/x86_win_vc/plugins/pywraps.plw</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>..\..\..\lib\x86_win_vc_32;c:\python26\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Release/pywraps.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Release/pywraps.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/pywraps.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/pywraps.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\include;c:\Python26\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;_PYWRAPS_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/pywraps.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4005;4800;4018;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/export:PLUGIN %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>ida.lib;python26.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>../../../bin/x86_win_vc/plugins/pywraps.plw</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>..\..\..\lib\x86_win_vc_32;c:\python26\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Release/pywraps.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Release/pywraps.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/pywraps.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/pywraps.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\include;c:\python26\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;_PYWRAPS_DEBUG;__EA64__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/pywraps.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4005;4800;4018;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/export:PLUGIN %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>ida.lib;python26.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>../../../bin/x86_win_vc/plugins/pywraps.p64</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>..\..\..\lib\vc.w64;c:\python26\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Release/pywraps.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TurnOffAssemblyGeneration>true</TurnOffAssemblyGeneration>
<ImportLibrary>.\Release/pywraps.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/pywraps.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/pywraps.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\include;c:\python26\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;__EA64__;_PYWRAPS_DEBUG;__PYWRAPS__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/pywraps.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/export:PLUGIN %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>ida.lib;python26.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>../../../bin/x86_win_vc/plugins/pywraps.p64</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>..\..\..\lib\vc.w64;c:\python26\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Release/pywraps.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Release/pywraps.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/pywraps.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/pywraps.tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\include;c:\python26\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;_USRDLL;__NT__;__IDP__;MAXSTR=1024;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/pywraps.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/export:PLUGIN %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>ida.lib;python26.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>../../../bin/x86_win_vc/plugins/pywraps.plw</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>..\..\..\lib\x86_win_vc_32;c:\python26\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Release/pywraps.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Release/pywraps.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release/pywraps.bsc</OutputFile>
</Bscmake>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="..\examples\ex_askusingform.py" />
<None Include="..\examples\ex_idphook_asm.py" />
<None Include="..\examples\ex_prefix_plugin.py" />
<None Include="..\examples\ex_pyqt.py" />
<None Include="..\examples\ex_pyside.py" />
<None Include="..\examples\ex_uihook.py" />
<None Include="..\swig\dbg.i" />
<None Include="..\swig\idd.i" />
<None Include="py_appcall.py" />
<None Include="..\swig\graph.i" />
<None Include="py_expr.py" />
<None Include="py_graph.py" />
<None Include="..\swig\diskio.i" />
<None Include="..\swig\fpro.i" />
<None Include="py_diskio.py" />
<None Include="..\swig\bytes.i" />
<None Include="py_custdata.py" />
<None Include="..\AUTHORS.txt" />
<None Include="..\build.py" />
<None Include="..\CHANGES.txt" />
<None Include="..\COPYING.txt" />
<None Include="deploy.bat" />
<None Include="deploy.py" />
<None Include="..\makefile" />
<None Include="..\README.txt" />
<None Include="..\STATUS.txt" />
<None Include="td.bat" />
<None Include="..\examples\chooser.py" />
<None Include="..\examples\colours.py" />
<None Include="..\examples\debughook.py" />
<None Include="..\examples\ex1_idaapi.py" />
<None Include="..\examples\ex1_idautils.py" />
<None Include="..\examples\ex_add_menu_item.py" />
<None Include="..\examples\ex_choose2.py" />
<None Include="..\examples\ex_cli.py" />
<None Include="..\examples\ex_custdata.py" />
<None Include="..\examples\ex_custview.py" />
<None Include="..\examples\ex_dbg.py" />
<None Include="..\examples\ex_debug_names.py" />
<None Include="..\examples\ex_func_chooser.py" />
<None Include="..\examples\ex_gdl_qflow_chart.py" />
<None Include="..\examples\ex_graph.py" />
<None Include="..\examples\ex_imports.py" />
<None Include="..\examples\ex_strings.py" />
<None Include="..\examples\hotkey.py" />
<None Include="..\examples\idapythonrc.py" />
<None Include="..\examples\structure.py" />
<None Include="..\swig\idaapi.i" />
<None Include="py_idaapi.py" />
<None Include="..\swig\typeinf.i" />
<None Include="..\swig\allins.i" />
<None Include="..\swig\area.i" />
<None Include="..\swig\auto.i" />
<None Include="..\swig\entry.i" />
<None Include="..\swig\enum.i" />
<None Include="..\swig\expr.i" />
<None Include="..\swig\fixup.i" />
<None Include="..\swig\frame.i" />
<None Include="..\swig\funcs.i" />
<None Include="..\swig\ida.i" />
<None Include="..\swig\ints.i" />
<None Include="..\swig\moves.i" />
<None Include="..\swig\name.i" />
<None Include="..\swig\netnode.i" />
<None Include="..\swig\offset.i" />
<None Include="..\swig\pro.i" />
<None Include="..\swig\queue.i" />
<None Include="..\swig\search.i" />
<None Include="..\swig\segment.i" />
<None Include="..\swig\srarea.i" />
<None Include="..\swig\strlist.i" />
<None Include="..\swig\struct.i" />
<None Include="..\swig\typeconv.i" />
<None Include="..\swig\xref.i" />
<None Include="..\swig\gdl.i" />
<None Include="py_gdl.py" />
<None Include="py_ua.py" />
<None Include="..\swig\ua.i" />
<None Include="..\python\idautils.py" />
<None Include="..\python\idc.py" />
<None Include="..\python\init.py" />
<None Include="..\python.cfg" />
<None Include="py_notifywhen.py" />
<None Include="..\swig\lines.i" />
<None Include="py_lines.py" />
<None Include="..\swig\nalt.i" />
<None Include="py_nalt.py" />
<None Include="..\swig\loader.i" />
<None Include="..\swig\idp.i" />
<None Include="..\swig\kernwin.i" />
<None Include="py_kernwin.py" />
<None Include="py_custview.py" />
<None Include="py_choose2.py" />
<None Include="py_cli.py" />
<None Include="py_plgform.py" />
<None Include="py_askusingform.py" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="driver_dbg.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_expr.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_graph.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver.cpp" />
<ClCompile Include="driver_diskio.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_bytes.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_custdata.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\obj\x86_win_vc_32\idaapi_include.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\python.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_notifywhen.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_nalt.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_kernwin.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_custview.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_chooser.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="driver_cli.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="swig_stub.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="py_dbg.hpp" />
<ClInclude Include="py_expr.hpp" />
<ClInclude Include="py_graph.hpp" />
<ClInclude Include="..\pywraps.hpp" />
<ClInclude Include="py_diskio.hpp" />
<ClInclude Include="py_linput.hpp" />
<ClInclude Include="py_qfile.hpp" />
<ClInclude Include="py_bytes.hpp" />
<ClInclude Include="py_custdata.hpp" />
<ClInclude Include="py_idaapi.hpp" />
<ClInclude Include="py_typeinf.hpp" />
<ClInclude Include="py_ua.hpp" />
<CustomBuildStep Include="..\obj\x86_win_vc_32\idaapi_include.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Rel64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebugx64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SemiDebug|Win32'">true</ExcludedFromBuild>
</CustomBuildStep>
<ClInclude Include="py_notifywhen.hpp" />
<ClInclude Include="py_lines.hpp" />
<ClInclude Include="py_nalt.hpp" />
<ClInclude Include="py_loader.hpp" />
<ClInclude Include="py_idp.hpp" />
<ClInclude Include="py_cvt.hpp" />
<ClInclude Include="py_kernwin.hpp" />
<ClInclude Include="py_custview.hpp" />
<ClInclude Include="py_choose2.hpp" />
<ClInclude Include="py_cli.hpp" />
<ClInclude Include="py_plgform.hpp" />
<ClInclude Include="py_askusingform.hpp" />
<ClInclude Include="py_choose.hpp" />
<ClInclude Include="swig_stub.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,518 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="py_dbgidd">
<UniqueIdentifier>{9fd646ab-4c34-4457-a88f-0b9efa521a7c}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="py_graph">
<UniqueIdentifier>{c7c2445a-144b-4574-a5a7-4547bf731f79}</UniqueIdentifier>
</Filter>
<Filter Include="pywraps">
<UniqueIdentifier>{a817be2b-11e4-441c-9e1e-ff3825b03d03}</UniqueIdentifier>
</Filter>
<Filter Include="py_diskio">
<UniqueIdentifier>{bfbff292-8186-40a9-a90f-09a530e2e5d2}</UniqueIdentifier>
</Filter>
<Filter Include="py_bytes">
<UniqueIdentifier>{2ebfadc0-402b-4ef7-b2bf-ab9fb8c5279b}</UniqueIdentifier>
</Filter>
<Filter Include="deploy">
<UniqueIdentifier>{0ad19987-f808-44a4-865b-985e7f8dca02}</UniqueIdentifier>
</Filter>
<Filter Include="deploy\examples">
<UniqueIdentifier>{1016cbe2-fa4e-49b5-9e8f-b8fc4a0656d3}</UniqueIdentifier>
</Filter>
<Filter Include="py_idaapi">
<UniqueIdentifier>{e57b232e-0cdb-4cc6-ad63-80ecfeaa25b9}</UniqueIdentifier>
</Filter>
<Filter Include="py_typeinf">
<UniqueIdentifier>{cfda7913-ffad-425d-b9ce-295bb647d8e5}</UniqueIdentifier>
</Filter>
<Filter Include="swig.i">
<UniqueIdentifier>{ec48a898-4c2f-443d-9236-c8b58c036050}</UniqueIdentifier>
</Filter>
<Filter Include="py_gdl">
<UniqueIdentifier>{12e97676-9f57-4e1f-af42-6bf0cd178ae6}</UniqueIdentifier>
</Filter>
<Filter Include="py_ua">
<UniqueIdentifier>{62308260-bfab-49eb-9b11-7522f7b671d8}</UniqueIdentifier>
</Filter>
<Filter Include="IDAPython">
<UniqueIdentifier>{f33949eb-15bb-4926-94e3-1648a4c3bca0}</UniqueIdentifier>
</Filter>
<Filter Include="py_notifywhen">
<UniqueIdentifier>{79a2a07e-7db7-43ac-8c41-fe08777e802c}</UniqueIdentifier>
</Filter>
<Filter Include="py_lines">
<UniqueIdentifier>{714c10e9-2a6f-4b86-a594-b53b28f9fc7e}</UniqueIdentifier>
</Filter>
<Filter Include="py_nalt">
<UniqueIdentifier>{22f57328-eb90-4341-bb06-464f6c7b2bd6}</UniqueIdentifier>
</Filter>
<Filter Include="py_loader">
<UniqueIdentifier>{ef594bc3-6670-4e55-a77f-e3bff3193d94}</UniqueIdentifier>
</Filter>
<Filter Include="py_idp">
<UniqueIdentifier>{7092618c-44fe-497b-a229-360bab592f3d}</UniqueIdentifier>
</Filter>
<Filter Include="py_utils">
<UniqueIdentifier>{c5616ba8-8b0d-41a0-bf78-583fdcfb3898}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin">
<UniqueIdentifier>{0cefa3d8-f4b6-4085-b2a2-6b2d97167252}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin\py_custview">
<UniqueIdentifier>{b21f3b63-396e-4725-83cc-2df9f5b6bb46}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin\py_choose2">
<UniqueIdentifier>{c4a9b8be-70fa-4287-bc47-73db56202dd6}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin\py_cli">
<UniqueIdentifier>{a103675f-abc2-4f84-a0b8-9ac7403f04db}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin\py_plgform">
<UniqueIdentifier>{ac94c213-e485-48ac-b554-3868e350d671}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin\py_askusingform">
<UniqueIdentifier>{833c766e-6e8d-4c00-947f-71a7b34378a6}</UniqueIdentifier>
</Filter>
<Filter Include="py_kernwin\py_choose">
<UniqueIdentifier>{8dc47ef4-3da0-4bf8-9ce2-5a9f8896b1b3}</UniqueIdentifier>
</Filter>
<Filter Include="swig_stub">
<UniqueIdentifier>{8e65a873-5b8f-4052-a929-e13e9e0f81ac}</UniqueIdentifier>
</Filter>
<Filter Include="IDAPython\Examples">
<UniqueIdentifier>{b7a7d68d-a3b0-487c-b4d0-bd716dd06280}</UniqueIdentifier>
</Filter>
<Filter Include="py_expr">
<UniqueIdentifier>{959b59d2-acb2-4c89-a828-eece77e502f4}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="..\swig\dbg.i">
<Filter>py_dbgidd</Filter>
</None>
<None Include="..\swig\idd.i">
<Filter>py_dbgidd</Filter>
</None>
<None Include="py_appcall.py">
<Filter>py_dbgidd</Filter>
</None>
<None Include="..\swig\graph.i">
<Filter>py_graph</Filter>
</None>
<None Include="py_graph.py">
<Filter>py_graph</Filter>
</None>
<None Include="..\swig\diskio.i">
<Filter>py_diskio</Filter>
</None>
<None Include="..\swig\fpro.i">
<Filter>py_diskio</Filter>
</None>
<None Include="py_diskio.py">
<Filter>py_diskio</Filter>
</None>
<None Include="..\swig\bytes.i">
<Filter>py_bytes</Filter>
</None>
<None Include="py_custdata.py">
<Filter>py_bytes</Filter>
</None>
<None Include="..\AUTHORS.txt">
<Filter>deploy</Filter>
</None>
<None Include="..\build.py">
<Filter>deploy</Filter>
</None>
<None Include="..\CHANGES.txt">
<Filter>deploy</Filter>
</None>
<None Include="..\COPYING.txt">
<Filter>deploy</Filter>
</None>
<None Include="deploy.bat">
<Filter>deploy</Filter>
</None>
<None Include="deploy.py">
<Filter>deploy</Filter>
</None>
<None Include="..\makefile">
<Filter>deploy</Filter>
</None>
<None Include="..\README.txt">
<Filter>deploy</Filter>
</None>
<None Include="..\STATUS.txt">
<Filter>deploy</Filter>
</None>
<None Include="td.bat">
<Filter>deploy</Filter>
</None>
<None Include="..\examples\chooser.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\colours.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\debughook.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex1_idaapi.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex1_idautils.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_add_menu_item.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_choose2.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_cli.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_custdata.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_custview.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_dbg.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_debug_names.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_func_chooser.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_gdl_qflow_chart.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_graph.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_imports.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\ex_strings.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\hotkey.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\idapythonrc.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\examples\structure.py">
<Filter>deploy\examples</Filter>
</None>
<None Include="..\swig\idaapi.i">
<Filter>py_idaapi</Filter>
</None>
<None Include="py_idaapi.py">
<Filter>py_idaapi</Filter>
</None>
<None Include="..\swig\typeinf.i">
<Filter>py_typeinf</Filter>
</None>
<None Include="..\swig\allins.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\area.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\auto.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\entry.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\enum.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\expr.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\fixup.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\frame.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\funcs.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\ida.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\ints.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\moves.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\name.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\netnode.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\offset.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\pro.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\queue.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\search.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\segment.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\srarea.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\strlist.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\struct.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\typeconv.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\xref.i">
<Filter>swig.i</Filter>
</None>
<None Include="..\swig\gdl.i">
<Filter>py_gdl</Filter>
</None>
<None Include="py_gdl.py">
<Filter>py_gdl</Filter>
</None>
<None Include="py_ua.py">
<Filter>py_ua</Filter>
</None>
<None Include="..\swig\ua.i">
<Filter>py_ua</Filter>
</None>
<None Include="..\python\idautils.py">
<Filter>IDAPython</Filter>
</None>
<None Include="..\python\idc.py">
<Filter>IDAPython</Filter>
</None>
<None Include="..\python\init.py">
<Filter>IDAPython</Filter>
</None>
<None Include="..\python.cfg">
<Filter>IDAPython</Filter>
</None>
<None Include="py_notifywhen.py">
<Filter>py_notifywhen</Filter>
</None>
<None Include="..\swig\lines.i">
<Filter>py_lines</Filter>
</None>
<None Include="py_lines.py">
<Filter>py_lines</Filter>
</None>
<None Include="..\swig\nalt.i">
<Filter>py_nalt</Filter>
</None>
<None Include="py_nalt.py">
<Filter>py_nalt</Filter>
</None>
<None Include="..\swig\loader.i">
<Filter>py_loader</Filter>
</None>
<None Include="..\swig\idp.i">
<Filter>py_idp</Filter>
</None>
<None Include="..\swig\kernwin.i">
<Filter>py_kernwin</Filter>
</None>
<None Include="py_kernwin.py">
<Filter>py_kernwin</Filter>
</None>
<None Include="py_custview.py">
<Filter>py_kernwin\py_custview</Filter>
</None>
<None Include="py_choose2.py">
<Filter>py_kernwin\py_choose2</Filter>
</None>
<None Include="py_cli.py">
<Filter>py_kernwin\py_cli</Filter>
</None>
<None Include="py_plgform.py">
<Filter>py_kernwin\py_plgform</Filter>
</None>
<None Include="py_askusingform.py">
<Filter>py_kernwin\py_askusingform</Filter>
</None>
<None Include="..\examples\ex_askusingform.py">
<Filter>py_kernwin\py_askusingform</Filter>
</None>
<None Include="..\examples\ex_uihook.py">
<Filter>py_kernwin</Filter>
</None>
<None Include="..\examples\ex_pyside.py">
<Filter>py_kernwin\py_plgform</Filter>
</None>
<None Include="..\examples\ex_pyqt.py">
<Filter>py_kernwin\py_plgform</Filter>
</None>
<None Include="..\examples\ex_idphook_asm.py">
<Filter>py_idp</Filter>
</None>
<None Include="..\examples\ex_prefix_plugin.py">
<Filter>py_kernwin</Filter>
</None>
<None Include="py_expr.py">
<Filter>py_expr</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClCompile Include="driver_dbg.cpp">
<Filter>py_dbgidd</Filter>
</ClCompile>
<ClCompile Include="driver_graph.cpp">
<Filter>py_graph</Filter>
</ClCompile>
<ClCompile Include="driver.cpp">
<Filter>pywraps</Filter>
</ClCompile>
<ClCompile Include="driver_diskio.cpp">
<Filter>py_diskio</Filter>
</ClCompile>
<ClCompile Include="driver_bytes.cpp">
<Filter>py_bytes</Filter>
</ClCompile>
<ClCompile Include="driver_custdata.cpp">
<Filter>py_bytes</Filter>
</ClCompile>
<ClCompile Include="..\obj\x86_win_vc_32\idaapi_include.cpp">
<Filter>IDAPython</Filter>
</ClCompile>
<ClCompile Include="..\python.cpp">
<Filter>IDAPython</Filter>
</ClCompile>
<ClCompile Include="driver_notifywhen.cpp">
<Filter>py_notifywhen</Filter>
</ClCompile>
<ClCompile Include="driver_nalt.cpp">
<Filter>py_nalt</Filter>
</ClCompile>
<ClCompile Include="driver_kernwin.cpp">
<Filter>py_kernwin</Filter>
</ClCompile>
<ClCompile Include="driver_custview.cpp">
<Filter>py_kernwin\py_custview</Filter>
</ClCompile>
<ClCompile Include="driver_chooser.cpp">
<Filter>py_kernwin\py_choose2</Filter>
</ClCompile>
<ClCompile Include="driver_cli.cpp">
<Filter>py_kernwin\py_cli</Filter>
</ClCompile>
<ClCompile Include="swig_stub.cpp">
<Filter>swig_stub</Filter>
</ClCompile>
<ClCompile Include="driver_expr.cpp">
<Filter>py_expr</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="py_dbg.hpp">
<Filter>py_dbgidd</Filter>
</ClInclude>
<ClInclude Include="py_graph.hpp">
<Filter>py_graph</Filter>
</ClInclude>
<ClInclude Include="..\pywraps.hpp">
<Filter>pywraps</Filter>
</ClInclude>
<ClInclude Include="py_diskio.hpp">
<Filter>py_diskio</Filter>
</ClInclude>
<ClInclude Include="py_linput.hpp">
<Filter>py_diskio</Filter>
</ClInclude>
<ClInclude Include="py_qfile.hpp">
<Filter>py_diskio</Filter>
</ClInclude>
<ClInclude Include="py_bytes.hpp">
<Filter>py_bytes</Filter>
</ClInclude>
<ClInclude Include="py_custdata.hpp">
<Filter>py_bytes</Filter>
</ClInclude>
<ClInclude Include="py_idaapi.hpp">
<Filter>py_idaapi</Filter>
</ClInclude>
<ClInclude Include="py_typeinf.hpp">
<Filter>py_typeinf</Filter>
</ClInclude>
<ClInclude Include="py_ua.hpp">
<Filter>py_ua</Filter>
</ClInclude>
<ClInclude Include="py_notifywhen.hpp">
<Filter>py_notifywhen</Filter>
</ClInclude>
<ClInclude Include="py_lines.hpp">
<Filter>py_lines</Filter>
</ClInclude>
<ClInclude Include="py_nalt.hpp">
<Filter>py_nalt</Filter>
</ClInclude>
<ClInclude Include="py_loader.hpp">
<Filter>py_loader</Filter>
</ClInclude>
<ClInclude Include="py_idp.hpp">
<Filter>py_idp</Filter>
</ClInclude>
<ClInclude Include="py_cvt.hpp">
<Filter>py_utils</Filter>
</ClInclude>
<ClInclude Include="py_kernwin.hpp">
<Filter>py_kernwin</Filter>
</ClInclude>
<ClInclude Include="py_custview.hpp">
<Filter>py_kernwin\py_custview</Filter>
</ClInclude>
<ClInclude Include="py_choose2.hpp">
<Filter>py_kernwin\py_choose2</Filter>
</ClInclude>
<ClInclude Include="py_cli.hpp">
<Filter>py_kernwin\py_cli</Filter>
</ClInclude>
<ClInclude Include="py_plgform.hpp">
<Filter>py_kernwin\py_plgform</Filter>
</ClInclude>
<ClInclude Include="py_askusingform.hpp">
<Filter>py_kernwin\py_askusingform</Filter>
</ClInclude>
<ClInclude Include="py_choose.hpp">
<Filter>py_kernwin\py_choose</Filter>
</ClInclude>
<ClInclude Include="swig_stub.h">
<Filter>swig_stub</Filter>
</ClInclude>
<ClInclude Include="py_expr.hpp">
<Filter>py_expr</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuildStep Include="..\obj\x86_win_vc_32\idaapi_include.h">
<Filter>IDAPython</Filter>
</CustomBuildStep>
</ItemGroup>
</Project>

116
pywraps/readme.txt Normal file
View File

@ -0,0 +1,116 @@
============================
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:
//<inline(NAME)>
C++ code
//</inline(NAME)>
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:
//<code(NAME)>
C++ code
//</code(NAME)>
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:
#<pycode(NAME)>
Py code
#</pycode(NAME)>
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:
#<pydoc>
# def OnClose(self):
# """
# Called when the window is being closed.
# This callback is mandatory.
# @return: nothing
# """
# pass
#</pydoc>
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:
/*
#<pydoc>
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
#</pydoc>
*/
static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
......
}
In this case, the code inside <pydoc> 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).

225
pywraps/sidaapi.py Normal file
View File

@ -0,0 +1,225 @@
import sys
import sidc
BUF = None
# ----------------------------------------------------------------------
def ua_next_byte():
p = cmd.ea
if p >= len(BUF):
return None
ch = ord(BUF[p])
ua_seek(p+1)
cmd.size += 1
return ch
def ua_next_word():
b1 = ua_next_byte()
b2 = ua_next_byte()
return (b2 << 8) | b1
def ua_next_long():
w1 = ua_next_word()
w2 = ua_next_word()
return (w2 << 16) | w1
def ua_next_qword():
d1 = ua_next_long()
d2 = ua_next_long()
return (d2 << 32) | d1
# ----------------------------------------------------------------------
def ua_set_data(data):
global BUF
BUF = data
ua_seek(0)
# ----------------------------------------------------------------------
def ua_seek(v):
cmd.ea = v
# ----------------------------------------------------------------------
def ua_get_seek():
return cmd.ea
# ----------------------------------------------------------------------
def init_file(fn):
global BUF, PTR
try:
f = open(fn, "rb")
BUF = f.read()
ua_seek(0)
f.close()
except Exception, e:
print "init_file()", e
return False
return True
# ----------------------------------------------------------------------
class cvar_t:
def __init__(self):
self.uFlag = 0
self.gl_comm = 1
# ----------------------------------------------------------------------
cvar = cvar_t()
cmd = sidc.insn_t()
# ----------------------------------------------------------------------
class processor_t(object):
def __init__(self):
# This is an opaque object
self.__idc_cvt_id__ = 2
# 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
"""
return idpdef['plnames'][0] + ':' + ':'.join(idpdef['psnames'])
def get_uFlag(self):
"""Use this utility function to retrieve the 'uFlag' global variable"""
return _idaapi.cvar.uFlag
def get_auxpref(self):
return self.cmd.auxpref
# ----------------------------------------------------------------------
BADADDR = 0xFFFFFFFFFFFFFFFFL
# ----------------------------------------------------------------------
"""
# Colors dump
attrs = [x for x in dir(idaapi) if x.startswith('SCOLOR')]
for x in attrs:
print "%s =%r;" % (x, getattr(idaapi, x))
attrs = [x for x in dir(idaapi) if x.startswith('COLOR')]
for x in attrs:
v = getattr(idaapi, x);
if isinstance(v, str):
v = ord(x[0])
print "%s =%r;" % (x, v)
"""
SCOLOR_ADDR ='(';
SCOLOR_ALTOP ='\x16';
SCOLOR_ASMDIR ='\x1b';
SCOLOR_AUTOCMT ='\x04';
SCOLOR_BINPREF ='\x14';
SCOLOR_CHAR ='\n';
SCOLOR_CNAME ='%';
SCOLOR_CODNAME ='\x1a';
SCOLOR_COLLAPSED ="'";
SCOLOR_CREF ='\x0e';
SCOLOR_CREFTAIL ='\x10';
SCOLOR_DATNAME ='\x06';
SCOLOR_DCHAR ='\x1e';
SCOLOR_DEFAULT ='\x01';
SCOLOR_DEMNAME ='\x08';
SCOLOR_DNAME ='\x07';
SCOLOR_DNUM ='\x1f';
SCOLOR_DREF ='\x0f';
SCOLOR_DREFTAIL ='\x11';
SCOLOR_DSTR ='\x1d';
SCOLOR_ERROR ='\x12';
SCOLOR_ESC ='\x03';
SCOLOR_EXTRA ='\x15';
SCOLOR_FG_MAX ='(';
SCOLOR_HIDNAME ='\x17';
SCOLOR_IMPNAME ='"';
SCOLOR_INSN ='\x05';
SCOLOR_INV ='\x04';
SCOLOR_KEYWORD =' ';
SCOLOR_LIBNAME ='\x18';
SCOLOR_LOCNAME ='\x19';
SCOLOR_MACRO ='\x1c';
SCOLOR_NUMBER ='\x0c';
SCOLOR_OFF ='\x02';
SCOLOR_ON ='\x01';
SCOLOR_OPND1 =')';
SCOLOR_OPND2 ='*';
SCOLOR_OPND3 ='+';
SCOLOR_OPND4 =',';
SCOLOR_OPND5 ='-';
SCOLOR_OPND6 ='.';
SCOLOR_PREFIX ='\x13';
SCOLOR_REG ='!';
SCOLOR_REGCMT ='\x02';
SCOLOR_RPTCMT ='\x03';
SCOLOR_SEGNAME ='#';
SCOLOR_STRING ='\x0b';
SCOLOR_SYMBOL ='\t';
SCOLOR_UNAME ='&';
SCOLOR_UNKNAME ='$';
SCOLOR_UTF8 ='2';
SCOLOR_VOIDOP ='\r';
COLOR_ADDR =40;
COLOR_ADDR_SIZE =8;
COLOR_ALTOP =22;
COLOR_ASMDIR =27;
COLOR_AUTOCMT =4;
COLOR_BG_MAX =12;
COLOR_BINPREF =20;
COLOR_CHAR =10;
COLOR_CNAME =37;
COLOR_CODE =5;
COLOR_CODNAME =26;
COLOR_COLLAPSED =39;
COLOR_CREF =14;
COLOR_CREFTAIL =16;
COLOR_CURITEM =9;
COLOR_CURLINE =10;
COLOR_DATA =6;
COLOR_DATNAME =6;
COLOR_DCHAR =30;
COLOR_DEFAULT =1;
COLOR_DEMNAME =8;
COLOR_DNAME =7;
COLOR_DNUM =31;
COLOR_DREF =15;
COLOR_DREFTAIL =17;
COLOR_DSTR =29;
COLOR_ERROR =18;
COLOR_ESC =3;
COLOR_EXTERN =8;
COLOR_EXTRA =21;
COLOR_FG_MAX =40;
COLOR_HIDLINE =11;
COLOR_HIDNAME =23;
COLOR_IMPNAME =34;
COLOR_INSN =5;
COLOR_INV =4;
COLOR_KEYWORD =32;
COLOR_LIBFUNC =3;
COLOR_LIBNAME =24;
COLOR_LOCNAME =25;
COLOR_MACRO =28;
COLOR_NUMBER =12;
COLOR_OFF = 2;
COLOR_ON = 1;
COLOR_OPND1 =41;
COLOR_OPND2 =42;
COLOR_OPND3 =43;
COLOR_OPND4 =44;
COLOR_OPND5 =45;
COLOR_OPND6 =46;
COLOR_PREFIX =19;
COLOR_REG =33;
COLOR_REGCMT =2;
COLOR_REGFUNC =4;
COLOR_RPTCMT =3;
COLOR_SEGNAME =35;
COLOR_SELECTED =2;
COLOR_STRING =11;
COLOR_SYMBOL =9;
COLOR_UNAME =38;
COLOR_UNKNAME =36;
COLOR_UNKNOWN =7;
COLOR_UTF8 =50;
COLOR_VOIDOP =13;

311
pywraps/sidc.py Normal file
View File

@ -0,0 +1,311 @@
# ----------------------------------------------------------------------
#
# Misc constants
#
UA_MAXOP = 6
# ----------------------------------------------------------------------
# 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 # IDP specific type
o_idpspec1 = 9 # IDP specific type
o_idpspec2 = 10 # IDP specific type
o_idpspec3 = 11 # IDP specific type
o_idpspec4 = 12 # IDP specific type
o_idpspec5 = 13 # IDP specific type
o_last = 14 # first unused type
#
# 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)
#
# 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
# ----------------------------------------------------------------------
# asm_t related constants
#
# asm_t.flag
#
AS_OFFST = 0x00000001 # offsets are 'offset xxx' ?
AS_COLON = 0x00000002 # create colons after data names ?
AS_UDATA = 0x00000004 # can use '?' in data directives
AS_2CHRE = 0x00000008 # double char constants are: "xy
AS_NCHRE = 0x00000010 # char constants are: 'x
AS_N2CHR = 0x00000020 # can't have 2 byte char consts
# ASCII directives:
AS_1TEXT = 0x00000040 # 1 text per line, no bytes
AS_NHIAS = 0x00000080 # no characters with high bit
AS_NCMAS = 0x00000100 # no commas in ascii directives
AS_HEXFM = 0x00000E00 # format of hex numbers:
ASH_HEXF0 = 0x00000000 # 34h
ASH_HEXF1 = 0x00000200 # h'34
ASH_HEXF2 = 0x00000400 # 34
ASH_HEXF3 = 0x00000600 # 0x34
ASH_HEXF4 = 0x00000800 # $34
ASH_HEXF5 = 0x00000A00 # <^R > (radix)
AS_DECFM = 0x00003000 # format of dec numbers:
ASD_DECF0 = 0x00000000 # 34
ASD_DECF1 = 0x00001000 # #34
ASD_DECF2 = 0x00002000 # 34.
ASD_DECF3 = 0x00003000 # .34
AS_OCTFM = 0x0001C000 # format of octal numbers:
ASO_OCTF0 = 0x00000000 # 123o
ASO_OCTF1 = 0x00004000 # 0123
ASO_OCTF2 = 0x00008000 # 123
ASO_OCTF3 = 0x0000C000 # @123
ASO_OCTF4 = 0x00010000 # o'123
ASO_OCTF5 = 0x00014000 # 123q
ASO_OCTF6 = 0x00018000 # ~123
AS_BINFM = 0x000E0000 # format of binary numbers:
ASB_BINF0 = 0x00000000 # 010101b
ASB_BINF1 = 0x00020000 # ^B010101
ASB_BINF2 = 0x00040000 # %010101
ASB_BINF3 = 0x00060000 # 0b1010101
ASB_BINF4 = 0x00080000 # b'1010101
ASB_BINF5 = 0x000A0000 # b'1010101'
AS_UNEQU = 0x00100000 # replace undefined data items
# with EQU (for ANTA's A80)
AS_ONEDUP = 0x00200000 # One array definition per line
AS_NOXRF = 0x00400000 # Disable xrefs during the output file generation
AS_XTRNTYPE = 0x00800000 # Assembler understands type of extrn
# symbols as ":type" suffix
AS_RELSUP = 0x01000000 # Checkarg: 'and','or','xor' operations
# with addresses are possible
AS_LALIGN = 0x02000000 # Labels at "align" keyword
# are supported.
AS_NOCODECLN = 0x04000000 # don't create colons after code names
AS_NOTAB = 0x08000000 # Disable tabulation symbols during the output file generation
AS_NOSPACE = 0x10000000 # No spaces in expressions
AS_ALIGN2 = 0x20000000 # .align directive expects an exponent rather than a power of 2
# (.align 5 means to align at 32byte boundary)
AS_ASCIIC = 0x40000000 # ascii directive accepts C-like
# escape sequences (\n,\x01 and similar)
AS_ASCIIZ = 0x80000000 # ascii directive inserts implicit
# zero byte at the end
# ----------------------------------------------------------------------
# processor_t related constants
IDP_INTERFACE_VERSION = 76
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.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
# ----------------------------------------------------------------------
OOF_SIGNMASK = 0x0003 # sign symbol (+/-) output:
OOFS_IFSIGN = 0x0000 # output sign if needed
OOFS_NOSIGN = 0x0001 # don't output sign, forbid the user to change the sign
OOFS_NEEDSIGN = 0x0002 # always out sign (+-)
OOF_SIGNED = 0x0004 # output as signed if < 0
OOF_NUMBER = 0x0008 # always as a number
OOF_WIDTHMASK = 0x0070 # width of value in bits:
OOFW_IMM = 0x0000 # take from x.dtyp
OOFW_8 = 0x0010 # 8 bit width
OOFW_16 = 0x0020 # 16 bit width
OOFW_24 = 0x0030 # 24 bit width
OOFW_32 = 0x0040 # 32 bit width
OOFW_64 = 0x0050 # 32 bit width
OOF_ADDR = 0x0080 # output x.addr, otherwise x.value
OOF_OUTER = 0x0100 # output outer operand
OOF_ZSTROFF = 0x0200 # meaningful only if isStroff(uFlag)
# append a struct field name if
# the field offset is zero?
# if AFL_ZSTROFF is set, then this flag
# is ignored.
OOF_NOBNOT = 0x0400 # prohibit use of binary not
OOF_SPACES = 0x0800 # do not suppress leading spaces
# currently works only for floating point numbers
# ----------------------------------------------------------------------
class insn_t(object):
def __init__(self, noperands = UA_MAXOP):
self.auxpref = 0
self.cs = 0
self.ea = 0
self.flags = 0
self.insnpref = 0
self.ip = 0
self.itype = 0
self.n = 0
self.segpref = 0
self.size = 0
self.Operands = []
# store the number of operands
self.n = noperands
# create operands
for i in xrange(0, noperands):
op = op_t()
op.n = i
self.Operands.append(op)
setattr(self, 'Op%d' % (i+1), op)
def __getitem__(self, i):
return self.Operands[i]
# ----------------------------------------------------------------------
class op_t(object):
def __init__(self):
self.addr = 0
self.dtyp = 0
self.flags = 0
self.n = 0
self.offb = 0
self.offo = 0
self.reg = 0
self.specval = 0
self.specflag1 = 0
self.specflag2 = 0
self.specflag3 = 0
self.specflag4 = 0
self.type = 0
self.value = 0
# make sure reg and phrase have the same value
def __setattr__(self, name, value):
if name == 'reg' or name == 'phrase':
object.__setattr__(self, 'reg', value)
object.__setattr__(self, 'phrase', value)
else:
object.__setattr__(self, name, value)

6
pywraps/swig_stub.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "swig_stub.h"
PyObject *SWIG_NewPointerObj(void *ptr, void *type, int flags)
{
return PyCObject_FromVoidPtr(ptr, NULL);
}

27
pywraps/swig_stub.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef __SWIG_STUB__
#define __SWIG_STUB__
#include <Python.h>
#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