IDA Pro 6.5 support

What's new:
- Proper multi-threaded support 
- Better PyObject reference counting with ref_t and newref_t helper classes
- Improved the pywraps/deployment script
- Added IDAViewWrapper class and example
- Added idc.GetDisasmEx()
- Added idc.AddSegEx()
- Added idc.GetLocalTinfo()
- Added idc.ApplyType()
- Updated type information implementation
- Introduced the idaapi.require() - see http://www.hexblog.com/?p=749
- set REMOVE_CWD_SYS_PATH=1 by default in python.cfg (remove current directory from the import search path).

Various bugfixes:
- fixed various memory leaks
- asklong/askaddr/asksel (and corresponding idc.py functions) were returning results truncated to 32 bits in IDA64
- fix wrong documentation for idc.SizeOf
- GetFloat/GetDouble functions did not take into account endianness of the processor
- idaapi.NO_PROCESS was not defined, and was causing GetProcessPid() to fail
- idc.py: insert escape characters to string parameter when call Eval()
- idc.SaveFile/savefile were always overwriting an existing file instead of writing only the new data
- PluginForm.Close() wasn't passing its arguments to the delegate function, resulting in an error.
This commit is contained in:
elias.bachaalany@gmail.com
2013-12-30 01:34:23 +00:00
parent c88a77e809
commit 78c79f85b9
77 changed files with 8952 additions and 5320 deletions
+1 -124
View File
@@ -1,125 +1,2 @@
@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:\python27\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 ..\..\..\tests\input\pc_win32_appcall.pe.hints
rem --------------------------------------------------------------------------
echo Deploying ex_custdata example
%PY% deploy.py ex_custdata ..\examples\ex_custdata.py ..\..\..\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
c:\python27\python.exe deploy_all.py
+8 -1
View File
@@ -13,7 +13,13 @@ 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 convert_path(path_in):
parts = path_in.split('/')
return os.sep.join(parts)
def deploy(mod_name, src_files, dest_file, silent = True):
dest_file = convert_path(dest_file)
src_files = map(convert_path, src_files)
# create regular expressions
templates = (
('pycode', make_re('pycode', mod_name, '#')),
@@ -88,4 +94,5 @@ def main(argv = None):
deploy(mod_name, src_files, dest_file)
#main(['', 'py_graph', 'py_graph.hpp,py_graph.py', 'graph.i'])
main()
if __name__ == '__main__':
main()
+194
View File
@@ -0,0 +1,194 @@
# Please use the same tag for the same .i file
# That means if many insertions are going to happen in one
# given .i file then don't use more than code marking tag
print "\n-------- DEPLOY started --------------------------------------------------\n"
deploys = {
"idaapi (common functions, notifywhen)" : {
"tag" : "py_idaapi",
"src" : ["py_cvt.hpp", "py_idaapi.hpp", "py_idaapi.py", "py_notifywhen.hpp", "py_notifywhen.py"],
"tgt" : "../swig/idaapi.i"
},
"View (common)" : {
"tag" : "py_view_base",
"src" : ["py_view_base.hpp", "py_view_base.py"],
"tgt" : "../swig/view.i"
},
"IDAView" : {
"tag" : "py_idaview",
"src" : ["py_idaview.hpp", "py_idaview.py"],
"tgt" : "../swig/view.i"
},
"Graph" : {
"tag" : "py_graph",
"src" : ["py_graph.hpp", "py_graph.py"],
"tgt" : "../swig/graph.i"
},
"custview" : {
"tag" : "py_custviewer",
"src" : ["py_custview.py","py_custview.hpp"],
"tgt" : "../swig/kernwin.i"
},
"plgform" : {
"tag" : "py_plgform",
"src" : ["py_plgform.hpp","py_plgform.py"],
"tgt" : "../swig/kernwin.i"
},
"expr" : {
"tag" : "py_expr",
"src" : ["py_expr.hpp","py_expr.py"],
"tgt" : "../swig/expr.i"
},
"cli" : {
"tag" : "py_cli",
"src" : ["py_cli.py","py_cli.hpp"],
"tgt" : "../swig/kernwin.i"
},
"Loader" : {
"tag" : "py_loader",
"src" : ["py_loader.hpp"],
"tgt" : "../swig/loader.i"
},
"kernwin, choose2, askusingform" : {
"tag" : "py_kernwin",
"src" : ["py_kernwin.hpp","py_kernwin.py","py_choose.hpp","py_choose2.hpp","py_choose2.py","py_askusingform.hpp","py_askusingform.py"],
"tgt" : "../swig/kernwin.i"
},
"idd" : {
"tag" : "py_idd",
"src" : ["py_dbg.hpp","py_appcall.py"],
"tgt" : "../swig/idd.i"
},
"idd (python)" : {
"tag" : "py_idd_2",
"src" : ["py_dbg.py"],
"tgt" : "../swig/idd.i"
},
"nalt" : {
"tag" : "py_nalt",
"src" : ["py_nalt.hpp","py_nalt.py"],
"tgt" : "../swig/nalt.i"
},
"dbg" : {
"tag" : "py_dbg",
"src" : ["py_dbg.hpp"],
"tgt" : "../swig/dbg.i"
},
"linput/diskio" : {
"tag" : "py_diskio",
"src" : ["py_linput.hpp","py_diskio.hpp","py_diskio.py"],
"tgt" : "../swig/diskio.i"
},
"name" : {
"tag" : "py_name",
"src" : ["py_name.hpp","py_name.py"],
"tgt" : "../swig/name.i"
},
"qfile" : {
"tag" : "py_qfile",
"src" : ["py_qfile.hpp"],
"tgt" : "../swig/fpro.i"
},
"bytes" : {
"tag" : "py_bytes",
"src" : ["py_bytes.hpp","py_custdata.py","py_custdata.hpp"],
"tgt" : "../swig/bytes.i"
},
"typeinf" : {
"tag" : "py_typeinf",
"src" : ["py_typeinf.hpp","py_typeinf.py"],
"tgt" : "../swig/typeinf.i"
},
"gdl" : {
"tag" : "py_gdl",
"src" : ["py_gdl.py"],
"tgt" : "../swig/gdl.i"
},
"ua" : {
"tag" : "py_ua",
"src" : ["py_ua.hpp","py_ua.py"],
"tgt" : "../swig/ua.i"
},
"idp" : {
"tag" : "py_idp",
"src" : ["py_idp.hpp"],
"tgt" : "../swig/idp.i"
},
"lines" : {
"tag" : "py_lines",
"src" : ["py_lines.hpp","py_lines.py"],
"tgt" : "../swig/lines.i"
},
"pc_win32_appcall" : {
"tag" : "appcalltest",
"src" : ["py_appcall.py"],
"tgt" : "../../../tests/input/pc_win32_appcall.pe.hints"
},
"ex_custdata example" : {
"tag" : "ex_custdata",
"src" : ["../examples/ex_custdata.py"],
"tgt" : "../../../tests/input/pc_win32_custdata1.pe.hints"
},
"ex_formchooser" : {
"tag" : "ex_formchooser",
"src" : ["py_askusingform.py"],
"tgt" : "../../formchooser/formchooser.py"
},
"ex_askusingform" : {
"tag" : "ex_askusingform",
"src" : ["py_askusingform.py"],
"tgt" : "../examples/ex_askusingform.py"
},
"ex_cli example" : {
"tag" : "ex_cli_ex1",
"src" : ["py_cli.py"],
"tgt" : "../examples/ex_cli.py"
},
"ex_expr example" : {
"tag" : "ex_expr",
"src" : ["py_expr.py"],
"tgt" : "../examples/ex_expr.py"
},
"ex_custview.py example" : {
"tag" : "py_custviewerex1",
"src" : ["py_custview.py"],
"tgt" : "../examples/ex_custview.py"
}
}
import deploy
for name in deploys:
data = deploys[name]
print "Deploying %s" % name
deploy.deploy(data["tag"], data["src"], data["tgt"])
+3 -2
View File
@@ -58,7 +58,8 @@ static PyObject *ex_pytoidc(
return NULL;
idc_value_t v;
int sn = 0;
if ( pyvar_to_idcvar(self, &v, &sn) < CIP_OK )
borref_t self_ref(self);
if ( pyvar_to_idcvar(self_ref, &v, &sn) < CIP_OK )
Py_RETURN_NONE;
Py_RETURN_TRUE;
}
@@ -75,4 +76,4 @@ static PyMethodDef py_methods_dbg[] =
{"pytoidc", ex_pytoidc, METH_VARARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */
};
DRIVER_INIT_METHODS(dbg);
DRIVER_INIT_METHODS(dbg);
+42 -2
View File
@@ -162,7 +162,7 @@ class Appcall_callable__(object):
def __get_size(self):
if self.__type == None:
return -1
r = _idaapi.get_type_size0(_idaapi.cvar.idati, self.__type)
r = _idaapi.calc_type_size(_idaapi.cvar.idati, self.__type)
if not r:
return -1
return r
@@ -658,6 +658,46 @@ def test_pck_bv():
return 1
# -----------------------------------------------------------------------
def test_local_types():
(type, fields) = GetLocalTinfo(1)
if not type:
return -1
decl = GetLocalType(1, PRTYPE_MULTI)
if decl != "enum\n"\
+ "{\n"\
+ " FEATURE_OBJECT_CACHING = 0x0,\n"\
+ " FEATURE_ZONE_ELEVATION = 0x1,\n"\
+ " FEATURE_MIME_HANDLING = 0x2,\n"\
+ " FEATURE_MIME_SNIFFING = 0x3,\n"\
+ " FEATURE_WINDOW_RESTRICTIONS = 0x4,\n"\
+ " FEATURE_WEBOC_POPUPMANAGEMENT = 0x5,\n"\
+ " FEATURE_BEHAVIORS = 0x6,\n"\
+ " FEATURE_DISABLE_MK_PROTOCOL = 0x7,\n"\
+ " FEATURE_LOCALMACHINE_LOCKDOWN = 0x8,\n"\
+ " FEATURE_SECURITYBAND = 0x9,\n"\
+ " FEATURE_RESTRICT_ACTIVEXINSTALL = 0xA,\n"\
+ " FEATURE_VALIDATE_NAVIGATE_URL = 0xB,\n"\
+ " FEATURE_RESTRICT_FILEDOWNLOAD = 0xC,\n"\
+ " FEATURE_ADDON_MANAGEMENT = 0xD,\n"\
+ " FEATURE_PROTOCOL_LOCKDOWN = 0xE,\n"\
+ " FEATURE_HTTP_USERNAME_PASSWORD_DISABLE = 0xF,\n"\
+ " FEATURE_SAFE_BINDTOOBJECT = 0x10,\n"\
+ " FEATURE_UNC_SAVEDFILECHECK = 0x11,\n"\
+ " FEATURE_GET_URL_DOM_FILEPATH_UNENCODED = 0x12,\n"\
+ " FEATURE_TABBED_BROWSING = 0x13,\n"\
+ " FEATURE_SSLUX = 0x14,\n"\
+ " FEATURE_DISABLE_NAVIGATION_SOUNDS = 0x15,\n"\
+ " FEATURE_DISABLE_LEGACY_COMPRESSION = 0x16,\n"\
+ " FEATURE_FORCE_ADDR_AND_STATUS = 0x17,\n"\
+ " FEATURE_XMLHTTP = 0x18,\n"\
+ " FEATURE_DISABLE_TELNET_PROTOCOL = 0x19,\n"\
+ " FEATURE_FEEDS = 0x1A,\n"\
+ " FEATURE_BLOCK_INPUT_PROMPTS = 0x1B,\n"\
+ " FEATURE_ENTRY_COUNT = 0x1C,\n"\
+ "} _tagINTERNETFEATURELIST\n":
print "decl = " + decl
return -2
return 1
# various tests
def test1(stage):
# call a method that takes a string buffer and appends a dot to its end
@@ -891,7 +931,7 @@ def test_exec_throw():
# -----------------------------------------------------------------------
# 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_unpack_raw, test_pck_idb, test_pck_bv, test_local_types,
test_enum_files, test2, test_exec_throw, test_loaddll)
test_log = None # test log file
+5 -1
View File
@@ -142,6 +142,7 @@ static PyObject *formchgcbfa_get_field_value(
size_t sz)
{
DECLARE_FORM_ACTIONS;
PYW_GIL_CHECK_LOCKED_SCOPE();
switch ( ft )
{
case 8:
@@ -213,7 +214,9 @@ static PyObject *formchgcbfa_get_field_value(
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
(*it)--;
return PyW_IntVecToPyList(intvec);
ref_t l(PyW_IntVecToPyList(intvec));
l.incref();
return l.o;
}
break;
}
@@ -276,6 +279,7 @@ static bool formchgcbfa_set_field_value(
PyObject *py_val)
{
DECLARE_FORM_ACTIONS;
PYW_GIL_CHECK_LOCKED_SCOPE();
switch ( ft )
{
+26 -35
View File
@@ -5,20 +5,17 @@
//------------------------------------------------------------------------
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;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_flags(PyLong_FromUnsignedLong(flags));
newref_t result(PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags.o, NULL));
return result != NULL && PyObject_IsTrue(result.o);
}
//------------------------------------------------------------------------
// Wraps the (next|prev)that()
static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_callable) )
return BADADDR;
else
@@ -33,20 +30,17 @@ static int idaapi py_visit_patched_bytes_cb(
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_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallFunction(
(PyObject *)ud,
PY_FMT64 "iII",
pyul_t(ea),
fpos,
o,
v));
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;
return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0;
}
//</code(py_bytes)>
//------------------------------------------------------------------------
@@ -74,6 +68,7 @@ def visit_patched_bytes(ea1, ea2, callable):
*/
static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_callable) )
return 0;
else
@@ -122,29 +117,23 @@ def get_many_bytes(ea, size):
*/
static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
if ( size <= 0 )
break;
// Allocate memory via Python
PyObject *py_buf = PyString_FromStringAndSize(NULL, Py_ssize_t(size));
newref_t 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 ( !get_many_bytes(ea, PyString_AsString(py_buf.o), size) )
Py_RETURN_NONE;
// If failed, dispose the Python string
if ( !ok )
{
Py_DECREF(py_buf);
py_buf = Py_None;
Py_INCREF(py_buf);
}
return py_buf;
py_buf.incref();
return py_buf.o;
} while ( false );
Py_RETURN_NONE;
}
@@ -195,9 +184,11 @@ static PyObject *py_get_ascii_contents2(
}
if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' )
used_size--;
PyObject *py_buf = PyString_FromStringAndSize((const char *)buf, used_size);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_buf(PyString_FromStringAndSize((const char *)buf, used_size));
qfree(buf);
return py_buf;
py_buf.incref();
return py_buf.o;
}
//---------------------------------------------------------------------------
/*
+18 -27
View File
@@ -6,45 +6,35 @@
//---------------------------------------------------------------------------
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;
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod((PyObject *)self, "sizer", ""));
return PyInt_AsLong(pyres.o);
}
//---------------------------------------------------------------------------
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;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
(PyObject *)self,
"getl",
"l",
n));
const char *res;
if (pyres == NULL || (res = PyString_AsString(pyres)) == NULL )
if (pyres == NULL || (res = PyString_AsString(pyres.o)) == 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;
PYW_GIL_GET;
newref_t res(PyObject_CallMethod((PyObject *)self, "enter", "l", n));
}
//---------------------------------------------------------------------------
@@ -57,8 +47,9 @@ uint32 choose_choose(
int deflt,
int icon)
{
PyObject *pytitle = PyObject_GetAttrString((PyObject *)self, "title");
const char *title = pytitle != NULL ? PyString_AsString(pytitle) : "Choose";
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t pytitle(PyObject_GetAttrString((PyObject *)self, "title"));
const char *title = pytitle != NULL ? PyString_AsString(pytitle.o) : "Choose";
int r = choose(
flags,
@@ -79,9 +70,9 @@ uint32 choose_choose(
NULL, /* destroy */
NULL, /* popup_names */
NULL);/* get_icon */
Py_XDECREF(pytitle);
return r;
}
//</inline(py_kernwin)>
#endif // __PY_CHOOSE__
#endif // __PY_CHOOSE__
+130 -174
View File
@@ -11,8 +11,8 @@
#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)); \
{ \
return thisobj->on_command(id, int(n)); \
}
//------------------------------------------------------------------------
@@ -100,6 +100,9 @@ private:
//------------------------------------------------------------------------
static int idaapi ui_cb(void *obj, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
// UI callback to handle chooser items with attributes
if ( notification_code != ui_get_chooser_item_attrs )
return 0;
@@ -209,6 +212,9 @@ private:
void on_get_line(int lineno, char * const *line_arr)
{
// Called from s_getl, which itself can be called from the kernel. Ensure GIL
PYW_GIL_GET;
// Get headers?
if ( lineno == 0 )
{
@@ -224,64 +230,51 @@ private:
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;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t list(PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1));
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));
borref_t item(PyList_GetItem(list.o, Py_ssize_t(i)));
if ( item == NULL )
continue;
const char *str = PyString_AsString(item);
const char *str = PyString_AsString(item.o);
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;
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL));
if ( pyres == NULL )
return 0;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
return PyInt_AsLong(pyres.o);
}
void on_refreshed()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL));
}
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);
PYW_GIL_GET;
ref_t py_list(PyW_IntVecToPyList(intvec));
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_SELECT, "O", py_list.o));
}
void on_close()
{
// Call Python
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL));
// Delete this instance if none modal and not embedded
if ( !is_modal() && get_embedded() == NULL )
@@ -290,123 +283,96 @@ private:
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;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_DELETE_LINE,
"i",
lineno - 1));
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o) + 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;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_REFRESH,
"i",
lineno - 1));
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o) + 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);
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_INSERT_LINE, NULL));
}
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);
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_SELECT_LINE,
"i",
lineno - 1));
}
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);
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_EDIT_LINE,
"i",
lineno - 1));
}
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;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_COMMAND,
"ii",
lineno - 1,
cmd_id));
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o);
}
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;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_GET_ICON,
"i",
lineno - 1));
return PyInt_AsLong(pyres.o);
}
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) )
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1));
if ( pyres != NULL )
{
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);
if ( PyList_Check(pyres.o) )
{
PyObject *item;
if ( (item = PyList_GetItem(pyres.o, 0)) != NULL )
attr->color = PyInt_AsLong(item);
if ( (item = PyList_GetItem(pyres.o, 1)) != NULL )
attr->flags = PyInt_AsLong(item);
}
}
Py_XDECREF(pyres);
}
public:
@@ -496,7 +462,7 @@ public:
// Adjust the title
ptitle = title_buf;
// Adjust the caption
p = strtok(NULL, delimiter);
caption += (p - temp);
@@ -507,12 +473,12 @@ public:
}
if ( !add_chooser_command(
ptitle,
caption,
menu_cbs[menu_cb_idx],
menu_index,
icon,
flags))
ptitle,
caption,
menu_cbs[menu_cb_idx],
menu_index,
icon,
flags))
{
return -1;
}
@@ -525,83 +491,71 @@ public:
// Otherwise the chooser window is created and displayed
int create(PyObject *self)
{
PyObject *attr;
PYW_GIL_CHECK_LOCKED_SCOPE();
// Get flags
attr = PyW_TryGetAttrString(self, S_FLAGS);
if ( attr == NULL )
ref_t flags_attr(PyW_TryGetAttrString(self, S_FLAGS));
if ( flags_attr == NULL )
return -1;
flags = PyInt_Check(attr) != 0 ? PyInt_AsLong(attr) : 0;
Py_DECREF(attr);
flags = PyInt_Check(flags_attr.o) != 0 ? PyInt_AsLong(flags_attr.o) : 0;
// Get the title
if ( !PyW_GetStringAttr(self, S_TITLE, &title) )
return -1;
// Get columns
attr = PyW_TryGetAttrString(self, "cols");
if ( attr == NULL )
ref_t cols_attr(PyW_TryGetAttrString(self, "cols"));
if ( cols_attr == NULL )
return -1;
// Get col count
int ncols = int(PyList_Size(attr));
int ncols = int(PyList_Size(cols_attr.o));
// 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);
borref_t list(PyList_GetItem(cols_attr.o, i));
borref_t v(PyList_GetItem(list.o, 0));
// Extract string
const char *str = v == NULL ? "" : PyString_AsString(v);
const char *str = v == NULL ? "" : PyString_AsString(v.o);
cols.push_back(str);
// Extract width
int width;
v = PyList_GetItem(list, 1);
borref_t v2(PyList_GetItem(list.o, 1));
// No width? Guess width from column title
if ( v == NULL )
if ( v2 == NULL )
width = strlen(str);
else
width = PyInt_AsLong(v);
width = PyInt_AsLong(v2.o);
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);
}
ref_t deflt_attr(PyW_TryGetAttrString(self, "deflt"));
if ( deflt_attr != NULL )
deflt = PyInt_AsLong(deflt_attr.o);
// Get *icon
int icon = -1;
if ( (attr = PyW_TryGetAttrString(self, "icon")) != NULL )
{
icon = PyInt_AsLong(attr);
Py_DECREF(attr);
}
ref_t icon_attr(PyW_TryGetAttrString(self, "icon"));
if ( icon_attr != NULL )
icon = PyInt_AsLong(icon_attr.o);
// 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 )
{
ref_t pt_attr(PyW_TryGetAttrString(self, pt_attrs[i]));
if ( pt_attr == NULL )
pts[i] = -1;
}
else
{
pts[i] = PyInt_AsLong(attr);
Py_DECREF(attr);
}
pts[i] = PyInt_AsLong(pt_attr.o);
}
// Check what callbacks we have
@@ -628,10 +582,8 @@ public:
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);
ref_t cb_attr(PyW_TryGetAttrString(self, callbacks[i].name));
bool have_cb = cb_attr != NULL && PyCallable_Check(cb_attr.o) != 0;
if ( have_cb )
{
cb_flags |= callbacks[i].have;
@@ -646,19 +598,18 @@ public:
// 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 )
ref_t pn_attr(PyW_TryGetAttrString(self, S_POPUP_NAMES));
if ( (pn_attr != NULL)
&& PyList_Check(pn_attr.o)
&& PyList_Size(pn_attr.o) == 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));
const char *str = PyString_AsString(PyList_GetItem(pn_attr.o, i));
popup_names[i] = qstrdup(str);
}
}
Py_XDECREF(attr);
// Adjust flags (if needed)
if ( (cb_flags & CHOOSE2_HAVE_GETATTR) != 0 )
@@ -672,8 +623,8 @@ public:
install_hooks(true);
// Check if *embedded
attr = PyW_TryGetAttrString(self, S_EMBEDDED);
if ( attr != NULL && PyObject_IsTrue(attr) == 1 )
ref_t emb_attr(PyW_TryGetAttrString(self, S_EMBEDDED));
if ( emb_attr != NULL && PyObject_IsTrue(emb_attr.o) == 1 )
{
// Create an embedded chooser structure
embedded = new chooser_info_t();
@@ -710,7 +661,6 @@ public:
embedded->refresh = NULL;
}
}
Py_XDECREF(attr);
// Create the chooser (if not embedded)
int r;
@@ -873,6 +823,8 @@ void choose2_activate(PyObject *self)
//------------------------------------------------------------------------
PyObject *choose2_get_embedded_selection(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_choose2_t *c2 = choose2_find_instance(self);
chooser_info_t *embedded;
@@ -886,13 +838,17 @@ PyObject *choose2_get_embedded_selection(PyObject *self)
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
(*it)--;
return PyW_IntVecToPyList(intvec);
ref_t ret(PyW_IntVecToPyList(intvec));
ret.incref();
return ret.o;
}
//------------------------------------------------------------------------
// Return the C instances as 64bit numbers
PyObject *choose2_get_embedded(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_choose2_t *c2 = choose2_find_instance(self);
chooser_info_t *embedded;
@@ -945,12 +901,12 @@ PyObject *choose2_get_embedded_selection(PyObject *self);
static void NT_CDECL choose2_test_embedded(chooser_info_t *embedded)
{
msg("cb=%d -> looks %valid\n",
embedded->cb,
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__
#endif // __PY_CHOOSE2__
+82 -80
View File
@@ -37,17 +37,17 @@ private:
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) \
#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_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); \
}
@@ -62,18 +62,15 @@ private:
// 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_GIL_GET;
newref_t result(
PyObject_CallMethod(
self,
(char *)S_ON_EXECUTE_LINE,
"s",
line));
PyW_ShowCbErr(S_ON_EXECUTE_LINE);
Py_XDECREF(result);
return ok;
return result != NULL && PyObject_IsTrue(result.o);
}
//--------------------------------------------------------------------------
@@ -95,41 +92,45 @@ private:
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;
PYW_GIL_GET;
newref_t result(
PyObject_CallMethod(
self,
(char *)S_ON_KEYDOWN,
"siiHi",
line->c_str(),
*p_x,
*p_sellen,
*vk_key,
shift));
bool ok = result != NULL && PyTuple_Check(result);
bool ok = result != NULL && PyTuple_Check(result.o);
PyW_ShowCbErr(S_ON_KEYDOWN);
if ( ok )
{
Py_ssize_t sz = PyTuple_Size(result);
Py_ssize_t sz = PyTuple_Size(result.o);
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;
#define GET_TUPLE_ENTRY(col, PyThingy, AsThingy, out) \
do \
{ \
if ( sz > col ) \
{ \
borref_t _r(PyTuple_GetItem(result.o, col)); \
if ( _r != NULL && PyThingy##_Check(_r.o) ) \
*out = PyThingy##_##AsThingy(_r.o); \
} \
} while ( false )
GET_TUPLE_ENTRY(0, PyString, AsString, line);
GET_TUPLE_ENTRY(1, PyInt, AsLong, p_x);
GET_TUPLE_ENTRY(2, PyInt, AsLong, p_sellen);
GET_TUPLE_ENTRY(3, PyInt, AsLong, vk_key);
*vk_key &= 0xffff;
#undef GET_TUPLE_ENTRY
}
Py_XDECREF(result);
return ok;
}
@@ -140,41 +141,41 @@ private:
// 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)
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_GIL_GET;
newref_t result(
PyObject_CallMethod(
self,
(char *)S_ON_COMPLETE_LINE,
"sisi",
prefix,
n,
line,
x));
bool ok = result != NULL && PyString_Check(result.o);
PyW_ShowCbErr(S_ON_COMPLETE_LINE);
if ( ok )
*completion = PyString_AsString(result);
Py_XDECREF(result);
*completion = PyString_AsString(result.o);
return ok;
}
// Private ctor (use bind())
py_cli_t()
{
py_cli_t()
{
}
public:
//---------------------------------------------------------------------------
static int bind(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
int cli_idx;
// Find an empty slot
for ( cli_idx = 0; cli_idx < MAX_PY_CLI; ++cli_idx )
@@ -183,7 +184,7 @@ public:
break;
}
py_cli_t *py_cli = NULL;
do
do
{
// No free slots?
if ( cli_idx >= MAX_PY_CLI )
@@ -197,14 +198,12 @@ public:
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);
ref_t flags_attr(PyW_TryGetAttrString(py_obj, S_FLAGS));
if ( flags_attr == NULL )
py_cli->cli.flags = 0;
else
py_cli->cli.flags = PyLong_AsLong(flags_attr.o);
}
// Store 'sname'
@@ -256,9 +255,12 @@ public:
py_cli_t *py_cli = py_clis[cli_idx];
remove_command_interpreter(&py_cli->cli);
Py_DECREF(py_cli->self);
delete py_cli;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_DECREF(py_cli->self);
delete py_cli;
}
py_clis[cli_idx] = NULL;
@@ -280,12 +282,12 @@ const py_cli_cbs_t py_cli_t::py_cli_cbs[MAX_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)>
+106 -122
View File
@@ -18,20 +18,18 @@ class py_custom_data_type_t
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_GIL_GET;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_MAY_CREATE_AT,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(nbytes)));
PyW_ShowCbErr(S_MAY_CREATE_AT);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
// !=NULL means variable size datatype
@@ -42,24 +40,23 @@ class py_custom_data_type_t
ea_t ea, // address of the item
asize_t maxsize) // maximal size of the item
{
PYW_GIL_GET;
// 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;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_CALC_ITEM_SIZE,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(maxsize)));
if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL )
return 0;
uint64 num = 0;
PyW_GetNumber(py_result, &num);
Py_XDECREF(py_result);
PyW_GetNumber(py_result.o, &num);
return asize_t(num);
}
@@ -77,6 +74,8 @@ public:
int register_dt(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Already registered?
if ( dtid >= 0 )
return dtid;
@@ -85,9 +84,10 @@ public:
dt.cbsize = sizeof(dt);
dt.ud = this;
PyObject *py_attr = NULL;
do
{
ref_t py_attr;
// name
if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) )
break;
@@ -108,30 +108,27 @@ public:
// 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);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
dt.value_size = PyInt_AsLong(py_attr.o);
py_attr = ref_t();
// 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);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
dt.props = PyInt_AsLong(py_attr.o);
py_attr = ref_t();
// may_create_at
py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
dt.may_create_at = s_may_create_at;
Py_XDECREF(py_attr);
py_attr = ref_t();
// calc_item_size
py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
dt.calc_item_size = s_calc_item_size;
Py_XDECREF(py_attr);
// Clear attribute
py_attr = NULL;
py_attr = ref_t();
// Now try to register
dtid = register_custom_data_type(&dt);
@@ -142,20 +139,16 @@ public:
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;
py_attr = newref_t(PyInt_FromLong(dtid));
PyObject_SetAttrString(py_obj, S_ID, py_attr.o);
} while ( false );
Py_XDECREF(py_attr);
return dtid;
}
bool unregister_dt()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dtid < 0 )
return true;
@@ -195,44 +188,41 @@ private:
int operand_num, // current operand number
int dtid) // custom data type id
{
PYW_GIL_GET;
// Build a string from the buffer
PyObject *py_value = PyString_FromStringAndSize(
(const char *)value,
Py_ssize_t(size));
newref_t 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);
newref_t py_result(PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value.o,
pyul_t(current_ea),
operand_num,
dtid));
// Error while calling the function?
if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL )
return false;
bool ok = false;
if ( PyString_Check(py_result) )
if ( PyString_Check(py_result.o) )
{
Py_ssize_t len;
char *buf;
if ( out != NULL && PyString_AsStringAndSize(py_result, &buf, &len) != -1 )
if ( out != NULL && PyString_AsStringAndSize(py_result.o, &buf, &len) != -1 )
{
out->qclear();
out->append(buf, len);
}
ok = true;
}
Py_DECREF(py_result);
return ok;
}
@@ -244,16 +234,17 @@ private:
int operand_num, // current operand number (-1 if unknown)
qstring *errstr) // buffer for error message
{
PYW_GIL_GET;
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;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num));
// Error while calling the function?
if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL)
@@ -263,15 +254,14 @@ private:
do
{
// We expect a tuple(bool, string|None)
if ( !PyTuple_Check(py_result) || PyTuple_Size(py_result) != 2 )
if ( !PyTuple_Check(py_result.o) || PyTuple_Size(py_result.o) != 2 )
break;
// Borrow references
PyObject *py_bool = PyTuple_GetItem(py_result, 0);
PyObject *py_val = PyTuple_GetItem(py_result, 1);
borref_t py_bool(PyTuple_GetItem(py_result.o, 0));
borref_t py_val(PyTuple_GetItem(py_result.o, 1));
// Get return code from Python
ok = PyObject_IsTrue(py_bool);
ok = PyObject_IsTrue(py_bool.o);
// We expect None or the value (depending on probe)
if ( ok )
@@ -282,7 +272,7 @@ private:
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_val, &buf, &len) != -1 )
if ( PyString_AsStringAndSize(py_val.o, &buf, &len) != -1 )
{
value->qclear();
value->append(buf, len);
@@ -292,16 +282,15 @@ private:
else
{
// Make sure the user returned (False, String)
if ( py_bool != Py_False || !PyString_Check(py_val) )
if ( py_bool.o != Py_False || !PyString_Check(py_val.o) )
{
*errstr = "Invalid return value returned from the Python callback!";
break;
}
// Get the error message
*errstr = PyString_AsString(py_val);
*errstr = PyString_AsString(py_val.o);
}
} while ( false );
Py_DECREF(py_result);
return ok;
}
@@ -313,19 +302,18 @@ private:
// xrefs from the current item.
// this callback may be missing.
{
PYW_GIL_GET;
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;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_ANALYZE,
PY_FMT64 "i",
pyul_t(current_ea),
operand_num));
PyW_ShowCbErr(S_ANALYZE);
Py_XDECREF(py_result);
}
public:
py_custom_data_format_t()
@@ -334,9 +322,9 @@ public:
py_self = NULL;
}
const char *get_name() const
{
return df_name.c_str();
const char *get_name() const
{
return df_name.c_str();
}
int register_df(int dtid, PyObject *py_obj)
@@ -348,10 +336,12 @@ public:
memset(&df, 0, sizeof(df));
df.cbsize = sizeof(df);
df.ud = this;
PyObject *py_attr = NULL;
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
ref_t py_attr;
// name
if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) )
break;
@@ -363,9 +353,8 @@ public:
// 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);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.props = PyInt_AsLong(py_attr.o);
// hotkey
if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) )
@@ -373,36 +362,28 @@ public:
// 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);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.value_size = PyInt_AsLong(py_attr.o);
// 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);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.text_width = PyInt_AsLong(py_attr.o);
// print cb
py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
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) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
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) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
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);
@@ -414,19 +395,16 @@ public:
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;
py_attr = newref_t(PyInt_FromLong(dfid));
PyObject_SetAttrString(py_obj, S_ID, py_attr.o);
} while ( false );
Py_XDECREF(py_attr);
return dfid;
}
bool unregister_df(int dtid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Never registered?
if ( dfid < 0 )
return true;
@@ -490,6 +468,8 @@ static py_custom_data_format_list_t py_df_list;
//------------------------------------------------------------------------
static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
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,
@@ -503,6 +483,8 @@ static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
//------------------------------------------------------------------------
static PyObject *py_data_format_to_py_dict(const data_format_t *df)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
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,
@@ -668,6 +650,7 @@ def get_custom_data_format(dtid, dfid):
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_format(int dtid, int fid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
const data_format_t *df = get_custom_data_format(dtid, fid);
if ( df == NULL )
Py_RETURN_NONE;
@@ -688,6 +671,7 @@ def get_custom_data_type(dtid):
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_type(int dtid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
const data_type_t *dt = get_custom_data_type(dtid);
if ( dt == NULL )
Py_RETURN_NONE;
+79 -73
View File
@@ -168,6 +168,7 @@ private:
static bool idaapi s_popup_cb(void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_popup();
}
@@ -179,6 +180,7 @@ private:
if ( it == _global_popup_map.end() )
return false;
PYW_GIL_GET;
return it->second.cv->on_popup_menu(it->second.menu_id);
}
@@ -188,6 +190,7 @@ private:
int shift,
void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_keydown(vk_key, shift);
}
@@ -195,6 +198,7 @@ private:
// The popup menu is being constructed
static void idaapi s_cv_popup(TCustomControl * /*cv*/, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
_this->on_popup();
}
@@ -202,6 +206,7 @@ private:
// The user clicked
static bool idaapi s_cv_click(TCustomControl * /*cv*/, int shift, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_click(shift);
}
@@ -209,6 +214,7 @@ private:
// The user double clicked
static bool idaapi s_cv_dblclick(TCustomControl * /*cv*/, int shift, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_dblclick(shift);
}
@@ -216,6 +222,7 @@ private:
// Cursor position has been changed
static void idaapi s_cv_curpos(TCustomControl * /*cv*/, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
_this->on_curpos_changed();
}
@@ -223,6 +230,8 @@ private:
//--------------------------------------------------------------------------
static int idaapi s_ui_cb(void *ud, int code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
switch ( code )
{
@@ -243,11 +252,12 @@ private:
TForm *form = va_arg(va, TForm *);
if ( _this->_form != form )
break;
unhook_from_notification_point(HT_UI, s_ui_cb, _this);
_this->on_close();
_this->on_post_close();
}
// fallthrough...
case ui_term:
unhook_from_notification_point(HT_UI, s_ui_cb, _this);
_this->on_close();
_this->on_post_close();
break;
}
@@ -541,6 +551,8 @@ private:
// Convert a tuple (String, [color, [bgcolor]]) to a simpleline_t
static bool py_to_simpleline(PyObject *py, simpleline_t &sl)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_Check(py) )
{
sl.line = PyString_AsString(py);
@@ -570,37 +582,29 @@ private:
//
virtual bool on_click(int shift)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift));
PyW_ShowCbErr(S_ON_CLICK);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
// OnDblClick
virtual bool on_dblclick(int shift)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift));
PyW_ShowCbErr(S_ON_DBL_CLICK);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
// OnCurorPositionChanged
virtual void on_curpos_changed()
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, NULL);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, NULL));
PyW_ShowCbErr(S_ON_CURSOR_POS_CHANGED);
Py_XDECREF(py_result);
}
//--------------------------------------------------------------------------
@@ -610,12 +614,9 @@ private:
// Call the close method if it is there and the object is still bound
if ( (features & HAVE_CLOSE) != 0 && py_self != NULL )
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, NULL);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, NULL));
PyW_ShowCbErr(S_ON_CLOSE);
Py_XDECREF(py_result);
// Cleanup
Py_DECREF(py_self);
@@ -627,36 +628,31 @@ private:
// OnKeyDown
virtual bool on_keydown(int vk_key, int shift)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_KEYDOWN,
"ii",
vk_key,
shift);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_KEYDOWN,
"ii",
vk_key,
shift));
PyW_ShowCbErr(S_ON_KEYDOWN);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
// OnPopupShow
virtual bool on_popup()
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP,
NULL);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP,
NULL));
PyW_ShowCbErr(S_ON_POPUP);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
@@ -664,28 +660,22 @@ private:
virtual bool on_hint(place_t *place, int *important_lines, qstring &hint)
{
size_t ln = data.to_lineno(place);
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_HINT,
PY_FMT64,
pyul_t(ln));
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_HINT,
PY_FMT64,
pyul_t(ln)));
PyW_ShowCbErr(S_ON_HINT);
bool ok = py_result != NULL && PyTuple_Check(py_result) && PyTuple_Size(py_result) == 2;
bool ok = py_result != NULL && PyTuple_Check(py_result.o) && PyTuple_Size(py_result.o) == 2;
if ( ok )
{
// Borrow references
PyObject *py_nlines = PyTuple_GetItem(py_result, 0);
PyObject *py_hint = PyTuple_GetItem(py_result, 1);
if ( important_lines != NULL )
*important_lines = PyInt_AsLong(py_nlines);
hint = PyString_AsString(py_hint);
*important_lines = PyInt_AsLong(PyTuple_GetItem(py_result.o, 0));
hint = PyString_AsString(PyTuple_GetItem(py_result.o, 1));
}
Py_XDECREF(py_result);
return ok;
}
@@ -693,18 +683,15 @@ private:
// OnPopupMenuClick
virtual bool on_popup_menu(size_t menu_id)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP_MENU,
PY_FMT64,
pyul_t(menu_id));
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP_MENU,
PY_FMT64,
pyul_t(menu_id)));
PyW_ShowCbErr(S_ON_POPUP_MENU);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
@@ -776,6 +763,7 @@ public:
place_t *pl;
int x, y;
pl = get_place(mouse, &x, &y);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( pl == NULL )
Py_RETURN_NONE;
return Py_BuildValue("(" PY_FMT64 "ii)", pyul_t(data.to_lineno(pl)), x, y);
@@ -786,6 +774,7 @@ public:
PyObject *get_line(size_t nline)
{
simpleline_t *r = data.get_line(nline);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( r == NULL )
Py_RETURN_NONE;
return Py_BuildValue("(sII)", r->line.c_str(), (unsigned int)r->color, (unsigned int)r->bgcolor);
@@ -835,6 +824,8 @@ public:
{S_ON_DBL_CLICK, HAVE_DBLCLICK},
{S_ON_CURSOR_POS_CHANGED, HAVE_CURPOS}
};
PYW_GIL_CHECK_LOCKED_SCOPE();
for ( size_t i=0; i<qnumber(cbtable); i++ )
{
if ( PyObject_HasAttrString(py_link, cbtable[i].cb_name) )
@@ -892,6 +883,7 @@ public:
PyObject *py_get_selection()
{
size_t x1, y1, x2, y2;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !get_selection(&x1, &y1, &x2, &y2) )
Py_RETURN_NONE;
return Py_BuildValue("(" PY_FMT64 PY_FMT64 PY_FMT64 PY_FMT64 ")", pyul_t(x1), pyul_t(y1), pyul_t(x2), pyul_t(y2));
@@ -899,6 +891,7 @@ public:
static py_simplecustview_t *get_this(PyObject *py_this)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_Check(py_this) ? (py_simplecustview_t *) PyCObject_AsVoidPtr(py_this) : NULL;
}
@@ -920,6 +913,7 @@ public:
//
PyObject *pyscv_init(PyObject *py_link, const char *title)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_simplecustview_t *_this = new py_simplecustview_t();
bool ok = _this->init(py_link, title);
if ( !ok )
@@ -964,6 +958,7 @@ bool pyscv_refresh_current(PyObject *py_this)
PyObject *pyscv_get_current_line(PyObject *py_this, bool mouse, bool notags)
{
DECL_THIS;
PYW_GIL_CHECK_LOCKED_SCOPE();
const char *line;
if ( _this == NULL || (line = _this->get_current_line(mouse, notags)) == NULL )
Py_RETURN_NONE;
@@ -1024,7 +1019,10 @@ PyObject *pyscv_get_line(PyObject *py_this, size_t nline)
{
DECL_THIS;
if ( _this == NULL )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
return _this->get_line(nline);
}
@@ -1034,7 +1032,10 @@ PyObject *pyscv_get_pos(PyObject *py_this, bool mouse)
{
DECL_THIS;
if ( _this == NULL )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
return _this->get_pos(mouse);
}
@@ -1044,6 +1045,7 @@ PyObject *pyscv_clear_lines(PyObject *py_this)
DECL_THIS;
if ( _this != NULL )
_this->clear();
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
@@ -1081,7 +1083,10 @@ PyObject *pyscv_get_selection(PyObject *py_this)
{
DECL_THIS;
if ( _this == NULL )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
return _this->py_get_selection();
}
@@ -1089,6 +1094,7 @@ PyObject *pyscv_get_selection(PyObject *py_this)
PyObject *pyscv_get_current_word(PyObject *py_this, bool mouse)
{
DECL_THIS;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( _this != NULL )
{
qstring word;
+502 -520
View File
File diff suppressed because it is too large Load Diff
+61 -33
View File
@@ -14,6 +14,8 @@ static bool dbg_can_query()
//-------------------------------------------------------------------------
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_list = PyList_New(areas.size());
meminfo_vec_t::const_iterator it, it_end(areas.end());
Py_ssize_t i = 0;
@@ -42,6 +44,8 @@ PyObject *py_appcall(
PyObject *py_fields,
PyObject *arg_list)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyList_Check(arg_list) )
return NULL;
@@ -57,11 +61,11 @@ PyObject *py_appcall(
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
borref_t py_item(PyList_GetItem(arg_list, i));
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
qstring s;
PyW_ObjectToString(py_item, &s);
PyW_ObjectToString(py_item.o, &s);
msg("obj[%d]->%s\n", int(i), s.c_str());
}
// Convert it
@@ -81,6 +85,10 @@ PyObject *py_appcall(
return NULL;
}
error_t ret;
idc_value_t idc_result;
Py_BEGIN_ALLOW_THREADS;
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("input variables:\n"
@@ -96,8 +104,7 @@ PyObject *py_appcall(
}
// Do Appcall
idc_value_t idc_result;
error_t ret = appcall(
ret = appcall(
func_ea,
tid,
(type_t *)type,
@@ -106,16 +113,17 @@ PyObject *py_appcall(
idc_args.begin(),
&idc_result);
Py_END_ALLOW_THREADS;
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);
ref_t py_appcall_exc;
idcvar_to_pyvar(idc_result, &py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc);
Py_DECREF(py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc.o);
return NULL;
}
// An error in the Appcall? (or an exception but AppCallOptions/DEBEV is not set)
@@ -145,7 +153,7 @@ PyObject *py_appcall(
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
borref_t 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 )
@@ -155,13 +163,13 @@ PyObject *py_appcall(
}
}
// Convert the result from IDC back to Python
PyObject *py_result(NULL);
ref_t py_result;
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;
}
QASSERT(30413, py_result.o->ob_refcnt == 1);
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("return var:\n"
@@ -170,7 +178,8 @@ PyObject *py_appcall(
VarPrint(&s, &idc_result);
msg("%s\n-----------\n", s.c_str());
}
return py_result;
py_result.incref();
return py_result.o;
}
//</code(py_idd)>
@@ -193,6 +202,8 @@ def dbg_get_registers():
*/
static PyObject *dbg_get_registers()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dbg == NULL )
Py_RETURN_NONE;
@@ -251,6 +262,8 @@ def dbg_get_thread_sreg_base(tid, sreg_value):
*/
static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) )
Py_RETURN_NONE;
ea_t answer;
@@ -277,6 +290,8 @@ def dbg_read_memory(ea, sz):
*/
static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 ea, sz;
if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) )
Py_RETURN_NONE;
@@ -314,6 +329,8 @@ def dbg_write_memory(ea, buffer):
*/
static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 ea;
if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) )
Py_RETURN_NONE;
@@ -338,6 +355,8 @@ def dbg_get_name():
*/
static PyObject *dbg_get_name()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dbg == NULL )
Py_RETURN_NONE;
else
@@ -359,15 +378,19 @@ def dbg_get_memory_info():
*/
static PyObject *dbg_get_memory_info()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() )
Py_RETURN_NONE;
// Invalidate memory
meminfo_vec_t areas;
Py_BEGIN_ALLOW_THREADS;
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
meminfo_vec_t areas;
get_dbg_memory_info(&areas);
Py_END_ALLOW_THREADS;
return meminfo_vec_t_to_py(areas);
}
@@ -459,6 +482,7 @@ static PyObject *refresh_debugger_memory()
// Invalidate the cache
isEnabled(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
@@ -466,74 +490,78 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
public:
virtual ~DBG_Hooks() { unhook(); };
virtual ~DBG_Hooks() { unhook(); }
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); };
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); };
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) { };
asize_t size) {}
virtual void dbg_process_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
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) { };
asize_t size) {}
virtual void dbg_process_detach(pid_t pid,
thid_t tid,
ea_t ea) { };
ea_t ea) {}
virtual void dbg_thread_start(pid_t pid,
thid_t tid,
ea_t ea) { };
ea_t ea) {}
virtual void dbg_thread_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
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) { };
asize_t size) {}
virtual void dbg_library_unload(pid_t pid,
thid_t tid,
ea_t ea,
char *libname) { };
char *libname) {}
virtual void dbg_information(pid_t pid,
thid_t tid,
ea_t ea,
char *info) { };
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; };
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 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)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class DBG_Hooks *proxy = (class DBG_Hooks *)ud;
debug_event_t *event;
int code = 0;
try
{
switch (notification_code)
+7
View File
@@ -0,0 +1,7 @@
#<pycode(py_idd_2)>
NO_PROCESS = 0xFFFFFFFF
NO_THREAD = 0
#</pycode(py_idd_2)>
+14 -12
View File
@@ -5,17 +5,17 @@
//--------------------------------------------------------------------------
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;
// No need to 'PYW_GIL_GET' here, as this is called synchronously
// and from the same thread as the one that executes
// 'py_enumerate_files'.
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_file(PyString_FromString(file));
newref_t py_ret(
PyObject_CallFunctionObjArgs(
(PyObject *)ud,
py_file.o,
NULL));
return (py_ret == NULL || !PyNumber_Check(py_ret.o)) ? 1 /* stop enum on failure */ : PyInt_AsLong(py_ret.o);
}
//</code(py_diskio)>
@@ -31,7 +31,7 @@ def enumerate_files(path, fname, callback):
@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:
@return:
None in case of script errors
tuple(code, fname) : If the callback returns non-zero
"""
@@ -40,6 +40,8 @@ def enumerate_files(path, fname, callback):
*/
PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
if ( !PyString_Check(path) || !PyString_Check(fname) || !PyCallable_Check(callback) )
+11 -15
View File
@@ -9,10 +9,12 @@ struct py_idcfunc_ctx_t
int nargs;
py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_INCREF(py_func);
}
~py_idcfunc_ctx_t()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_DECREF(py_func);
}
};
@@ -26,25 +28,25 @@ static error_t py_call_idc_func(
// 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)) )
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_vec_t pargs;
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, true, 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]);
newref_t py_result(PyObject_CallObject(
ctx->py_func,
pargs.empty() ? NULL : pargs[0].o));
error_t err;
if ( PyW_GetError(errbuf, sizeof(errbuf)) )
{
err = PyW_CreateIdcException(r, errbuf);
Py_XDECREF(py_result);
}
else
{
@@ -55,13 +57,7 @@ static error_t py_call_idc_func(
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;
}
@@ -153,4 +149,4 @@ bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize)
}
//</inline(py_expr)>
#endif
#endif
+502 -549
View File
File diff suppressed because it is too large Load Diff
+2 -8
View File
@@ -1,5 +1,5 @@
#<pycode(py_graph)>
class GraphViewer(object):
class GraphViewer(CustomIDAMemo):
"""This class wraps the user graphing facility provided by the graph.hpp file"""
def __init__(self, title, close_open = False):
"""
@@ -52,12 +52,6 @@ class GraphViewer(object):
"""
_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
@@ -166,4 +160,4 @@ class GraphViewer(object):
# """
# print "command:", cmd_id
#</pydoc>
#</pycode(py_graph)>
#</pycode(py_graph)>
+202 -182
View File
@@ -53,11 +53,23 @@ 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_ON_CREATING_GROUP[] = "OnCreatingGroup";
static const char S_ON_DELETING_GROUP[] = "OnDeletingGroup";
static const char S_ON_GROUP_VISIBILITY[] = "OnGroupVisibility";
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__";
static const char S_ON_VIEW_ACTIVATED[] = "OnViewActivated";
static const char S_ON_VIEW_DEACTIVATED[] = "OnViewDeactivated";
static const char S_ON_VIEW_KEYDOWN[] = "OnViewKeydown";
static const char S_ON_VIEW_CLICK[] = "OnViewClick";
static const char S_ON_VIEW_DBLCLICK[] = "OnViewDblclick";
static const char S_ON_VIEW_CURPOS[] = "OnViewCurpos";
static const char S_ON_VIEW_SWITCHED[] = "OnViewSwitched";
static const char S_ON_VIEW_MOUSE_OVER[] = "OnViewMouseOver";
#ifdef __PYWRAPS__
static const char S_PY_IDAAPI_MODNAME[] = "__main__";
@@ -66,7 +78,7 @@ static const char S_PY_IDAAPI_MODNAME[] = S_IDAAPI_MODNAME;
#endif
//------------------------------------------------------------------------
static PyObject *py_cvt_helper_module = NULL;
static ref_t py_cvt_helper_module;
static bool pywraps_initialized = false;
//---------------------------------------------------------------------------
@@ -155,19 +167,16 @@ static error_t idaapi idc_py_invoke0(
idc_value_t *argv,
idc_value_t *res)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *pyfunc = (PyObject *) argv[0].pvoid;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(pyfunc, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(py_result);
newref_t py_result(PyObject_CallFunctionObjArgs(pyfunc, NULL));
// Report Python error as IDC exception
qstring err;
error_t err_code = eOk;
if ( PyW_GetError(&err) )
return PyW_CreateIdcException(res, err.c_str());
return eOk;
err_code = PyW_CreateIdcException(res, err.c_str());
return err_code;
}
//------------------------------------------------------------------------
@@ -223,8 +232,11 @@ void deinit_pywraps()
return;
pywraps_initialized = false;
Py_XDECREF(py_cvt_helper_module);
py_cvt_helper_module = NULL;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_cvt_helper_module = ref_t(); // Deref.
}
// Unregister the IDC PyInvoke0 method (helper function for add_idc_hotkey())
set_idc_func_ex(S_PYINVOKE0, NULL, idc_py_invoke0_args, 0);
@@ -232,47 +244,34 @@ void deinit_pywraps()
//------------------------------------------------------------------------
// Utility function to create a class instance whose constructor takes zero arguments
PyObject *create_idaapi_class_instance0(const char *clsname)
ref_t create_idaapi_class_instance0(const char *clsname)
{
PyObject *py_cls = get_idaapi_attr(clsname);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_cls(get_idaapi_attr(clsname));
if ( py_cls == NULL )
return NULL;
return ref_t();
PYW_GIL_ENSURE;
PyObject *py_obj = PyObject_CallFunctionObjArgs(py_cls, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_cls);
ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL));
if ( PyW_GetError() || py_obj == NULL )
{
Py_XDECREF(py_obj);
Py_RETURN_NONE;
}
py_obj = ref_t();
return py_obj;
}
//------------------------------------------------------------------------
// Utility function to create linked class instances
PyObject *create_idaapi_linked_class_instance(
ref_t create_idaapi_linked_class_instance(
const char *clsname,
void *lnk)
{
PyObject *py_cls = get_idaapi_attr(clsname);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t 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);
return ref_t();
newref_t py_lnk(PyCObject_FromVoidPtr(lnk, NULL));
ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, py_lnk.o, NULL));
if ( PyW_GetError() || py_obj == NULL )
{
Py_XDECREF(py_obj);
py_obj = NULL;
}
py_obj = ref_t();
return py_obj;
}
@@ -280,10 +279,10 @@ PyObject *create_idaapi_linked_class_instance(
// 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)
ref_t get_idaapi_attr_by_id(const int class_id)
{
if ( class_id >= PY_CLSID_LAST || py_cvt_helper_module == NULL )
return NULL;
return ref_t();
// Some class names. The array is parallel with the PY_CLSID_xxx consts
static const char *class_names[]=
@@ -292,16 +291,18 @@ PyObject *get_idaapi_attr_by_id(const int class_id)
"object_t",
"PyIdc_cvt_refclass__"
};
return PyObject_GetAttrString(py_cvt_helper_module, class_names[class_id]);
PYW_GIL_CHECK_LOCKED_SCOPE();
return newref_t(PyObject_GetAttrString(py_cvt_helper_module.o, class_names[class_id]));
}
//------------------------------------------------------------------------
// Gets a class reference by name
PyObject *get_idaapi_attr(const char *attrname)
ref_t get_idaapi_attr(const char *attrname)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return py_cvt_helper_module == NULL
? NULL
: PyW_TryGetAttrString(py_cvt_helper_module, attrname);
? ref_t()
: PyW_TryGetAttrString(py_cvt_helper_module.o, attrname);
}
//------------------------------------------------------------------------
@@ -311,41 +312,39 @@ bool PyW_GetStringAttr(
const char *attr_name,
qstring *str)
{
PyObject *py_attr = PyW_TryGetAttrString(py_obj, attr_name);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_attr(PyW_TryGetAttrString(py_obj, attr_name));
if ( py_attr == NULL )
return false;
bool ok = PyString_Check(py_attr) != 0;
bool ok = PyString_Check(py_attr.o) != 0;
if ( ok )
*str = PyString_AsString(py_attr);
*str = PyString_AsString(py_attr.o);
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)
ref_t PyW_TryGetAttrString(PyObject *py_obj, const char *attr)
{
if ( !PyObject_HasAttrString(py_obj, attr) )
return NULL;
else
return PyObject_GetAttrString(py_obj, attr);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t o;
if ( PyObject_HasAttrString(py_obj, attr) )
o = newref_t(PyObject_GetAttrString(py_obj, attr));
return o;
}
//------------------------------------------------------------------------
// Tries to import a module and clears the exception on failure
PyObject *PyW_TryImportModule(const char *name)
ref_t 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t result(PyImport_ImportModule(name));
if ( result == NULL && PyErr_Occurred() )
PyErr_Clear();
return result;
}
//-------------------------------------------------------------------------
@@ -358,144 +357,158 @@ PyObject *PyW_TryImportModule(const char *name)
// 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
do
{
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
{
rc = false;
break;
}
// 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;
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
idc_var->set_long(l);
break;
}
// 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);
break;
}
PyErr_Clear();
idc_var->set_int64(PyLong_AsLongLong(py_var));
} while ( false );
return rc;
}
//-------------------------------------------------------------------------
// 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
#define SETNUM(numexpr, is64_expr) \
do \
{ \
if ( num != NULL ) \
*num = numexpr; \
if ( is_64 != NULL ) \
*is_64 = is64_expr; \
} while ( false )
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
do
{
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 )
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
{
PyErr_Clear();
ull = PyLong_AsUnsignedLongLong(py_num);
if ( !PyErr_Occurred() )
rc = false;
break;
}
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(l), false);
break;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(ul), false);
break;
}
PyErr_Clear();
// Try to parse as int64
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(ll), true);
break;
}
PyErr_Clear();
// Try to parse as uint64
unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var);
PyObject *err = PyErr_Occurred();
if ( err == NULL )
{
SETNUM(uint64(ull), true);
break;
}
// Negative number? _And_ it with uint64(-1)
rc = false;
if ( err == PyExc_TypeError )
{
newref_t py_mask(Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull));
newref_t py_num(PyNumber_And(py_var, py_mask.o));
if ( py_num != NULL && py_mask != NULL )
{
if ( num != NULL )
*num = uint64(ull);
if ( is_64 != NULL )
*is_64 = true;
ok = true;
PyErr_Clear();
ull = PyLong_AsUnsignedLongLong(py_num.o);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(ull), true);
rc = true;
}
}
}
Py_XDECREF(py_num);
Py_XDECREF(py_mask);
}
PyErr_Clear();
return ok;
PyErr_Clear();
} while ( false );
return rc;
#undef SETNUM
}
//-------------------------------------------------------------------------
// 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 )
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
do
{
PyErr_Clear();
return false;
}
return true;
if ( !PySequence_Check(obj) )
{
rc = false;
break;
}
Py_ssize_t sz = PySequence_Size(obj);
if ( sz == -1 || PyErr_Occurred() != NULL )
{
PyErr_Clear();
rc = false;
break;
}
} while ( false );
return rc;
}
//-------------------------------------------------------------------------
// 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;
}
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_str(PyObject_Str(obj));
bool ok = py_str != NULL;
if ( ok )
*out = PyString_AsString(py_str.o);
else
{
out->qclear();
return false;
}
return ok;
}
//--------------------------------------------------------------------------
@@ -503,6 +516,8 @@ bool PyW_ObjectToString(PyObject *obj, qstring *out)
// exception string
bool PyW_GetError(qstring *out, bool clear_err)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() == NULL )
return false;
@@ -523,23 +538,18 @@ bool PyW_GetError(qstring *out, bool clear_err)
PyErr_Restore(err_type, err_value, err_traceback);
// Resolve FormatExc()
PyObject *py_fmtexc = get_idaapi_attr(S_IDAAPI_FORMATEXC);
ref_t 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,
py_fmtexc.o,
err_type,
err_value,
err_traceback,
NULL);
PYW_GIL_RELEASE;
// Dispose helper reference
Py_DECREF(py_fmtexc);
}
// Clear the error
@@ -576,6 +586,8 @@ bool PyW_GetError(qstring *out, bool clear_err)
//-------------------------------------------------------------------------
bool PyW_GetError(char *buf, size_t bufsz, bool clear_err)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstring s;
if ( !PyW_GetError(&s, clear_err) )
return false;
@@ -589,6 +601,8 @@ bool PyW_GetError(char *buf, size_t bufsz, bool clear_err)
// This method is used to display errors that occurred in a callback
bool PyW_ShowCbErr(const char *cb_name)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
static qstring err_str;
if ( !PyW_GetError(&err_str) )
return false;
@@ -600,10 +614,11 @@ bool PyW_ShowCbErr(const char *cb_name)
//---------------------------------------------------------------------------
void *pyobj_get_clink(PyObject *pyobj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// 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);
ref_t attr(PyW_TryGetAttrString(pyobj, S_CLINK_NAME));
void *t = attr != NULL && PyCObject_Check(attr.o) ? PyCObject_AsVoidPtr(attr.o) : NULL;
return t;
}
@@ -624,8 +639,10 @@ def parse_command_line(cmdline):
*/
static PyObject *py_parse_command_line(const char *cmdline)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t args;
if ( parse_command_line2(cmdline, &args, NULL) == 0 )
if ( parse_command_line3(cmdline, &args, NULL, LP_PATH_WITH_ARGS) == 0 )
Py_RETURN_NONE;
PyObject *py_list = PyList_New(args.size());
@@ -727,6 +744,7 @@ static bool qstrvec_t_assign(PyObject *self, PyObject *other)
static PyObject *qstrvec_t_addressof(PyObject *self, size_t idx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t *sv = qstrvec_t_get_clink(self);
if ( sv == NULL || idx >= sv->size() )
Py_RETURN_NONE;
@@ -751,6 +769,7 @@ static bool qstrvec_t_from_list(
PyObject *self,
PyObject *py_list)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t *sv = qstrvec_t_get_clink(self);
return sv == NULL ? false : PyW_PyListToStrVec(py_list, *sv);
}
@@ -763,6 +782,7 @@ static size_t qstrvec_t_size(PyObject *self)
static PyObject *qstrvec_t_get(PyObject *self, size_t idx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t *sv = qstrvec_t_get_clink(self);
if ( sv == NULL || idx >= sv->size() )
Py_RETURN_NONE;
+85 -12
View File
@@ -18,6 +18,36 @@ import os
import sys
import bisect
import __builtin__
import imp
def require(modulename):
"""
Load, or reload a module.
When under heavy development, a user's tool might consist of multiple
modules. If those are imported using the standard 'import' mechanism,
there is no guarantee that the Python implementation will re-read
and re-evaluate the module's Python code. In fact, it usually doesn't.
What should be done instead is 'reload()'-ing that module.
This is a simple helper function that will do just that: In case the
module doesn't exist, it 'import's it, and if it does exist,
'reload()'s it.
For more information, see: <http://www.hexblog.com/?p=749>.
"""
if modulename in sys.modules.keys():
reload(sys.modules[modulename])
else:
import importlib
import inspect
m = importlib.import_module(modulename)
frame_obj, filename, line_number, function_name, lines, index = inspect.stack()[1]
importer_module = inspect.getmodule(frame_obj)
if importer_module is None: # No importer module; called from command line
importer_module = sys.modules['__main__']
setattr(importer_module, modulename, m)
sys.modules[modulename] = m
# -----------------------------------------------------------------------
@@ -403,11 +433,7 @@ def IDAPython_ExecScript(script, g):
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
@@ -421,18 +447,65 @@ def IDAPython_ExecScript(script, g):
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
# Restore state
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
# ------------------------------------------------------------
def IDAPython_LoadProcMod(script, g):
"""
Load processor module.
"""
pname = g['__name__'] if g and g.has_key("__name__") else '__main__'
parent = sys.modules[pname]
scriptpath, scriptname = os.path.split(script)
if len(scriptpath) and scriptpath not in sys.path:
sys.path.append(scriptpath)
procmod_name = os.path.splitext(scriptname)[0]
procobj = None
fp = None
try:
fp, pathname, description = imp.find_module(procmod_name)
procmod = imp.load_module(procmod_name, fp, pathname, description)
if parent:
setattr(parent, procmod_name, procmod)
# export attrs from parent to processor module
parent_attrs = getattr(parent, '__all__',
(attr for attr in dir(parent) if not attr.startswith('_')))
for pa in parent_attrs:
setattr(procmod, pa, getattr(parent, pa))
# instantiate processor object
if getattr(procmod, 'PROCESSOR_ENTRY', None):
procobj = procmod.PROCESSOR_ENTRY()
PY_COMPILE_ERR = None
except Exception as e:
PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc())
print(PY_COMPILE_ERR)
finally:
if fp: fp.close()
sys.path.remove(scriptpath)
return (PY_COMPILE_ERR, procobj)
# ------------------------------------------------------------
def IDAPython_UnLoadProcMod(script, g):
"""
Unload processor module.
"""
pname = g['__name__'] if g and g.has_key("__name__") else '__main__'
parent = sys.modules[pname]
scriptname = os.path.split(script)[1]
procmod_name = os.path.splitext(scriptname)[0]
if getattr(parent, procmod_name, None):
delattr(parent, procmod_name)
del sys.modules[procmod_name]
PY_COMPILE_ERR = None
return PY_COMPILE_ERR
# ----------------------------------------------------------------------
+75
View File
@@ -0,0 +1,75 @@
#ifndef __PY_IDA_VIEW__
#define __PY_IDA_VIEW__
//<code(py_idaview)>
class py_idaview_t : public py_customidamemo_t
{
typedef py_customidamemo_t inherited;
public:
static bool Bind(PyObject *self);
};
//-------------------------------------------------------------------------
bool py_idaview_t::Bind(PyObject *self)
{
// Already a py_idaview_t associated to this object?
py_idaview_t *_this = view_extract_this<py_idaview_t>(self);
if ( _this != NULL )
return false;
qstring title;
if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) )
return false;
// Get the IDAView associated to this TForm
TForm *tform = find_tform(title.c_str());
if ( tform == NULL )
return false;
TCustomControl *v = get_tform_idaview(tform);
if ( v == NULL )
return false;
// Get unique py_idaview_t associated to that tform
py_idaview_t *py_view;
TCustomControl *found_view;
if ( lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) )
{
// If we have a py_idaview_t for that form, ensure it has
// the expected view.
QASSERT(30451, found_view == v);
}
else
{
py_view = new py_idaview_t();
lookup_info.add(tform, v, py_view);
}
// Finally, bind:
// py_idaview_t <=> IDAViewWrapper
// py_idaview_t => TCustomControl
bool ok = py_view->bind(self, v);
if ( ok )
{
ok = py_view->collect_pyobject_callbacks(self);
if ( !ok )
delete py_view;
}
return ok;
}
//-------------------------------------------------------------------------
bool pyidag_bind(PyObject *self)
{
return py_idaview_t::Bind(self);
}
//</code(py_idaview)>
//--------------------------------------------------------------------------
//<inline(py_idaview)>
bool pyidag_bind(PyObject *self);
//</inline(py_idaview)>
#endif // __PY_IDA_VIEW__
+16
View File
@@ -0,0 +1,16 @@
#<pycode(py_idaview)>
class IDAViewWrapper(CustomIDAMemo):
"""This class wraps access to native IDA views. See kernwin.hpp file"""
def __init__(self, title):
"""
Constructs the IDAViewWrapper object around the view
whose title is 'title'.
@param title: The title of the existing IDA view. E.g., 'IDA View-A'
"""
self._title = title
def Bind(self):
return _idaapi.pyidag_bind(self)
#</pycode(py_idaview)>
+45 -21
View File
@@ -33,12 +33,17 @@ static PyObject *AssembleLine(
{
int inslen;
char buf[MAXSTR];
bool ok = false;
if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
{
return PyString_FromStringAndSize(buf, inslen);
ok = true;
}
Py_RETURN_NONE;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return PyString_FromStringAndSize(buf, inslen);
else
Py_RETURN_NONE;
}
//---------------------------------------------------------------------------
@@ -66,17 +71,20 @@ bool assemble(
{
int inslen;
char buf[MAXSTR];
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = false;
Py_BEGIN_ALLOW_THREADS;
if (ph.notify != NULL)
{
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
if (inslen > 0)
{
patch_many_bytes(ea, buf, inslen);
return true;
rc = true;
}
}
return false;
Py_END_ALLOW_THREADS;
return rc;
}
//-------------------------------------------------------------------------
@@ -318,6 +326,7 @@ def ph_get_instruc():
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start);
for ( const instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end;
p != end;
@@ -341,10 +350,10 @@ def ph_get_regnames():
static PyObject *ph_get_regnames()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
return py_result;
}
@@ -372,6 +381,10 @@ static PyObject *ph_get_operand_info(
ea_t ea,
int n)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool ok = false;
idd_opinfo_t opinf;
Py_BEGIN_ALLOW_THREADS;
do
{
if ( dbg == NULL || n == - 1 )
@@ -386,7 +399,6 @@ static PyObject *ph_get_operand_info(
break;
// Call the processor module
idd_opinfo_t opinf;
if ( ph.notify(ph.get_operand_info,
ea,
n,
@@ -397,14 +409,19 @@ static PyObject *ph_get_operand_info(
{
break;
}
return Py_BuildValue("(i" PY_FMT64 "Kii)",
opinf.modified,
opinf.ea,
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
ok = true;
} while (false);
Py_RETURN_NONE;
Py_END_ALLOW_THREADS;
if ( ok )
return Py_BuildValue("(i" PY_FMT64 "Kii)",
opinf.modified,
opinf.ea,
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
@@ -785,6 +802,7 @@ public:
bool /*use32*/,
const char * /*line*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
};
@@ -847,6 +865,8 @@ public:
//-------------------------------------------------------------------------
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
IDP_Hooks *proxy = (IDP_Hooks *)ud;
int ret = 0;
try
@@ -868,16 +888,16 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
case processor_t::custom_outop:
{
op_t *op = va_arg(va, op_t *);
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
ref_t py_obj(create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op));
if ( py_obj == NULL )
break;
ret = proxy->custom_outop(py_obj) ? 2 : 0;
Py_XDECREF(py_obj);
ret = proxy->custom_outop(py_obj.o) ? 2 : 0;
break;
}
case processor_t::custom_mnem:
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_ret = proxy->custom_mnem();
if ( py_ret != NULL && PyString_Check(py_ret) )
{
@@ -1009,6 +1029,7 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
// Extract user buffer (we hardcode the MAXSTR size limit)
uchar *bin = va_arg(va, uchar *);
// Call python
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line);
if ( py_buffer != NULL && PyString_Check(py_buffer) )
{
@@ -1328,6 +1349,7 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in IDP Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
@@ -1337,6 +1359,9 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
//---------------------------------------------------------------------------
int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
ea_t ea, ea2;
bool repeatable_cmt;
@@ -1508,10 +1533,9 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in IDB Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if (PyErr_Occurred())
{
PyErr_Print();
}
}
return 0;
}
+105 -80
View File
@@ -24,6 +24,8 @@ def register_timer(interval, callback):
*/
static PyObject *py_register_timer(int interval, PyObject *py_callback)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( py_callback == NULL || !PyCallable_Check(py_callback) )
Py_RETURN_NONE;
@@ -32,17 +34,15 @@ static PyObject *py_register_timer(int interval, PyObject *py_callback)
{
static int idaapi callback(void *ud)
{
PYW_GIL_GET;
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;
newref_t py_result(PyObject_CallFunctionObjArgs(ctx->pycallback, NULL));
int ret = py_result == NULL ? -1 : PyLong_AsLong(py_result.o);
// Timer has been unregistered?
if ( ret == -1 )
{
// Fee the context
// Free the context
Py_DECREF(ctx->pycallback);
delete ctx;
}
@@ -83,6 +83,8 @@ def unregister_timer(timer_obj):
*/
static PyObject *py_unregister_timer(PyObject *py_timerctx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( py_timerctx == NULL || !PyCObject_Check(py_timerctx) )
Py_RETURN_FALSE;
@@ -111,6 +113,7 @@ def choose_idasgn():
static PyObject *py_choose_idasgn()
{
char *name = choose_idasgn();
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( name == NULL )
{
Py_RETURN_NONE;
@@ -140,6 +143,7 @@ static PyObject *py_get_highlighted_identifier(int flags = 0)
{
char buf[MAXSTR];
bool ok = get_highlighted_identifier(buf, sizeof(buf), flags);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !ok )
Py_RETURN_NONE;
else
@@ -157,6 +161,7 @@ static int py_load_custom_icon_data(PyObject *data, const char *format)
{
Py_ssize_t len;
char *s;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_AsStringAndSize(data, &s, &len) == -1 )
return 0;
else
@@ -191,6 +196,7 @@ def asktext(max_text, defval, prompt):
*/
PyObject *py_asktext(int max_text, const char *defval, const char *prompt)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( max_text <= 0 )
Py_RETURN_NONE;
@@ -231,6 +237,26 @@ ea_t py_str2ea(const char *str, ea_t screenEA = BADADDR)
return ok ? ea : BADADDR;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def str2user(str):
"""
Insert C-style escape characters to string
@return: new string with escape characters inserted
"""
pass
#</pydoc>
*/
PyObject *py_str2user(const char *str)
{
qstring qstr(str);
qstring retstr;
qstr2user(&retstr, qstr);
return PyString_FromString(retstr.c_str());
}
//------------------------------------------------------------------------
/*
#<pydoc>
@@ -265,6 +291,7 @@ def del_menu_item(menu_ctx):
*/
static bool py_del_menu_item(PyObject *py_ctx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_ctx) )
return false;
@@ -297,6 +324,7 @@ def del_hotkey(ctx):
*/
bool py_del_hotkey(PyObject *pyctx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(pyctx) )
return false;
@@ -327,6 +355,7 @@ def add_hotkey(hotkey, pyfunc):
*/
PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Make sure a callable was passed
if ( !PyCallable_Check(pyfunc) )
return NULL;
@@ -414,6 +443,7 @@ static PyObject *py_add_menu_item(
PyObject *pyfunc,
PyObject *args)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool no_args;
// No slash in the menu path?
@@ -512,55 +542,55 @@ def execute_sync(callable, reqf):
//------------------------------------------------------------------------
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
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc = -1;
// Callable?
if ( PyCallable_Check(py_callable) )
{
PyObject *py_callable;
bool no_wait;
virtual int idaapi execute()
struct py_exec_request_t : exec_request_t
{
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;
ref_t py_callable;
virtual int idaapi execute()
{
PYW_GIL_GET;
newref_t py_result(PyObject_CallFunctionObjArgs(py_callable.o, NULL));
int ret = py_result == NULL || !PyInt_Check(py_result.o)
? -1
: PyInt_AsLong(py_result.o);
// if the requesting thread decided not to wait for the request to
// complete, we have to self-destroy, nobody else will do it
if ( (code & MFF_NOWAIT) != 0 )
delete this;
return ret;
}
py_exec_request_t(PyObject *pyc)
{
// No need to GIL-ensure here, since this is created
// within the py_execute_sync() scope.
py_callable = borref_t(pyc);
}
virtual ~py_exec_request_t()
{
// Need to GIL-ensure here, since this might be called
// from the main thread.
PYW_GIL_GET;
py_callable = ref_t(); // Release callable
}
};
py_exec_request_t *req = new py_exec_request_t(py_callable);
// 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;
// Release GIL before executing, or if this is running in the
// non-main thread, this will wait on the req.sem, while the main
// thread might be waiting for the GIL to be available.
Py_BEGIN_ALLOW_THREADS;
rc = execute_sync(*req, reqf);
Py_END_ALLOW_THREADS;
// destroy the request once it is finished. exception: NOWAIT requests
// will be handled in the future, so do not destroy them yet!
if ( (reqf & MFF_NOWAIT) == 0 )
delete req;
}
return rc;
}
//------------------------------------------------------------------------
@@ -585,23 +615,22 @@ static bool py_execute_ui_requests(PyObject *py_list)
struct py_ui_request_t: public ui_request_t
{
private:
ppyobject_vec_t py_callables;
ref_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)
const ref_t &py_item,
Py_ssize_t index,
void *ud)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Not callable? Terminate iteration
if ( !PyCallable_Check(py_item) )
if ( !PyCallable_Check(py_item.o) )
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:
@@ -611,14 +640,13 @@ static bool py_execute_ui_requests(PyObject *py_list)
virtual bool idaapi run()
{
// Get callable
PyObject *py_callable = py_callables.at(py_callable_idx);
PYW_GIL_GET;
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;
// Get callable
ref_t py_callable = py_callables.at(py_callable_idx);
bool reschedule;
newref_t py_result(PyObject_CallFunctionObjArgs(py_callable.o, NULL));
reschedule = py_result != NULL && PyObject_IsTrue(py_result.o);
// No rescheduling? Then advance to the next callable
if ( !reschedule )
@@ -640,13 +668,7 @@ static bool py_execute_ui_requests(PyObject *py_list)
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_callables.clear();
}
};
@@ -809,6 +831,7 @@ public:
virtual PyObject *get_ea_hint(ea_t /*ea*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
};
};
@@ -821,6 +844,8 @@ public:
//---------------------------------------------------------------------------
int idaapi UI_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
UI_Hooks *proxy = (UI_Hooks *)ud;
int ret = 0;
try
@@ -857,6 +882,7 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
char *_buf;
Py_ssize_t _len;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_str = proxy->get_ea_hint(ea);
if ( py_str != NULL
&& PyString_Check(py_str)
@@ -872,6 +898,7 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in UI Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
@@ -881,15 +908,15 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
//------------------------------------------------------------------------
bool idaapi py_menu_item_callback(void *userdata)
{
PYW_GIL_GET;
// 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;
newref_t result(PyEval_CallObject(func, args));
// We cannot raise an exception in the callback, just print it.
if ( result == NULL )
@@ -898,10 +925,8 @@ bool idaapi py_menu_item_callback(void *userdata)
return false;
}
bool ret = PyObject_IsTrue(result) != 0;
Py_DECREF(result);
return ret;
return PyObject_IsTrue(result.o) != 0;
}
//</code(py_kernwin)>
#endif
#endif
+14 -11
View File
@@ -12,10 +12,12 @@ static void idaapi s_py_get_user_defined_prefix(
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);
PYW_GIL_GET;
newref_t 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
@@ -23,14 +25,13 @@ static void idaapi s_py_get_user_defined_prefix(
{
Py_ssize_t py_len;
char *py_str;
if ( PyString_AsStringAndSize(py_ret, &py_str, &py_len) != -1 )
if ( PyString_AsStringAndSize(py_ret.o, &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)>
@@ -65,6 +66,7 @@ def set_user_defined_prefix(width, callback):
*/
static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( width == 0 || pycb == Py_None )
{
// Release old callback reference
@@ -110,6 +112,7 @@ def tag_remove(colstr):
*/
PyObject *py_tag_remove(const char *instr)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
size_t sz = strlen(instr);
char *buf = new char[sz + 5];
if ( buf == NULL )
@@ -135,6 +138,7 @@ PyObject *py_tag_addr(ea_t ea)
{
char buf[100];
tag_addr(buf, buf + sizeof(buf), ea);
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(buf);
}
@@ -180,6 +184,7 @@ PyObject *py_generate_disassembly(
bool as_stack,
bool notags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( max_lines <= 0 )
Py_RETURN_NONE;
@@ -188,7 +193,7 @@ PyObject *py_generate_disassembly(
int lnnum;
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
PyObject *py_tuple = PyTuple_New(nlines);
newref_t py_tuple(PyTuple_New(nlines));
for ( int i=0; i<nlines; i++ )
{
const char *s = lines[i];
@@ -199,13 +204,11 @@ PyObject *py_generate_disassembly(
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0];
}
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
PyTuple_SetItem(py_tuple.o, 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;
return Py_BuildValue("(iO)", lnnum, py_tuple.o);
}
//</inline(py_lines)>
#endif
+87 -31
View File
@@ -110,6 +110,7 @@ private:
//--------------------------------------------------------------------------
void _from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
this->set_linput((linput_t *)PyCObject_AsVoidPtr(pycobject));
}
@@ -133,6 +134,7 @@ public:
//--------------------------------------------------------------------------
loader_input_t(PyObject *pycobject = NULL): li(NULL), own(OWN_NONE), __idc_cvt_id__(PY_ICID_OPAQUE)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( pycobject != NULL && PyCObject_Check(pycobject) )
_from_cobject(pycobject);
}
@@ -143,11 +145,13 @@ public:
if ( li == NULL )
return;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
if ( own == OWN_CREATE )
close_linput(li);
else if ( own == OWN_FROM_FP )
unmake_linput(li);
Py_END_ALLOW_THREADS;
li = NULL;
own = OWN_NONE;
}
@@ -162,14 +166,17 @@ public:
bool open(const char *filename, bool remote = false)
{
close();
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
li = open_linput(filename, remote);
if ( li == NULL )
return false;
// Save file name
fn = filename;
own = OWN_CREATE;
return true;
if ( li != NULL )
{
// Save file name
fn = filename;
own = OWN_CREATE;
}
Py_END_ALLOW_THREADS;
return li != NULL;
}
//--------------------------------------------------------------------------
@@ -193,6 +200,7 @@ public:
// This method can be used to pass a linput_t* from C code
static loader_input_t *from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(pycobject) )
return NULL;
loader_input_t *l = new loader_input_t();
@@ -203,14 +211,18 @@ public:
//--------------------------------------------------------------------------
static loader_input_t *from_fp(FILE *fp)
{
PYW_GIL_GET;
loader_input_t *l = NULL;
Py_BEGIN_ALLOW_THREADS;
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;
if ( fp_li != NULL )
{
l = new loader_input_t();
l->own = OWN_FROM_FP;
l->fn.sprnt("<FILE * %p>", fp);
l->li = fp_li;
}
Py_END_ALLOW_THREADS;
return l;
}
@@ -223,37 +235,55 @@ public:
//--------------------------------------------------------------------------
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;
PYW_GIL_GET;
linput_t *l;
Py_BEGIN_ALLOW_THREADS;
l = create_memory_linput(start, size);
if ( l != NULL )
{
close();
li = l;
fn = "<memory>";
own = OWN_CREATE;
}
Py_END_ALLOW_THREADS;
return l != NULL;
}
//--------------------------------------------------------------------------
int32 seek(int32 pos, int whence = SEEK_SET)
{
return qlseek(li, pos, whence);
int32 r;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
r = qlseek(li, pos, whence);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
int32 tell()
{
return qltell(li);
int32 r;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
r = qltell(li);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
PyObject *getz(size_t sz, int32 fpos = -1)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(sz + 5);
if ( buf == NULL )
break;
Py_BEGIN_ALLOW_THREADS;
qlgetz(li, fpos, buf, sz);
Py_END_ALLOW_THREADS;
PyObject *ret = PyString_FromString(buf);
free(buf);
return ret;
@@ -264,12 +294,17 @@ public:
//--------------------------------------------------------------------------
PyObject *gets(size_t len)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(len + 5);
if ( buf == NULL )
break;
if ( qlgets(buf, len, li) == NULL )
bool ok;
Py_BEGIN_ALLOW_THREADS;
ok = qlgets(buf, len, li) != NULL;
Py_END_ALLOW_THREADS;
if ( !ok )
{
free(buf);
break;
@@ -284,12 +319,16 @@ public:
//--------------------------------------------------------------------------
PyObject *read(size_t size)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
ssize_t r = qlread(li, buf, size);
ssize_t r;
Py_BEGIN_ALLOW_THREADS;
r = qlread(li, buf, size);
Py_END_ALLOW_THREADS;
if ( r == -1 )
{
free(buf);
@@ -311,12 +350,16 @@ public:
//--------------------------------------------------------------------------
PyObject *readbytes(size_t size, bool big_endian)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = lreadbytes(li, buf, size, big_endian);
int r;
Py_BEGIN_ALLOW_THREADS;
r = lreadbytes(li, buf, size, big_endian);
Py_END_ALLOW_THREADS;
if ( r == -1 )
{
free(buf);
@@ -332,25 +375,38 @@ public:
//--------------------------------------------------------------------------
int file2base(int32 pos, ea_t ea1, ea_t ea2, int patchable)
{
return ::file2base(li, pos, ea1, ea2, patchable);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = ::file2base(li, pos, ea1, ea2, patchable);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 size()
{
return qlsize(li);
int32 rc;
Py_BEGIN_ALLOW_THREADS;
rc = qlsize(li);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
PyObject *filename()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qlgetc(li);
PYW_GIL_CHECK_LOCKED_SCOPE();
int ch;
Py_BEGIN_ALLOW_THREADS;
ch = qlgetc(li);
Py_END_ALLOW_THREADS;
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
+17 -3
View File
@@ -25,8 +25,11 @@ 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;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
return 0;
}
return mem2base((void *)buf, ea, ea+len, fpos);
}
@@ -47,6 +50,7 @@ def load_plugin(name):
static PyObject *py_load_plugin(const char *name)
{
plugin_t *r = load_plugin(name);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( r == NULL )
Py_RETURN_NONE;
else
@@ -67,10 +71,20 @@ def run_plugin(plg):
*/
static bool py_run_plugin(PyObject *plg, int arg)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(plg) )
{
return false;
}
else
return run_plugin((plugin_t *)PyCObject_AsVoidPtr(plg), arg);
{
plugin_t *p = (plugin_t *)PyCObject_AsVoidPtr(plg);
bool rc;
Py_BEGIN_ALLOW_THREADS;
rc = run_plugin(p, arg);
Py_END_ALLOW_THREADS;
return rc;
}
}
//</inline(py_loader)>
+55 -43
View File
@@ -21,53 +21,35 @@ static int idaapi py_import_enum_cb(
if ( name == NULL )
name = get_true_name(BADADDR, ea, name_buf, sizeof(name_buf));
PyObject *py_name;
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_name;
if ( name == NULL )
{
py_name = Py_None;
Py_INCREF(Py_None);
}
py_name = borref_t(Py_None);
else
{
py_name = PyString_FromString(name);
}
py_name = newref_t(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;
newref_t py_ord(Py_BuildValue(PY_FMT64, pyul_t(ord)));
newref_t py_ea(Py_BuildValue(PY_FMT64, pyul_t(ea)));
newref_t py_result(
PyObject_CallFunctionObjArgs(
(PyObject *)param,
py_ea.o,
py_name.o,
py_ord.o,
NULL));
return py_result != NULL && PyObject_IsTrue(py_result.o) ? 1 : 0;
}
//-------------------------------------------------------------------------
switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
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;
newref_t attr(PyObject_GetAttrString(self, S_CLINK_NAME));
return PyCObject_Check(attr.o) ? ((switch_info_ex_t *) PyCObject_AsVoidPtr(attr.o)) : NULL;
}
//</code(py_nalt)>
@@ -86,10 +68,11 @@ def get_import_module_name(path, fname, callback):
*/
static PyObject *py_get_import_module_name(int mod_index)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
char buf[MAXSTR];
if ( !get_import_module_name(mod_index, buf, sizeof(buf)) )
Py_RETURN_NONE;
return PyString_FromString(buf);
}
@@ -108,14 +91,16 @@ def get_switch_info_ex(ea):
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
ref_t py_obj;
PYW_GIL_CHECK_LOCKED_SCOPE();
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;
py_obj.incref();
return py_obj.o;
}
//-------------------------------------------------------------------------
@@ -129,7 +114,7 @@ def create_switch_xrefs(insn_ea, si):
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
@@ -157,7 +142,7 @@ idaman bool ida_export py_create_switch_xrefs(
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
@@ -173,7 +158,7 @@ idaman bool ida_export py_create_switch_table(
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;
}
@@ -232,9 +217,9 @@ def enum_import_names(mod_index, callback):
*/
static int py_enum_import_names(int mod_index, PyObject *py_cb)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_cb) )
return -1;
return enum_import_names(mod_index, py_import_enum_cb, py_cb);
}
@@ -242,12 +227,14 @@ static int py_enum_import_names(int mod_index, PyObject *py_cb)
static PyObject *switch_info_ex_t_create()
{
switch_info_ex_t *inst = new switch_info_ex_t();
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(inst, NULL);
}
//---------------------------------------------------------------------------
static bool switch_info_ex_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
switch_info_ex_t *inst = (switch_info_ex_t *) PyCObject_AsVoidPtr(py_obj);
@@ -273,6 +260,7 @@ static bool switch_info_ex_t_assign(PyObject *self, PyObject *other)
static PyObject *switch_info_ex_t_get_regdtyp(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("b", (char)link->regdtyp);
@@ -282,12 +270,14 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->flags2);
@@ -297,12 +287,14 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->jcases);
@@ -312,12 +304,14 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", (int)link->regnum);
@@ -327,12 +321,14 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (ushort)link->flags);
@@ -342,12 +338,14 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (uint16)link->ncases);
@@ -357,12 +355,14 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->defjump);
@@ -372,6 +372,7 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 v(0); PyW_GetNumber(value, &v);
link->defjump = (pyul_t)v;
}
@@ -388,6 +389,7 @@ 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;
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 v(0); PyW_GetNumber(value, &v);
link->jumps = (pyul_t)v;
}
@@ -395,6 +397,7 @@ static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_elbase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->elbase);
@@ -405,6 +408,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->elbase = (pyul_t)v;
}
@@ -412,6 +416,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_startea(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->startea);
@@ -422,6 +427,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->startea = (pyul_t)v;
}
@@ -429,6 +435,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_custom(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->custom);
@@ -439,6 +446,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->custom = (pyul_t)v;
}
@@ -446,6 +454,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_ind_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->ind_lowcase);
@@ -456,6 +465,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->ind_lowcase = (pyul_t)v;
}
@@ -463,6 +473,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_values_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->values);
@@ -473,6 +484,7 @@ static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->values = (pyul_t)v;
}
+10 -7
View File
@@ -5,16 +5,19 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
{
// Get debug names
ea_name_vec_t names;
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_BEGIN_ALLOW_THREADS;
get_debug_names(ea1, ea2, names);
Py_END_ALLOW_THREADS;
PyObject *dict = Py_BuildValue("{}");
if (dict == NULL)
return NULL;
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
if (dict != NULL)
{
PyDict_SetItem(dict,
Py_BuildValue(PY_FMT64, it->ea),
PyString_FromString(it->name.c_str()));
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;
}
+48 -45
View File
@@ -8,7 +8,7 @@
//------------------------------------------------------------------------
class pywraps_notify_when_t
{
ppyobject_vec_t table[NW_EVENTSCNT];
ref_vec_t table[NW_EVENTSCNT];
qstring err;
bool in_notify;
struct notify_when_args_t
@@ -22,6 +22,8 @@ class pywraps_notify_when_t
//------------------------------------------------------------------------
static int idaapi idp_callback(void *ud, int event_id, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud;
switch ( event_id )
{
@@ -60,32 +62,29 @@ class pywraps_notify_when_t
//------------------------------------------------------------------------
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);
borref_t callable_ref(py_callable);
ref_vec_t &tbl = table[slot];
ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref);
// Already added
if ( it != it_end )
return;
// Increment reference
Py_INCREF(py_callable);
// Insert the element
tbl.push_back(py_callable);
tbl.push_back(callable_ref);
}
//------------------------------------------------------------------------
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);
borref_t callable_ref(py_callable);
ref_vec_t &tbl = table[slot];
ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref);
// Not found?
if ( it == it_end )
return;
// Decrement reference
Py_DECREF(py_callable);
// Delete the element
tbl.erase(it);
}
@@ -101,11 +100,11 @@ public:
bool deinit()
{
// Uninstall all objects
ppyobject_vec_t::iterator it, it_end;
ref_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);
unregister_callback(slot, it->o);
}
// ...and remove the notification
return unhook_from_notification_point(HT_IDP, idp_callback, this);
@@ -154,6 +153,8 @@ public:
//------------------------------------------------------------------------
bool notify_va(int slot, va_list va)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Sanity bounds check!
if ( slot < 0 || slot >= NW_EVENTSCNT )
return false;
@@ -161,42 +162,38 @@ public:
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 )
for (ref_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end();
it != it_end;
++it)
{
case NW_CLOSEIDB_SLOT:
case NW_INITIDA_SLOT:
case NW_TERMIDA_SLOT:
// Form the notification code
newref_t py_code(PyInt_FromLong(1 << slot));
ref_t py_result;
switch ( slot )
{
PYW_GIL_ENSURE;
py_result = PyObject_CallFunctionObjArgs(*it, py_code, NULL);
PYW_GIL_RELEASE;
break;
case NW_CLOSEIDB_SLOT:
case NW_INITIDA_SLOT:
case NW_TERMIDA_SLOT:
{
py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, NULL));
break;
}
case NW_OPENIDB_SLOT:
{
newref_t py_old(PyInt_FromLong(old));
py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, py_old.o, NULL));
}
break;
}
case NW_OPENIDB_SLOT:
if ( PyW_GetError(&err) || py_result == NULL )
{
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);
PyErr_Clear();
warning("notify_when(): Error occured while notifying object.\n%s", err.c_str());
ok = false;
}
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;
@@ -211,6 +208,7 @@ public:
}
delayed_notify_when_list.qclear();
}
return ok;
}
@@ -247,6 +245,10 @@ bool pywraps_nw_notify(int slot, ...)
if ( g_nw == NULL )
return false;
// Appears to be called from 'driver_notifywhen.cpp', which
// itself is called from possibly non-python code.
// I.e., we must acquire the GIL.
PYW_GIL_GET;
va_list va;
va_start(va, slot);
bool ok = g_nw->notify_va(slot, va);
@@ -261,11 +263,11 @@ 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;
@@ -296,6 +298,7 @@ def notify_when(when, callback):
*/
static bool notify_when(int when, PyObject *py_callable)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( g_nw == NULL || !PyCallable_Check(py_callable) )
return false;
return g_nw->notify_when(when, py_callable);
+24 -25
View File
@@ -6,11 +6,14 @@
class plgform_t
{
private:
PyObject *py_obj;
ref_t py_obj;
TForm *form;
static int idaapi s_callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
plgform_t *_this = (plgform_t *)ud;
if ( notification_code == ui_tform_visible )
{
@@ -21,15 +24,12 @@ private:
// 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;
newref_t py_result(
PyObject_CallMethod(
_this->py_obj.o,
(char *)S_ON_CREATE, "O",
PyCObject_FromVoidPtr(form, NULL)));
PyW_ShowCbErr(S_ON_CREATE);
Py_XDECREF(py_result);
}
}
else if ( notification_code == ui_tform_invisible )
@@ -37,16 +37,14 @@ private:
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);
{
newref_t py_result(
PyObject_CallMethod(
_this->py_obj.o,
(char *)S_ON_CLOSE, "O",
PyCObject_FromVoidPtr(form, NULL)));
PyW_ShowCbErr(S_ON_CLOSE);
}
_this->unhook();
}
}
@@ -59,11 +57,12 @@ private:
form = NULL;
// Call DECREF at last, since it may trigger __del__
Py_XDECREF(py_obj);
PYW_GIL_CHECK_LOCKED_SCOPE();
py_obj = ref_t();
}
public:
plgform_t(): py_obj(NULL), form(NULL)
plgform_t(): form(NULL)
{
}
@@ -98,8 +97,7 @@ public:
return false;
}
py_obj = obj;
Py_INCREF(obj);
py_obj = borref_t(obj);
if ( is_idaq() )
options |= FORM_QWIDGET;
@@ -117,6 +115,7 @@ public:
static PyObject *create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new plgform_t(), destroy);
}
@@ -129,7 +128,7 @@ public:
//<inline(py_plgform)>
//---------------------------------------------------------------------------
#define DECL_PLGFORM plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link);
#define DECL_PLGFORM PYW_GIL_CHECK_LOCKED_SCOPE(); plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link);
static PyObject *plgform_new()
{
return plgform_t::create();
@@ -155,4 +154,4 @@ static void plgform_close(
#undef DECL_PLGFORM
//</inline(py_plgform)>
#endif // __PY_PLGFORM__
#endif // __PY_PLGFORM__
+15 -2
View File
@@ -59,6 +59,19 @@ class PluginForm(object):
@param ctx: Context. Reference to a module that already imported QtGui module
"""
if form is None:
return None
if type(form).__name__ == "SwigPyObject":
# Since 'form' is a SwigPyObject, we first need to convert it to a PyCObject.
# However, there's no easy way of doing it, so we'll use a rather brutal approach:
# converting the SwigPyObject to a 'long' (will go through 'SwigPyObject_long',
# that will return the pointer's value as a long), and then convert that value
# back to a pointer into a PyCObject.
ptr_l = long(form)
from ctypes import pythonapi, c_void_p, py_object
pythonapi.PyCObject_FromVoidPtr.restype = py_object
pythonapi.PyCObject_AsVoidPtr.argtypes = [c_void_p, c_void_p]
form = pythonapi.PyCObject_FromVoidPtr(ptr_l, 0)
return ctx.QtGui.QWidget.FromCObject(form)
@@ -89,7 +102,7 @@ class PluginForm(object):
@return: None
"""
return _idaapi.plgform_close(self.__clink__)
return _idaapi.plgform_close(self.__clink__, options)
FORM_SAVE = 0x1
"""Save state in desktop config"""
@@ -105,4 +118,4 @@ class PluginForm(object):
#</pycode(py_plgform)>
plg = PluginForm()
plg.Show("This is it")
plg.Show("This is it")
+96 -16
View File
@@ -102,6 +102,7 @@ private:
}
inline void _from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
_from_fp((FILE *)PyCObject_AsVoidPtr(pycobject));
}
public:
@@ -119,7 +120,12 @@ public:
own = true;
fn.qclear();
__idc_cvt_id__ = PY_ICID_OPAQUE;
if ( pycobject != NULL && PyCObject_Check(pycobject) )
bool ok;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
ok = pycobject != NULL && PyCObject_Check(pycobject);
}
if ( ok )
_from_cobject(pycobject);
}
@@ -135,7 +141,11 @@ public:
if ( fp == NULL )
return;
if ( own )
{
Py_BEGIN_ALLOW_THREADS;
qfclose(fp);
Py_END_ALLOW_THREADS;
}
fp = NULL;
own = true;
}
@@ -150,7 +160,9 @@ public:
bool open(const char *filename, const char *mode)
{
close();
Py_BEGIN_ALLOW_THREADS;
fp = qfopen(filename, mode);
Py_END_ALLOW_THREADS;
if ( fp == NULL )
return false;
// Save file name
@@ -181,7 +193,11 @@ public:
//--------------------------------------------------------------------------
static qfile_t *tmpfile()
{
return from_fp(qtmpfile());
FILE *fp;
Py_BEGIN_ALLOW_THREADS;
fp = qtmpfile();
Py_END_ALLOW_THREADS;
return from_fp(fp);
}
//--------------------------------------------------------------------------
@@ -193,13 +209,21 @@ public:
//--------------------------------------------------------------------------
int seek(int32 offset, int whence = SEEK_SET)
{
return qfseek(fp, offset, whence);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfseek(fp, offset, whence);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 tell()
{
return qftell(fp);
int32 rc;
Py_BEGIN_ALLOW_THREADS;
rc = qftell(fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
@@ -210,12 +234,17 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = freadbytes(fp, buf, size, big_endian);
PYW_GIL_CHECK_LOCKED_SCOPE();
int r;
Py_BEGIN_ALLOW_THREADS;
r = freadbytes(fp, buf, size, big_endian);
Py_END_ALLOW_THREADS;
if ( r != 0 )
{
free(buf);
break;
}
PyObject *ret = PyString_FromStringAndSize(buf, r);
free(buf);
return ret;
@@ -231,7 +260,11 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = qfread(fp, buf, size);
PYW_GIL_CHECK_LOCKED_SCOPE();
int r;
Py_BEGIN_ALLOW_THREADS;
r = qfread(fp, buf, size);
Py_END_ALLOW_THREADS;
if ( r <= 0 )
{
free(buf);
@@ -252,7 +285,12 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
if ( qfgets(buf, size, fp) == NULL )
PYW_GIL_CHECK_LOCKED_SCOPE();
char *p;
Py_BEGIN_ALLOW_THREADS;
p = qfgets(buf, size, fp);
Py_END_ALLOW_THREADS;
if ( p == NULL )
{
free(buf);
break;
@@ -267,50 +305,87 @@ public:
//--------------------------------------------------------------------------
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);
Py_ssize_t sz;
void *buf;
PYW_GIL_CHECK_LOCKED_SCOPE();
sz = PyString_GET_SIZE(py_buf);
buf = (void *)PyString_AS_STRING(py_buf);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = fwritebytes(fp, buf, int(sz), big_endian);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int write(PyObject *py_buf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_buf) )
return 0;
return qfwrite(fp, (void *)PyString_AS_STRING(py_buf), PyString_GET_SIZE(py_buf));
// Just so that there is no risk that the buffer returned by
// 'PyString_AS_STRING' gets deallocated within the
// Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_buf_ref(py_buf);
void *p = (void *)PyString_AS_STRING(py_buf);
Py_ssize_t sz = PyString_GET_SIZE(py_buf);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfwrite(fp, p, sz);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int puts(const char *str)
{
return qfputs(str, fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfputs(str, fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 size()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
int32 r;
Py_BEGIN_ALLOW_THREADS;
int pos = qfseek(fp, 0, SEEK_END);
int32 r = qftell(fp);
r = qftell(fp);
qfseek(fp, pos, SEEK_SET);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
int flush()
{
return qflush(fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qflush(fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
PyObject *filename()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qfgetc(fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int ch;
Py_BEGIN_ALLOW_THREADS;
ch = qfgetc(fp);
Py_END_ALLOW_THREADS;
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
@@ -319,7 +394,12 @@ public:
//--------------------------------------------------------------------------
int put_char(char chr)
{
return qfputc(chr, fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfputc(chr, fp);
Py_END_ALLOW_THREADS;
return rc;
}
};
//</inline(py_qfile)>
+284 -54
View File
@@ -5,22 +5,26 @@
//-------------------------------------------------------------------------
PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
{
qtype fields, type;
tinfo_t tif;
qstring name;
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
if ( !ok )
Py_RETURN_NONE;
qtype fields, type;
bool ok = parse_decl2(ti, decl, &name, &tif, flags);
if ( ok )
ok = tif.serialize(&type, &fields, NULL, SUDT_FAST);
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_type_size0(ti, tp):
def calc_type_size(ti, tp):
"""
Returns the size of a type
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@@ -32,25 +36,69 @@ def get_type_size0(ti, tp):
pass
#</pydoc>
*/
PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
PyObject *py_calc_type_size(const til_t *ti, PyObject *tp)
{
if ( !PyString_Check(tp) )
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_Check(tp) )
{
// To avoid release of 'data' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t tpref(tp);
const type_t *data = (type_t *)PyString_AsString(tp);
size_t sz;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
tif.deserialize(ti, &data, NULL, NULL);
sz = tif.get_size();
Py_END_ALLOW_THREADS;
if ( sz != BADSIZE )
return PyInt_FromLong(sz);
Py_RETURN_NONE;
}
else
{
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):
def apply_type(ti, ea, tp_name, py_type, py_fields, flags)
"""
Apply the specified type to the address
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param py_type: type string
@param py_fields: type fields
@param ea: the address of the object
@param flags: combination of TINFO_... constants or 0
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_t ea, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
const type_t *type = (const type_t *) PyString_AsString(py_type);
const p_list *fields = (const p_list *) PyString_AsString(py_fields);
bool rc;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
rc = tif.deserialize(ti, &type, &fields, NULL) && apply_tinfo2(ea, tif, flags);
Py_END_ALLOW_THREADS;
return rc;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def print_type(ea, one_line):
"""
Returns the type of an item
@return:
@@ -62,14 +110,13 @@ def print_type(ea, on_line):
*/
static PyObject *py_print_type(ea_t ea, bool one_line)
{
char buf[MAXSTR];
if ( print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI) )
{
qstrncat(buf, ";", sizeof(buf));
char buf[64*MAXSTR];
int flags = PRTYPE_SEMI | (one_line ? PRTYPE_1LINE : PRTYPE_MULTI);
bool ok = print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return PyString_FromString(buf);
}
else
Py_RETURN_NONE;
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
@@ -90,17 +137,24 @@ PyObject *py_unpack_object_from_idb(
ea_t ea,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// 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(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = unpack_object_from_idb(
&idc_obj,
ti,
type,
@@ -108,22 +162,21 @@ PyObject *py_unpack_object_from_idb(
ea,
NULL,
pio_flags);
Py_END_ALLOW_THREADS;
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
ref_t py_ret;
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;
else
return Py_BuildValue("(iO)", 1, py_ret.o);
}
//-------------------------------------------------------------------------
@@ -152,12 +205,17 @@ PyObject *py_unpack_object_from_bv(
PyObject *py_bytes,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) && !PyString_Check(py_bytes) )
{
PyErr_SetString(PyExc_ValueError, "Incorrect argument type!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
@@ -168,29 +226,30 @@ PyObject *py_unpack_object_from_bv(
memcpy(bytes.begin(), PyString_AsString(py_bytes), bytes.size());
idc_value_t idc_obj;
error_t err = unpack_object_from_bv(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = unpack_object_from_bv(
&idc_obj,
ti,
type,
fields,
bytes,
pio_flags);
Py_END_ALLOW_THREADS;
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
ref_t py_ret;
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;
return Py_BuildValue("(iO)", 1, py_ret.o);
}
//-------------------------------------------------------------------------
@@ -218,6 +277,7 @@ PyObject *py_pack_object_to_idb(
ea_t ea,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
@@ -226,15 +286,24 @@ PyObject *py_pack_object_to_idb(
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
borref_t py_obj_ref(py_obj);
if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) )
return NULL;
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
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);
// error_t err;
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags);
Py_END_ALLOW_THREADS;
return PyInt_FromLong(err);
}
@@ -265,6 +334,7 @@ PyObject *py_pack_object_to_bv(
ea_t base_ea,
int pio_flags=0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
@@ -273,16 +343,23 @@ PyObject *py_pack_object_to_bv(
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
borref_t py_obj_ref(py_obj);
if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) )
return NULL;
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
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(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = pack_object_to_bv(
&idc_obj,
ti,
type,
@@ -290,19 +367,172 @@ PyObject *py_pack_object_to_bv(
&bytes,
NULL,
pio_flags);
do
{
if ( err != eOk )
break;
if ( !bytes.relocate(base_ea, inf.mf) )
{
if ( err == eOk && !bytes.relocate(base_ea, inf.mf) )
err = -1;
break;
}
Py_END_ALLOW_THREADS;
if ( err == eOk )
return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size());
} while ( false );
return Py_BuildValue("(ii)", 0, err);
else
return Py_BuildValue("(ii)", 0, err);
}
//-------------------------------------------------------------------------
/* Parse types from a string or file. See ParseTypes() in idc.py */
int idc_parse_types(const char *input, int flags)
{
int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT;
if ((flags & 1) != 0)
hti |= HTI_FIL;
return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti);
}
//-------------------------------------------------------------------------
PyObject *py_idc_get_type_raw(ea_t ea)
{
qtype type, fields;
bool ok = get_tinfo(ea, &type, &fields);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str());
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
PyObject *py_idc_get_local_type_raw(int ordinal)
{
const type_t *type;
const p_list *fields;
bool ok = get_numbered_type(idati, ordinal, &type, &fields);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(ss)", (char *)type, (char *)fields);
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
char *idc_guess_type(ea_t ea, char *buf, size_t bufsize)
{
tinfo_t tif;
if ( guess_tinfo2(ea, &tif) )
{
qstring out;
if ( tif.print(&out) )
return qstrncpy(buf, out.begin(), bufsize);
}
return NULL;
}
//-------------------------------------------------------------------------
char *idc_get_type(ea_t ea, char *buf, size_t bufsize)
{
tinfo_t tif;
if ( get_tinfo2(ea, &tif) )
{
qstring out;
if ( tif.print(&out) )
{
qstrncpy(buf, out.c_str(), bufsize);
return buf;
}
}
return NULL;
}
//-------------------------------------------------------------------------
int idc_set_local_type(int ordinal, const char *dcl, int flags)
{
if (dcl == NULL || dcl[0] == '\0')
{
if ( !del_numbered_type(idati, ordinal) )
return 0;
}
else
{
tinfo_t tif;
qstring name;
if ( !parse_decl2(idati, dcl, &name, &tif, flags) )
return 0;
if ( ordinal <= 0 )
{
if ( !name.empty() )
ordinal = get_type_ordinal(idati, name.begin());
if ( ordinal <= 0 )
ordinal = alloc_type_ordinal(idati);
}
if ( tif.set_numbered_type(idati, ordinal, 0, name.c_str()) != TERR_OK )
return 0;
}
return ordinal;
}
//-------------------------------------------------------------------------
int idc_get_local_type(int ordinal, int flags, char *buf, size_t maxsize)
{
tinfo_t tif;
if ( !tif.get_numbered_type(idati, ordinal) )
{
buf[0] = 0;
return false;
}
qstring res;
const char *name = get_numbered_type_name(idati, ordinal);
if ( !tif.print(&res, name, flags, 2, 40) )
{
buf[0] = 0;
return false;
}
qstrncpy(buf, res.begin(), maxsize);
return true;
}
//-------------------------------------------------------------------------
PyObject *idc_print_type(PyObject *py_type, PyObject *py_fields, const char *name, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
qstring res;
const type_t *type = (type_t *)PyString_AsString(py_type);
const p_list *fields = (p_list *)PyString_AsString(py_fields);
bool ok;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
ok = tif.deserialize(idati, &type, &fields, NULL)
&& tif.print(&res, name, flags, 2, 40);
Py_END_ALLOW_THREADS;
if ( ok )
return PyString_FromString(res.begin());
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize)
{
const char *name = get_numbered_type_name(idati, ordinal);
if ( name == NULL )
return false;
qstrncpy(buf, name, bufsize);
return true;
}
//</inline(py_typeinf)>
#endif
+15
View File
@@ -0,0 +1,15 @@
#<pycode(py_typeinf)>
def get_type_size0(ti, tp):
"""
DEPRECATED. Please use calc_type_size instead
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
"""
return calc_type_size(ti, tp)
#</pycode(py_typeinf)>
+88 -6
View File
@@ -35,6 +35,8 @@ def init_output_buffer(size = MAXSTR):
*/
PyObject *py_init_output_buffer(size_t size = MAXSTR)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Let Python allocate a writable string buffer for us
PyObject *py_str = PyString_FromStringAndSize(NULL, size);
if ( py_str == NULL )
@@ -73,6 +75,7 @@ PyObject *py_decode_preceding_insn(ea_t ea)
{
bool farref;
ea_t r = decode_preceding_insn(ea, &farref);
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0);
}
@@ -117,6 +120,7 @@ def get_stkvar(op, v):
*/
PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v;
if ( op == NULL || !PyW_GetNumber(py_v, &v) )
@@ -150,6 +154,7 @@ def add_stkvar3(op, v, flags):
*/
bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
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;
@@ -192,11 +197,24 @@ bool py_apply_type_to_stkarg(
const char *name)
{
uint64 v;
PYW_GIL_CHECK_LOCKED_SCOPE();
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);
{
const type_t *t = (type_t *) PyString_AsString(py_type);
tinfo_t tif;
tif.deserialize(idati, &t);
borref_t br(py_op);
bool rc;
Py_BEGIN_ALLOW_THREADS;
rc = apply_tinfo_to_stkarg(*op, uval_t(v), tif, name);
Py_END_ALLOW_THREADS;
return rc;
}
}
//-------------------------------------------------------------------------
@@ -213,6 +231,7 @@ def OutImmChar(op, outflags = 0):
*/
static void py_OutImmChar(PyObject *x)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(x);
if ( op != NULL )
OutImmChar(*op);
@@ -233,6 +252,7 @@ def ua_stkvar2(op, outflags = 0):
*/
static bool py_ua_stkvar2(PyObject *x, adiff_t v, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(x);
return op == NULL ? false : ua_stkvar2(*op, v, flags);
}
@@ -252,6 +272,7 @@ def ua_add_off_drefs(op, type):
*/
ea_t py_ua_add_off_drefs(PyObject *py_op, dref_t type)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs(*op, type);
}
@@ -270,6 +291,7 @@ def ua_add_off_drefs2(op, type, outf):
*/
ea_t py_ua_add_off_drefs2(PyObject *py_op, dref_t type, int outf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs2(*op, type, outf);
}
@@ -295,6 +317,7 @@ bool py_out_name_expr(
ea_t ea,
PyObject *py_off)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v(0);
adiff_t off;
@@ -302,13 +325,14 @@ bool py_out_name_expr(
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)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( i < 0 || i >= UA_MAXOP || !PyCObject_Check(py_insn_lnk) )
Py_RETURN_NONE;
@@ -322,18 +346,21 @@ static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i)
//-------------------------------------------------------------------------
static PyObject *insn_t_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new insn_t(), NULL);
}
//-------------------------------------------------------------------------
static PyObject *op_t_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new op_t(), NULL);
}
//-------------------------------------------------------------------------
static bool op_t_assign(PyObject *self, PyObject *other)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *lhs = op_t_get_clink(self);
op_t *rhs = op_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
@@ -346,6 +373,7 @@ static bool op_t_assign(PyObject *self, PyObject *other)
//-------------------------------------------------------------------------
static bool insn_t_assign(PyObject *self, PyObject *other)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *lhs = insn_t_get_clink(self);
insn_t *rhs = insn_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
@@ -358,6 +386,7 @@ static bool insn_t_assign(PyObject *self, PyObject *other)
//-------------------------------------------------------------------------
static bool op_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
@@ -370,6 +399,7 @@ static bool op_t_destroy(PyObject *py_obj)
//-------------------------------------------------------------------------
static bool insn_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
@@ -381,13 +411,16 @@ static bool insn_t_destroy(PyObject *py_obj)
// Returns a C link to the global 'cmd' variable
static PyObject *py_get_global_cmd_link()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(&::cmd, NULL);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_is_canon_insn(int itype)
{
if ( ph.is_canon_insn(itype) )
bool ok = ph.is_canon_insn(itype);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@@ -396,13 +429,17 @@ static PyObject *insn_t_is_canon_insn(int itype)
//-------------------------------------------------------------------------
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);
uint32 v = ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("I", v);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_mnem(int itype)
{
if ( ph.is_canon_insn(itype) )
bool ok = ph.is_canon_insn(itype);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name);
else
Py_RETURN_NONE;
@@ -411,6 +448,7 @@ static PyObject *insn_t_get_canon_mnem(int itype)
//-------------------------------------------------------------------------
static PyObject *insn_t_get_cs(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -419,10 +457,11 @@ static PyObject *insn_t_get_cs(PyObject *self)
static void insn_t_set_cs(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyW_GetNumber(value, &v);
link->cs = ea_t(v);
@@ -430,6 +469,7 @@ static void insn_t_set_cs(PyObject *self, PyObject *value)
static PyObject *insn_t_get_ip(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -438,6 +478,7 @@ static PyObject *insn_t_get_ip(PyObject *self)
static void insn_t_set_ip(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -448,6 +489,7 @@ static void insn_t_set_ip(PyObject *self, PyObject *value)
static PyObject *insn_t_get_ea(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -456,6 +498,7 @@ static PyObject *insn_t_get_ea(PyObject *self)
static void insn_t_set_ea(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -466,6 +509,7 @@ static void insn_t_set_ea(PyObject *self, PyObject *value)
static PyObject *insn_t_get_itype(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -474,6 +518,7 @@ static PyObject *insn_t_get_itype(PyObject *self)
static void insn_t_set_itype(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -482,6 +527,7 @@ static void insn_t_set_itype(PyObject *self, PyObject *value)
static PyObject *insn_t_get_size(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -490,6 +536,7 @@ static PyObject *insn_t_get_size(PyObject *self)
static void insn_t_set_size(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -498,6 +545,7 @@ static void insn_t_set_size(PyObject *self, PyObject *value)
static PyObject *insn_t_get_auxpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -506,6 +554,7 @@ static PyObject *insn_t_get_auxpref(PyObject *self)
static void insn_t_set_auxpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -514,6 +563,7 @@ static void insn_t_set_auxpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_segpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -522,6 +572,7 @@ static PyObject *insn_t_get_segpref(PyObject *self)
static void insn_t_set_segpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -530,6 +581,7 @@ static void insn_t_set_segpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_insnpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -538,6 +590,7 @@ static PyObject *insn_t_get_insnpref(PyObject *self)
static void insn_t_set_insnpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -546,6 +599,7 @@ static void insn_t_set_insnpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_flags(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -554,6 +608,7 @@ static PyObject *insn_t_get_flags(PyObject *self)
static void insn_t_set_flags(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@@ -563,6 +618,7 @@ static void insn_t_set_flags(PyObject *self, PyObject *value)
//-------------------------------------------------------------------------
static PyObject *op_t_get_n(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -579,6 +635,7 @@ static void op_t_set_n(PyObject *self, PyObject *value)
static PyObject *op_t_get_type(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -587,6 +644,7 @@ static PyObject *op_t_get_type(PyObject *self)
static void op_t_set_type(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -595,6 +653,7 @@ static void op_t_set_type(PyObject *self, PyObject *value)
static PyObject *op_t_get_offb(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -603,6 +662,7 @@ static PyObject *op_t_get_offb(PyObject *self)
static void op_t_set_offb(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -611,6 +671,7 @@ static void op_t_set_offb(PyObject *self, PyObject *value)
static PyObject *op_t_get_offo(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -619,6 +680,7 @@ static PyObject *op_t_get_offo(PyObject *self)
static void op_t_set_offo(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -627,6 +689,7 @@ static void op_t_set_offo(PyObject *self, PyObject *value)
static PyObject *op_t_get_flags(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -635,6 +698,7 @@ static PyObject *op_t_get_flags(PyObject *self)
static void op_t_set_flags(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -643,6 +707,7 @@ static void op_t_set_flags(PyObject *self, PyObject *value)
static PyObject *op_t_get_dtyp(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -651,6 +716,7 @@ static PyObject *op_t_get_dtyp(PyObject *self)
static void op_t_set_dtyp(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -659,6 +725,7 @@ static void op_t_set_dtyp(PyObject *self, PyObject *value)
static PyObject *op_t_get_reg_phrase(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -666,6 +733,7 @@ static PyObject *op_t_get_reg_phrase(PyObject *self)
}
static void op_t_set_reg_phrase(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -674,6 +742,7 @@ static void op_t_set_reg_phrase(PyObject *self, PyObject *value)
static PyObject *op_t_get_value(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -682,6 +751,7 @@ static PyObject *op_t_get_value(PyObject *self)
static void op_t_set_value(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -690,6 +760,7 @@ static void op_t_set_value(PyObject *self, PyObject *value)
static PyObject *op_t_get_addr(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -698,6 +769,7 @@ static PyObject *op_t_get_addr(PyObject *self)
static void op_t_set_addr(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -708,6 +780,7 @@ static void op_t_set_addr(PyObject *self, PyObject *value)
static PyObject *op_t_get_specval(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -716,6 +789,7 @@ static PyObject *op_t_get_specval(PyObject *self)
static void op_t_set_specval(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -726,6 +800,7 @@ static void op_t_set_specval(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag1(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -734,6 +809,7 @@ static PyObject *op_t_get_specflag1(PyObject *self)
static void op_t_set_specflag1(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -742,6 +818,7 @@ static void op_t_set_specflag1(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag2(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -750,6 +827,7 @@ static PyObject *op_t_get_specflag2(PyObject *self)
static void op_t_set_specflag2(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -758,6 +836,7 @@ static void op_t_set_specflag2(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag3(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -766,6 +845,7 @@ static PyObject *op_t_get_specflag3(PyObject *self)
static void op_t_set_specflag3(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@@ -774,6 +854,7 @@ static void op_t_set_specflag3(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag4(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@@ -782,6 +863,7 @@ static PyObject *op_t_get_specflag4(PyObject *self)
static void op_t_set_specflag4(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
+810
View File
@@ -0,0 +1,810 @@
#ifndef __PY_VIEW_BASE__
#define __PY_VIEW_BASE__
//<code(py_view_base)>
//#define PYGDBG_ENABLED
#ifdef PYGDBG_ENABLED
#define PYGLOG(...) msg(__VA_ARGS__)
#else
#define PYGLOG(...)
#endif
//-------------------------------------------------------------------------
class py_customidamemo_t;
class lookup_info_t
{
public:
void add(TForm *form, TCustomControl *view, py_customidamemo_t *py_view)
{
QASSERT(0, form != NULL && view != NULL && py_view != NULL
&& !find_by_form(NULL, NULL, form)
&& !find_by_view(NULL, NULL, view)
&& !find_by_py_view(NULL, NULL, py_view));
entry_t &e = entries.push_back();
e.form = form;
e.view = view;
e.py_view = py_view;
}
#define FIND_BY__BODY(crit, res1, res2) \
{ \
for ( entries_t::const_iterator it = entries.begin(); it != entries.end(); ++it ) \
{ \
const entry_t &e = *it; \
if ( e.crit == crit ) \
{ \
if ( out_##res1 != NULL ) \
*out_##res1 = e.res1; \
if ( out_##res2 != NULL ) \
*out_##res2 = e.res2; \
return true; \
} \
} \
return false; \
}
bool find_by_form(TCustomControl **out_view, py_customidamemo_t **out_py_view, const TForm *form) const FIND_BY__BODY(form, view, py_view);
bool find_by_view(TForm **out_form, py_customidamemo_t **out_py_view, const TCustomControl *view) const FIND_BY__BODY(view, form, py_view);
bool find_by_py_view(TForm **out_form, TCustomControl **out_view, const py_customidamemo_t *py_view) const FIND_BY__BODY(py_view, view, form);
#undef FIND_BY__BODY
bool del_by_py_view(const py_customidamemo_t *py_view)
{
for ( entries_t::iterator it = entries.begin(); it != entries.end(); ++it )
{
if ( it->py_view == py_view )
{
entries.erase(it);
return true;
}
}
return false;
}
private:
struct entry_t
{
TForm *form;
TCustomControl *view;
py_customidamemo_t *py_view;
};
typedef qvector<entry_t> entries_t;
entries_t entries;
};
//-------------------------------------------------------------------------
template <typename T>
T *view_extract_this(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_this(PyW_TryGetAttrString(self, S_M_THIS));
if ( py_this == NULL || !PyCObject_Check(py_this.o) )
return NULL;
return (T*) PyCObject_AsVoidPtr(py_this.o);
}
//-------------------------------------------------------------------------
class py_customidamemo_t
{
void convert_node_info(
node_info_t *out,
uint32 *out_flags,
ref_t py_nodeinfo)
{
if ( out_flags != NULL )
*out_flags = 0;
#define COPY_PROP(checker, converter, pname, flag) \
do \
{ \
newref_t pname(PyObject_GetAttrString(py_nodeinfo.o, #pname)); \
if ( pname != NULL && checker(pname.o) ) \
{ \
out->pname = converter(pname.o); \
if ( out_flags != NULL ) \
*out_flags |= flag; \
} \
} while ( false )
#define COPY_ULONG_PROP(pname, flag) COPY_PROP(PyNumber_Check, PyLong_AsUnsignedLong, pname, flag)
#define COPY_STRING_PROP(pname, flag) COPY_PROP(PyString_Check, PyString_AsString, pname, flag)
COPY_ULONG_PROP(bg_color, NIF_BG_COLOR);
COPY_ULONG_PROP(frame_color, NIF_FRAME_COLOR);
COPY_ULONG_PROP(ea, NIF_EA);
COPY_STRING_PROP(text, NIF_TEXT);
#undef COPY_STRING_PROP
#undef COPY_ULONG_PROP
#undef COPY_PROP
}
enum
{
GRBASE_HAVE_VIEW_ACTIVATED = 0x001,
GRBASE_HAVE_VIEW_DEACTIVATED = 0x002,
GRBASE_HAVE_KEYDOWN = 0x004,
GRBASE_HAVE_POPUP = 0x008,
GRBASE_HAVE_VIEW_CLICK = 0x010,
GRBASE_HAVE_VIEW_DBLCLICK = 0x020,
GRBASE_HAVE_VIEW_CURPOS = 0x040,
GRBASE_HAVE_CLOSE = 0x080,
GRBASE_HAVE_VIEW_SWITCHED = 0x100,
GRBASE_HAVE_VIEW_MOUSE_OVER = 0x200,
};
static void ensure_view_callbacks_installed();
int cb_flags;
protected:
ref_t self;
TCustomControl *view;
// This is called after having modified the
// node properties in the IDB. In case an
// implementation is performing some caching,
// this is a chance to update that cache.
// If 'ni' is NULL, then the node info was deleted.
virtual void node_info_modified(
int /*n*/,
const node_info_t * /*ni*/,
uint32 /*flags*/) {}
struct callback_id_t
{
qstring name;
int have;
};
struct callbacks_ids_t : public qvector<callback_id_t>
{
void add(const char *_n, int _h)
{
callback_id_t &o = push_back();
o.name = _n;
o.have = _h;
}
};
callbacks_ids_t cbids;
bool collect_pyobject_callbacks(PyObject *self);
virtual void collect_class_callbacks_ids(callbacks_ids_t *out);
// Bi-directionally bind/unbind the Python object and this controller.
bool bind(PyObject *_self, TCustomControl *view);
void unbind();
static lookup_info_t lookup_info;
public:
py_customidamemo_t();
virtual ~py_customidamemo_t();
virtual void refresh()
{
refresh_viewer(view);
}
void set_node_info(PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags);
void set_nodes_infos(PyObject *dict);
PyObject *get_node_info(PyObject *py_node_idx);
void del_nodes_infos(PyObject *py_nodes);
PyObject *get_current_renderer_type();
void set_current_renderer_type(PyObject *py_rto);
PyObject *create_groups(PyObject *groups_infos);
PyObject *delete_groups(PyObject *groups, PyObject *new_current);
PyObject *set_groups_visibility(PyObject *groups, PyObject *expand, PyObject *new_current);
// View events
void on_view_activated();
void on_view_deactivated();
void on_view_keydown(int key, int state);
void on_view_popup();
void on_view_click(const view_mouse_event_t *event);
void on_view_dblclick(const view_mouse_event_t *event);
void on_view_curpos();
void on_view_close();
void on_view_switched(tcc_renderer_type_t rt);
void on_view_mouse_over(const view_mouse_event_t *event);
inline bool has_callback(int flag) { return (cb_flags & flag) != 0; }
};
//-------------------------------------------------------------------------
py_customidamemo_t::py_customidamemo_t()
: self(newref_t(NULL)),
view(NULL)
{
PYGLOG("%p: py_customidamemo_t()\n", this);
ensure_view_callbacks_installed();
}
//-------------------------------------------------------------------------
py_customidamemo_t::~py_customidamemo_t()
{
PYGLOG("%p: ~py_customidamemo_t()\n", this);
unbind();
lookup_info.del_by_py_view(this);
}
//-------------------------------------------------------------------------
void py_customidamemo_t::ensure_view_callbacks_installed()
{
static bool installed = false;
if ( !installed )
{
struct ida_local lambda_t
{
static int idaapi callback(void * /*ud*/, int code, va_list va)
{
py_customidamemo_t *py_view;
if ( lookup_info.find_by_view(NULL, &py_view, va_arg(va, TCustomControl *)) )
{
PYW_GIL_GET;
switch ( code )
{
case view_activated:
py_view->on_view_activated();
break;
case view_deactivated:
py_view->on_view_deactivated();
break;
case view_keydown:
{
int key = va_arg(va, int);
int state = va_arg(va, int);
py_view->on_view_keydown(key, state);
}
break;
case view_popup:
py_view->on_view_popup();
break;
case view_click:
case view_dblclick:
{
const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*);
if ( code == view_click )
py_view->on_view_click(event);
else
py_view->on_view_dblclick(event);
}
break;
case view_curpos:
py_view->on_view_curpos();
break;
case view_close:
py_view->on_view_close();
delete py_view;
break;
case view_switched:
{
tcc_renderer_type_t rt = (tcc_renderer_type_t) va_arg(va, int);
py_view->on_view_switched(rt);
}
break;
case view_mouse_over:
{
const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*);
py_view->on_view_mouse_over(event);
}
break;
}
}
return 0;
}
};
hook_to_notification_point(HT_VIEW, lambda_t::callback, NULL);
installed = true;
}
}
//-------------------------------------------------------------------------
void py_customidamemo_t::set_node_info(
PyObject *py_node_idx,
PyObject *py_node_info,
PyObject *py_flags)
{
if ( !PyNumber_Check(py_node_idx) || !PyNumber_Check(py_flags) )
return;
borref_t py_idx(py_node_idx);
borref_t py_ni(py_node_info);
borref_t py_fl(py_flags);
node_info_t ni;
convert_node_info(&ni, NULL, py_ni);
int idx = PyInt_AsLong(py_idx.o);
uint32 flgs = PyLong_AsLong(py_fl.o);
viewer_set_node_info(view, idx, ni, flgs);
node_info_modified(idx, &ni, flgs);
}
//-------------------------------------------------------------------------
void py_customidamemo_t::set_nodes_infos(PyObject *dict)
{
if ( !PyDict_Check(dict) )
return;
Py_ssize_t pos = 0;
PyObject *o_key, *o_value;
while ( PyDict_Next(dict, &pos, &o_key, &o_value) )
{
borref_t key(o_key);
borref_t value(o_value);
if ( !PyNumber_Check(key.o) )
continue;
uint32 flags;
node_info_t ni;
convert_node_info(&ni, &flags, value);
int idx = PyInt_AsLong(key.o);
viewer_set_node_info(view, idx, ni, flags);
node_info_modified(idx, &ni, flags);
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::get_node_info(PyObject *py_node_idx)
{
if ( !PyNumber_Check(py_node_idx) )
Py_RETURN_NONE;
node_info_t ni;
if ( !viewer_get_node_info(view, &ni, PyInt_AsLong(py_node_idx)) )
Py_RETURN_NONE;
return Py_BuildValue("(kkks)", ni.bg_color, ni.frame_color, ni.ea, ni.text.c_str());
}
//-------------------------------------------------------------------------
void py_customidamemo_t::del_nodes_infos(PyObject *py_nodes)
{
if ( !PySequence_Check(py_nodes) )
return;
Py_ssize_t sz = PySequence_Size(py_nodes);
for ( Py_ssize_t i = 0; i < sz; ++i )
{
newref_t item(PySequence_GetItem(py_nodes, i));
if ( !PyNumber_Check(item.o) )
continue;
int idx = PyInt_AsLong(item.o);
viewer_del_node_info(view, idx);
node_info_modified(idx, NULL, 0);
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::get_current_renderer_type()
{
tcc_renderer_type_t rt = get_view_renderer_type(view);
return PyLong_FromLong(long(rt));
}
//-------------------------------------------------------------------------
void py_customidamemo_t::set_current_renderer_type(PyObject *py_rto)
{
tcc_renderer_type_t rt = TCCRT_INVALID;
borref_t py_rt(py_rto);
if ( PyNumber_Check(py_rt.o) )
{
rt = tcc_renderer_type_t(PyLong_AsLong(py_rt.o));
set_view_renderer_type(view, rt);
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos)
{
if ( !PySequence_Check(_groups_infos) )
Py_RETURN_NONE;
borref_t groups_infos(_groups_infos);
groups_crinfos_t gis;
Py_ssize_t sz = PySequence_Size(groups_infos.o);
for ( Py_ssize_t i = 0; i < sz; ++i )
{
newref_t item(PySequence_GetItem(groups_infos.o, i));
if ( !PyDict_Check(item.o) )
continue;
borref_t nodes(PyDict_GetItemString(item.o, "nodes"));
if ( nodes.o == NULL || !PySequence_Check(nodes.o) )
continue;
borref_t text(PyDict_GetItemString(item.o, "text"));
if ( text.o == NULL || !PyString_Check(text.o) )
continue;
group_crinfo_t gi;
Py_ssize_t nodes_cnt = PySequence_Size(nodes.o);
for ( Py_ssize_t k = 0; k < nodes_cnt; ++k )
{
newref_t node(PySequence_GetItem(nodes.o, k));
if ( PyInt_Check(node.o) )
gi.nodes.insert(PyInt_AsLong(node.o));
}
if ( !gi.nodes.empty() )
{
gi.text = PyString_AsString(text.o);
gis.push_back(gi);
}
}
intset_t groups;
if ( gis.empty() || !viewer_create_groups(view, &groups, gis) || groups.empty() )
Py_RETURN_NONE;
PyObject *py_groups = PyList_New(0);
for ( intset_t::const_iterator it = groups.begin(); it != groups.end(); ++it )
PyList_Append(py_groups, PyInt_FromLong(long(*it)));
return py_groups;
}
//-------------------------------------------------------------------------
static void pynodes_to_idanodes(intset_t *idanodes, ref_t pynodes)
{
Py_ssize_t sz = PySequence_Size(pynodes.o);
for ( Py_ssize_t i = 0; i < sz; ++i )
{
newref_t item(PySequence_GetItem(pynodes.o, i));
if ( !PyInt_Check(item.o) )
continue;
idanodes->insert(PyInt_AsLong(item.o));
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::delete_groups(PyObject *_groups, PyObject *_new_current)
{
if ( !PySequence_Check(_groups) || !PyNumber_Check(_new_current) )
Py_RETURN_NONE;
borref_t groups(_groups);
borref_t new_current(_new_current);
intset_t ida_groups;
pynodes_to_idanodes(&ida_groups, groups);
if ( ida_groups.empty() )
Py_RETURN_NONE;
if ( viewer_delete_groups(view, ida_groups, int(PyInt_AsLong(new_current.o))) )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::set_groups_visibility(PyObject *_groups, PyObject *_expand, PyObject *_new_current)
{
if ( !PySequence_Check(_groups)
|| !PyBool_Check(_expand)
|| !PyNumber_Check(_new_current) )
Py_RETURN_NONE;
borref_t groups(_groups);
borref_t expand(_expand);
borref_t new_current(_new_current);
intset_t ida_groups;
pynodes_to_idanodes(&ida_groups, groups);
if ( ida_groups.empty() )
Py_RETURN_NONE;
if ( viewer_set_groups_visibility(view, ida_groups, expand.o == Py_True, int(PyInt_AsLong(new_current.o))) )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
//-------------------------------------------------------------------------
bool py_customidamemo_t::bind(PyObject *_self, TCustomControl *view)
{
if ( this->self != NULL || this->view != NULL )
return false;
PYGLOG("%p: py_customidamemo_t::bind(_self=%p, view=%p)\n", this, _self, view);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_cobj(PyCObject_FromVoidPtr(this, NULL));
PyObject_SetAttrString(_self, S_M_THIS, py_cobj.o);
this->self = borref_t(_self);
this->view = view;
return true;
}
//-------------------------------------------------------------------------
void py_customidamemo_t::unbind()
{
if ( self == NULL )
return;
PYGLOG("%p: py_customidamemo_t::unbind(); self.o=%p, view=%p\n", this, self.o, view);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_cobj(PyCObject_FromVoidPtr(NULL, NULL));
PyObject_SetAttrString(self.o, S_M_THIS, py_cobj.o);
self = newref_t(NULL);
view = NULL;
}
//-------------------------------------------------------------------------
void py_customidamemo_t::collect_class_callbacks_ids(callbacks_ids_t *out)
{
out->add(S_ON_VIEW_ACTIVATED, GRBASE_HAVE_VIEW_ACTIVATED);
out->add(S_ON_VIEW_DEACTIVATED, GRBASE_HAVE_VIEW_DEACTIVATED);
out->add(S_ON_VIEW_KEYDOWN, GRBASE_HAVE_KEYDOWN);
out->add(S_ON_POPUP, GRBASE_HAVE_POPUP);
out->add(S_ON_VIEW_CLICK, GRBASE_HAVE_VIEW_CLICK);
out->add(S_ON_VIEW_DBLCLICK, GRBASE_HAVE_VIEW_DBLCLICK);
out->add(S_ON_VIEW_CURPOS, GRBASE_HAVE_VIEW_CURPOS);
out->add(S_ON_CLOSE, GRBASE_HAVE_CLOSE);
out->add(S_ON_VIEW_SWITCHED, GRBASE_HAVE_VIEW_SWITCHED);
out->add(S_ON_VIEW_MOUSE_OVER, GRBASE_HAVE_VIEW_MOUSE_OVER);
}
//-------------------------------------------------------------------------
bool py_customidamemo_t::collect_pyobject_callbacks(PyObject *o)
{
callbacks_ids_t cbids;
collect_class_callbacks_ids(&cbids);
cb_flags = 0;
for ( callbacks_ids_t::const_iterator it = cbids.begin(); it != cbids.end(); ++it )
{
const callback_id_t &cbid = *it;
ref_t attr(PyW_TryGetAttrString(o, cbid.name.c_str()));
int have = cbid.have;
// Mandatory fields not present?
if ( (attr == NULL && have <= 0 )
// Mandatory callback fields present but not callable?
|| (attr != NULL && have >= 0 && PyCallable_Check(attr.o) == 0))
{
return false;
}
if ( have > 0 && attr != NULL )
cb_flags |= have;
}
return true;
}
//-------------------------------------------------------------------------
#define CHK_EVT(flag_needed) \
if ( self == NULL || !has_callback(flag_needed) ) \
return; \
PYW_GIL_CHECK_LOCKED_SCOPE()
#ifdef PYGDBG_ENABLED
#define CHK_RES() PYGLOG("%s: return code: %p\n", __FUNCTION__, result.o)
#else
#define CHK_RES()
#endif
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_activated()
{
CHK_EVT(GRBASE_HAVE_VIEW_ACTIVATED);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_ACTIVATED,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_deactivated()
{
CHK_EVT(GRBASE_HAVE_VIEW_DEACTIVATED);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_DEACTIVATED,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_keydown(int key, int state)
{
CHK_EVT(GRBASE_HAVE_KEYDOWN);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_KEYDOWN,
"ii",
key, state));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_popup()
{
CHK_EVT(GRBASE_HAVE_POPUP);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_POPUP,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_click(const view_mouse_event_t *event)
{
CHK_EVT(GRBASE_HAVE_VIEW_CLICK);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_CLICK,
"iii",
event->x, event->y, event->state));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_dblclick(const view_mouse_event_t *event)
{
CHK_EVT(GRBASE_HAVE_VIEW_DBLCLICK);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_DBLCLICK,
"iii",
event->x, event->y, event->state));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_curpos()
{
CHK_EVT(GRBASE_HAVE_VIEW_CURPOS);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_CURPOS,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_close()
{
CHK_EVT(GRBASE_HAVE_CLOSE);
newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_CLOSE, NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_switched(tcc_renderer_type_t rt)
{
CHK_EVT(GRBASE_HAVE_VIEW_SWITCHED);
newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_VIEW_SWITCHED, "i", int(rt)));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_mouse_over(const view_mouse_event_t *event)
{
CHK_EVT(GRBASE_HAVE_VIEW_MOUSE_OVER);
if ( event->rtype == TCCRT_GRAPH || event->rtype == TCCRT_PROXIMITY )
{
const selection_item_t *item = event->location.item;
int icode;
ref_t tuple;
if ( item != NULL )
{
if ( item->is_node )
{
icode = 1;
tuple = newref_t(Py_BuildValue("(i)", item->node));
}
else
{
icode = 2;
tuple = newref_t(Py_BuildValue("(ii)", item->elp.e.src, item->elp.e.dst));
}
}
else
{
icode = 0;
tuple = newref_t(Py_BuildValue("()"));
}
newref_t result(PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_MOUSE_OVER,
"iiiiO",
event->x, event->y, event->state, icode, tuple.o));
CHK_RES();
}
}
#undef CHK_RES
#undef CHK_EVT
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
#define GET_THIS() py_customidamemo_t *_this = view_extract_this<py_customidamemo_t>(self)
#define CHK_THIS() \
GET_THIS(); \
if ( _this == NULL ) \
return
#define CHK_THIS_OR_NONE() \
GET_THIS(); \
if ( _this == NULL ) \
Py_RETURN_NONE
//-------------------------------------------------------------------------
void pygc_refresh(PyObject *self)
{
CHK_THIS();
_this->refresh();
}
//-------------------------------------------------------------------------
void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags)
{
CHK_THIS();
_this->set_node_info(py_node_idx, py_node_info, py_flags);
}
//-------------------------------------------------------------------------
void pygc_set_nodes_infos(PyObject *self, PyObject *values)
{
CHK_THIS();
_this->set_nodes_infos(values);
}
//-------------------------------------------------------------------------
PyObject *pygc_get_node_info(PyObject *self, PyObject *py_node_idx)
{
GET_THIS();
if ( _this != NULL )
return _this->get_node_info(py_node_idx);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
void pygc_del_nodes_infos(PyObject *self, PyObject *py_nodes)
{
CHK_THIS();
_this->del_nodes_infos(py_nodes);
}
//-------------------------------------------------------------------------
PyObject *pygc_get_current_renderer_type(PyObject *self)
{
GET_THIS();
if ( _this != NULL )
return _this->get_current_renderer_type();
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt)
{
CHK_THIS();
_this->set_current_renderer_type(py_rt);
}
//-------------------------------------------------------------------------
PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos)
{
CHK_THIS_OR_NONE();
return _this->create_groups(groups_infos);
}
//-------------------------------------------------------------------------
PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current)
{
CHK_THIS_OR_NONE();
return _this->delete_groups(groups, new_current);
}
//-------------------------------------------------------------------------
PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current)
{
CHK_THIS_OR_NONE();
return _this->set_groups_visibility(groups, expand, new_current);
}
#undef CHK_THIS_OR_NONE
#undef CHK_THIS
#undef GET_THIS
//-------------------------------------------------------------------------
lookup_info_t py_customidamemo_t::lookup_info;
//</code(py_view_base)>
//<inline(py_view_base)>
void pygc_refresh(PyObject *self);
void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags);
void pygc_set_nodes_infos(PyObject *self, PyObject *values);
PyObject *pygc_get_node_info(PyObject *self, PyObject *py_node_idx);
void pygc_del_nodes_infos(PyObject *self, PyObject *py_nodes);
PyObject *pygc_get_current_renderer_type(PyObject *self);
void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt);
PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos);
PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current);
PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current);
//</inline(py_view_base)>
#endif // __PY_VIEW_BASE__
+107
View File
@@ -0,0 +1,107 @@
#<pycode(py_view_base)>
class CustomIDAMemo(object):
def Refresh(self):
"""
Refreshes the graph. This causes the OnRefresh() to be called
"""
_idaapi.pygc_refresh(self)
def GetCurrentRendererType(self):
return _idaapi.pygc_get_current_renderer_type(self)
def SetCurrentRendererType(self, rtype):
"""
Set the current view's renderer.
@param rtype: The renderer type. Should be one of the idaapi.TCCRT_* values.
"""
_idaapi.pygc_set_current_renderer_type(self, rtype)
def SetNodeInfo(self, node_index, node_info, flags):
"""
Set the properties for the given node.
Example usage (set second nodes's bg color to red):
inst = ...
p = idaapi.node_info_t()
p.bg_color = 0x00ff0000
inst.SetNodeInfo(1, p, idaapi.NIF_BG_COLOR)
@param node_index: The node index.
@param node_info: An idaapi.node_info_t instance.
@param flags: An OR'ed value of NIF_* values.
"""
_idaapi.pygc_set_node_info(self, node_index, node_info, flags)
def SetNodesInfos(self, values):
"""
Set the properties for the given nodes.
Example usage (set first three nodes's bg color to purple):
inst = ...
p = idaapi.node_info_t()
p.bg_color = 0x00ff00ff
inst.SetNodesInfos({0 : p, 1 : p, 2 : p})
@param values: A dictionary of 'int -> node_info_t' objects.
"""
_idaapi.pygc_set_nodes_infos(self, values)
def GetNodeInfo(self, node):
"""
Get the properties for the given node.
@param node: The index of the node.
@return: A tuple (bg_color, frame_color, ea, text), or None.
"""
return _idaapi.pygc_get_node_info(self, node)
def DelNodesInfos(self, *nodes):
"""
Delete the properties for the given node(s).
@param nodes: A list of node IDs
"""
return _idaapi.pygc_del_nodes_infos(self, nodes)
def CreateGroups(self, groups_infos):
"""
Send a request to modify the graph by creating a
(set of) group(s), and perform an animation.
Each object in the 'groups_infos' list must be of the format:
{
"nodes" : [<int>, <int>, <int>, ...] # The list of nodes to group
"text" : <string> # The synthetic text for that group
}
@param groups_infos: A list of objects that describe those groups.
@return: A [<int>, <int>, ...] list of group nodes, or None (failure).
"""
return _idaapi.pygc_create_groups(self, groups_infos)
def DeleteGroups(self, groups, new_current = -1):
"""
Send a request to delete the specified groups in the graph,
and perform an animation.
@param groups: A list of group node numbers.
@param new_current: A node to focus on after the groups have been deleted
@return: True on success, False otherwise.
"""
return _idaapi.pygc_delete_groups(self, groups, new_current)
def SetGroupsVisibility(self, groups, expand, new_current = -1):
"""
Send a request to expand/collapse the specified groups in the graph,
and perform an animation.
@param groups: A list of group node numbers.
@param expand: True to expand the group, False otherwise.
@param new_current: A node to focus on after the groups have been expanded/collapsed.
@return: True on success, False otherwise.
"""
return _idaapi.pygc_set_groups_visibility(self, groups, expand, new_current)
#</pycode(py_view_base)>
+4
View File
@@ -90,6 +90,10 @@ class processor_t(object):
# ----------------------------------------------------------------------
BADADDR = 0xFFFFFFFFFFFFFFFFL
# ----------------------------------------------------------------------
UA_MAXOP = 6
o_last = 14
o_void = 0
# ----------------------------------------------------------------------
"""