mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-30 21:14:20 +01:00
added PyWraps sources. This will facilitate deployment, development and debugging of IDAPython additions
This commit is contained in:
parent
1258fab948
commit
930d7cbcd4
125
pywraps/deploy.bat
Normal file
125
pywraps/deploy.bat
Normal 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
91
pywraps/deploy.py
Normal 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
172
pywraps/driver.cpp
Normal 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
19
pywraps/driver_bytes.cpp
Normal 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
109
pywraps/driver_chooser.cpp
Normal 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
29
pywraps/driver_cli.cpp
Normal 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);
|
77
pywraps/driver_custdata.cpp
Normal file
77
pywraps/driver_custdata.cpp
Normal 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
384
pywraps/driver_custview.cpp
Normal 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, ¬ags) )
|
||||||
|
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
78
pywraps/driver_dbg.cpp
Normal 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
47
pywraps/driver_diskio.cpp
Normal 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
56
pywraps/driver_expr.cpp
Normal 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
44
pywraps/driver_graph.cpp
Normal 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);
|
78
pywraps/driver_kernwin.cpp
Normal file
78
pywraps/driver_kernwin.cpp
Normal 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
18
pywraps/driver_nalt.cpp
Normal 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);
|
36
pywraps/driver_notifywhen.cpp
Normal file
36
pywraps/driver_notifywhen.cpp
Normal 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
336
pywraps/link_gen.py
Normal 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
978
pywraps/py_appcall.py
Normal 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
355
pywraps/py_askusingform.hpp
Normal 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
1876
pywraps/py_askusingform.py
Normal file
File diff suppressed because it is too large
Load Diff
218
pywraps/py_bytes.hpp
Normal file
218
pywraps/py_bytes.hpp
Normal 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
87
pywraps/py_choose.hpp
Normal 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
956
pywraps/py_choose2.hpp
Normal 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
390
pywraps/py_choose2.py
Normal 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
293
pywraps/py_cli.hpp
Normal 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
187
pywraps/py_cli.py
Normal 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
699
pywraps/py_custdata.hpp
Normal 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
241
pywraps/py_custdata.py
Normal 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
1110
pywraps/py_custview.hpp
Normal file
File diff suppressed because it is too large
Load Diff
458
pywraps/py_custview.py
Normal file
458
pywraps/py_custview.py
Normal 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
1095
pywraps/py_cvt.hpp
Normal file
File diff suppressed because it is too large
Load Diff
699
pywraps/py_dbg.hpp
Normal file
699
pywraps/py_dbg.hpp
Normal 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
62
pywraps/py_diskio.hpp
Normal 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
5
pywraps/py_diskio.py
Normal 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
156
pywraps/py_expr.hpp
Normal 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
169
pywraps/py_expr.py
Normal 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
88
pywraps/py_gdl.py
Normal 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
816
pywraps/py_graph.hpp
Normal 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
169
pywraps/py_graph.py
Normal 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
804
pywraps/py_idaapi.hpp
Normal 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
513
pywraps/py_idaapi.py
Normal 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
1536
pywraps/py_idp.hpp
Normal file
File diff suppressed because it is too large
Load Diff
902
pywraps/py_kernwin.hpp
Normal file
902
pywraps/py_kernwin.hpp
Normal 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
110
pywraps/py_kernwin.py
Normal 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
211
pywraps/py_lines.hpp
Normal 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
34
pywraps/py_lines.py
Normal 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
361
pywraps/py_linput.hpp
Normal 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
78
pywraps/py_loader.hpp
Normal 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
486
pywraps/py_nalt.hpp
Normal 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
191
pywraps/py_nalt.py
Normal 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
23
pywraps/py_name.hpp
Normal 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
52
pywraps/py_name.py
Normal 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
307
pywraps/py_notifywhen.hpp
Normal 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
63
pywraps/py_notifywhen.py
Normal 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
158
pywraps/py_plgform.hpp
Normal 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
108
pywraps/py_plgform.py
Normal 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
327
pywraps/py_qfile.hpp
Normal 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
308
pywraps/py_typeinf.hpp
Normal 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
793
pywraps/py_ua.hpp
Normal 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
519
pywraps/py_ua.py
Normal 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
2
pywraps/pywraps.hpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Just a proxy header
|
||||||
|
#include "../pywraps.hpp"
|
32
pywraps/pywraps.sln
Normal file
32
pywraps/pywraps.sln
Normal 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
1844
pywraps/pywraps.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
663
pywraps/pywraps.vcxproj
Normal file
663
pywraps/pywraps.vcxproj
Normal 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>
|
518
pywraps/pywraps.vcxproj.filters
Normal file
518
pywraps/pywraps.vcxproj.filters
Normal 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
116
pywraps/readme.txt
Normal 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
225
pywraps/sidaapi.py
Normal 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
311
pywraps/sidc.py
Normal 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
6
pywraps/swig_stub.cpp
Normal 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
27
pywraps/swig_stub.h
Normal 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
|
Loading…
Reference in New Issue
Block a user