mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-30 13:04:18 +01:00
IDA Pro 6.6 support
What's new: - added the decompiler bindings - Expose simpleline_t type to IDAPython. That lets the user to set the bgcolor & text for each line in the decompilation. - Wrapped new functions from the IDA SDK Various fixes: for non-code locations, idc.GetOpnd() would create instructions instead of returning empty result - idb_event::area_cmt_changed was never received in IDB_Hooks (and descendants) - idb_event::ti_changed, and idb_event::op_ti_changed notifications were not accessible in IDAPython - op_t.value was truncated to 32 bits under IDA64. - print_tinfo() wouldn't return a valid string. - readsel2() was not usable. - read_selection() was buggy for 64-bit programs. - StructMembers() considered holes in structures, and didn't properly iterate through the whole structure definition. - There was no way to call calc_switch_cases() from IDAPython. - when using multi-select/multi-edit choosers, erroneous event codes could be sent at beginning & end of batch deletion of lines. - When, in a PluginForm#OnCreate, the layout of IDA was requested to change (for example by starting a debugging session), that PluginForm could be deleted and create an access violation. - tinfo_t objects created from IDAPython could cause an assertion failure at exit time. - Usage of IDAPython's DropdownListControl was broken.
This commit is contained in:
parent
1c6752de40
commit
fbb5bfabd6
@ -8,11 +8,11 @@ The IDAPython Team:
|
||||
* Hex-Rays - http://www.hex-rays.com/ - <support@hex-rays.com>
|
||||
|
||||
Hex-Rays joined the IDAPython project in September 2009 and started contributing.
|
||||
It is primarily maintained by Arnaud Diederen.
|
||||
It is primarily maintained, updated and improved by Arnaud Diederen of Hex-Rays.
|
||||
|
||||
* Elias Bachaalany - http://0xeb.wordpress.com/
|
||||
* Elias Bachaalany - elias.bachaalany@gmail.com
|
||||
Maintains IDAPython online source code repository and coordinates patches/updates/contributions from Hex-Rays and 3rd party contributors
|
||||
|
||||
Current project owner and maintainer
|
||||
|
||||
* Ero Carrera - http://dkbza.org/
|
||||
|
||||
|
9
build.py
9
build.py
@ -24,7 +24,7 @@ from distutils import sysconfig
|
||||
VERBOSE = True
|
||||
|
||||
IDA_MAJOR_VERSION = 6
|
||||
IDA_MINOR_VERSION = 5
|
||||
IDA_MINOR_VERSION = 6
|
||||
|
||||
if 'IDA' in os.environ:
|
||||
IDA_SDK = os.environ['IDA']
|
||||
@ -35,7 +35,7 @@ else:
|
||||
|
||||
# IDAPython version
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 6
|
||||
VERSION_MINOR = 7
|
||||
VERSION_PATCH = 0
|
||||
|
||||
# Determine Python version
|
||||
@ -339,13 +339,14 @@ def build_plugin(
|
||||
idasdkdir,
|
||||
plugin_name,
|
||||
options):
|
||||
""" Build the plugin from the SWIG wrapper and plugin main source """
|
||||
|
||||
global SWIG_OPTIONS
|
||||
|
||||
# Get the arguments
|
||||
ea64 = options[S_EA64]
|
||||
with_hexrays = options[S_WITH_HEXRAYS]
|
||||
|
||||
global SWIG_OPTIONS
|
||||
""" Build the plugin from the SWIG wrapper and plugin main source """
|
||||
# Path to the IDA SDK headers
|
||||
ida_include_directory = os.path.join(idasdkdir, "include")
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to use the graphing functionality in Python
|
||||
# This is an example illustrating how to use the user graphing functionality
|
||||
# in Python
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import GraphViewer
|
||||
|
@ -17,9 +17,8 @@ def main():
|
||||
return True
|
||||
|
||||
sv = cfunc.get_pseudocode();
|
||||
for i in xrange(0, sv.size()):
|
||||
line = idaapi.tag_remove(str(sv[i]));
|
||||
print line
|
||||
for sline in sv:
|
||||
print idaapi.tag_remove(sline.line);
|
||||
|
||||
return True
|
||||
|
||||
|
@ -66,9 +66,9 @@ class XrefsForm(idaapi.PluginForm):
|
||||
x = self.target.operands['x']
|
||||
m = self.target.operands['m']
|
||||
|
||||
xtype = typestring(x.type.u_str())
|
||||
xtype = x.type
|
||||
xtype.remove_ptr_or_array()
|
||||
typename = str(xtype)
|
||||
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
|
||||
|
||||
sid = idc.GetStrucIdByName(typename)
|
||||
member = idc.GetMemberName(sid, m)
|
||||
@ -137,11 +137,10 @@ class XrefsForm(idaapi.PluginForm):
|
||||
lines = []
|
||||
for stmt in insnvec:
|
||||
|
||||
qs = idaapi.qstring()
|
||||
qp = idaapi.qstring_printer_t(cfunc.__deref__(), qs, False)
|
||||
qp = idaapi.qstring_printer_t(cfunc.__deref__(), False)
|
||||
|
||||
stmt._print(0, qp)
|
||||
s = str(qs).split('\n')[0]
|
||||
s = qp.s.split('\n')[0]
|
||||
|
||||
#~ s = idaapi.tag_remove(s)
|
||||
lines.append(s)
|
||||
@ -156,7 +155,6 @@ class XrefsForm(idaapi.PluginForm):
|
||||
for ea in frm:
|
||||
try:
|
||||
cfunc = idaapi.decompile(ea)
|
||||
cfunc.refcnt += 1
|
||||
|
||||
self.functions.append(cfunc.entry_ea)
|
||||
self.items.append((ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea)))
|
||||
@ -172,16 +170,15 @@ class XrefsForm(idaapi.PluginForm):
|
||||
x = self.target.operands['x']
|
||||
m = self.target.operands['m']
|
||||
|
||||
xtype = typestring(x.type.u_str())
|
||||
xtype = x.type
|
||||
xtype.remove_ptr_or_array()
|
||||
typename = str(xtype)
|
||||
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
|
||||
|
||||
addresses = []
|
||||
for ea in idautils.Functions():
|
||||
|
||||
try:
|
||||
cfunc = idaapi.decompile(ea)
|
||||
cfunc.refcnt += 1
|
||||
except:
|
||||
print 'Decompilation of %x failed' % (ea, )
|
||||
continue
|
||||
@ -195,9 +192,9 @@ class XrefsForm(idaapi.PluginForm):
|
||||
|
||||
_x = citem.operands['x']
|
||||
_m = citem.operands['m']
|
||||
_xtype = typestring(_x.type.u_str())
|
||||
_xtype = _x.type
|
||||
_xtype.remove_ptr_or_array()
|
||||
_typename = str(_xtype)
|
||||
_typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, _xtype, '', '')
|
||||
|
||||
#~ print 'in', hex(cfunc.entry_ea), _typename, _m
|
||||
|
||||
|
@ -96,7 +96,7 @@
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>.\pywraps;..\..\include;\python27\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\pywraps;..\..\include;c:\python27\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WITH_HEXRAYS;NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=3;PLUGINFIX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
|
194
python.cpp
194
python.cpp
@ -69,7 +69,8 @@ enum script_run_when
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Global variables
|
||||
static bool g_initialized = false;
|
||||
static bool g_instance_initialized = false; // This instance of the plugin is the one
|
||||
// that initialized the python interpreter.
|
||||
static int g_run_when = -1;
|
||||
static char g_run_script[QMAXPATH];
|
||||
static char g_idapython_dir[QMAXPATH];
|
||||
@ -133,7 +134,8 @@ static int break_check(PyObject *obj, _frame *frame, int what, PyObject *arg)
|
||||
if ( wasBreak() )
|
||||
{
|
||||
// User pressed Cancel in the waitbox; send KeyboardInterrupt exception
|
||||
PyErr_SetInterrupt();
|
||||
PyErr_SetString(PyExc_KeyboardInterrupt, "User interrupted");
|
||||
return -1;
|
||||
}
|
||||
else if ( !box_displayed && ++ninsns > 10 )
|
||||
{
|
||||
@ -637,48 +639,6 @@ static bool parse_py_modname(
|
||||
return p != NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Compile callback for Python external language evaluator
|
||||
bool idaapi IDAPython_extlang_compile(
|
||||
const char *name,
|
||||
ea_t /*current_ea*/,
|
||||
const char *expr,
|
||||
char *errbuf,
|
||||
size_t errbufsize)
|
||||
{
|
||||
PYW_GIL_GET;
|
||||
PyObject *globals = GetMainGlobals();
|
||||
|
||||
PyCodeObject *code = (PyCodeObject *)Py_CompileString(expr, "<string>", Py_eval_input);
|
||||
if ( code == NULL )
|
||||
{
|
||||
handle_python_error(errbuf, errbufsize);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the desired function name
|
||||
Py_XDECREF(code->co_name);
|
||||
code->co_name = PyString_FromString(name);
|
||||
|
||||
// Create a function out of code
|
||||
PyObject *func = PyFunction_New((PyObject *)code, globals);
|
||||
|
||||
if ( func == NULL )
|
||||
{
|
||||
ERR:
|
||||
handle_python_error(errbuf, errbufsize);
|
||||
Py_XDECREF(code);
|
||||
return false;
|
||||
}
|
||||
|
||||
int err = PyDict_SetItemString(globals, name, func);
|
||||
Py_XDECREF(func);
|
||||
if ( err )
|
||||
goto ERR;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Run callback for Python external language evaluator
|
||||
bool idaapi IDAPython_extlang_run(
|
||||
@ -743,6 +703,68 @@ bool idaapi IDAPython_extlang_run(
|
||||
return ok;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Compile callback for Python external language evaluator
|
||||
bool idaapi IDAPython_extlang_compile(
|
||||
const char *name,
|
||||
ea_t /*current_ea*/,
|
||||
const char *expr,
|
||||
char *errbuf,
|
||||
size_t errbufsize)
|
||||
{
|
||||
PYW_GIL_GET;
|
||||
PyObject *globals = GetMainGlobals();
|
||||
bool is_func = false;
|
||||
|
||||
PyCodeObject *code = (PyCodeObject *)Py_CompileString(expr, "<string>", Py_eval_input);
|
||||
if ( code == NULL )
|
||||
{
|
||||
// try compiling as a list of statements
|
||||
// wrap them into a function
|
||||
handle_python_error(errbuf, errbufsize);
|
||||
qstring expr_copy = expr;
|
||||
expr_copy.replace("\n", "\n ");
|
||||
qstring qexpr;
|
||||
qexpr.sprnt("def %s():\n %s", name, expr_copy.c_str());
|
||||
code = (PyCodeObject *)Py_CompileString(qexpr.c_str(), "<string>", Py_file_input);
|
||||
if ( code == NULL )
|
||||
{
|
||||
handle_python_error(errbuf, errbufsize);
|
||||
return false;
|
||||
}
|
||||
is_func = true;
|
||||
}
|
||||
|
||||
// Set the desired function name
|
||||
Py_XDECREF(code->co_name);
|
||||
code->co_name = PyString_FromString(name);
|
||||
|
||||
// Create a function out of code
|
||||
PyObject *func = PyFunction_New((PyObject *)code, globals);
|
||||
|
||||
if ( func == NULL )
|
||||
{
|
||||
ERR:
|
||||
handle_python_error(errbuf, errbufsize);
|
||||
Py_XDECREF(code);
|
||||
return false;
|
||||
}
|
||||
|
||||
int err = PyDict_SetItemString(globals, name, func);
|
||||
Py_XDECREF(func);
|
||||
|
||||
if ( err )
|
||||
goto ERR;
|
||||
|
||||
if ( is_func )
|
||||
{
|
||||
const idc_value_t args;
|
||||
idc_value_t result;
|
||||
return IDAPython_extlang_run(name, 0, &args, &result, errbuf, errbufsize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Compile callback for Python external language evaluator
|
||||
bool idaapi IDAPython_extlang_compile_file(
|
||||
@ -1273,8 +1295,11 @@ void convert_idc_args()
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static int idaapi script_runner_cb(void *, int code, va_list)
|
||||
static int idaapi on_ui_notification(void *, int code, va_list va)
|
||||
{
|
||||
#ifdef WITH_HEXRAYS
|
||||
qnotused(va);
|
||||
#endif
|
||||
switch ( code )
|
||||
{
|
||||
case ui_ready_to_run:
|
||||
@ -1296,12 +1321,66 @@ static int idaapi script_runner_cb(void *, int code, va_list)
|
||||
RunScript(g_run_script);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef WITH_HEXRAYS
|
||||
// FIXME: HACK! THERE SHOULD BE A UI (or IDB?) NOTIFICATION
|
||||
// WHEN A PLUGIN GETS [UN]LOADED!
|
||||
// In the meantime, we're checking to see whether the Hex-Rays
|
||||
// plugin gets loaded/pulled away.
|
||||
case ui_add_menu_item:
|
||||
if ( hexdsp == NULL )
|
||||
{
|
||||
const char *name = va_arg(va, char *);
|
||||
name = va_arg(va, char *); // Drop 'menupath'. Look for 'name'.
|
||||
if ( streq(name, "Jump to pseudocode") )
|
||||
{
|
||||
init_hexrays_plugin(0);
|
||||
if ( hexdsp != NULL )
|
||||
msg("IDAPython Hex-Rays bindings initialized.\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ui_del_menu_item:
|
||||
{
|
||||
if ( hexdsp != NULL )
|
||||
{
|
||||
// Hex-Rays will close. Make sure all the refcounted cfunc_t objects
|
||||
// are cleared right away.
|
||||
const char *menupath = va_arg(va, char *);
|
||||
if ( streq(menupath, "Jump/Jump to pseudocode") )
|
||||
{
|
||||
hexrays_clear_python_cfuncptr_t_references();
|
||||
hexdsp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//lint -esym(526,til_clear_python_tinfo_t_instances) not defined
|
||||
extern void til_clear_python_tinfo_t_instances(void);
|
||||
static int idaapi on_idp_notification(void *, int code, va_list)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
case processor_t::closebase:
|
||||
// The til machinery is about to garbage-collect: We must go
|
||||
// through all the tinfo_t objects that are embedded in SWIG wrappers,
|
||||
// (i.e., that were created from Python) and clear those.
|
||||
til_clear_python_tinfo_t_instances();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
//------------------------------------------------------------------------
|
||||
// extern int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag);
|
||||
@ -1379,8 +1458,7 @@ static bool initsite(void)
|
||||
// Initialize the Python environment
|
||||
bool IDAPython_Init(void)
|
||||
{
|
||||
// Already initialized?
|
||||
if ( g_initialized )
|
||||
if ( Py_IsInitialized() != 0 )
|
||||
return true;
|
||||
|
||||
// Form the absolute path to IDA\python folder
|
||||
@ -1404,7 +1482,7 @@ bool IDAPython_Init(void)
|
||||
|
||||
#ifdef __MAC__
|
||||
// We should set python home to the module's path, otherwise it can pick up stray modules from $PATH
|
||||
NSModule pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
|
||||
NSModule pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_InitializeEx"));
|
||||
// Use dylib functions to find out where the framework was loaded from
|
||||
const char *buf = (char *)NSLibraryNameForModule(pythonModule);
|
||||
if ( buf != NULL )
|
||||
@ -1443,11 +1521,11 @@ bool IDAPython_Init(void)
|
||||
Py_NoSiteFlag = 1;
|
||||
|
||||
// Start the interpreter
|
||||
Py_Initialize();
|
||||
Py_InitializeEx(0 /* Don't catch SIGPIPE, SIGXFZ, SIGXFSZ & SIGINT signals */);
|
||||
|
||||
if ( !Py_IsInitialized() )
|
||||
{
|
||||
warning("IDAPython: Py_Initialize() failed");
|
||||
warning("IDAPython: Py_InitializeEx() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1505,6 +1583,7 @@ bool IDAPython_Init(void)
|
||||
"%s\n"
|
||||
"\n"
|
||||
"Refer to the message window to see the full error log.", tmp);
|
||||
remove_extlang(&extlang_python);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1512,6 +1591,7 @@ bool IDAPython_Init(void)
|
||||
if ( !init_pywraps() || !pywraps_nw_init() )
|
||||
{
|
||||
warning("IDAPython: init_pywraps() failed!");
|
||||
remove_extlang(&extlang_python);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1536,16 +1616,17 @@ bool IDAPython_Init(void)
|
||||
#ifdef _DEBUG
|
||||
hook_to_notification_point(HT_UI, ui_debug_handler_cb, NULL);
|
||||
#endif
|
||||
hook_to_notification_point(HT_UI, script_runner_cb, NULL);
|
||||
hook_to_notification_point(HT_UI, on_ui_notification, NULL);
|
||||
hook_to_notification_point(HT_IDP, on_idp_notification, NULL);
|
||||
|
||||
// Enable the CLI by default
|
||||
enable_python_cli(true);
|
||||
|
||||
g_initialized = true;
|
||||
pywraps_nw_notify(NW_INITIDA_SLOT);
|
||||
|
||||
PyEval_ReleaseThread(PyThreadState_Get());
|
||||
|
||||
g_instance_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1553,6 +1634,9 @@ bool IDAPython_Init(void)
|
||||
// Cleaning up Python
|
||||
void IDAPython_Term(void)
|
||||
{
|
||||
if ( !g_instance_initialized || Py_IsInitialized() == 0 )
|
||||
return;
|
||||
|
||||
if ( PyGILState_GetThisThreadState() )
|
||||
{
|
||||
// Note: No 'PYW_GIL_GET' here, as it would try to release
|
||||
@ -1563,7 +1647,8 @@ void IDAPython_Term(void)
|
||||
PyGILState_Ensure();
|
||||
}
|
||||
|
||||
unhook_from_notification_point(HT_UI, script_runner_cb, NULL);
|
||||
unhook_from_notification_point(HT_IDP, on_idp_notification, NULL);
|
||||
unhook_from_notification_point(HT_UI, on_ui_notification, NULL);
|
||||
#ifdef _DEBUG
|
||||
unhook_from_notification_point(HT_UI, ui_debug_handler_cb, NULL);
|
||||
#endif
|
||||
@ -1588,8 +1673,7 @@ void IDAPython_Term(void)
|
||||
|
||||
// Shut the interpreter down
|
||||
Py_Finalize();
|
||||
|
||||
g_initialized = false;
|
||||
g_instance_initialized = false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -481,6 +481,12 @@ def SaveBase(idbname, flags=0):
|
||||
|
||||
DBFL_BAK = idaapi.DBFL_BAK # for compatiblity with older versions, eventually delete this
|
||||
|
||||
def ValidateNames():
|
||||
"""
|
||||
check consistency of IDB name records
|
||||
@return: number of inconsistent name records
|
||||
"""
|
||||
return idaapi.validate_idb_names()
|
||||
|
||||
def Exit(code):
|
||||
"""
|
||||
@ -2245,8 +2251,12 @@ def GetOpnd(ea, n):
|
||||
0 - the first operand
|
||||
1 - the second operand
|
||||
|
||||
@return: the current text representation of operand
|
||||
@return: the current text representation of operand or ""
|
||||
"""
|
||||
|
||||
if not isCode(idaapi.get_flags_novalue(ea)):
|
||||
return ""
|
||||
|
||||
res = idaapi.ua_outop2(ea, n)
|
||||
|
||||
if not res:
|
||||
@ -6931,7 +6941,10 @@ def SetType(ea, newtype):
|
||||
@return: 1-ok, 0-failed.
|
||||
"""
|
||||
if newtype is not '':
|
||||
pt = ParseType(newtype, 0)[1:]
|
||||
pt = ParseType(newtype, 0)
|
||||
if pt is None:
|
||||
# parsing failed
|
||||
return None
|
||||
else:
|
||||
pt = None
|
||||
return ApplyType(ea, pt, TINFO_DEFINITE)
|
||||
@ -8132,6 +8145,13 @@ def CheckTraceFile(filename):
|
||||
"""
|
||||
return idaapi.is_valid_trace_file(filename)
|
||||
|
||||
def DiffTraceFile(filename):
|
||||
"""
|
||||
Diff current trace buffer against given trace
|
||||
@param filename: trace file
|
||||
"""
|
||||
return idaapi.diff_trace_file(filename)
|
||||
|
||||
def ClearTraceFile(filename):
|
||||
"""
|
||||
Clear the current trace buffer
|
||||
|
36
pywraps.hpp
36
pywraps.hpp
@ -58,40 +58,6 @@
|
||||
#define CIP_OK 1 // Success
|
||||
#define CIP_OK_OPAQUE 2 // Success, but the data pointed to by the PyObject* is an opaque object.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Helper macro to create C counterparts of Python py_clinked_object_t object
|
||||
#ifdef __PYWRAPS__
|
||||
#define DECLARE_PY_CLINKED_OBJECT(type) \
|
||||
static PyObject *type##_create() \
|
||||
{ \
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE(); \
|
||||
return PyCObject_FromVoidPtr(new type(), NULL); \
|
||||
} \
|
||||
static bool type##_destroy(PyObject *py_obj) \
|
||||
{ \
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE(); \
|
||||
if ( !PyCObject_Check(py_obj) ) \
|
||||
return false; \
|
||||
delete (type *)PyCObject_AsVoidPtr(py_obj); \
|
||||
return true; \
|
||||
} \
|
||||
static type *type##_get_clink(PyObject *self) \
|
||||
{ \
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE(); \
|
||||
return (type *)pyobj_get_clink(self); \
|
||||
} \
|
||||
static PyObject *type##_get_clink_ptr(PyObject *self) \
|
||||
{ \
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE(); \
|
||||
return PyLong_FromUnsignedLongLong( \
|
||||
(unsigned PY_LONG_LONG)pyobj_get_clink(self)); \
|
||||
}
|
||||
#else
|
||||
// SWIG does not expand macros and thus those definitions won't be wrapped
|
||||
// Use DECLARE_PY_CLINKED_OBJECT(type) inside the .i file
|
||||
#define DECLARE_PY_CLINKED_OBJECT(type)
|
||||
#endif // __PYWRAPS__
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
class gil_lock_t
|
||||
{
|
||||
@ -367,4 +333,6 @@ bool pywraps_check_autoscripts(char *buf, size_t bufsize);
|
||||
bool init_pywraps();
|
||||
void deinit_pywraps();
|
||||
|
||||
void hexrays_clear_python_cfuncptr_t_references(void);
|
||||
|
||||
#endif
|
||||
|
@ -9,8 +9,6 @@
|
||||
#define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
DECLARE_PY_CLINKED_OBJECT(textctrl_info_t);
|
||||
|
||||
static bool textctrl_info_t_assign(PyObject *self, PyObject *other)
|
||||
{
|
||||
textctrl_info_t *lhs = textctrl_info_t_get_clink(self);
|
||||
@ -145,20 +143,21 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
switch ( ft )
|
||||
{
|
||||
// dropdown list
|
||||
case 8:
|
||||
{
|
||||
// Readonly? Then return the selected index
|
||||
if ( sz == 1 )
|
||||
{
|
||||
int sel_idx;
|
||||
if ( fa->get_field_value(fid, &sel_idx) )
|
||||
if ( fa->get_combobox_value(fid, &sel_idx) )
|
||||
return PyLong_FromLong(sel_idx);
|
||||
}
|
||||
// Not readonly? Then return the qstring
|
||||
else
|
||||
{
|
||||
qstring val;
|
||||
if ( fa->get_field_value(fid, &val) )
|
||||
if ( fa->get_combobox_value(fid, &val) )
|
||||
return PyString_FromString(val.c_str());
|
||||
}
|
||||
break;
|
||||
@ -167,15 +166,15 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
case 7:
|
||||
{
|
||||
textctrl_info_t ti;
|
||||
if ( fa->get_field_value(fid, &ti) )
|
||||
if ( fa->get_text_value(fid, &ti) )
|
||||
return Py_BuildValue("(sII)", ti.text.c_str(), ti.flags, ti.tabsize);
|
||||
break;
|
||||
}
|
||||
// button - uint32
|
||||
case 4:
|
||||
{
|
||||
uint32 val;
|
||||
if ( fa->get_field_value(fid, &val) )
|
||||
uval_t val;
|
||||
if ( fa->get_unsigned_value(fid, &val) )
|
||||
return PyLong_FromUnsignedLong(val);
|
||||
break;
|
||||
}
|
||||
@ -183,7 +182,7 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
case 2:
|
||||
{
|
||||
ushort val;
|
||||
if ( fa->get_field_value(fid, &val) )
|
||||
if ( fa->_get_field_value(fid, &val) )
|
||||
return PyLong_FromUnsignedLong(val);
|
||||
break;
|
||||
}
|
||||
@ -191,7 +190,7 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
case 1:
|
||||
{
|
||||
char val[MAXSTR];
|
||||
if ( fa->get_field_value(fid, val) )
|
||||
if ( fa->get_ascii_value(fid, val, sizeof(val)) )
|
||||
return PyString_FromString(val);
|
||||
break;
|
||||
}
|
||||
@ -200,7 +199,7 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
{
|
||||
qstring val;
|
||||
val.resize(sz + 1);
|
||||
if ( fa->get_field_value(fid, val.begin()) )
|
||||
if ( fa->get_ascii_value(fid, val.begin(), val.size()) )
|
||||
return PyString_FromString(val.begin());
|
||||
break;
|
||||
}
|
||||
@ -208,12 +207,11 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
{
|
||||
intvec_t intvec;
|
||||
// Returned as 1-base
|
||||
if (fa->get_field_value(fid, &intvec))
|
||||
if (fa->get_chooser_value(fid, &intvec))
|
||||
{
|
||||
// Make 0-based
|
||||
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
|
||||
(*it)--;
|
||||
|
||||
ref_t l(PyW_IntVecToPyList(intvec));
|
||||
l.incref();
|
||||
return l.o;
|
||||
@ -234,33 +232,38 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
{
|
||||
case 'S': // sel_t
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.sel) )
|
||||
if ( fa->get_segment_value(fid, &u.sel) )
|
||||
return Py_BuildValue(PY_FMT64, u.sel);
|
||||
break;
|
||||
}
|
||||
// sval_t
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 'D':
|
||||
case 'O':
|
||||
case 'Y':
|
||||
case 'H':
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.sval) )
|
||||
if ( fa->get_signed_value(fid, &u.sval) )
|
||||
return Py_BuildValue(PY_SFMT64, u.sval);
|
||||
break;
|
||||
}
|
||||
case 'L': // uint64
|
||||
case 'l': // int64
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.ull) )
|
||||
return Py_BuildValue(sz == 'L' ? "K" : "L", u.ull);
|
||||
if ( fa->_get_field_value(fid, &u.ull) )
|
||||
return Py_BuildValue("K", u.ull);
|
||||
break;
|
||||
}
|
||||
case 'N':
|
||||
case 'M': // uval_t
|
||||
{
|
||||
if ( fa->get_unsigned_value(fid, &u.uval) )
|
||||
return Py_BuildValue(PY_FMT64, u.uval);
|
||||
break;
|
||||
}
|
||||
case '$': // ea_t
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.uval) )
|
||||
if ( fa->get_ea_value(fid, &u.uval) )
|
||||
return Py_BuildValue(PY_FMT64, u.uval);
|
||||
break;
|
||||
}
|
||||
@ -290,13 +293,13 @@ static bool formchgcbfa_set_field_value(
|
||||
if ( PyString_Check(py_val) )
|
||||
{
|
||||
qstring val(PyString_AsString(py_val));
|
||||
return fa->set_field_value(fid, &val);
|
||||
return fa->set_combobox_value(fid, &val);
|
||||
}
|
||||
// Readonly dropdown list
|
||||
else
|
||||
{
|
||||
int sel_idx = PyLong_AsLong(py_val);
|
||||
return fa->set_field_value(fid, &sel_idx);
|
||||
return fa->set_combobox_value(fid, &sel_idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -304,24 +307,24 @@ static bool formchgcbfa_set_field_value(
|
||||
case 7:
|
||||
{
|
||||
textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(py_val);
|
||||
return ti == NULL ? false : fa->set_field_value(fid, ti);
|
||||
return ti == NULL ? false : fa->set_text_value(fid, ti);
|
||||
}
|
||||
// button - uint32
|
||||
case 4:
|
||||
{
|
||||
uint32 val = PyLong_AsUnsignedLong(py_val);
|
||||
return fa->set_field_value(fid, &val);
|
||||
uval_t val = PyLong_AsUnsignedLong(py_val);
|
||||
return fa->set_unsigned_value(fid, &val);
|
||||
}
|
||||
// ushort
|
||||
case 2:
|
||||
{
|
||||
ushort val = PyLong_AsUnsignedLong(py_val) & 0xffff;
|
||||
return fa->set_field_value(fid, &val);
|
||||
return fa->_set_field_value(fid, &val);
|
||||
}
|
||||
// strings
|
||||
case 3:
|
||||
case 1:
|
||||
return fa->set_field_value(fid, PyString_AsString(py_val));
|
||||
return fa->set_ascii_value(fid, PyString_AsString(py_val));
|
||||
// intvec_t
|
||||
case 5:
|
||||
{
|
||||
@ -334,14 +337,14 @@ static bool formchgcbfa_set_field_value(
|
||||
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
|
||||
(*it)++;
|
||||
|
||||
return fa->set_field_value(fid, &intvec);
|
||||
return fa->set_chooser_value(fid, &intvec);
|
||||
}
|
||||
// Numeric
|
||||
case 6:
|
||||
{
|
||||
uint64 num;
|
||||
if ( PyW_GetNumber(py_val, &num) )
|
||||
return fa->set_field_value(fid, &num);
|
||||
return fa->_set_field_value(fid, &num);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -351,6 +354,11 @@ static bool formchgcbfa_set_field_value(
|
||||
|
||||
static size_t py_get_AskUsingForm()
|
||||
{
|
||||
// Return a pointer to the function. Note that, although
|
||||
// the C implementation of AskUsingForm_cv will do some
|
||||
// Qt/txt widgets generation, the Python's ctypes
|
||||
// implementation through which the call well go will first
|
||||
// unblock other threads. No need to do it ourselves.
|
||||
return (size_t)AskUsingForm_c;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ try:
|
||||
from _idaapi import set_script_timeout
|
||||
import idaapi
|
||||
from idaapi import py_clinked_object_t
|
||||
from idaapi import qstrvec_t
|
||||
from idaapi import _qstrvec_t
|
||||
stdalone = False
|
||||
except:
|
||||
stdalone = True
|
||||
@ -50,7 +50,7 @@ try:
|
||||
from py_choose2 import *
|
||||
py_clinked_object_t = idaapi.py_clinked_object_t
|
||||
textctrl_info_t = idaapi.textctrl_info_t
|
||||
qstrvec_t = idaapi.qstrvec_t
|
||||
_qstrvec_t = idaapi._qstrvec_t
|
||||
|
||||
_idaapi.BADADDR = 0xFFFFFFFF
|
||||
_idaapi.MAXSTR = 1024
|
||||
@ -776,7 +776,7 @@ class Form(object):
|
||||
Form.Control.free(self)
|
||||
|
||||
|
||||
class DropdownListControl(InputControl, qstrvec_t):
|
||||
class DropdownListControl(InputControl, _qstrvec_t):
|
||||
"""
|
||||
Dropdown control
|
||||
This control allows manipulating a dropdown control
|
||||
@ -803,7 +803,7 @@ class Form(object):
|
||||
hlp)
|
||||
|
||||
# Init the associated qstrvec
|
||||
qstrvec_t.__init__(self, items)
|
||||
_qstrvec_t.__init__(self, items)
|
||||
|
||||
# Remember if readonly or not
|
||||
self.readonly = readonly
|
||||
@ -814,7 +814,7 @@ class Form(object):
|
||||
val_addr = addressof(self.__selval)
|
||||
else:
|
||||
# Create an strvec with one qstring
|
||||
self.__selval = qstrvec_t([selval])
|
||||
self.__selval = _qstrvec_t([selval])
|
||||
# Get address of the first element
|
||||
val_addr = self.__selval.addressof(0)
|
||||
|
||||
|
@ -289,8 +289,8 @@ private:
|
||||
self,
|
||||
(char *)S_ON_DELETE_LINE,
|
||||
"i",
|
||||
lineno - 1));
|
||||
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o) + 1;
|
||||
IS_CHOOSER_EVENT(lineno) ? lineno : lineno-1));
|
||||
return pyres == NULL ? 1 : PyInt_AsLong(pyres.o);
|
||||
}
|
||||
|
||||
int on_refresh(int lineno)
|
||||
|
@ -112,7 +112,6 @@ private:
|
||||
|
||||
static cmdid_map_t cmdid_pyg;
|
||||
|
||||
// TForm *form;
|
||||
bool refresh_needed;
|
||||
nodetext_cache_map_t node_cache;
|
||||
|
||||
@ -122,6 +121,7 @@ private:
|
||||
// static callback
|
||||
static int idaapi s_callback(void *obj, int code, va_list va)
|
||||
{
|
||||
QASSERT(30453, py_customidamemo_t::lookup_info.find_by_py_view(NULL, NULL, (py_graph_t *) obj));
|
||||
PYW_GIL_GET;
|
||||
return ((py_graph_t *)obj)->gr_callback(code, va);
|
||||
}
|
||||
@ -255,13 +255,13 @@ private:
|
||||
}
|
||||
|
||||
// a group is being created
|
||||
int on_creating_group(mutable_graph_t *my_g, intset_t *my_nodes)
|
||||
int on_creating_group(mutable_graph_t *my_g, intvec_t *my_nodes)
|
||||
{
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
printf("my_g: %p; my_nodes: %p\n", my_g, my_nodes);
|
||||
newref_t py_nodes(PyList_New(my_nodes->size()));
|
||||
int i;
|
||||
intset_t::const_iterator p;
|
||||
intvec_t::const_iterator p;
|
||||
for ( i = 0, p=my_nodes->begin(); p != my_nodes->end(); ++p, ++i )
|
||||
PyList_SetItem(py_nodes.o, i, PyInt_FromLong(*p));
|
||||
newref_t py_result(
|
||||
@ -331,6 +331,7 @@ private:
|
||||
TForm *form = create_tform(title, &hwnd);
|
||||
if ( hwnd != NULL ) // Created new tform
|
||||
{
|
||||
lookup_info_t::entry_t &e = lookup_info.new_entry(this);
|
||||
// get a unique graph id
|
||||
netnode id;
|
||||
char grnode[MAXSTR];
|
||||
@ -342,8 +343,7 @@ private:
|
||||
viewer_fit_window(pview);
|
||||
bind(self, pview);
|
||||
refresh();
|
||||
// Link "form" and "py_graph"
|
||||
lookup_info.add(form, view, this);
|
||||
lookup_info.commit(e, form, view);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -700,7 +700,7 @@ int py_graph_t::gr_callback(int code, va_list va)
|
||||
case grcode_creating_group: // a group is being created
|
||||
{
|
||||
mutable_graph_t *g = va_arg(va, mutable_graph_t*);
|
||||
intset_t *nodes = va_arg(va, intset_t*);
|
||||
intvec_t *nodes = va_arg(va, intvec_t*);
|
||||
ret = on_creating_group(g, nodes);
|
||||
}
|
||||
break;
|
||||
|
@ -726,12 +726,9 @@ def RunPythonStatement(stmt):
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
/*
|
||||
//---------------------------------------------------------------------------
|
||||
// qstrvec_t wrapper
|
||||
// qstrvec_t wrapper (INTERNAL! Don't expose. See py_idaapi.py)
|
||||
//---------------------------------------------------------------------------
|
||||
DECLARE_PY_CLINKED_OBJECT(qstrvec_t);
|
||||
|
||||
static bool qstrvec_t_assign(PyObject *self, PyObject *other)
|
||||
{
|
||||
qstrvec_t *lhs = qstrvec_t_get_clink(self);
|
||||
@ -833,7 +830,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
||||
sv->erase(sv->begin()+idx);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//</inline(py_idaapi)>
|
||||
|
||||
|
@ -171,6 +171,12 @@ class object_t(object):
|
||||
"""Allow access to object attributes by index (like dictionaries)"""
|
||||
return getattr(self, idx)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def _bounded_getitem_iterator(self):
|
||||
"""Helper function, to be set as __iter__ method for qvector-, or array-based classes."""
|
||||
for i in range(len(self)):
|
||||
yield self[i]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class plugin_t(pyidc_opaque_object_t):
|
||||
"""Base class for all scripted plugins."""
|
||||
@ -237,72 +243,79 @@ class PyIdc_cvt_int64__(pyidc_cvt_helper__):
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# qstrvec_t clinked object
|
||||
# class qstrvec_t(py_clinked_object_t):
|
||||
# """Class representing an qstrvec_t"""
|
||||
class _qstrvec_t(py_clinked_object_t):
|
||||
"""
|
||||
WARNING: It is very unlikely an IDAPython user should ever, ever
|
||||
have to use this type. It should only be used for IDAPython internals.
|
||||
|
||||
# def __init__(self, items=None):
|
||||
# py_clinked_object_t.__init__(self)
|
||||
# # Populate the list if needed
|
||||
# if items:
|
||||
# self.from_list(items)
|
||||
For example, in py_askusingform.py, we ctypes-expose to the IDA
|
||||
kernel & UI a qstrvec instance, in case a DropdownListControl is
|
||||
constructed.
|
||||
That's because that's what AskUsingForm expects, and we have no
|
||||
choice but to make a DropdownListControl hold a qstrvec_t.
|
||||
This is, afaict, the only situation where a Python
|
||||
_qstrvec_t is required.
|
||||
"""
|
||||
|
||||
# def _create_clink(self):
|
||||
# return _idaapi.qstrvec_t_create()
|
||||
def __init__(self, items=None):
|
||||
py_clinked_object_t.__init__(self)
|
||||
# Populate the list if needed
|
||||
if items:
|
||||
self.from_list(items)
|
||||
|
||||
# def _del_clink(self, lnk):
|
||||
# return _idaapi.qstrvec_t_destroy(lnk)
|
||||
def _create_clink(self):
|
||||
return _idaapi.qstrvec_t_create()
|
||||
|
||||
# def _get_clink_ptr(self):
|
||||
# return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
def _del_clink(self, lnk):
|
||||
return _idaapi.qstrvec_t_destroy(lnk)
|
||||
|
||||
# def assign(self, other):
|
||||
# """Copies the contents of 'other' to 'self'"""
|
||||
# return _idaapi.qstrvec_t_assign(self, other)
|
||||
def _get_clink_ptr(self):
|
||||
return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
|
||||
# def __setitem__(self, idx, s):
|
||||
# """Sets string at the given index"""
|
||||
# return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
def assign(self, other):
|
||||
"""Copies the contents of 'other' to 'self'"""
|
||||
return _idaapi.qstrvec_t_assign(self, other)
|
||||
|
||||
# def __getitem__(self, idx):
|
||||
# """Gets the string at the given index"""
|
||||
# return _idaapi.qstrvec_t_get(self, idx)
|
||||
def __setitem__(self, idx, s):
|
||||
"""Sets string at the given index"""
|
||||
return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
|
||||
# def __get_size(self):
|
||||
# return _idaapi.qstrvec_t_size(self)
|
||||
def __getitem__(self, idx):
|
||||
"""Gets the string at the given index"""
|
||||
return _idaapi.qstrvec_t_get(self, idx)
|
||||
|
||||
# size = property(__get_size)
|
||||
# """Returns the count of elements"""
|
||||
def __get_size(self):
|
||||
return _idaapi.qstrvec_t_size(self)
|
||||
|
||||
# def addressof(self, idx):
|
||||
# """Returns the address (as number) of the qstring at the given index"""
|
||||
# return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
size = property(__get_size)
|
||||
"""Returns the count of elements"""
|
||||
|
||||
# def add(self, s):
|
||||
# """Add a string to the vector"""
|
||||
# return _idaapi.qstrvec_t_add(self, s)
|
||||
def addressof(self, idx):
|
||||
"""Returns the address (as number) of the qstring at the given index"""
|
||||
return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
|
||||
def add(self, s):
|
||||
"""Add a string to the vector"""
|
||||
return _idaapi.qstrvec_t_add(self, s)
|
||||
|
||||
# def from_list(self, lst):
|
||||
# """Populates the vector from a Python string list"""
|
||||
# return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
def from_list(self, lst):
|
||||
"""Populates the vector from a Python string list"""
|
||||
return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
|
||||
def clear(self, qclear=False):
|
||||
"""
|
||||
Clears all strings from the vector.
|
||||
@param qclear: Just reset the size but do not actually free the memory
|
||||
"""
|
||||
return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
|
||||
# def clear(self, qclear=False):
|
||||
# """
|
||||
# Clears all strings from the vector.
|
||||
# @param qclear: Just reset the size but do not actually free the memory
|
||||
# """
|
||||
# return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
def insert(self, idx, s):
|
||||
"""Insert a string into the vector"""
|
||||
return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
|
||||
|
||||
# def insert(self, idx, s):
|
||||
# """Insert a string into the vector"""
|
||||
# return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
|
||||
|
||||
# def remove(self, idx):
|
||||
# """Removes a string from the vector"""
|
||||
# return _idaapi.qstrvec_t_remove(self, idx)
|
||||
def remove(self, idx):
|
||||
"""Removes a string from the vector"""
|
||||
return _idaapi.qstrvec_t_remove(self, idx)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
||||
@ -580,7 +593,13 @@ class __IDAPython_Completion_Util(object):
|
||||
|
||||
return s
|
||||
|
||||
# Instantiate a completion object
|
||||
# Instantiate an IDAPython command completion object (for use with IDA's CLI bar)
|
||||
IDAPython_Completion = __IDAPython_Completion_Util()
|
||||
|
||||
def _listify_types(*classes):
|
||||
for cls in classes:
|
||||
cls.__getitem__ = cls.at
|
||||
cls.__len__ = cls.size
|
||||
cls.__iter__ = _bounded_getitem_iterator
|
||||
|
||||
#</pycode(py_idaapi)>
|
||||
|
@ -42,7 +42,8 @@ bool py_idaview_t::Bind(PyObject *self)
|
||||
else
|
||||
{
|
||||
py_view = new py_idaview_t();
|
||||
lookup_info.add(tform, v, py_view);
|
||||
lookup_info_t::entry_t &e = lookup_info.new_entry(py_view);
|
||||
lookup_info.commit(e, tform, v);
|
||||
}
|
||||
|
||||
// Finally, bind:
|
||||
|
@ -807,6 +807,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum areacb_type_t
|
||||
{
|
||||
AREACB_TYPE_UNKNOWN,
|
||||
AREACB_TYPE_FUNC,
|
||||
AREACB_TYPE_SEGMENT,
|
||||
AREACB_TYPE_HIDDEN_AREA,
|
||||
AREACB_TYPE_SRAREA,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// IDB hooks
|
||||
//---------------------------------------------------------------------------
|
||||
@ -827,8 +836,9 @@ public:
|
||||
// Hook functions to override in Python
|
||||
virtual int byte_patched(ea_t /*ea*/) { return 0; };
|
||||
virtual int cmt_changed(ea_t, bool /*repeatable_cmt*/) { return 0; };
|
||||
virtual int ti_changed(ea_t /*ea*/, const type_t * /*type*/, const p_list * /*fnames*/) { msg("ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int op_ti_changed(ea_t /*ea*/, int /*n*/, const type_t * /*type*/, const p_list * /*fnames*/) { msg("op_ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int area_cmt_changed(areacb_t * /*areas*/, area_t * /*area*/, const char * /*cmt*/, bool /*repeatable*/) { return 0; }
|
||||
virtual int ti_changed(ea_t /*ea*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; };
|
||||
virtual int op_ti_changed(ea_t /*ea*/, int /*n*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; };
|
||||
virtual int op_type_changed(ea_t /*ea*/, int /*n*/) { return 0; };
|
||||
virtual int enum_created(enum_t /*id*/) { return 0; };
|
||||
virtual int enum_deleted(enum_t /*id*/) { return 0; };
|
||||
@ -1365,8 +1375,8 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
|
||||
ea_t ea, ea2;
|
||||
bool repeatable_cmt;
|
||||
/*type_t *type;*/
|
||||
/* p_list *fnames; */
|
||||
type_t *type;
|
||||
p_list *fnames;
|
||||
int n;
|
||||
enum_t id;
|
||||
const_t cid;
|
||||
@ -1390,20 +1400,29 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
ea = va_arg(va, ea_t);
|
||||
repeatable_cmt = va_arg(va, int);
|
||||
return proxy->cmt_changed(ea, repeatable_cmt);
|
||||
#if 0
|
||||
|
||||
case idb_event::area_cmt_changed:
|
||||
{
|
||||
areacb_t *cb = va_arg(va, areacb_t*);
|
||||
area_t *area = va_arg(va, area_t*);
|
||||
const char *cmt = va_arg(va, char*);
|
||||
repeatable_cmt = va_arg(va, int);
|
||||
return proxy->area_cmt_changed(cb, area, cmt, repeatable_cmt);
|
||||
}
|
||||
|
||||
case idb_event::ti_changed:
|
||||
ea = va_arg(va, ea_t);
|
||||
type = va_arg(va, type_t *);
|
||||
fnames = va_arg(va, fnames);
|
||||
fnames = va_arg(va, p_list *);
|
||||
return proxy->ti_changed(ea, type, fnames);
|
||||
|
||||
case idb_event::op_ti_changed:
|
||||
ea = va_arg(va, ea_t);
|
||||
n = va_arg(va, int);
|
||||
type = va_arg(va, type_t *);
|
||||
fnames = va_arg(va, fnames);
|
||||
fnames = va_arg(va, p_list *);
|
||||
return proxy->op_ti_changed(ea, n, type, fnames);
|
||||
#endif
|
||||
|
||||
case idb_event::op_type_changed:
|
||||
ea = va_arg(va, ea_t);
|
||||
n = va_arg(va, int);
|
||||
|
@ -5,30 +5,6 @@
|
||||
//<inline(py_kernwin)>
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def read_selection():
|
||||
"""
|
||||
Returns selected area boundaries
|
||||
|
||||
@return: tuple(ok: bool, start_ea, end_ea)
|
||||
"""
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
static PyObject *py_read_selection()
|
||||
{
|
||||
ea_t ea1, ea2;
|
||||
bool b = read_selection(&ea1, &ea2);
|
||||
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
return Py_BuildValue(
|
||||
"(i" PY_FMT64 PY_FMT64 ")",
|
||||
b ? 1 : 0,
|
||||
pyul_t(ea1), pyul_t(ea2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
@ -203,6 +179,45 @@ def free_custom_icon(icon_id):
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def readsel2(view, p0, p1):
|
||||
"""
|
||||
Read the user selection, and store its information in p0 (from) and p1 (to).
|
||||
|
||||
This can be used as follows:
|
||||
|
||||
|
||||
>>> p0 = idaapi.twinpos_t()
|
||||
p1 = idaapi.twinpos_t()
|
||||
view = idaapi.get_current_viewer()
|
||||
idaapi.readsel2(view, p0, p1)
|
||||
|
||||
|
||||
At that point, p0 and p1 hold information for the selection.
|
||||
But, the 'at' property of p0 and p1 is not properly typed.
|
||||
To specialize it, call #place() on it, passing it the view
|
||||
they were retrieved from. Like so:
|
||||
|
||||
|
||||
>>> place0 = p0.place(view)
|
||||
place1 = p1.place(view)
|
||||
|
||||
|
||||
This will effectively "cast" the place into a specialized type,
|
||||
holding proper information, depending on the view type (e.g.,
|
||||
disassembly, structures, enums, ...)
|
||||
|
||||
@param view: The view to retrieve the selection for.
|
||||
@param p0: Storage for the "from" part of the selection.
|
||||
@param p1: Storage for the "to" part of the selection.
|
||||
@return: a bool value indicating success.
|
||||
"""
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
|
@ -135,6 +135,54 @@ idaman bool ida_export py_create_switch_xrefs(
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct cases_and_targets_t
|
||||
{
|
||||
casevec_t cases;
|
||||
eavec_t targets;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def calc_switch_cases(insn_ea, si):
|
||||
"""
|
||||
Get information about a switch's cases.
|
||||
|
||||
The returned information can be used as follows:
|
||||
|
||||
for idx in xrange(len(results.cases)):
|
||||
cur_case = results.cases[idx]
|
||||
for cidx in xrange(len(cur_case)):
|
||||
print "case: %d" % cur_case[cidx]
|
||||
print " goto 0x%x" % results.targets[idx]
|
||||
|
||||
@param insn_ea: address of the 'indirect jump' instruction
|
||||
@param si: switch information
|
||||
|
||||
@return: a structure with 2 members: 'cases', and 'targets'.
|
||||
"""
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
idaman cases_and_targets_t *ida_export py_calc_switch_cases(
|
||||
ea_t insn_ea,
|
||||
PyObject *py_swi)
|
||||
{
|
||||
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
|
||||
if ( swi == NULL )
|
||||
return NULL;
|
||||
|
||||
cases_and_targets_t *ct = new cases_and_targets_t;
|
||||
if ( !calc_switch_cases(insn_ea, swi, &ct->cases, &ct->targets) )
|
||||
{
|
||||
delete ct;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ct;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
|
@ -532,7 +532,49 @@ char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize)
|
||||
qstrncpy(buf, name, bufsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
//</inline(py_typeinf)>
|
||||
|
||||
//<code(py_typeinf)>
|
||||
//-------------------------------------------------------------------------
|
||||
// A set of tinfo_t objects that were created from IDAPython.
|
||||
// This is necessary in order to clear all the "type details" that are
|
||||
// associated, in the kernel, with the tinfo_t instances.
|
||||
//
|
||||
// Unfortunately the IDAPython plugin has to terminate _after_ the IDB is
|
||||
// closed, but the "type details" must be cleared _before_ the IDB is closed.
|
||||
static qvector<tinfo_t*> python_tinfos;
|
||||
void til_clear_python_tinfo_t_instances(void)
|
||||
{
|
||||
// Pre-emptive strike: clear all the python-exposed tinfo_t instances: if that
|
||||
// were not done here, ~tinfo_t() calls happening as part of the python shutdown
|
||||
// process will try and clear() their details. ..but the kernel's til-related
|
||||
// functions will already have deleted those details at that point.
|
||||
for ( size_t i = 0, n = python_tinfos.size(); i < n; ++i )
|
||||
python_tinfos[i]->clear();
|
||||
// NOTE: Don't clear() the array of pointers. All the python-exposed tinfo_t
|
||||
// instances will be deleted through the python shutdown/ref-decrementing
|
||||
// process anyway (which will cause til_deregister_..() calls), and the
|
||||
// entries will be properly pulled out of the vector when that happens.
|
||||
}
|
||||
|
||||
void til_register_python_tinfo_t_instance(tinfo_t *tif)
|
||||
{
|
||||
// Let's add_unique() it, because every reference to an object's
|
||||
// tinfo_t property will end up trying to register it.
|
||||
python_tinfos.add_unique(tif);
|
||||
}
|
||||
|
||||
void til_deregister_python_tinfo_t_instance(tinfo_t *tif)
|
||||
{
|
||||
qvector<tinfo_t*>::iterator found = python_tinfos.find(tif);
|
||||
if ( found != python_tinfos.end() )
|
||||
{
|
||||
tif->clear();
|
||||
python_tinfos.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
//</code(py_typeinf)>
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -746,7 +746,7 @@ static PyObject *op_t_get_value(PyObject *self)
|
||||
op_t *link = op_t_get_clink(self);
|
||||
if ( link == NULL )
|
||||
Py_RETURN_NONE;
|
||||
return Py_BuildValue("I", link->value);
|
||||
return Py_BuildValue(PY_FMT64, (pyul_t)link->value);
|
||||
}
|
||||
|
||||
static void op_t_set_value(PyObject *self, PyObject *value)
|
||||
@ -755,7 +755,9 @@ static void op_t_set_value(PyObject *self, PyObject *value)
|
||||
op_t *link = op_t_get_clink(self);
|
||||
if ( link == NULL )
|
||||
return;
|
||||
link->value = PyInt_AsLong(value);
|
||||
uint64 v(0);
|
||||
PyW_GetNumber(value, &v);
|
||||
link->value = uval_t(v);
|
||||
}
|
||||
|
||||
static PyObject *op_t_get_addr(PyObject *self)
|
||||
|
@ -15,16 +15,33 @@ class py_customidamemo_t;
|
||||
class lookup_info_t
|
||||
{
|
||||
public:
|
||||
void add(TForm *form, TCustomControl *view, py_customidamemo_t *py_view)
|
||||
struct entry_t
|
||||
{
|
||||
QASSERT(0, form != NULL && view != NULL && py_view != NULL
|
||||
entry_t() : form(NULL), view(NULL), py_view(NULL) {}
|
||||
private:
|
||||
TForm *form;
|
||||
TCustomControl *view;
|
||||
py_customidamemo_t *py_view;
|
||||
friend class lookup_info_t;
|
||||
};
|
||||
|
||||
entry_t &new_entry(py_customidamemo_t *py_view)
|
||||
{
|
||||
QASSERT(30454, py_view != NULL && !find_by_py_view(NULL, NULL, py_view));
|
||||
entry_t &e = entries.push_back();
|
||||
e.py_view = py_view;
|
||||
return e;
|
||||
}
|
||||
|
||||
void commit(entry_t &e, TForm *form, TCustomControl *view)
|
||||
{
|
||||
QASSERT(30455, &e >= entries.begin() && &e < entries.end());
|
||||
QASSERT(30456, form != NULL && view != NULL && e.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();
|
||||
&& find_by_py_view(NULL, NULL, e.py_view));
|
||||
e.form = form;
|
||||
e.view = view;
|
||||
e.py_view = py_view;
|
||||
}
|
||||
|
||||
#define FIND_BY__BODY(crit, res1, res2) \
|
||||
@ -62,12 +79,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
struct entry_t
|
||||
{
|
||||
TForm *form;
|
||||
TCustomControl *view;
|
||||
py_customidamemo_t *py_view;
|
||||
};
|
||||
typedef qvector<entry_t> entries_t;
|
||||
entries_t entries;
|
||||
};
|
||||
@ -131,6 +142,8 @@ class py_customidamemo_t
|
||||
|
||||
static void ensure_view_callbacks_installed();
|
||||
int cb_flags;
|
||||
// number of arguments for OnViewClick implementation
|
||||
int ovc_num_args;
|
||||
|
||||
protected:
|
||||
ref_t self;
|
||||
@ -199,6 +212,7 @@ public:
|
||||
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; }
|
||||
int get_py_method_arg_count(char *method_name);
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -208,6 +222,7 @@ py_customidamemo_t::py_customidamemo_t()
|
||||
{
|
||||
PYGLOG("%p: py_customidamemo_t()\n", this);
|
||||
ensure_view_callbacks_installed();
|
||||
ovc_num_args = -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -402,7 +417,7 @@ PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos)
|
||||
{
|
||||
newref_t node(PySequence_GetItem(nodes.o, k));
|
||||
if ( PyInt_Check(node.o) )
|
||||
gi.nodes.insert(PyInt_AsLong(node.o));
|
||||
gi.nodes.add_unique(PyInt_AsLong(node.o));
|
||||
}
|
||||
if ( !gi.nodes.empty() )
|
||||
{
|
||||
@ -410,18 +425,18 @@ PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos)
|
||||
gis.push_back(gi);
|
||||
}
|
||||
}
|
||||
intset_t groups;
|
||||
intvec_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 )
|
||||
for ( intvec_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)
|
||||
static void pynodes_to_idanodes(intvec_t *idanodes, ref_t pynodes)
|
||||
{
|
||||
Py_ssize_t sz = PySequence_Size(pynodes.o);
|
||||
for ( Py_ssize_t i = 0; i < sz; ++i )
|
||||
@ -429,7 +444,7 @@ static void pynodes_to_idanodes(intset_t *idanodes, ref_t pynodes)
|
||||
newref_t item(PySequence_GetItem(pynodes.o, i));
|
||||
if ( !PyInt_Check(item.o) )
|
||||
continue;
|
||||
idanodes->insert(PyInt_AsLong(item.o));
|
||||
idanodes->add_unique(PyInt_AsLong(item.o));
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,7 +455,7 @@ PyObject *py_customidamemo_t::delete_groups(PyObject *_groups, PyObject *_new_cu
|
||||
Py_RETURN_NONE;
|
||||
borref_t groups(_groups);
|
||||
borref_t new_current(_new_current);
|
||||
intset_t ida_groups;
|
||||
intvec_t ida_groups;
|
||||
pynodes_to_idanodes(&ida_groups, groups);
|
||||
if ( ida_groups.empty() )
|
||||
Py_RETURN_NONE;
|
||||
@ -460,7 +475,7 @@ PyObject *py_customidamemo_t::set_groups_visibility(PyObject *_groups, PyObject
|
||||
borref_t groups(_groups);
|
||||
borref_t expand(_expand);
|
||||
borref_t new_current(_new_current);
|
||||
intset_t ida_groups;
|
||||
intvec_t ida_groups;
|
||||
pynodes_to_idanodes(&ida_groups, groups);
|
||||
if ( ida_groups.empty() )
|
||||
Py_RETURN_NONE;
|
||||
@ -499,6 +514,23 @@ void py_customidamemo_t::unbind()
|
||||
view = NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
int py_customidamemo_t::get_py_method_arg_count(char *method_name)
|
||||
{
|
||||
newref_t method(PyObject_GetAttrString(self.o, method_name));
|
||||
if ( method != NULL && PyCallable_Check(method.o) )
|
||||
{
|
||||
newref_t fc(PyObject_GetAttrString(method.o, "func_code"));
|
||||
if ( fc != NULL )
|
||||
{
|
||||
newref_t ac(PyObject_GetAttrString(fc.o, "co_argcount"));
|
||||
if ( ac != NULL )
|
||||
return PyInt_AsLong(ac.o);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void py_customidamemo_t::collect_class_callbacks_ids(callbacks_ids_t *out)
|
||||
{
|
||||
@ -604,12 +636,26 @@ void py_customidamemo_t::on_view_popup()
|
||||
void py_customidamemo_t::on_view_click(const view_mouse_event_t *event)
|
||||
{
|
||||
CHK_EVT(GRBASE_HAVE_VIEW_CLICK);
|
||||
if ( ovc_num_args < 0 )
|
||||
ovc_num_args = get_py_method_arg_count((char*)S_ON_VIEW_CLICK);
|
||||
if ( ovc_num_args == 5 )
|
||||
{
|
||||
newref_t result(
|
||||
PyObject_CallMethod(
|
||||
self.o,
|
||||
(char *)S_ON_VIEW_CLICK,
|
||||
"iiii",
|
||||
event->x, event->y, event->state, event->button));
|
||||
}
|
||||
else
|
||||
{
|
||||
newref_t result(
|
||||
PyObject_CallMethod(
|
||||
self.o,
|
||||
(char *)S_ON_VIEW_CLICK,
|
||||
"iii",
|
||||
event->x, event->y, event->state));
|
||||
}
|
||||
CHK_RES();
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@
|
||||
%ignore term_flags;
|
||||
%ignore reset_flags;
|
||||
%ignore flush_flags;
|
||||
%ignore get_flags_linput;
|
||||
%ignore data_type_t;
|
||||
%ignore data_format_t;
|
||||
%ignore get_custom_data_type;
|
||||
|
24
swig/dbg.i
24
swig/dbg.i
@ -22,6 +22,8 @@ typedef struct
|
||||
%ignore bpt_t::write;
|
||||
%ignore bpt_t::erase;
|
||||
%ignore bpt_t::cndbody;
|
||||
%ignore bpt_t::get_cnd_elang;
|
||||
%ignore bpt_t::set_cnd_elang;
|
||||
%rename (get_manual_regions) py_get_manual_regions;
|
||||
%ignore set_manual_regions;
|
||||
%ignore inform_idc_about_debthread;
|
||||
@ -45,6 +47,7 @@ static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
|
||||
%extend bpt_t
|
||||
{
|
||||
PyObject *condition;
|
||||
PyObject *elang;
|
||||
}
|
||||
%{
|
||||
PyObject *bpt_t_condition_get(bpt_t *bpt)
|
||||
@ -56,6 +59,27 @@ void bpt_t_condition_set(bpt_t *bpt, PyObject *val)
|
||||
{
|
||||
if ( PyString_Check(val) )
|
||||
bpt->cndbody = PyString_AsString(val);
|
||||
else
|
||||
PyErr_SetString(PyExc_ValueError, "expected a string");
|
||||
}
|
||||
|
||||
PyObject *bpt_t_elang_get(bpt_t *bpt)
|
||||
{
|
||||
return PyString_FromString(bpt->get_cnd_elang());
|
||||
}
|
||||
|
||||
void bpt_t_elang_set(bpt_t *bpt, PyObject *val)
|
||||
{
|
||||
if ( PyString_Check(val) )
|
||||
{
|
||||
char *cval = PyString_AsString(val);
|
||||
if ( !bpt->set_cnd_elang(cval) )
|
||||
PyErr_SetString(PyExc_ValueError, "too many extlangs");
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "expected a string");
|
||||
}
|
||||
}
|
||||
%}
|
||||
%inline %{
|
||||
|
@ -29,6 +29,7 @@
|
||||
%ignore make_linput;
|
||||
%ignore unmake_linput;
|
||||
%ignore create_remote_linput;
|
||||
%ignore make_filehandle_linput;
|
||||
|
||||
// FIXME: These should be wrapped for completeness
|
||||
%ignore eread;
|
||||
|
@ -43,6 +43,7 @@
|
||||
%ignore init_idc;
|
||||
%ignore term_idc;
|
||||
%ignore create_default_idc_classes;
|
||||
%ignore notify_extlang_changed;
|
||||
%ignore insn_to_idc;
|
||||
%ignore find_builtin_idc_func;
|
||||
%ignore idc_mutex;
|
||||
|
12
swig/graph.i
12
swig/graph.i
@ -115,7 +115,6 @@ private:
|
||||
|
||||
static cmdid_map_t cmdid_pyg;
|
||||
|
||||
// TForm *form;
|
||||
bool refresh_needed;
|
||||
nodetext_cache_map_t node_cache;
|
||||
|
||||
@ -125,6 +124,7 @@ private:
|
||||
// static callback
|
||||
static int idaapi s_callback(void *obj, int code, va_list va)
|
||||
{
|
||||
QASSERT(30453, py_customidamemo_t::lookup_info.find_by_py_view(NULL, NULL, (py_graph_t *) obj));
|
||||
PYW_GIL_GET;
|
||||
return ((py_graph_t *)obj)->gr_callback(code, va);
|
||||
}
|
||||
@ -258,13 +258,13 @@ private:
|
||||
}
|
||||
|
||||
// a group is being created
|
||||
int on_creating_group(mutable_graph_t *my_g, intset_t *my_nodes)
|
||||
int on_creating_group(mutable_graph_t *my_g, intvec_t *my_nodes)
|
||||
{
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
printf("my_g: %p; my_nodes: %p\n", my_g, my_nodes);
|
||||
newref_t py_nodes(PyList_New(my_nodes->size()));
|
||||
int i;
|
||||
intset_t::const_iterator p;
|
||||
intvec_t::const_iterator p;
|
||||
for ( i = 0, p=my_nodes->begin(); p != my_nodes->end(); ++p, ++i )
|
||||
PyList_SetItem(py_nodes.o, i, PyInt_FromLong(*p));
|
||||
newref_t py_result(
|
||||
@ -334,6 +334,7 @@ private:
|
||||
TForm *form = create_tform(title, &hwnd);
|
||||
if ( hwnd != NULL ) // Created new tform
|
||||
{
|
||||
lookup_info_t::entry_t &e = lookup_info.new_entry(this);
|
||||
// get a unique graph id
|
||||
netnode id;
|
||||
char grnode[MAXSTR];
|
||||
@ -345,8 +346,7 @@ private:
|
||||
viewer_fit_window(pview);
|
||||
bind(self, pview);
|
||||
refresh();
|
||||
// Link "form" and "py_graph"
|
||||
lookup_info.add(form, view, this);
|
||||
lookup_info.commit(e, form, view);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -703,7 +703,7 @@ int py_graph_t::gr_callback(int code, va_list va)
|
||||
case grcode_creating_group: // a group is being created
|
||||
{
|
||||
mutable_graph_t *g = va_arg(va, mutable_graph_t*);
|
||||
intset_t *nodes = va_arg(va, intset_t*);
|
||||
intvec_t *nodes = va_arg(va, intvec_t*);
|
||||
ret = on_creating_group(g, nodes);
|
||||
}
|
||||
break;
|
||||
|
309
swig/hexrays.i
309
swig/hexrays.i
@ -21,27 +21,25 @@
|
||||
#pragma SWIG nowarn=454 // Setting a pointer/reference variable may leak memory
|
||||
|
||||
#define _STD_BEGIN
|
||||
#define typename
|
||||
|
||||
%{
|
||||
#include "hexrays.hpp"
|
||||
%}
|
||||
#ifdef __NT__
|
||||
%include <windows.i>
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// some defines to calm SWIG down.
|
||||
#define DEFINE_MEMORY_ALLOCATION_FUNCS()
|
||||
//#define DECLARE_UNCOPYABLE(f)
|
||||
#define AS_PRINTF(format_idx, varg_idx)
|
||||
#define idaapi
|
||||
#define __fastcall
|
||||
|
||||
%ignore vd_printer_t::vprint;
|
||||
%ignore string_printer_t::vprint;
|
||||
%ignore typestring::dstr;
|
||||
%ignore typestring::multiprint;
|
||||
%ignore vdui_t::vdui_t;
|
||||
%ignore cblock_t::find;
|
||||
%ignore cfunc_t::cfunc_t;
|
||||
%ignore cfunc_t::sv; // lazy member. Use get_pseudocode() instead
|
||||
%ignore cfunc_t::boundaries; // lazy member. Use get_boundaries() instead
|
||||
%ignore cfunc_t::eamap; // lazy member. Use get_eamap() instead
|
||||
%ignore ctree_item_t::verify;
|
||||
%ignore ccases_t::find_value;
|
||||
%ignore ccases_t::print;
|
||||
@ -60,27 +58,61 @@
|
||||
%ignore lvar_t::is_promoted_arg;
|
||||
%ignore lvar_t::lvar_t;
|
||||
%ignore strtype_info_t::find_strmem;
|
||||
%ignore typestring::resolve_func_type;
|
||||
%ignore typestring::common_type;
|
||||
%ignore typestring::noarray_size;
|
||||
%ignore file_printer_t::_print;
|
||||
%ignore file_printer_t;
|
||||
%ignore qstring_printer_t::qstring_printer_t(const cfunc_t *, qstring &, bool);
|
||||
|
||||
%extend cfunc_t {
|
||||
%immutable rgas;
|
||||
%immutable stas;
|
||||
%immutable argidx;
|
||||
|
||||
qstring __str__() {
|
||||
qstring qs;
|
||||
qstring_printer_t p($self, qs, 0);
|
||||
$self->print_func(p);
|
||||
return qs;
|
||||
}
|
||||
};
|
||||
|
||||
%ignore qstring_printer_t::qstring_printer_t(const cfunc_t *, qstring &, bool);
|
||||
%ignore qstring_printer_t::~qstring_printer_t();
|
||||
|
||||
%extend qstring_printer_t {
|
||||
|
||||
qstring_printer_t(const cfunc_t *f, bool tags);
|
||||
~qstring_printer_t();
|
||||
|
||||
qstring get_s() {
|
||||
return $self->s;
|
||||
}
|
||||
|
||||
%pythoncode {
|
||||
s = property(lambda self: self.get_s())
|
||||
}
|
||||
};
|
||||
|
||||
%rename(dereference_uint16) operator uint16*;
|
||||
%rename(dereference_const_uint16) operator const uint16*;
|
||||
|
||||
// this is a dummy class template to allow swig to do its thing.
|
||||
#if !defined(__MAC__) || (MACSDKVER >= 1060)
|
||||
#define HAS_MAP_AT
|
||||
#endif
|
||||
|
||||
// Provide trivial std::map facade so basic operations are available.
|
||||
template<class key_type, class mapped_type> class std::map {
|
||||
public:
|
||||
#ifdef HAS_MAP_AT
|
||||
mapped_type& at(const key_type& _Keyval);
|
||||
#endif
|
||||
size_t size() const;
|
||||
};
|
||||
|
||||
#ifndef HAS_MAP_AT
|
||||
#warning "std::map doesn't provide at(). Augmenting it."
|
||||
%extend std::map {
|
||||
mapped_type& at(const key_type& _Keyval) { return $self->operator[](_Keyval); }
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%extend citem_t {
|
||||
// define these two struct members that can be used for casting.
|
||||
@ -150,15 +182,21 @@ public:
|
||||
%ignore qvector< citem_t *>::grow;
|
||||
%ignore qvector< cinsn_t *>::grow;
|
||||
|
||||
|
||||
//~ %template(qwstrvec_t) qvector<qwstring>; // vector of unicode strings
|
||||
typedef intvec_t svalvec_t; // vector of signed values
|
||||
typedef intvec_t eavec_t;// vector of addresses
|
||||
|
||||
// director classes make it possible to override virtual functions from python.
|
||||
%feature("director") ctree_visitor_t;
|
||||
%feature("director") ctree_parentee_t;
|
||||
%feature("director") cfunc_parentee_t;
|
||||
%feature("director") user_lvar_visitor_t;
|
||||
// At this point, SWIG doesn't know about this
|
||||
// type yet (kernwin.i is included later). Therefore,
|
||||
// unless we do this, swig will consider 'strvec_t' to be
|
||||
// just a regular type, and when retrieving structure
|
||||
// members of type 'strvec_t', 2 issues:
|
||||
// - an additional copy will be made, and
|
||||
// - SWIG will use SWIGTYPE_p_strvec_t, which has a != Python type
|
||||
// information than SWIGTYPE_p_qvectorT_simpleline_t_t, and no
|
||||
// proper Python 'strvec_t' proxy instance will be created.
|
||||
typedef qvector<simpleline_t> strvec_t;
|
||||
|
||||
// hexrays templates
|
||||
%template(user_numforms_t) std::map<operand_locator_t, number_format_t>;
|
||||
@ -172,6 +210,29 @@ typedef intvec_t eavec_t;// vector of addresses
|
||||
%template(cinsnptrvec_t) qvector<cinsn_t *>;
|
||||
%template(eamap_t) std::map<ea_t, cinsnptrvec_t>;
|
||||
%template(boundaries_t) std::map<cinsn_t *, areaset_t>;
|
||||
// WARNING: The order here is VERY important:
|
||||
// 1) The '%extend' directive. Note that
|
||||
// - the template name must be used, not the typedef (i.e., not 'cfuncptr_t')
|
||||
// - to override the destructor, the destructor must have the template parameters.
|
||||
// 2) The '%ignore' directive.
|
||||
// - Again, using the template name, but this time
|
||||
// - not qualifying the destructor with template parameters
|
||||
// 3) The '%template' directive, that will indeed instantiate
|
||||
// the template for swig.
|
||||
%{ void hexrays_deregister_python_cfuncptr_t_instance(cfuncptr_t *fp); %}
|
||||
%extend qrefcnt_t<cfunc_t> {
|
||||
// The typemap above will take care of registering newly-constructed cfuncptr_t
|
||||
// instances. However, there's no such thing as a destructor typemap.
|
||||
// Therefore, we need to do the grunt work of de-registering ourselves.
|
||||
// Note: The 'void' here is important: Without it, SWIG considers it to
|
||||
// be a different destructor (which, of course, makes a ton of sense.)
|
||||
~qrefcnt_t<cfunc_t>(void)
|
||||
{
|
||||
hexrays_deregister_python_cfuncptr_t_instance($self);
|
||||
delete $self;
|
||||
}
|
||||
}
|
||||
%ignore qrefcnt_t<cfunc_t>::~qrefcnt_t(void);
|
||||
%template(cfuncptr_t) qrefcnt_t<cfunc_t>;
|
||||
%template(qvector_history_t) qvector<history_item_t>;
|
||||
%template(history_t) qstack<history_item_t>;
|
||||
@ -215,25 +276,6 @@ class qlist_cinsn_t_iterator {};
|
||||
const char *c_str() const { return self->c_str(); }
|
||||
};
|
||||
|
||||
%{
|
||||
cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf)
|
||||
{
|
||||
try
|
||||
{
|
||||
cfuncptr_t cfunc = decompile(pfn, hf);
|
||||
return cfunc;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
error("Hex-Rays Python: decompiler threw an exception.\n");
|
||||
}
|
||||
return cfuncptr_t(0);
|
||||
}
|
||||
%}
|
||||
|
||||
cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf);
|
||||
%ignore decompile;
|
||||
|
||||
void qswap(cinsn_t &a, cinsn_t &b);
|
||||
%include "typemaps.i"
|
||||
|
||||
@ -245,6 +287,19 @@ void qswap(cinsn_t &a, cinsn_t &b);
|
||||
|
||||
%{
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
qstring_printer_t *new_qstring_printer_t(const cfunc_t *f, bool tags)
|
||||
{
|
||||
return new qstring_printer_t(f, * (new qstring()), tags);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void delete_qstring_printer_t(qstring_printer_t *qs)
|
||||
{
|
||||
delete &(qs->s);
|
||||
delete qs;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
static int hexrays_python_call(ref_t fct, ref_t args)
|
||||
{
|
||||
@ -524,8 +579,89 @@ int __remove_hexrays_callback(PyObject *hx_cblist_callback)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
|
||||
%{
|
||||
//-------------------------------------------------------------------------
|
||||
// A set of cfuncptr_t objects that were created from IDAPython.
|
||||
// This is necessary in order to delete those objects before the hexrays
|
||||
// plugin is unloaded. Otherwise, IDAPython will still delete them, but
|
||||
// the plugin's 'hexdsp' dispatcher function will point to dlclose()'d
|
||||
// code.
|
||||
static qvector<cfuncptr_t*> python_cfuncptrs;
|
||||
void hexrays_clear_python_cfuncptr_t_references(void)
|
||||
{
|
||||
for ( size_t i = 0, n = python_cfuncptrs.size(); i < n; ++i )
|
||||
python_cfuncptrs[i]->reset();
|
||||
// NOTE: Don't clear() the array of pointers. All the python-exposed
|
||||
// cfuncptr_t instances will be deleted through the python
|
||||
// shutdown/ref-decrementing process anyway, and the entries will be
|
||||
// properly pulled out of the vector when that happens.
|
||||
}
|
||||
|
||||
void hexrays_register_python_cfuncptr_t_instance(cfuncptr_t *fp)
|
||||
{
|
||||
QASSERT(30457, !python_cfuncptrs.has(fp));
|
||||
python_cfuncptrs.push_back(fp);
|
||||
}
|
||||
|
||||
void hexrays_deregister_python_cfuncptr_t_instance(cfuncptr_t *fp)
|
||||
{
|
||||
qvector<cfuncptr_t*>::iterator found = python_cfuncptrs.find(fp);
|
||||
if ( found != python_cfuncptrs.end() )
|
||||
{
|
||||
fp->reset();
|
||||
python_cfuncptrs.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#if SWIG_VERSION == 0x20012
|
||||
%typemap(out) cfuncptr_t {}
|
||||
%typemap(ret) cfuncptr_t
|
||||
{
|
||||
// ret cfuncptr_t
|
||||
cfuncptr_t *ni = new cfuncptr_t($1);
|
||||
hexrays_register_python_cfuncptr_t_instance(ni);
|
||||
$result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0);
|
||||
}
|
||||
|
||||
|
||||
%typemap(out) cfuncptr_t *{}
|
||||
%typemap(ret) cfuncptr_t *
|
||||
{
|
||||
// ret cfuncptr_t*
|
||||
cfuncptr_t *ni = new cfuncptr_t(*($1));
|
||||
hexrays_register_python_cfuncptr_t_instance(ni);
|
||||
$result = SWIG_NewPointerObj(ni, $1_descriptor, SWIG_POINTER_OWN | 0);
|
||||
}
|
||||
#else
|
||||
#error Ensure cfuncptr_t wrapping is compatible with this version of SWIG
|
||||
#endif
|
||||
|
||||
%{
|
||||
cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf)
|
||||
{
|
||||
try
|
||||
{
|
||||
cfuncptr_t cfunc = decompile(pfn, hf);
|
||||
return cfunc;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
error("Hex-Rays Python: decompiler threw an exception.\n");
|
||||
}
|
||||
return cfuncptr_t(0);
|
||||
}
|
||||
%}
|
||||
|
||||
cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf);
|
||||
%ignore decompile;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%define %python_callback_in(CB)
|
||||
%typemap(check) CB {
|
||||
@ -540,6 +676,17 @@ int __remove_hexrays_callback(PyObject *hx_cblist_callback)
|
||||
%python_callback_in(PyObject *hx_cblist_callback);
|
||||
%python_callback_in(PyObject *custom_viewer_popup_item_callback);
|
||||
|
||||
%ignore cexpr_t::get_1num_op(const cexpr_t **, const cexpr_t **) const;
|
||||
#pragma SWIG nowarn=503
|
||||
%warnfilter(514) user_lvar_visitor_t; // Director base class 'x' has no virtual destructor.
|
||||
%warnfilter(514) ctree_visitor_t; // ditto
|
||||
%warnfilter(514) ctree_parentee_t; // ditto
|
||||
%warnfilter(514) cfunc_parentee_t; // ditto
|
||||
%warnfilter(473) user_lvar_visitor_t::get_info_mapping_for_saving; // Returning a pointer or reference in a director method is not recommended.
|
||||
%feature("director") ctree_visitor_t;
|
||||
%feature("director") ctree_parentee_t;
|
||||
%feature("director") cfunc_parentee_t;
|
||||
%feature("director") user_lvar_visitor_t;
|
||||
%include "hexrays.hpp"
|
||||
|
||||
%pythoncode %{
|
||||
@ -582,53 +729,19 @@ def decompile(ea, hf=None):
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# stringify all string types
|
||||
qtype.__str__ = qtype.c_str
|
||||
typestring.__str__ = typestring._print
|
||||
qstring.__str__ = qstring.c_str
|
||||
citem_cmt_t.__str__ = citem_cmt_t.c_str
|
||||
|
||||
typestring.size = property(typestring.size)
|
||||
typestring.is_user_cc = property(typestring.is_user_cc)
|
||||
typestring.is_vararg = property(typestring.is_vararg)
|
||||
typestring.is_ptr_or_array = property(typestring.is_ptr_or_array)
|
||||
typestring.is_paf = property(typestring.is_paf)
|
||||
typestring.is_funcptr = property(typestring.is_funcptr)
|
||||
typestring.is_ptr = property(typestring.is_ptr)
|
||||
typestring.is_enum = property(typestring.is_enum)
|
||||
typestring.is_func = property(typestring.is_func)
|
||||
typestring.is_void = property(typestring.is_void)
|
||||
typestring.is_array = property(typestring.is_array)
|
||||
typestring.is_float = property(typestring.is_float)
|
||||
typestring.is_union = property(typestring.is_union)
|
||||
typestring.is_struct = property(typestring.is_struct)
|
||||
typestring.is_struni = property(typestring.is_struni)
|
||||
typestring.is_double = property(typestring.is_double)
|
||||
typestring.is_ldouble = property(typestring.is_ldouble)
|
||||
typestring.is_floating = property(typestring.is_floating)
|
||||
typestring.is_const = property(typestring.is_const)
|
||||
typestring.is_correct = property(typestring.is_correct)
|
||||
typestring.is_scalar = property(typestring.is_scalar)
|
||||
typestring.is_small_struni = property(typestring.is_small_struni)
|
||||
typestring.is_like_scalar = property(typestring.is_like_scalar)
|
||||
typestring.is_pvoid = property(typestring.is_pvoid)
|
||||
typestring.is_partial_ptr = property(typestring.is_partial_ptr)
|
||||
typestring.is_well_defined = property(typestring.is_well_defined)
|
||||
typestring.requires_cot_ref = property(typestring.requires_cot_ref)
|
||||
typestring.partial_type_num = property(typestring.partial_type_num)
|
||||
#qtype.__str__ = qtype.c_str
|
||||
#qstring.__str__ = qstring.c_str
|
||||
#citem_cmt_t.__str__ = citem_cmt_t.c_str
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# listify all list types
|
||||
def _vectors_iterator(self):
|
||||
for i in range(len(self)):
|
||||
yield self[i]
|
||||
for cls in [cinsnptrvec_t, ctree_items_t, uvalvec_t, \
|
||||
intvec_t, boolvec_t, hexwarns_t, \
|
||||
history_t, strvec_t, qvector_lvar_t,
|
||||
qvector_carg_t, qvector_ccase_t
|
||||
]:
|
||||
cls.__getitem__ = cls.at
|
||||
cls.__len__ = cls.size
|
||||
cls.__iter__ = _vectors_iterator
|
||||
_listify_types(cinsnptrvec_t,
|
||||
ctree_items_t,
|
||||
qvector_lvar_t,
|
||||
qvector_carg_t,
|
||||
qvector_ccase_t,
|
||||
hexwarns_t,
|
||||
history_t)
|
||||
|
||||
def citem_to_specific_type(self):
|
||||
""" cast the citem_t object to its more specific type, either cexpr_t or cinsn_t. """
|
||||
@ -786,27 +899,17 @@ def cblock_insert(self, index, item):
|
||||
return
|
||||
cblock_t.insert = cblock_insert
|
||||
|
||||
def cfunc___str__(self):
|
||||
qs = qstring()
|
||||
p = qstring_printer_t(self, qs, 0)
|
||||
self.print_func(p)
|
||||
return qs.c_str()
|
||||
cfunc_t.__str__ = cfunc___str__
|
||||
cfuncptr_t.__str__ = lambda self: str(self.__deref__())
|
||||
|
||||
def cfunc_typestring(self):
|
||||
""" Get the function's return type typestring object. The full prototype \
|
||||
can be obtained via typestring._print() method. """
|
||||
|
||||
ts = typestring()
|
||||
qt = qtype()
|
||||
|
||||
result = self.get_func_type(ts, qt)
|
||||
if not result: return
|
||||
|
||||
return ts
|
||||
cfunc_t.typestring = property(cfunc_typestring)
|
||||
cfuncptr_t.typestring = property(lambda self: self.__deref__().typestring)
|
||||
def cfunc_type(self):
|
||||
""" Get the function's return type tinfo_t object. """
|
||||
tif = tinfo_t()
|
||||
result = self.get_func_type(tif)
|
||||
if not result:
|
||||
return
|
||||
return tif
|
||||
cfunc_t.type = property(cfunc_type)
|
||||
cfuncptr_t.type = property(lambda self: self.__deref__().type)
|
||||
|
||||
cfunc_t.arguments = property(lambda self: [o for o in self.lvars if o.is_arg_var])
|
||||
cfuncptr_t.arguments = property(lambda self: self.__deref__().arguments)
|
||||
@ -822,6 +925,8 @@ cfuncptr_t.eamap = property(lambda self: self.__deref__().get_eamap())
|
||||
cfunc_t.boundaries = property(cfunc_t.get_boundaries)
|
||||
cfuncptr_t.boundaries = property(lambda self: self.__deref__().get_boundaries())
|
||||
|
||||
#pragma SWIG nowarn=+503
|
||||
|
||||
lvar_t.used = property(lvar_t.used)
|
||||
lvar_t.typed = property(lvar_t.typed)
|
||||
lvar_t.mreg_done = property(lvar_t.mreg_done)
|
||||
@ -989,7 +1094,7 @@ def _map_as_dict(maptype, name, keytype, valuetype):
|
||||
maptype.popitem = _map_popitem
|
||||
maptype.setdefault = _map_setdefault
|
||||
|
||||
_map_as_dict(user_labels_t, 'user_labels', (int, long), qstring)
|
||||
#_map_as_dict(user_labels_t, 'user_labels', (int, long), qstring)
|
||||
_map_as_dict(user_cmts_t, 'user_cmts', treeloc_t, citem_cmt_t)
|
||||
_map_as_dict(user_numforms_t, 'user_numforms', operand_locator_t, number_format_t)
|
||||
_map_as_dict(user_iflags_t, 'user_iflags', citem_locator_t, (int, long))
|
||||
|
137
swig/idaapi.i
137
swig/idaapi.i
@ -25,10 +25,12 @@
|
||||
%inline %{
|
||||
static PyObject *type##_create()
|
||||
{
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
return PyCObject_FromVoidPtr(new type(), NULL);
|
||||
}
|
||||
static bool type##_destroy(PyObject *py_obj)
|
||||
{
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
if ( !PyCObject_Check(py_obj) )
|
||||
return false;
|
||||
delete (type *)PyCObject_AsVoidPtr(py_obj);
|
||||
@ -36,11 +38,14 @@ static bool type##_destroy(PyObject *py_obj)
|
||||
}
|
||||
static type *type##_get_clink(PyObject *self)
|
||||
{
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
return (type *)pyobj_get_clink(self);
|
||||
}
|
||||
static PyObject *type##_get_clink_ptr(PyObject *self)
|
||||
{
|
||||
return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)pyobj_get_clink(self));
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
return PyLong_FromUnsignedLongLong(
|
||||
(unsigned PY_LONG_LONG)pyobj_get_clink(self));
|
||||
}
|
||||
%}
|
||||
%enddef
|
||||
@ -2266,6 +2271,12 @@ class object_t(object):
|
||||
"""Allow access to object attributes by index (like dictionaries)"""
|
||||
return getattr(self, idx)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def _bounded_getitem_iterator(self):
|
||||
"""Helper function, to be set as __iter__ method for qvector-, or array-based classes."""
|
||||
for i in range(len(self)):
|
||||
yield self[i]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class plugin_t(pyidc_opaque_object_t):
|
||||
"""Base class for all scripted plugins."""
|
||||
@ -2332,72 +2343,79 @@ class PyIdc_cvt_int64__(pyidc_cvt_helper__):
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# qstrvec_t clinked object
|
||||
# class qstrvec_t(py_clinked_object_t):
|
||||
# """Class representing an qstrvec_t"""
|
||||
class _qstrvec_t(py_clinked_object_t):
|
||||
"""
|
||||
WARNING: It is very unlikely an IDAPython user should ever, ever
|
||||
have to use this type. It should only be used for IDAPython internals.
|
||||
|
||||
# def __init__(self, items=None):
|
||||
# py_clinked_object_t.__init__(self)
|
||||
# # Populate the list if needed
|
||||
# if items:
|
||||
# self.from_list(items)
|
||||
For example, in py_askusingform.py, we ctypes-expose to the IDA
|
||||
kernel & UI a qstrvec instance, in case a DropdownListControl is
|
||||
constructed.
|
||||
That's because that's what AskUsingForm expects, and we have no
|
||||
choice but to make a DropdownListControl hold a qstrvec_t.
|
||||
This is, afaict, the only situation where a Python
|
||||
_qstrvec_t is required.
|
||||
"""
|
||||
|
||||
# def _create_clink(self):
|
||||
# return _idaapi.qstrvec_t_create()
|
||||
def __init__(self, items=None):
|
||||
py_clinked_object_t.__init__(self)
|
||||
# Populate the list if needed
|
||||
if items:
|
||||
self.from_list(items)
|
||||
|
||||
# def _del_clink(self, lnk):
|
||||
# return _idaapi.qstrvec_t_destroy(lnk)
|
||||
def _create_clink(self):
|
||||
return _idaapi.qstrvec_t_create()
|
||||
|
||||
# def _get_clink_ptr(self):
|
||||
# return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
def _del_clink(self, lnk):
|
||||
return _idaapi.qstrvec_t_destroy(lnk)
|
||||
|
||||
# def assign(self, other):
|
||||
# """Copies the contents of 'other' to 'self'"""
|
||||
# return _idaapi.qstrvec_t_assign(self, other)
|
||||
def _get_clink_ptr(self):
|
||||
return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
|
||||
# def __setitem__(self, idx, s):
|
||||
# """Sets string at the given index"""
|
||||
# return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
def assign(self, other):
|
||||
"""Copies the contents of 'other' to 'self'"""
|
||||
return _idaapi.qstrvec_t_assign(self, other)
|
||||
|
||||
# def __getitem__(self, idx):
|
||||
# """Gets the string at the given index"""
|
||||
# return _idaapi.qstrvec_t_get(self, idx)
|
||||
def __setitem__(self, idx, s):
|
||||
"""Sets string at the given index"""
|
||||
return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
|
||||
# def __get_size(self):
|
||||
# return _idaapi.qstrvec_t_size(self)
|
||||
def __getitem__(self, idx):
|
||||
"""Gets the string at the given index"""
|
||||
return _idaapi.qstrvec_t_get(self, idx)
|
||||
|
||||
# size = property(__get_size)
|
||||
# """Returns the count of elements"""
|
||||
def __get_size(self):
|
||||
return _idaapi.qstrvec_t_size(self)
|
||||
|
||||
# def addressof(self, idx):
|
||||
# """Returns the address (as number) of the qstring at the given index"""
|
||||
# return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
size = property(__get_size)
|
||||
"""Returns the count of elements"""
|
||||
|
||||
# def add(self, s):
|
||||
# """Add a string to the vector"""
|
||||
# return _idaapi.qstrvec_t_add(self, s)
|
||||
def addressof(self, idx):
|
||||
"""Returns the address (as number) of the qstring at the given index"""
|
||||
return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
|
||||
def add(self, s):
|
||||
"""Add a string to the vector"""
|
||||
return _idaapi.qstrvec_t_add(self, s)
|
||||
|
||||
# def from_list(self, lst):
|
||||
# """Populates the vector from a Python string list"""
|
||||
# return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
def from_list(self, lst):
|
||||
"""Populates the vector from a Python string list"""
|
||||
return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
|
||||
def clear(self, qclear=False):
|
||||
"""
|
||||
Clears all strings from the vector.
|
||||
@param qclear: Just reset the size but do not actually free the memory
|
||||
"""
|
||||
return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
|
||||
# def clear(self, qclear=False):
|
||||
# """
|
||||
# Clears all strings from the vector.
|
||||
# @param qclear: Just reset the size but do not actually free the memory
|
||||
# """
|
||||
# return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
def insert(self, idx, s):
|
||||
"""Insert a string into the vector"""
|
||||
return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
|
||||
|
||||
# def insert(self, idx, s):
|
||||
# """Insert a string into the vector"""
|
||||
# return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
|
||||
|
||||
# def remove(self, idx):
|
||||
# """Removes a string from the vector"""
|
||||
# return _idaapi.qstrvec_t_remove(self, idx)
|
||||
def remove(self, idx):
|
||||
"""Removes a string from the vector"""
|
||||
return _idaapi.qstrvec_t_remove(self, idx)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
||||
@ -2678,6 +2696,12 @@ class __IDAPython_Completion_Util(object):
|
||||
# Instantiate a completion object
|
||||
IDAPython_Completion = __IDAPython_Completion_Util()
|
||||
|
||||
def _listify_types(*classes):
|
||||
for cls in classes:
|
||||
cls.__getitem__ = cls.at
|
||||
cls.__len__ = cls.size
|
||||
cls.__iter__ = _bounded_getitem_iterator
|
||||
|
||||
|
||||
|
||||
# The general callback format of notify_when() is:
|
||||
@ -2744,10 +2768,13 @@ NW_REMOVE = 0x0010
|
||||
%include "fixup.i"
|
||||
%include "frame.i"
|
||||
%include "funcs.i"
|
||||
%include "typeinf.i"
|
||||
#ifdef WITH_HEXRAYS
|
||||
%include "hexrays.i"
|
||||
#endif
|
||||
|
||||
SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)
|
||||
|
||||
%inline %{
|
||||
|
||||
//<inline(py_idaapi)>
|
||||
@ -2852,12 +2879,9 @@ def RunPythonStatement(stmt):
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
/*
|
||||
//---------------------------------------------------------------------------
|
||||
// qstrvec_t wrapper
|
||||
// qstrvec_t wrapper (INTERNAL! Don't expose. See py_idaapi.py)
|
||||
//---------------------------------------------------------------------------
|
||||
DECLARE_PY_CLINKED_OBJECT(qstrvec_t);
|
||||
|
||||
static bool qstrvec_t_assign(PyObject *self, PyObject *other)
|
||||
{
|
||||
qstrvec_t *lhs = qstrvec_t_get_clink(self);
|
||||
@ -2959,7 +2983,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
||||
sv->erase(sv->begin()+idx);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -3006,7 +3030,6 @@ static bool notify_when(int when, PyObject *py_callable)
|
||||
%include "srarea.i"
|
||||
%include "strlist.i"
|
||||
%include "struct.i"
|
||||
%include "typeinf.i"
|
||||
%include "ua.i"
|
||||
%include "xref.i"
|
||||
%include "view.i"
|
||||
|
52
swig/idp.i
52
swig/idp.i
@ -42,6 +42,23 @@
|
||||
%include "idp.hpp"
|
||||
%feature("director") IDB_Hooks;
|
||||
%feature("director") IDP_Hooks;
|
||||
|
||||
%extend areacb_t {
|
||||
areacb_type_t get_type()
|
||||
{
|
||||
areacb_type_t t = AREACB_TYPE_UNKNOWN;
|
||||
if ( $self == &funcs )
|
||||
t = AREACB_TYPE_FUNC;
|
||||
else if ( $self == &segs )
|
||||
t = AREACB_TYPE_SEGMENT;
|
||||
else if ( $self == &hidden_areas )
|
||||
t = AREACB_TYPE_HIDDEN_AREA;
|
||||
else if ( $self == &SRareas )
|
||||
t = AREACB_TYPE_SRAREA;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
%inline %{
|
||||
|
||||
//<inline(py_idp)>
|
||||
@ -849,6 +866,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum areacb_type_t
|
||||
{
|
||||
AREACB_TYPE_UNKNOWN,
|
||||
AREACB_TYPE_FUNC,
|
||||
AREACB_TYPE_SEGMENT,
|
||||
AREACB_TYPE_HIDDEN_AREA,
|
||||
AREACB_TYPE_SRAREA,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// IDB hooks
|
||||
//---------------------------------------------------------------------------
|
||||
@ -869,8 +895,9 @@ public:
|
||||
// Hook functions to override in Python
|
||||
virtual int byte_patched(ea_t /*ea*/) { return 0; };
|
||||
virtual int cmt_changed(ea_t, bool /*repeatable_cmt*/) { return 0; };
|
||||
virtual int ti_changed(ea_t /*ea*/, const type_t * /*type*/, const p_list * /*fnames*/) { msg("ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int op_ti_changed(ea_t /*ea*/, int /*n*/, const type_t * /*type*/, const p_list * /*fnames*/) { msg("op_ti_changed hook not supported yet\n"); return 0; };
|
||||
virtual int area_cmt_changed(areacb_t * /*areas*/, area_t * /*area*/, const char * /*cmt*/, bool /*repeatable*/) { return 0; }
|
||||
virtual int ti_changed(ea_t /*ea*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; };
|
||||
virtual int op_ti_changed(ea_t /*ea*/, int /*n*/, const type_t * /*type*/, const p_list * /*fnames*/) { return 0; };
|
||||
virtual int op_type_changed(ea_t /*ea*/, int /*n*/) { return 0; };
|
||||
virtual int enum_created(enum_t /*id*/) { return 0; };
|
||||
virtual int enum_deleted(enum_t /*id*/) { return 0; };
|
||||
@ -1408,8 +1435,8 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
|
||||
ea_t ea, ea2;
|
||||
bool repeatable_cmt;
|
||||
/*type_t *type;*/
|
||||
/* p_list *fnames; */
|
||||
type_t *type;
|
||||
p_list *fnames;
|
||||
int n;
|
||||
enum_t id;
|
||||
const_t cid;
|
||||
@ -1433,20 +1460,29 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
|
||||
ea = va_arg(va, ea_t);
|
||||
repeatable_cmt = va_arg(va, int);
|
||||
return proxy->cmt_changed(ea, repeatable_cmt);
|
||||
#if 0
|
||||
|
||||
case idb_event::area_cmt_changed:
|
||||
{
|
||||
areacb_t *cb = va_arg(va, areacb_t*);
|
||||
area_t *area = va_arg(va, area_t*);
|
||||
const char *cmt = va_arg(va, char*);
|
||||
repeatable_cmt = va_arg(va, int);
|
||||
return proxy->area_cmt_changed(cb, area, cmt, repeatable_cmt);
|
||||
}
|
||||
|
||||
case idb_event::ti_changed:
|
||||
ea = va_arg(va, ea_t);
|
||||
type = va_arg(va, type_t *);
|
||||
fnames = va_arg(va, fnames);
|
||||
fnames = va_arg(va, p_list *);
|
||||
return proxy->ti_changed(ea, type, fnames);
|
||||
|
||||
case idb_event::op_ti_changed:
|
||||
ea = va_arg(va, ea_t);
|
||||
n = va_arg(va, int);
|
||||
type = va_arg(va, type_t *);
|
||||
fnames = va_arg(va, fnames);
|
||||
fnames = va_arg(va, p_list *);
|
||||
return proxy->op_ti_changed(ea, n, type, fnames);
|
||||
#endif
|
||||
|
||||
case idb_event::op_type_changed:
|
||||
ea = va_arg(va, ea_t);
|
||||
n = va_arg(va, int);
|
||||
|
180
swig/kernwin.i
180
swig/kernwin.i
@ -43,7 +43,6 @@
|
||||
%ignore restore_database_snapshot;
|
||||
%ignore destroy_custom_viewer;
|
||||
%ignore destroy_custom_viewerdestroy_custom_viewer;
|
||||
%ignore get_custom_viewer_place;
|
||||
%ignore set_custom_viewer_popup_menu;
|
||||
%ignore set_custom_viewer_handler;
|
||||
%ignore set_custom_viewer_range;
|
||||
@ -72,18 +71,12 @@
|
||||
%rename (asktext) py_asktext;
|
||||
%rename (str2ea) py_str2ea;
|
||||
%rename (str2user) py_str2user;
|
||||
|
||||
%ignore process_ui_action;
|
||||
%rename (process_ui_action) py_process_ui_action;
|
||||
|
||||
%ignore exec_request_t;
|
||||
|
||||
%ignore execute_sync;
|
||||
%ignore exec_request_t;
|
||||
%rename (execute_sync) py_execute_sync;
|
||||
|
||||
%ignore read_selection;
|
||||
%rename (read_selection) py_read_selection;
|
||||
|
||||
%ignore ui_request_t;
|
||||
%ignore execute_ui_requests;
|
||||
%rename (execute_ui_requests) py_execute_ui_requests;
|
||||
@ -136,39 +129,12 @@ void refresh_lists(void)
|
||||
# This is for get_cursor()
|
||||
%apply int *OUTPUT {int *x, int *y};
|
||||
|
||||
# This is for read_selection()
|
||||
%apply unsigned long *OUTPUT { ea_t *ea1, ea_t *ea2 };
|
||||
|
||||
SWIG_DECLARE_PY_CLINKED_OBJECT(textctrl_info_t)
|
||||
|
||||
%inline %{
|
||||
//<inline(py_kernwin)>
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def read_selection():
|
||||
"""
|
||||
Returns selected area boundaries
|
||||
|
||||
@return: tuple(ok: bool, start_ea, end_ea)
|
||||
"""
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
static PyObject *py_read_selection()
|
||||
{
|
||||
ea_t ea1, ea2;
|
||||
bool b = read_selection(&ea1, &ea2);
|
||||
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
return Py_BuildValue(
|
||||
"(i" PY_FMT64 PY_FMT64 ")",
|
||||
b ? 1 : 0,
|
||||
pyul_t(ea1), pyul_t(ea2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
@ -343,6 +309,45 @@ def free_custom_icon(icon_id):
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def readsel2(view, p0, p1):
|
||||
"""
|
||||
Read the user selection, and store its information in p0 (from) and p1 (to).
|
||||
|
||||
This can be used as follows:
|
||||
|
||||
|
||||
>>> p0 = idaapi.twinpos_t()
|
||||
p1 = idaapi.twinpos_t()
|
||||
view = idaapi.get_current_viewer()
|
||||
idaapi.readsel2(view, p0, p1)
|
||||
|
||||
|
||||
At that point, p0 and p1 hold information for the selection.
|
||||
But, the 'at' property of p0 and p1 is not properly typed.
|
||||
To specialize it, call #place() on it, passing it the view
|
||||
they were retrieved from. Like so:
|
||||
|
||||
|
||||
>>> place0 = p0.place(view)
|
||||
place1 = p1.place(view)
|
||||
|
||||
|
||||
This will effectively "cast" the place into a specialized type,
|
||||
holding proper information, depending on the view type (e.g.,
|
||||
disassembly, structures, enums, ...)
|
||||
|
||||
@param view: The view to retrieve the selection for.
|
||||
@param p0: Storage for the "from" part of the selection.
|
||||
@param p1: Storage for the "to" part of the selection.
|
||||
@return: a bool value indicating success.
|
||||
"""
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
@ -1086,8 +1091,6 @@ PyObject *choose2_get_embedded_selection(PyObject *self);
|
||||
#define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
DECLARE_PY_CLINKED_OBJECT(textctrl_info_t);
|
||||
|
||||
static bool textctrl_info_t_assign(PyObject *self, PyObject *other)
|
||||
{
|
||||
textctrl_info_t *lhs = textctrl_info_t_get_clink(self);
|
||||
@ -1222,20 +1225,21 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
PYW_GIL_CHECK_LOCKED_SCOPE();
|
||||
switch ( ft )
|
||||
{
|
||||
// dropdown list
|
||||
case 8:
|
||||
{
|
||||
// Readonly? Then return the selected index
|
||||
if ( sz == 1 )
|
||||
{
|
||||
int sel_idx;
|
||||
if ( fa->get_field_value(fid, &sel_idx) )
|
||||
if ( fa->get_combobox_value(fid, &sel_idx) )
|
||||
return PyLong_FromLong(sel_idx);
|
||||
}
|
||||
// Not readonly? Then return the qstring
|
||||
else
|
||||
{
|
||||
qstring val;
|
||||
if ( fa->get_field_value(fid, &val) )
|
||||
if ( fa->get_combobox_value(fid, &val) )
|
||||
return PyString_FromString(val.c_str());
|
||||
}
|
||||
break;
|
||||
@ -1244,15 +1248,15 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
case 7:
|
||||
{
|
||||
textctrl_info_t ti;
|
||||
if ( fa->get_field_value(fid, &ti) )
|
||||
if ( fa->get_text_value(fid, &ti) )
|
||||
return Py_BuildValue("(sII)", ti.text.c_str(), ti.flags, ti.tabsize);
|
||||
break;
|
||||
}
|
||||
// button - uint32
|
||||
case 4:
|
||||
{
|
||||
uint32 val;
|
||||
if ( fa->get_field_value(fid, &val) )
|
||||
uval_t val;
|
||||
if ( fa->get_unsigned_value(fid, &val) )
|
||||
return PyLong_FromUnsignedLong(val);
|
||||
break;
|
||||
}
|
||||
@ -1260,7 +1264,7 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
case 2:
|
||||
{
|
||||
ushort val;
|
||||
if ( fa->get_field_value(fid, &val) )
|
||||
if ( fa->_get_field_value(fid, &val) )
|
||||
return PyLong_FromUnsignedLong(val);
|
||||
break;
|
||||
}
|
||||
@ -1268,7 +1272,7 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
case 1:
|
||||
{
|
||||
char val[MAXSTR];
|
||||
if ( fa->get_field_value(fid, val) )
|
||||
if ( fa->get_ascii_value(fid, val, sizeof(val)) )
|
||||
return PyString_FromString(val);
|
||||
break;
|
||||
}
|
||||
@ -1277,7 +1281,7 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
{
|
||||
qstring val;
|
||||
val.resize(sz + 1);
|
||||
if ( fa->get_field_value(fid, val.begin()) )
|
||||
if ( fa->get_ascii_value(fid, val.begin(), val.size()) )
|
||||
return PyString_FromString(val.begin());
|
||||
break;
|
||||
}
|
||||
@ -1285,12 +1289,11 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
{
|
||||
intvec_t intvec;
|
||||
// Returned as 1-base
|
||||
if (fa->get_field_value(fid, &intvec))
|
||||
if (fa->get_chooser_value(fid, &intvec))
|
||||
{
|
||||
// Make 0-based
|
||||
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
|
||||
(*it)--;
|
||||
|
||||
ref_t l(PyW_IntVecToPyList(intvec));
|
||||
l.incref();
|
||||
return l.o;
|
||||
@ -1311,33 +1314,38 @@ static PyObject *formchgcbfa_get_field_value(
|
||||
{
|
||||
case 'S': // sel_t
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.sel) )
|
||||
if ( fa->get_segment_value(fid, &u.sel) )
|
||||
return Py_BuildValue(PY_FMT64, u.sel);
|
||||
break;
|
||||
}
|
||||
// sval_t
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 'D':
|
||||
case 'O':
|
||||
case 'Y':
|
||||
case 'H':
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.sval) )
|
||||
if ( fa->get_signed_value(fid, &u.sval) )
|
||||
return Py_BuildValue(PY_SFMT64, u.sval);
|
||||
break;
|
||||
}
|
||||
case 'L': // uint64
|
||||
case 'l': // int64
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.ull) )
|
||||
return Py_BuildValue(sz == 'L' ? "K" : "L", u.ull);
|
||||
if ( fa->_get_field_value(fid, &u.ull) )
|
||||
return Py_BuildValue("K", u.ull);
|
||||
break;
|
||||
}
|
||||
case 'N':
|
||||
case 'M': // uval_t
|
||||
{
|
||||
if ( fa->get_unsigned_value(fid, &u.uval) )
|
||||
return Py_BuildValue(PY_FMT64, u.uval);
|
||||
break;
|
||||
}
|
||||
case '$': // ea_t
|
||||
{
|
||||
if ( fa->get_field_value(fid, &u.uval) )
|
||||
if ( fa->get_ea_value(fid, &u.uval) )
|
||||
return Py_BuildValue(PY_FMT64, u.uval);
|
||||
break;
|
||||
}
|
||||
@ -1367,13 +1375,13 @@ static bool formchgcbfa_set_field_value(
|
||||
if ( PyString_Check(py_val) )
|
||||
{
|
||||
qstring val(PyString_AsString(py_val));
|
||||
return fa->set_field_value(fid, &val);
|
||||
return fa->set_combobox_value(fid, &val);
|
||||
}
|
||||
// Readonly dropdown list
|
||||
else
|
||||
{
|
||||
int sel_idx = PyLong_AsLong(py_val);
|
||||
return fa->set_field_value(fid, &sel_idx);
|
||||
return fa->set_combobox_value(fid, &sel_idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1381,24 +1389,24 @@ static bool formchgcbfa_set_field_value(
|
||||
case 7:
|
||||
{
|
||||
textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(py_val);
|
||||
return ti == NULL ? false : fa->set_field_value(fid, ti);
|
||||
return ti == NULL ? false : fa->set_text_value(fid, ti);
|
||||
}
|
||||
// button - uint32
|
||||
case 4:
|
||||
{
|
||||
uint32 val = PyLong_AsUnsignedLong(py_val);
|
||||
return fa->set_field_value(fid, &val);
|
||||
uval_t val = PyLong_AsUnsignedLong(py_val);
|
||||
return fa->set_unsigned_value(fid, &val);
|
||||
}
|
||||
// ushort
|
||||
case 2:
|
||||
{
|
||||
ushort val = PyLong_AsUnsignedLong(py_val) & 0xffff;
|
||||
return fa->set_field_value(fid, &val);
|
||||
return fa->_set_field_value(fid, &val);
|
||||
}
|
||||
// strings
|
||||
case 3:
|
||||
case 1:
|
||||
return fa->set_field_value(fid, PyString_AsString(py_val));
|
||||
return fa->set_ascii_value(fid, PyString_AsString(py_val));
|
||||
// intvec_t
|
||||
case 5:
|
||||
{
|
||||
@ -1411,14 +1419,14 @@ static bool formchgcbfa_set_field_value(
|
||||
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
|
||||
(*it)++;
|
||||
|
||||
return fa->set_field_value(fid, &intvec);
|
||||
return fa->set_chooser_value(fid, &intvec);
|
||||
}
|
||||
// Numeric
|
||||
case 6:
|
||||
{
|
||||
uint64 num;
|
||||
if ( PyW_GetNumber(py_val, &num) )
|
||||
return fa->set_field_value(fid, &num);
|
||||
return fa->_set_field_value(fid, &num);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1428,6 +1436,11 @@ static bool formchgcbfa_set_field_value(
|
||||
|
||||
static size_t py_get_AskUsingForm()
|
||||
{
|
||||
// Return a pointer to the function. Note that, although
|
||||
// the C implementation of AskUsingForm_cv will do some
|
||||
// Qt/txt widgets generation, the Python's ctypes
|
||||
// implementation through which the call well go will first
|
||||
// unblock other threads. No need to do it ourselves.
|
||||
return (size_t)AskUsingForm_c;
|
||||
}
|
||||
|
||||
@ -1813,8 +1826,8 @@ private:
|
||||
self,
|
||||
(char *)S_ON_DELETE_LINE,
|
||||
"i",
|
||||
lineno - 1));
|
||||
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o) + 1;
|
||||
IS_CHOOSER_EVENT(lineno) ? lineno : lineno-1));
|
||||
return pyres == NULL ? 1 : PyInt_AsLong(pyres.o);
|
||||
}
|
||||
|
||||
int on_refresh(int lineno)
|
||||
@ -3980,8 +3993,39 @@ uint32 choose_choose(PyObject *self,
|
||||
int deflt,
|
||||
int icon);
|
||||
|
||||
%extend place_t {
|
||||
static idaplace_t *as_idaplace_t(place_t *p) { return (idaplace_t *) p; }
|
||||
static enumplace_t *as_enumplace_t(place_t *p) { return (enumplace_t *) p; }
|
||||
static structplace_t *as_structplace_t(place_t *p) { return (structplace_t *) p; }
|
||||
static simpleline_place_t *as_simpleline_place_t(place_t *p) { return (simpleline_place_t *) p; }
|
||||
}
|
||||
|
||||
%extend twinpos_t {
|
||||
|
||||
%pythoncode {
|
||||
def place_as_idaplace_t(self):
|
||||
return place_t.as_idaplace_t(self.at)
|
||||
def place_as_enumplace_t(self):
|
||||
return place_t.as_enumplace_t(self.at)
|
||||
def place_as_structplace_t(self):
|
||||
return place_t.as_structplace_t(self.at)
|
||||
def place_as_simpleline_place_t(self):
|
||||
return place_t.as_simpleline_place_t(self.at)
|
||||
|
||||
def place(self, view):
|
||||
ptype = get_viewer_place_type(view)
|
||||
if ptype == TCCPT_IDAPLACE:
|
||||
return self.place_as_idaplace_t()
|
||||
elif ptype == TCCPT_ENUMPLACE:
|
||||
return self.place_as_enumplace_t()
|
||||
elif ptype == TCCPT_STRUCTPLACE:
|
||||
return self.place_as_structplace_t()
|
||||
elif ptype == TCCPT_SIMPLELINE_PLACE:
|
||||
return self.place_as_simpleline_place_t()
|
||||
else:
|
||||
return self.at
|
||||
}
|
||||
}
|
||||
|
||||
%pythoncode %{
|
||||
|
||||
@ -4995,7 +5039,7 @@ class Form(object):
|
||||
Form.Control.free(self)
|
||||
|
||||
|
||||
class DropdownListControl(InputControl, qstrvec_t):
|
||||
class DropdownListControl(InputControl, _qstrvec_t):
|
||||
"""
|
||||
Dropdown control
|
||||
This control allows manipulating a dropdown control
|
||||
@ -5022,7 +5066,7 @@ class Form(object):
|
||||
hlp)
|
||||
|
||||
# Init the associated qstrvec
|
||||
qstrvec_t.__init__(self, items)
|
||||
_qstrvec_t.__init__(self, items)
|
||||
|
||||
# Remember if readonly or not
|
||||
self.readonly = readonly
|
||||
@ -5033,7 +5077,7 @@ class Form(object):
|
||||
val_addr = addressof(self.__selval)
|
||||
else:
|
||||
# Create an strvec with one qstring
|
||||
self.__selval = qstrvec_t([selval])
|
||||
self.__selval = _qstrvec_t([selval])
|
||||
# Get address of the first element
|
||||
val_addr = self.__selval.addressof(0)
|
||||
|
||||
@ -6094,5 +6138,3 @@ class simplecustviewer_t(object):
|
||||
#</pydoc>
|
||||
#</pycode(py_custviewer)>
|
||||
%}
|
||||
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
%ignore term_marks;
|
||||
%ignore change_jumps_stack_format;
|
||||
%ignore move_marks;
|
||||
%ignore curloc_after_segments_moved;
|
||||
%ignore curloc::rebase_stack;
|
||||
%ignore loc_gtag;
|
||||
%ignore DEFINE_CURLOC_HELPERS;
|
||||
%ignore DEFINE_LOCATION_HELPERS;
|
||||
|
55
swig/nalt.i
55
swig/nalt.i
@ -12,11 +12,11 @@
|
||||
%ignore unregister_custom_refinfo;
|
||||
%ignore get_custom_refinfos;
|
||||
|
||||
%template (ids_array) wrapped_array<tid_t,32>;
|
||||
%template (ids_array) wrapped_array_t<tid_t,32>;
|
||||
|
||||
%extend strpath_t {
|
||||
wrapped_array<tid_t,32> __getIds() {
|
||||
return wrapped_array<tid_t,32>($self->ids);
|
||||
wrapped_array_t<tid_t,32> __getIds() {
|
||||
return wrapped_array_t<tid_t,32>($self->ids);
|
||||
}
|
||||
|
||||
%pythoncode {
|
||||
@ -85,6 +85,7 @@ switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self)
|
||||
%rename (del_switch_info_ex) py_del_switch_info_ex;
|
||||
%rename (create_switch_xrefs) py_create_switch_xrefs;
|
||||
%rename (create_switch_table) py_create_switch_table;
|
||||
%rename (calc_switch_cases) py_calc_switch_cases;
|
||||
|
||||
%inline %{
|
||||
//<inline(py_nalt)>
|
||||
@ -169,6 +170,54 @@ idaman bool ida_export py_create_switch_xrefs(
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct cases_and_targets_t
|
||||
{
|
||||
casevec_t cases;
|
||||
eavec_t targets;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
def calc_switch_cases(insn_ea, si):
|
||||
"""
|
||||
Get information about a switch's cases.
|
||||
|
||||
The returned information can be used as follows:
|
||||
|
||||
for idx in xrange(len(results.cases)):
|
||||
cur_case = results.cases[idx]
|
||||
for cidx in xrange(len(cur_case)):
|
||||
print "case: %d" % cur_case[cidx]
|
||||
print " goto 0x%x" % results.targets[idx]
|
||||
|
||||
@param insn_ea: address of the 'indirect jump' instruction
|
||||
@param si: switch information
|
||||
|
||||
@return: a structure with 2 members: 'cases', and 'targets'.
|
||||
"""
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
idaman cases_and_targets_t *ida_export py_calc_switch_cases(
|
||||
ea_t insn_ea,
|
||||
PyObject *py_swi)
|
||||
{
|
||||
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
|
||||
if ( swi == NULL )
|
||||
return NULL;
|
||||
|
||||
cases_and_targets_t *ct = new cases_and_targets_t;
|
||||
if ( !calc_switch_cases(insn_ea, swi, &ct->cases, &ct->targets) )
|
||||
{
|
||||
delete ct;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ct;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
|
@ -87,6 +87,7 @@
|
||||
%ignore netnode::altadjust;
|
||||
%ignore netnode::getblob(void *buf, size_t *bufsize, nodeidx_t start, char tag);
|
||||
%ignore netnode::operator nodeidx_t;
|
||||
%ignore netnode::validate_names;
|
||||
|
||||
// Renaming one version of hashset() otherwise SWIG will not be able to activate the other one
|
||||
%rename (hashset_idx) netnode::hashset(const char *idx, nodeidx_t value, char tag=htag);
|
||||
@ -136,4 +137,3 @@
|
||||
return self->hashset(idx, buf, sz, tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
64
swig/pro.i
64
swig/pro.i
@ -16,6 +16,7 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
%ignore wchar2char;
|
||||
%ignore hit_counter_t;
|
||||
%ignore reg_hit_counter;
|
||||
@ -55,6 +56,7 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
|
||||
%ignore qstrchr;
|
||||
%ignore qstrrchr;
|
||||
%ignore bytevec_t;
|
||||
%ignore qstrvec_t;
|
||||
%ignore reloc_info_t;
|
||||
%ignore relobj_t;
|
||||
%ignore wchar2char;
|
||||
@ -63,6 +65,7 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
|
||||
%ignore base64_encode;
|
||||
%ignore base64_decode;
|
||||
%ignore utf8_unicode;
|
||||
%ignore unicode_utf8;
|
||||
%ignore win_utf2idb;
|
||||
%ignore char2oem;
|
||||
%ignore oem2char;
|
||||
@ -112,22 +115,59 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
|
||||
|
||||
void qvector<uval_t>::grow(const unsigned int &x=0);
|
||||
%ignore qvector<uval_t>::grow;
|
||||
%ignore qvector::at(size_t);
|
||||
|
||||
// simpleline_t doesn't implement '=='. Therefore, all these cannot be present in the instantiated template.
|
||||
%ignore qvector<simpleline_t>::operator==;
|
||||
%ignore qvector<simpleline_t>::operator!=;
|
||||
%ignore qvector<simpleline_t>::find;
|
||||
%ignore qvector<simpleline_t>::has;
|
||||
%ignore qvector<simpleline_t>::del;
|
||||
%ignore qvector<simpleline_t>::add_unique;
|
||||
|
||||
%include "pro.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%template(uvalvec_t) qvector<uval_t>; // vector of unsigned values
|
||||
%template(intvec_t) qvector<int>; // vector of integers
|
||||
%template(qstrvec_t) qvector<qstring>; // vector of strings
|
||||
%template(boolvec_t) qvector<bool>; // vector of bools
|
||||
%extend qvector {
|
||||
inline size_t __len__() const { return $self->size(); }
|
||||
|
||||
// The fact that we are returning a const version of a reference to the
|
||||
// type is what allows SWIG to generate a wrapper for this method, that
|
||||
// will build an proper object (int, unsigned int, ...) instead
|
||||
// of a pointer. Remove the 'const', and you'll see that, in
|
||||
// SWIGINTERN PyObject *_wrap_uvalvec_t___getitem__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
|
||||
// it will produce this:
|
||||
// resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_unsigned_int, 0 | 0 );
|
||||
// instead of that:
|
||||
// resultobj = SWIG_From_unsigned_SS_int(static_cast< unsigned int >(*result));
|
||||
inline const T& __getitem__(size_t i) const throw(std::out_of_range) {
|
||||
if (i >= $self->size() || i < 0)
|
||||
throw std::out_of_range("out of bounds access");
|
||||
return $self->at(i);
|
||||
}
|
||||
|
||||
inline void __setitem__(size_t i, const T& v) throw(std::out_of_range) {
|
||||
if (i >= $self->size() || i < 0)
|
||||
throw std::out_of_range("out of bounds access");
|
||||
$self->at(i) = v;
|
||||
}
|
||||
|
||||
%pythoncode {
|
||||
__iter__ = _bounded_getitem_iterator
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
class qstring {
|
||||
public:
|
||||
const char *c_str() const { return self->c_str(); }
|
||||
};
|
||||
%template(uvalvec_t) qvector<uval_t>; // unsigned values
|
||||
%template(intvec_t) qvector<int>;
|
||||
%template(boolvec_t) qvector<bool>;
|
||||
%template(casevec_t) qvector<qvector<sval_t> >; // signed values
|
||||
%template(strvec_t) qvector<simpleline_t>;
|
||||
|
||||
class qtype {
|
||||
public:
|
||||
const uchar *c_str() const { return self->c_str(); }
|
||||
};
|
||||
%pythoncode %{
|
||||
_listify_types(uvalvec_t,
|
||||
intvec_t,
|
||||
boolvec_t,
|
||||
casevec_t,
|
||||
strvec_t)
|
||||
%}
|
||||
|
@ -31,10 +31,12 @@ void segment_t_startEA_set(segment_t *segm, ea_t newea)
|
||||
segm->startEA = newea;
|
||||
}
|
||||
}
|
||||
|
||||
ea_t segment_t_startEA_get(segment_t *segm)
|
||||
{
|
||||
return segm->startEA;
|
||||
}
|
||||
|
||||
void segment_t_endEA_set(segment_t *segm, ea_t newea)
|
||||
{
|
||||
if ( getseg(segm->startEA) == segm )
|
||||
@ -46,6 +48,7 @@ void segment_t_endEA_set(segment_t *segm, ea_t newea)
|
||||
segm->endEA = newea;
|
||||
}
|
||||
}
|
||||
|
||||
ea_t segment_t_endEA_get(segment_t *segm)
|
||||
{
|
||||
return segm->endEA;
|
||||
@ -56,6 +59,7 @@ ea_t segment_t_endEA_get(segment_t *segm)
|
||||
ea_t startEA;
|
||||
ea_t endEA;
|
||||
}
|
||||
|
||||
%include "segment.hpp"
|
||||
|
||||
%inline %{
|
||||
|
@ -133,8 +133,32 @@
|
||||
}
|
||||
%enddef
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// IN/OUT qstring
|
||||
//---------------------------------------------------------------------
|
||||
%typemap(in,numinputs=0) qstring *result (qstring temp) {
|
||||
$1 = &temp;
|
||||
}
|
||||
%typemap(argout) qstring *result {
|
||||
Py_XDECREF(resultobj);
|
||||
if (result)
|
||||
{
|
||||
resultobj = PyString_FromStringAndSize($1->begin(), $1->length());
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
}
|
||||
%typemap(freearg) qstring* result
|
||||
{
|
||||
// Nothing. We certainly don't want 'temp' to be deleted.
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Check that the argument is a callable Python object
|
||||
//---------------------------------------------------------------------
|
||||
%typemap(in) PyObject *pyfunc {
|
||||
if (!PyCallable_Check($input)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expected a callable object");
|
||||
@ -155,8 +179,10 @@
|
||||
$1 = ea_t($1_temp);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Convert qstring
|
||||
//---------------------------------------------------------------------
|
||||
// IN qstring
|
||||
//---------------------------------------------------------------------
|
||||
// This is used to set/retrieve qstring that are structure members.
|
||||
%typemap(in) qstring*
|
||||
{
|
||||
char *buf;
|
||||
@ -167,25 +193,32 @@
|
||||
$1 = new qstring(buf, length);
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(freearg) qstring*
|
||||
{
|
||||
delete $1;
|
||||
}
|
||||
|
||||
%typemap(out) qstring*
|
||||
{
|
||||
$result = PyString_FromStringAndSize($1->c_str(), $1->length());
|
||||
}
|
||||
%typemap(out) qstring
|
||||
{
|
||||
$result = PyString_FromStringAndSize($1.c_str(), $1.length());
|
||||
}
|
||||
%apply qstring { _qstring<char> }
|
||||
%apply qstring* { _qstring<char>* }
|
||||
|
||||
|
||||
#ifdef __EA64__
|
||||
%apply longlong *INOUT { sval_t *value };
|
||||
%apply ulonglong *INOUT { ea_t *addr };
|
||||
%apply ulonglong *INOUT { sel_t *sel };
|
||||
%apply ulonglong *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection()
|
||||
#else
|
||||
%apply int *INOUT { sval_t *value };
|
||||
%apply unsigned int *INOUT { ea_t *addr };
|
||||
%apply unsigned int *INOUT { sel_t *sel };
|
||||
%apply unsigned int *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection()
|
||||
#endif
|
||||
|
||||
|
||||
@ -200,14 +233,14 @@
|
||||
%immutable;
|
||||
%inline %{
|
||||
template <typename Type, size_t N>
|
||||
struct wrapped_array {
|
||||
struct wrapped_array_t {
|
||||
Type (&data)[N];
|
||||
wrapped_array(Type (&data)[N]) : data(data) { }
|
||||
wrapped_array_t(Type (&data)[N]) : data(data) { }
|
||||
};
|
||||
%}
|
||||
%mutable;
|
||||
|
||||
%extend wrapped_array {
|
||||
%extend wrapped_array_t {
|
||||
inline size_t __len__() const { return N; }
|
||||
|
||||
inline const Type& __getitem__(size_t i) const throw(std::out_of_range) {
|
||||
@ -221,5 +254,49 @@ struct wrapped_array {
|
||||
throw std::out_of_range("out of bounds access");
|
||||
$self->data[i] = v;
|
||||
}
|
||||
|
||||
%pythoncode {
|
||||
__iter__ = _bounded_getitem_iterator
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#if SWIG_VERSION == 0x20012
|
||||
%typemap(out) tinfo_t {}
|
||||
%typemap(ret) tinfo_t
|
||||
{
|
||||
// ret tinfo_t
|
||||
tinfo_t *ni = new tinfo_t($1);
|
||||
til_register_python_tinfo_t_instance(ni);
|
||||
$result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0);
|
||||
}
|
||||
|
||||
|
||||
// KLUDGE: We'll let the compiler (or at worse the runtime)
|
||||
// decide of the flags to use, depending on the method we are currently
|
||||
// wrapping: at new-time, a SWIG_POINTER_NEW is required.
|
||||
%typemap(out) tinfo_t* {}
|
||||
%typemap(ret) tinfo_t*
|
||||
{
|
||||
// ret tinfo_t*
|
||||
tinfo_t *ni = new tinfo_t(*($1));
|
||||
til_register_python_tinfo_t_instance(ni);
|
||||
if ( strcmp("new_tinfo_t", "$symname") == 0 )
|
||||
{
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr(ni), $1_descriptor, SWIG_POINTER_NEW | 0);
|
||||
delete $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr(ni), $1_descriptor, SWIG_POINTER_OWN | 0);
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(check) tinfo_t*
|
||||
{
|
||||
if ( $1 == NULL )
|
||||
SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
|
||||
}
|
||||
#else
|
||||
#error Ensure tinfo_t wrapping is compatible with this version of SWIG
|
||||
#endif
|
||||
|
@ -68,6 +68,7 @@
|
||||
%ignore skip_function_arg_names;
|
||||
%ignore perform_funcarg_conversion;
|
||||
%ignore get_argloc_info;
|
||||
%ignore argloc_t::dstr;
|
||||
|
||||
%ignore extract_pstr;
|
||||
%ignore extract_name;
|
||||
@ -148,7 +149,10 @@
|
||||
%ignore format_data_info_t;
|
||||
%ignore valinfo_t;
|
||||
%ignore print_c_data;
|
||||
%ignore print_cdata;
|
||||
%ignore format_c_data;
|
||||
%ignore format_cdata;
|
||||
%ignore format_cdata2;
|
||||
%ignore format_c_number;
|
||||
%ignore get_enum_member_expr;
|
||||
%ignore extend_sign;
|
||||
@ -165,6 +169,81 @@
|
||||
%ignore enum_type_data_t::deserialize_enum;
|
||||
%ignore valstr_deprecated_t;
|
||||
%ignore valinfo_deprecated_t;
|
||||
%ignore valstr_deprecated2_t;
|
||||
%ignore valinfo_deprecated2_t;
|
||||
|
||||
%ignore custloc_desc_t;
|
||||
%ignore install_custom_argloc;
|
||||
%ignore remove_custom_argloc;
|
||||
%ignore retrieve_custom_argloc;
|
||||
|
||||
%{
|
||||
//<code(py_typeinf)>
|
||||
//-------------------------------------------------------------------------
|
||||
// A set of tinfo_t objects that were created from IDAPython.
|
||||
// This is necessary in order to clear all the "type details" that are
|
||||
// associated, in the kernel, with the tinfo_t instances.
|
||||
//
|
||||
// Unfortunately the IDAPython plugin has to terminate _after_ the IDB is
|
||||
// closed, but the "type details" must be cleared _before_ the IDB is closed.
|
||||
static qvector<tinfo_t*> python_tinfos;
|
||||
void til_clear_python_tinfo_t_instances(void)
|
||||
{
|
||||
// Pre-emptive strike: clear all the python-exposed tinfo_t instances: if that
|
||||
// were not done here, ~tinfo_t() calls happening as part of the python shutdown
|
||||
// process will try and clear() their details. ..but the kernel's til-related
|
||||
// functions will already have deleted those details at that point.
|
||||
for ( size_t i = 0, n = python_tinfos.size(); i < n; ++i )
|
||||
python_tinfos[i]->clear();
|
||||
// NOTE: Don't clear() the array of pointers. All the python-exposed tinfo_t
|
||||
// instances will be deleted through the python shutdown/ref-decrementing
|
||||
// process anyway (which will cause til_deregister_..() calls), and the
|
||||
// entries will be properly pulled out of the vector when that happens.
|
||||
}
|
||||
|
||||
void til_register_python_tinfo_t_instance(tinfo_t *tif)
|
||||
{
|
||||
// Let's add_unique() it, because every reference to an object's
|
||||
// tinfo_t property will end up trying to register it.
|
||||
python_tinfos.add_unique(tif);
|
||||
}
|
||||
|
||||
void til_deregister_python_tinfo_t_instance(tinfo_t *tif)
|
||||
{
|
||||
qvector<tinfo_t*>::iterator found = python_tinfos.find(tif);
|
||||
if ( found != python_tinfos.end() )
|
||||
{
|
||||
tif->clear();
|
||||
python_tinfos.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
//</code(py_typeinf)>
|
||||
%}
|
||||
|
||||
%extend tinfo_t {
|
||||
|
||||
bool deserialize(
|
||||
const til_t *til,
|
||||
const type_t *type,
|
||||
const p_list *fields,
|
||||
const p_list *cmts = NULL)
|
||||
{
|
||||
return $self->deserialize(til, &type, &fields, cmts == NULL ? NULL : &cmts);
|
||||
}
|
||||
|
||||
// The typemap in typeconv.i will take care of registering newly-constructed
|
||||
// tinfo_t instances. However, there's no such thing as a destructor typemap.
|
||||
// Therefore, we need to do the grunt work of de-registering ourselves.
|
||||
// Note: The 'void' here is important: Without it, SWIG considers it to
|
||||
// be a different destructor (which, of course, makes a ton of sense.)
|
||||
~tinfo_t(void)
|
||||
{
|
||||
til_deregister_python_tinfo_t_instance($self);
|
||||
delete $self;
|
||||
}
|
||||
}
|
||||
%ignore tinfo_t::~tinfo_t(void);
|
||||
|
||||
%include "typeinf.hpp"
|
||||
|
||||
@ -710,7 +789,6 @@ char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize)
|
||||
qstrncpy(buf, name, bufsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
//</inline(py_typeinf)>
|
||||
til_t *load_til(const char *tildir, const char *name)
|
||||
{
|
||||
|
@ -771,7 +771,7 @@ static PyObject *op_t_get_value(PyObject *self)
|
||||
op_t *link = op_t_get_clink(self);
|
||||
if ( link == NULL )
|
||||
Py_RETURN_NONE;
|
||||
return Py_BuildValue("I", link->value);
|
||||
return Py_BuildValue(PY_FMT64, (pyul_t)link->value);
|
||||
}
|
||||
|
||||
static void op_t_set_value(PyObject *self, PyObject *value)
|
||||
@ -780,7 +780,9 @@ static void op_t_set_value(PyObject *self, PyObject *value)
|
||||
op_t *link = op_t_get_clink(self);
|
||||
if ( link == NULL )
|
||||
return;
|
||||
link->value = PyInt_AsLong(value);
|
||||
uint64 v(0);
|
||||
PyW_GetNumber(value, &v);
|
||||
link->value = uval_t(v);
|
||||
}
|
||||
|
||||
static PyObject *op_t_get_addr(PyObject *self)
|
||||
|
85
swig/view.i
85
swig/view.i
@ -14,16 +14,33 @@ class py_customidamemo_t;
|
||||
class lookup_info_t
|
||||
{
|
||||
public:
|
||||
void add(TForm *form, TCustomControl *view, py_customidamemo_t *py_view)
|
||||
struct entry_t
|
||||
{
|
||||
QASSERT(0, form != NULL && view != NULL && py_view != NULL
|
||||
entry_t() : form(NULL), view(NULL), py_view(NULL) {}
|
||||
private:
|
||||
TForm *form;
|
||||
TCustomControl *view;
|
||||
py_customidamemo_t *py_view;
|
||||
friend class lookup_info_t;
|
||||
};
|
||||
|
||||
entry_t &new_entry(py_customidamemo_t *py_view)
|
||||
{
|
||||
QASSERT(30454, py_view != NULL && !find_by_py_view(NULL, NULL, py_view));
|
||||
entry_t &e = entries.push_back();
|
||||
e.py_view = py_view;
|
||||
return e;
|
||||
}
|
||||
|
||||
void commit(entry_t &e, TForm *form, TCustomControl *view)
|
||||
{
|
||||
QASSERT(30455, &e >= entries.begin() && &e < entries.end());
|
||||
QASSERT(30456, form != NULL && view != NULL && e.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();
|
||||
&& find_by_py_view(NULL, NULL, e.py_view));
|
||||
e.form = form;
|
||||
e.view = view;
|
||||
e.py_view = py_view;
|
||||
}
|
||||
|
||||
#define FIND_BY__BODY(crit, res1, res2) \
|
||||
@ -61,12 +78,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
struct entry_t
|
||||
{
|
||||
TForm *form;
|
||||
TCustomControl *view;
|
||||
py_customidamemo_t *py_view;
|
||||
};
|
||||
typedef qvector<entry_t> entries_t;
|
||||
entries_t entries;
|
||||
};
|
||||
@ -130,6 +141,8 @@ class py_customidamemo_t
|
||||
|
||||
static void ensure_view_callbacks_installed();
|
||||
int cb_flags;
|
||||
// number of arguments for OnViewClick implementation
|
||||
int ovc_num_args;
|
||||
|
||||
protected:
|
||||
ref_t self;
|
||||
@ -198,6 +211,7 @@ public:
|
||||
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; }
|
||||
int get_py_method_arg_count(char *method_name);
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -207,6 +221,7 @@ py_customidamemo_t::py_customidamemo_t()
|
||||
{
|
||||
PYGLOG("%p: py_customidamemo_t()\n", this);
|
||||
ensure_view_callbacks_installed();
|
||||
ovc_num_args = -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -401,7 +416,7 @@ PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos)
|
||||
{
|
||||
newref_t node(PySequence_GetItem(nodes.o, k));
|
||||
if ( PyInt_Check(node.o) )
|
||||
gi.nodes.insert(PyInt_AsLong(node.o));
|
||||
gi.nodes.add_unique(PyInt_AsLong(node.o));
|
||||
}
|
||||
if ( !gi.nodes.empty() )
|
||||
{
|
||||
@ -409,18 +424,18 @@ PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos)
|
||||
gis.push_back(gi);
|
||||
}
|
||||
}
|
||||
intset_t groups;
|
||||
intvec_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 )
|
||||
for ( intvec_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)
|
||||
static void pynodes_to_idanodes(intvec_t *idanodes, ref_t pynodes)
|
||||
{
|
||||
Py_ssize_t sz = PySequence_Size(pynodes.o);
|
||||
for ( Py_ssize_t i = 0; i < sz; ++i )
|
||||
@ -428,7 +443,7 @@ static void pynodes_to_idanodes(intset_t *idanodes, ref_t pynodes)
|
||||
newref_t item(PySequence_GetItem(pynodes.o, i));
|
||||
if ( !PyInt_Check(item.o) )
|
||||
continue;
|
||||
idanodes->insert(PyInt_AsLong(item.o));
|
||||
idanodes->add_unique(PyInt_AsLong(item.o));
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,7 +454,7 @@ PyObject *py_customidamemo_t::delete_groups(PyObject *_groups, PyObject *_new_cu
|
||||
Py_RETURN_NONE;
|
||||
borref_t groups(_groups);
|
||||
borref_t new_current(_new_current);
|
||||
intset_t ida_groups;
|
||||
intvec_t ida_groups;
|
||||
pynodes_to_idanodes(&ida_groups, groups);
|
||||
if ( ida_groups.empty() )
|
||||
Py_RETURN_NONE;
|
||||
@ -459,7 +474,7 @@ PyObject *py_customidamemo_t::set_groups_visibility(PyObject *_groups, PyObject
|
||||
borref_t groups(_groups);
|
||||
borref_t expand(_expand);
|
||||
borref_t new_current(_new_current);
|
||||
intset_t ida_groups;
|
||||
intvec_t ida_groups;
|
||||
pynodes_to_idanodes(&ida_groups, groups);
|
||||
if ( ida_groups.empty() )
|
||||
Py_RETURN_NONE;
|
||||
@ -498,6 +513,23 @@ void py_customidamemo_t::unbind()
|
||||
view = NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
int py_customidamemo_t::get_py_method_arg_count(char *method_name)
|
||||
{
|
||||
newref_t method(PyObject_GetAttrString(self.o, method_name));
|
||||
if ( method != NULL && PyCallable_Check(method.o) )
|
||||
{
|
||||
newref_t fc(PyObject_GetAttrString(method.o, "func_code"));
|
||||
if ( fc != NULL )
|
||||
{
|
||||
newref_t ac(PyObject_GetAttrString(fc.o, "co_argcount"));
|
||||
if ( ac != NULL )
|
||||
return PyInt_AsLong(ac.o);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void py_customidamemo_t::collect_class_callbacks_ids(callbacks_ids_t *out)
|
||||
{
|
||||
@ -603,12 +635,26 @@ void py_customidamemo_t::on_view_popup()
|
||||
void py_customidamemo_t::on_view_click(const view_mouse_event_t *event)
|
||||
{
|
||||
CHK_EVT(GRBASE_HAVE_VIEW_CLICK);
|
||||
if ( ovc_num_args < 0 )
|
||||
ovc_num_args = get_py_method_arg_count((char*)S_ON_VIEW_CLICK);
|
||||
if ( ovc_num_args == 5 )
|
||||
{
|
||||
newref_t result(
|
||||
PyObject_CallMethod(
|
||||
self.o,
|
||||
(char *)S_ON_VIEW_CLICK,
|
||||
"iiii",
|
||||
event->x, event->y, event->state, event->button));
|
||||
}
|
||||
else
|
||||
{
|
||||
newref_t result(
|
||||
PyObject_CallMethod(
|
||||
self.o,
|
||||
(char *)S_ON_VIEW_CLICK,
|
||||
"iii",
|
||||
event->x, event->y, event->state));
|
||||
}
|
||||
CHK_RES();
|
||||
}
|
||||
|
||||
@ -958,7 +1004,8 @@ bool py_idaview_t::Bind(PyObject *self)
|
||||
else
|
||||
{
|
||||
py_view = new py_idaview_t();
|
||||
lookup_info.add(tform, v, py_view);
|
||||
lookup_info_t::entry_t &e = lookup_info.new_entry(py_view);
|
||||
lookup_info.commit(e, tform, v);
|
||||
}
|
||||
|
||||
// Finally, bind:
|
||||
|
@ -11,6 +11,7 @@
|
||||
%ignore destroy_switch_info;
|
||||
%ignore create_switch_xrefs;
|
||||
%ignore create_switch_table;
|
||||
%rename (calc_switch_cases) py_calc_switch_cases;
|
||||
|
||||
// These functions should not be called directly (according to docs)
|
||||
%ignore xrefblk_t_first_from;
|
||||
|
Loading…
Reference in New Issue
Block a user