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:
elias.bachaalany@gmail.com 2014-07-04 22:02:42 +00:00
parent 1c6752de40
commit fbb5bfabd6
44 changed files with 3195 additions and 2395 deletions

View File

@ -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/
Current project owner and maintainer
* Elias Bachaalany - elias.bachaalany@gmail.com
Maintains IDAPython online source code repository and coordinates patches/updates/contributions from Hex-Rays and 3rd party contributors
* Ero Carrera - http://dkbza.org/

View File

@ -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")

View File

@ -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

View File

@ -1,27 +1,26 @@
import idaapi
def main():
if not idaapi.init_hexrays_plugin():
return False
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
f = idaapi.get_func(idaapi.get_screen_ea());
if f is None:
print "Please position the cursor within a function"
return True
cfunc = idaapi.decompile(f);
if cfunc is None:
print "Failed to decompile!"
return True
sv = cfunc.get_pseudocode();
for i in xrange(0, sv.size()):
line = idaapi.tag_remove(str(sv[i]));
print line
return True
if main():
idaapi.term_hexrays_plugin();
import idaapi
def main():
if not idaapi.init_hexrays_plugin():
return False
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
f = idaapi.get_func(idaapi.get_screen_ea());
if f is None:
print "Please position the cursor within a function"
return True
cfunc = idaapi.decompile(f);
if cfunc is None:
print "Failed to decompile!"
return True
sv = cfunc.get_pseudocode();
for sline in sv:
print idaapi.tag_remove(sline.line);
return True
if main():
idaapi.term_hexrays_plugin();

View File

@ -1,196 +1,196 @@
""" Invert the then and else blocks of a cif_t.
Author: EiNSTeiN_ <einstein@g3nius.org>
This is a rewrite in Python of the vds3 example that comes with hexrays sdk.
The main difference with the original C code is that when we create the inverted
condition object, the newly created cexpr_t instance is given to the hexrays and
must not be freed by swig. To achieve this, we have to change the 'thisown' flag
when appropriate. See http://www.swig.org/Doc1.3/Python.html#Python_nn35
"""
import idautils
import idaapi
import idc
import traceback
NETNODE_NAME = '$ hexrays-inverted-if'
class hexrays_callback_info(object):
def __init__(self):
self.vu = None
self.node = idaapi.netnode()
if not self.node.create(NETNODE_NAME):
# node exists
self.load()
else:
self.stored = []
return
def load(self):
self.stored = []
try:
data = self.node.getblob(0, 'I')
if data:
self.stored = eval(data)
print 'Invert-if: Loaded %s' % (repr(self.stored), )
except:
print 'Failed to load invert-if locations'
traceback.print_exc()
return
return
def save(self):
try:
self.node.setblob(repr(self.stored), 0, 'I')
except:
print 'Failed to save invert-if locations'
traceback.print_exc()
return
return
def invert_if(self, cfunc, insn):
if insn.opname != 'if':
return False
cif = insn.details
if not cif.ithen or not cif.ielse:
return False
idaapi.qswap(cif.ithen, cif.ielse)
cond = idaapi.cexpr_t(cif.expr)
notcond = idaapi.lnot(cond)
cond.thisown = 0 # the new wrapper 'notcond' now holds the reference to the cexpr_t
cif.expr.swap(notcond)
return True
def add_location(self, ea):
if ea in self.stored:
self.stored.remove(ea)
else:
self.stored.append(ea)
self.save()
return
def find_if_statement(self, vu):
vu.get_current_item(idaapi.USE_KEYBOARD)
item = vu.item
if item.is_citem() and item.it.op == idaapi.cit_if and item.it.to_specific_type.cif.ielse is not None:
return item.it.to_specific_type
if vu.tail.citype == idaapi.VDI_TAIL and vu.tail.loc.itp == idaapi.ITP_ELSE:
# for tail marks, we know only the corresponding ea,
# not the pointer to if-statement
# find it by walking the whole ctree
class if_finder_t(idaapi.ctree_visitor_t):
def __init__(self, ea):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
self.ea = ea
self.found = None
return
def visit_insn(self, i):
if i.op == idaapi.cit_if and i.ea == self.ea:
self.found = i
return 1 # stop enumeration
return 0
iff = if_finder_t(vu.tail.loc.ea)
if iff.apply_to(vu.cfunc.body, None):
return iff.found
return
def invert_if_event(self, vu):
cfunc = vu.cfunc.__deref__()
i = self.find_if_statement(vu)
if not i:
return False
if self.invert_if(cfunc, i):
vu.refresh_ctext()
self.add_location(i.ea)
return True
def restore(self, cfunc):
class visitor(idaapi.ctree_visitor_t):
def __init__(self, inverter, cfunc):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
self.inverter = inverter
self.cfunc = cfunc
return
def visit_insn(self, i):
try:
if i.op == idaapi.cit_if and i.ea in self.inverter.stored:
self.inverter.invert_if(self.cfunc, i)
except:
traceback.print_exc()
return 0 # continue enumeration
visitor(self, cfunc).apply_to(cfunc.body, None)
return
def menu_callback(self):
try:
self.invert_if_event(self.vu)
except:
traceback.print_exc()
return 0
def event_callback(self, event, *args):
try:
if event == idaapi.hxe_keyboard:
vu, keycode, shift = args
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("I") and shift == 0:
if self.invert_if_event(vu):
return 1
elif event == idaapi.hxe_right_click:
self.vu, = args
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Invert then/else", "I", self.menu_callback)
elif event == idaapi.hxe_maturity:
cfunc, maturity = args
if maturity == idaapi.CMAT_FINAL:
self.restore(cfunc)
except:
traceback.print_exc()
return 0
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'invert-if: hexrays is not available.'
""" Invert the then and else blocks of a cif_t.
Author: EiNSTeiN_ <einstein@g3nius.org>
This is a rewrite in Python of the vds3 example that comes with hexrays sdk.
The main difference with the original C code is that when we create the inverted
condition object, the newly created cexpr_t instance is given to the hexrays and
must not be freed by swig. To achieve this, we have to change the 'thisown' flag
when appropriate. See http://www.swig.org/Doc1.3/Python.html#Python_nn35
"""
import idautils
import idaapi
import idc
import traceback
NETNODE_NAME = '$ hexrays-inverted-if'
class hexrays_callback_info(object):
def __init__(self):
self.vu = None
self.node = idaapi.netnode()
if not self.node.create(NETNODE_NAME):
# node exists
self.load()
else:
self.stored = []
return
def load(self):
self.stored = []
try:
data = self.node.getblob(0, 'I')
if data:
self.stored = eval(data)
print 'Invert-if: Loaded %s' % (repr(self.stored), )
except:
print 'Failed to load invert-if locations'
traceback.print_exc()
return
return
def save(self):
try:
self.node.setblob(repr(self.stored), 0, 'I')
except:
print 'Failed to save invert-if locations'
traceback.print_exc()
return
return
def invert_if(self, cfunc, insn):
if insn.opname != 'if':
return False
cif = insn.details
if not cif.ithen or not cif.ielse:
return False
idaapi.qswap(cif.ithen, cif.ielse)
cond = idaapi.cexpr_t(cif.expr)
notcond = idaapi.lnot(cond)
cond.thisown = 0 # the new wrapper 'notcond' now holds the reference to the cexpr_t
cif.expr.swap(notcond)
return True
def add_location(self, ea):
if ea in self.stored:
self.stored.remove(ea)
else:
self.stored.append(ea)
self.save()
return
def find_if_statement(self, vu):
vu.get_current_item(idaapi.USE_KEYBOARD)
item = vu.item
if item.is_citem() and item.it.op == idaapi.cit_if and item.it.to_specific_type.cif.ielse is not None:
return item.it.to_specific_type
if vu.tail.citype == idaapi.VDI_TAIL and vu.tail.loc.itp == idaapi.ITP_ELSE:
# for tail marks, we know only the corresponding ea,
# not the pointer to if-statement
# find it by walking the whole ctree
class if_finder_t(idaapi.ctree_visitor_t):
def __init__(self, ea):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
self.ea = ea
self.found = None
return
def visit_insn(self, i):
if i.op == idaapi.cit_if and i.ea == self.ea:
self.found = i
return 1 # stop enumeration
return 0
iff = if_finder_t(vu.tail.loc.ea)
if iff.apply_to(vu.cfunc.body, None):
return iff.found
return
def invert_if_event(self, vu):
cfunc = vu.cfunc.__deref__()
i = self.find_if_statement(vu)
if not i:
return False
if self.invert_if(cfunc, i):
vu.refresh_ctext()
self.add_location(i.ea)
return True
def restore(self, cfunc):
class visitor(idaapi.ctree_visitor_t):
def __init__(self, inverter, cfunc):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST | idaapi.CV_INSNS)
self.inverter = inverter
self.cfunc = cfunc
return
def visit_insn(self, i):
try:
if i.op == idaapi.cit_if and i.ea in self.inverter.stored:
self.inverter.invert_if(self.cfunc, i)
except:
traceback.print_exc()
return 0 # continue enumeration
visitor(self, cfunc).apply_to(cfunc.body, None)
return
def menu_callback(self):
try:
self.invert_if_event(self.vu)
except:
traceback.print_exc()
return 0
def event_callback(self, event, *args):
try:
if event == idaapi.hxe_keyboard:
vu, keycode, shift = args
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("I") and shift == 0:
if self.invert_if_event(vu):
return 1
elif event == idaapi.hxe_right_click:
self.vu, = args
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Invert then/else", "I", self.menu_callback)
elif event == idaapi.hxe_maturity:
cfunc, maturity = args
if maturity == idaapi.CMAT_FINAL:
self.restore(cfunc)
except:
traceback.print_exc()
return 0
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'invert-if: hexrays is not available.'

View File

@ -1,123 +1,123 @@
""" Print user-defined details to the output window.
Author: EiNSTeiN_ <einstein@g3nius.org>
This is a rewrite in Python of the vds4 example that comes with hexrays sdk.
"""
import idautils
import idaapi
import idc
import traceback
def run():
cfunc = idaapi.decompile(idaapi.get_screen_ea())
if not cfunc:
print 'Please move the cursor into a function.'
return
entry_ea = cfunc.entry_ea
print "Dump of user-defined information for function at %x" % (entry_ea, )
# Display user defined labels.
labels = idaapi.restore_user_labels(entry_ea);
if labels is not None:
print "------- %u user defined labels" % (len(labels), )
for org_label, name in labels.iteritems():
print "Label %d: %s" % (org_label, str(name))
idaapi.user_labels_free(labels)
# Display user defined comments
cmts = idaapi.restore_user_cmts(entry_ea);
if cmts is not None:
print "------- %u user defined comments" % (len(cmts), )
for tl, cmt in cmts.iteritems():
print "Comment at %x, preciser %x:\n%s\n" % (tl.ea, tl.itp, str(cmt))
idaapi.user_cmts_free(cmts)
# Display user defined citem iflags
iflags = idaapi.restore_user_iflags(entry_ea)
if iflags is not None:
print "------- %u user defined citem iflags" % (len(iflags), )
for cl, t in iflags.iteritems():
print "%a(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & CIT_COLLAPSED else "")
idaapi.user_iflags_free(iflags)
# Display user defined number formats
numforms = idaapi.restore_user_numforms(entry_ea)
if numforms is not None:
print "------- %u user defined number formats" % (len(numforms), )
for ol, nf in numforms.iteritems():
print "Number format at %a, operand %d: %s" % (ol.ea, ol.opnum, "negated " if (nf.props & NF_NEGATE) != 0 else "")
if nf.isEnum():
print "enum %s (serial %d)" % (str(nf.type_name), nf.serial)
elif nf.isChar():
print "char"
elif nf.isStroff():
print "struct offset %s" % (str(nf.type_name), )
else:
print "number base=%d" % (idaapi.getRadix(nf.flags, ol.opnum), )
idaapi.user_numforms_free(numforms)
# Display user-defined local variable information
# First defined the visitor class
class dump_lvar_info_t(idaapi.user_lvar_visitor_t):
def __init__(self):
idaapi.user_lvar_visitor_t.__init__(self)
self.displayed_header = False
return
def get_info_qty_for_saving(self):
return 0
def get_info_for_saving(self, lv):
return False
def handle_retrieved_info(self, lv):
try:
if not self.displayed_header:
self.displayed_header = True;
print "------- User defined local variable information"
print "Lvar defined at %x" % (lv.ll.defea, )
if len(str(lv.name)):
print " Name: %s" % (str(lv.name), )
if len(str(lv.type)):
#~ print_type_to_one_line(buf, sizeof(buf), idati, .c_str());
print " Type: %s" % (str(lv.type), )
if len(str(lv.cmt)):
print " Comment: %s" % (str(lv.cmt), )
except:
traceback.print_exc()
return 0
def handle_retrieved_mapping(self, lm):
return 0
def get_info_mapping_for_saving(self):
return None
# Now iterate over all user definitions
dli = dump_lvar_info_t();
idaapi.restore_user_lvar_settings(entry_ea, dli)
return
if idaapi.init_hexrays_plugin():
run()
else:
print 'dump user info: hexrays is not available.'
""" Print user-defined details to the output window.
Author: EiNSTeiN_ <einstein@g3nius.org>
This is a rewrite in Python of the vds4 example that comes with hexrays sdk.
"""
import idautils
import idaapi
import idc
import traceback
def run():
cfunc = idaapi.decompile(idaapi.get_screen_ea())
if not cfunc:
print 'Please move the cursor into a function.'
return
entry_ea = cfunc.entry_ea
print "Dump of user-defined information for function at %x" % (entry_ea, )
# Display user defined labels.
labels = idaapi.restore_user_labels(entry_ea);
if labels is not None:
print "------- %u user defined labels" % (len(labels), )
for org_label, name in labels.iteritems():
print "Label %d: %s" % (org_label, str(name))
idaapi.user_labels_free(labels)
# Display user defined comments
cmts = idaapi.restore_user_cmts(entry_ea);
if cmts is not None:
print "------- %u user defined comments" % (len(cmts), )
for tl, cmt in cmts.iteritems():
print "Comment at %x, preciser %x:\n%s\n" % (tl.ea, tl.itp, str(cmt))
idaapi.user_cmts_free(cmts)
# Display user defined citem iflags
iflags = idaapi.restore_user_iflags(entry_ea)
if iflags is not None:
print "------- %u user defined citem iflags" % (len(iflags), )
for cl, t in iflags.iteritems():
print "%a(%d): %08X%s" % (cl.ea, cl.op, f, " CIT_COLLAPSED" if f & CIT_COLLAPSED else "")
idaapi.user_iflags_free(iflags)
# Display user defined number formats
numforms = idaapi.restore_user_numforms(entry_ea)
if numforms is not None:
print "------- %u user defined number formats" % (len(numforms), )
for ol, nf in numforms.iteritems():
print "Number format at %a, operand %d: %s" % (ol.ea, ol.opnum, "negated " if (nf.props & NF_NEGATE) != 0 else "")
if nf.isEnum():
print "enum %s (serial %d)" % (str(nf.type_name), nf.serial)
elif nf.isChar():
print "char"
elif nf.isStroff():
print "struct offset %s" % (str(nf.type_name), )
else:
print "number base=%d" % (idaapi.getRadix(nf.flags, ol.opnum), )
idaapi.user_numforms_free(numforms)
# Display user-defined local variable information
# First defined the visitor class
class dump_lvar_info_t(idaapi.user_lvar_visitor_t):
def __init__(self):
idaapi.user_lvar_visitor_t.__init__(self)
self.displayed_header = False
return
def get_info_qty_for_saving(self):
return 0
def get_info_for_saving(self, lv):
return False
def handle_retrieved_info(self, lv):
try:
if not self.displayed_header:
self.displayed_header = True;
print "------- User defined local variable information"
print "Lvar defined at %x" % (lv.ll.defea, )
if len(str(lv.name)):
print " Name: %s" % (str(lv.name), )
if len(str(lv.type)):
#~ print_type_to_one_line(buf, sizeof(buf), idati, .c_str());
print " Type: %s" % (str(lv.type), )
if len(str(lv.cmt)):
print " Comment: %s" % (str(lv.cmt), )
except:
traceback.print_exc()
return 0
def handle_retrieved_mapping(self, lm):
return 0
def get_info_mapping_for_saving(self):
return None
# Now iterate over all user definitions
dli = dump_lvar_info_t();
idaapi.restore_user_lvar_settings(entry_ea, dli)
return
if idaapi.init_hexrays_plugin():
run()
else:
print 'dump user info: hexrays is not available.'

View File

@ -1,62 +1,62 @@
""" It demonstrates how to iterate a cblock_t object.
Author: EiNSTeiN_ <einstein@g3nius.org>
This is a rewrite in Python of the vds7 example that comes with hexrays sdk.
"""
import idautils
import idaapi
import idc
import traceback
class cblock_visitor_t(idaapi.ctree_visitor_t):
def __init__(self):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST)
return
def visit_insn(self, ins):
try:
if ins.op == idaapi.cit_block:
self.dump_block(ins.ea, ins.cblock)
except:
traceback.print_exc()
return 0
def dump_block(self, ea, b):
# iterate over all block instructions
print "dumping block %x" % (ea, )
for ins in b:
print " %x: insn %s" % (ins.ea, ins.opname)
return
class hexrays_callback_info(object):
def __init__(self):
return
def event_callback(self, event, *args):
try:
if event == idaapi.hxe_maturity:
cfunc, maturity = args
if maturity == idaapi.CMAT_BUILT:
cbv = cblock_visitor_t()
cbv.apply_to(cfunc.body, None)
except:
traceback.print_exc()
return 0
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'cblock visitor: hexrays is not available.'
""" It demonstrates how to iterate a cblock_t object.
Author: EiNSTeiN_ <einstein@g3nius.org>
This is a rewrite in Python of the vds7 example that comes with hexrays sdk.
"""
import idautils
import idaapi
import idc
import traceback
class cblock_visitor_t(idaapi.ctree_visitor_t):
def __init__(self):
idaapi.ctree_visitor_t.__init__(self, idaapi.CV_FAST)
return
def visit_insn(self, ins):
try:
if ins.op == idaapi.cit_block:
self.dump_block(ins.ea, ins.cblock)
except:
traceback.print_exc()
return 0
def dump_block(self, ea, b):
# iterate over all block instructions
print "dumping block %x" % (ea, )
for ins in b:
print " %x: insn %s" % (ins.ea, ins.opname)
return
class hexrays_callback_info(object):
def __init__(self):
return
def event_callback(self, event, *args):
try:
if event == idaapi.hxe_maturity:
cfunc, maturity = args
if maturity == idaapi.CMAT_BUILT:
cbv = cblock_visitor_t()
cbv.apply_to(cfunc.body, None)
except:
traceback.print_exc()
return 0
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'cblock visitor: hexrays is not available.'

View File

@ -1,319 +1,316 @@
""" Xref plugin for Hexrays Decompiler
Author: EiNSTeiN_ <einstein@g3nius.org>
Show decompiler-style Xref when the X key is pressed in the Decompiler window.
- It supports any global name: functions, strings, integers, etc.
- It supports structure member.
"""
import idautils
import idaapi
import idc
import traceback
try:
from PyQt4 import QtCore, QtGui
print 'Using PyQt'
except:
print 'PyQt not available'
try:
from PySide import QtGui, QtCore
print 'Using PySide'
except:
print 'PySide not available'
XREF_EA = 0
XREF_STRUC_MEMBER = 1
class XrefsForm(idaapi.PluginForm):
def __init__(self, target):
idaapi.PluginForm.__init__(self)
self.target = target
if type(self.target) == idaapi.cfunc_t:
self.__type = XREF_EA
self.__ea = self.target.entry_ea
self.__name = 'Xrefs of %x' % (self.__ea, )
elif type(self.target) == idaapi.cexpr_t and self.target.opname == 'obj':
self.__type = XREF_EA
self.__ea = self.target.obj_ea
self.__name = 'Xrefs of %x' % (self.__ea, )
elif type(self.target) == idaapi.cexpr_t and self.target.opname in ('memptr', 'memref'):
self.__type = XREF_STRUC_MEMBER
name = self.get_struc_name()
self.__name = 'Xrefs of %s' % (name, )
else:
raise ValueError('cannot show xrefs for this kind of target')
return
def get_struc_name(self):
x = self.target.operands['x']
m = self.target.operands['m']
xtype = typestring(x.type.u_str())
xtype.remove_ptr_or_array()
typename = str(xtype)
sid = idc.GetStrucIdByName(typename)
member = idc.GetMemberName(sid, m)
return '%s::%s' % (typename, member)
def OnCreate(self, form):
# Get parent widget
try:
self.parent = self.FormToPySideWidget(form)
except:
self.parent = self.FormToPyQtWidget(form)
self.populate_form()
return
def Show(self):
idaapi.PluginForm.Show(self, self.__name)
return
def populate_form(self):
# Create layout
layout = QtGui.QVBoxLayout()
layout.addWidget(QtGui.QLabel(self.__name))
self.table = QtGui.QTableWidget()
layout.addWidget(self.table)
self.table.setColumnCount(3)
self.table.setHorizontalHeaderItem(0, QtGui.QTableWidgetItem("Address"))
self.table.setHorizontalHeaderItem(1, QtGui.QTableWidgetItem("Function"))
self.table.setHorizontalHeaderItem(2, QtGui.QTableWidgetItem("Line"))
self.table.setColumnWidth(0, 80)
self.table.setColumnWidth(1, 150)
self.table.setColumnWidth(2, 450)
self.table.cellDoubleClicked.connect(self.double_clicked)
#~ self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows )
self.parent.setLayout(layout)
self.populate_table()
return
def double_clicked(self, row, column):
ea = self.functions[row]
idaapi.open_pseudocode(ea, True)
return
def get_decompiled_line(self, cfunc, ea):
print repr(ea)
if ea not in cfunc.eamap:
print 'strange, %x is not in %x eamap' % (ea, cfunc.entry_ea)
return
insnvec = cfunc.eamap[ea]
lines = []
for stmt in insnvec:
qs = idaapi.qstring()
qp = idaapi.qstring_printer_t(cfunc.__deref__(), qs, False)
stmt._print(0, qp)
s = str(qs).split('\n')[0]
#~ s = idaapi.tag_remove(s)
lines.append(s)
return '\n'.join(lines)
def get_items_for_ea(self, ea):
frm = [x.frm for x in idautils.XrefsTo(self.__ea)]
items = []
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)))
except Exception as e:
print 'could not decompile: %s' % (str(e), )
raise
return
def get_items_for_type(self):
x = self.target.operands['x']
m = self.target.operands['m']
xtype = typestring(x.type.u_str())
xtype.remove_ptr_or_array()
typename = str(xtype)
addresses = []
for ea in idautils.Functions():
try:
cfunc = idaapi.decompile(ea)
cfunc.refcnt += 1
except:
print 'Decompilation of %x failed' % (ea, )
continue
str(cfunc)
for citem in cfunc.treeitems:
citem = citem.to_specific_type
if not (type(citem) == idaapi.cexpr_t and citem.opname in ('memptr', 'memref')):
continue
_x = citem.operands['x']
_m = citem.operands['m']
_xtype = typestring(_x.type.u_str())
_xtype.remove_ptr_or_array()
_typename = str(_xtype)
#~ print 'in', hex(cfunc.entry_ea), _typename, _m
if not (_typename == typename and _m == m):
continue
parent = citem
while parent:
if type(parent.to_specific_type) == idaapi.cinsn_t:
break
parent = cfunc.body.find_parent_of(parent)
if not parent:
print 'cannot find parent statement (?!)'
continue
if parent.ea in addresses:
continue
if parent.ea == idaapi.BADADDR:
print 'parent.ea is BADADDR'
continue
addresses.append(parent.ea)
self.functions.append(cfunc.entry_ea)
self.items.append((parent.ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, int(parent.ea))))
return []
def populate_table(self):
self.functions = []
self.items = []
if self.__type == XREF_EA:
self.get_items_for_ea(self.__ea)
else:
self.get_items_for_type()
self.table.setRowCount(len(self.items))
i = 0
for item in self.items:
address, func, line = item
item = QtGui.QTableWidgetItem('0x%x' % (address, ))
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
self.table.setItem(i, 0, item)
item = QtGui.QTableWidgetItem(func)
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
self.table.setItem(i, 1, item)
item = QtGui.QTableWidgetItem(line)
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
self.table.setItem(i, 2, item)
i += 1
self.table.resizeRowsToContents()
return
def OnClose(self, form):
pass
class hexrays_callback_info(object):
def __init__(self):
self.vu = None
return
def show_xrefs(self, vu):
vu.get_current_item(idaapi.USE_KEYBOARD)
item = vu.item
sel = None
if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'):
# if an expression is selected. verify that it's either a cot_obj, cot_memref or cot_memptr
sel = item.it.to_specific_type
elif item.citype == idaapi.VDI_FUNC:
# if the function itself is selected, show xrefs to it.
sel = item.f
else:
return False
form = XrefsForm(sel)
form.Show()
return True
def menu_callback(self):
self.show_xrefs(self.vu)
return 0
def event_callback(self, event, *args):
try:
if event == idaapi.hxe_keyboard:
vu, keycode, shift = args
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("X") and shift == 0:
if self.show_xrefs(vu):
return 1
elif event == idaapi.hxe_right_click:
self.vu = args[0]
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Xrefs", "X", self.menu_callback)
except:
traceback.print_exc()
return 0
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'invert-if: hexrays is not available.'
""" Xref plugin for Hexrays Decompiler
Author: EiNSTeiN_ <einstein@g3nius.org>
Show decompiler-style Xref when the X key is pressed in the Decompiler window.
- It supports any global name: functions, strings, integers, etc.
- It supports structure member.
"""
import idautils
import idaapi
import idc
import traceback
try:
from PyQt4 import QtCore, QtGui
print 'Using PyQt'
except:
print 'PyQt not available'
try:
from PySide import QtGui, QtCore
print 'Using PySide'
except:
print 'PySide not available'
XREF_EA = 0
XREF_STRUC_MEMBER = 1
class XrefsForm(idaapi.PluginForm):
def __init__(self, target):
idaapi.PluginForm.__init__(self)
self.target = target
if type(self.target) == idaapi.cfunc_t:
self.__type = XREF_EA
self.__ea = self.target.entry_ea
self.__name = 'Xrefs of %x' % (self.__ea, )
elif type(self.target) == idaapi.cexpr_t and self.target.opname == 'obj':
self.__type = XREF_EA
self.__ea = self.target.obj_ea
self.__name = 'Xrefs of %x' % (self.__ea, )
elif type(self.target) == idaapi.cexpr_t and self.target.opname in ('memptr', 'memref'):
self.__type = XREF_STRUC_MEMBER
name = self.get_struc_name()
self.__name = 'Xrefs of %s' % (name, )
else:
raise ValueError('cannot show xrefs for this kind of target')
return
def get_struc_name(self):
x = self.target.operands['x']
m = self.target.operands['m']
xtype = x.type
xtype.remove_ptr_or_array()
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
sid = idc.GetStrucIdByName(typename)
member = idc.GetMemberName(sid, m)
return '%s::%s' % (typename, member)
def OnCreate(self, form):
# Get parent widget
try:
self.parent = self.FormToPySideWidget(form)
except:
self.parent = self.FormToPyQtWidget(form)
self.populate_form()
return
def Show(self):
idaapi.PluginForm.Show(self, self.__name)
return
def populate_form(self):
# Create layout
layout = QtGui.QVBoxLayout()
layout.addWidget(QtGui.QLabel(self.__name))
self.table = QtGui.QTableWidget()
layout.addWidget(self.table)
self.table.setColumnCount(3)
self.table.setHorizontalHeaderItem(0, QtGui.QTableWidgetItem("Address"))
self.table.setHorizontalHeaderItem(1, QtGui.QTableWidgetItem("Function"))
self.table.setHorizontalHeaderItem(2, QtGui.QTableWidgetItem("Line"))
self.table.setColumnWidth(0, 80)
self.table.setColumnWidth(1, 150)
self.table.setColumnWidth(2, 450)
self.table.cellDoubleClicked.connect(self.double_clicked)
#~ self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows )
self.parent.setLayout(layout)
self.populate_table()
return
def double_clicked(self, row, column):
ea = self.functions[row]
idaapi.open_pseudocode(ea, True)
return
def get_decompiled_line(self, cfunc, ea):
print repr(ea)
if ea not in cfunc.eamap:
print 'strange, %x is not in %x eamap' % (ea, cfunc.entry_ea)
return
insnvec = cfunc.eamap[ea]
lines = []
for stmt in insnvec:
qp = idaapi.qstring_printer_t(cfunc.__deref__(), False)
stmt._print(0, qp)
s = qp.s.split('\n')[0]
#~ s = idaapi.tag_remove(s)
lines.append(s)
return '\n'.join(lines)
def get_items_for_ea(self, ea):
frm = [x.frm for x in idautils.XrefsTo(self.__ea)]
items = []
for ea in frm:
try:
cfunc = idaapi.decompile(ea)
self.functions.append(cfunc.entry_ea)
self.items.append((ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea)))
except Exception as e:
print 'could not decompile: %s' % (str(e), )
raise
return
def get_items_for_type(self):
x = self.target.operands['x']
m = self.target.operands['m']
xtype = x.type
xtype.remove_ptr_or_array()
typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '')
addresses = []
for ea in idautils.Functions():
try:
cfunc = idaapi.decompile(ea)
except:
print 'Decompilation of %x failed' % (ea, )
continue
str(cfunc)
for citem in cfunc.treeitems:
citem = citem.to_specific_type
if not (type(citem) == idaapi.cexpr_t and citem.opname in ('memptr', 'memref')):
continue
_x = citem.operands['x']
_m = citem.operands['m']
_xtype = _x.type
_xtype.remove_ptr_or_array()
_typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, _xtype, '', '')
#~ print 'in', hex(cfunc.entry_ea), _typename, _m
if not (_typename == typename and _m == m):
continue
parent = citem
while parent:
if type(parent.to_specific_type) == idaapi.cinsn_t:
break
parent = cfunc.body.find_parent_of(parent)
if not parent:
print 'cannot find parent statement (?!)'
continue
if parent.ea in addresses:
continue
if parent.ea == idaapi.BADADDR:
print 'parent.ea is BADADDR'
continue
addresses.append(parent.ea)
self.functions.append(cfunc.entry_ea)
self.items.append((parent.ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, int(parent.ea))))
return []
def populate_table(self):
self.functions = []
self.items = []
if self.__type == XREF_EA:
self.get_items_for_ea(self.__ea)
else:
self.get_items_for_type()
self.table.setRowCount(len(self.items))
i = 0
for item in self.items:
address, func, line = item
item = QtGui.QTableWidgetItem('0x%x' % (address, ))
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
self.table.setItem(i, 0, item)
item = QtGui.QTableWidgetItem(func)
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
self.table.setItem(i, 1, item)
item = QtGui.QTableWidgetItem(line)
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
self.table.setItem(i, 2, item)
i += 1
self.table.resizeRowsToContents()
return
def OnClose(self, form):
pass
class hexrays_callback_info(object):
def __init__(self):
self.vu = None
return
def show_xrefs(self, vu):
vu.get_current_item(idaapi.USE_KEYBOARD)
item = vu.item
sel = None
if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'):
# if an expression is selected. verify that it's either a cot_obj, cot_memref or cot_memptr
sel = item.it.to_specific_type
elif item.citype == idaapi.VDI_FUNC:
# if the function itself is selected, show xrefs to it.
sel = item.f
else:
return False
form = XrefsForm(sel)
form.Show()
return True
def menu_callback(self):
self.show_xrefs(self.vu)
return 0
def event_callback(self, event, *args):
try:
if event == idaapi.hxe_keyboard:
vu, keycode, shift = args
if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("X") and shift == 0:
if self.show_xrefs(vu):
return 1
elif event == idaapi.hxe_right_click:
self.vu = args[0]
idaapi.add_custom_viewer_popup_item(self.vu.ct, "Xrefs", "X", self.menu_callback)
except:
traceback.print_exc()
return 0
if idaapi.init_hexrays_plugin():
i = hexrays_callback_info()
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'invert-if: hexrays is not available.'

View File

@ -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>

View File

@ -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;
}
//-------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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)>

View File

@ -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)>

View File

@ -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:

View File

@ -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;
@ -1382,152 +1392,161 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
try {
switch (notification_code)
{
case idb_event::byte_patched:
ea = va_arg(va, ea_t);
return proxy->byte_patched(ea);
case idb_event::byte_patched:
ea = va_arg(va, ea_t);
return proxy->byte_patched(ea);
case idb_event::cmt_changed:
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int);
return proxy->cmt_changed(ea, repeatable_cmt);
#if 0
case idb_event::ti_changed:
ea = va_arg(va, ea_t);
type = va_arg(va, type_t *);
fnames = va_arg(va, fnames);
return proxy->ti_changed(ea, type, fnames);
case idb_event::cmt_changed:
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int);
return proxy->cmt_changed(ea, repeatable_cmt);
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);
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);
return proxy->op_type_changed(ea, n);
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::enum_created:
id = va_arg(va, enum_t);
return proxy->enum_created(id);
case idb_event::ti_changed:
ea = va_arg(va, ea_t);
type = va_arg(va, type_t *);
fnames = va_arg(va, p_list *);
return proxy->ti_changed(ea, type, fnames);
case idb_event::enum_deleted:
id = va_arg(va, enum_t);
return proxy->enum_deleted(id);
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, p_list *);
return proxy->op_ti_changed(ea, n, type, fnames);
case idb_event::enum_bf_changed:
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id);
case idb_event::op_type_changed:
ea = va_arg(va, ea_t);
n = va_arg(va, int);
return proxy->op_type_changed(ea, n);
case idb_event::enum_cmt_changed:
id = va_arg(va, enum_t);
return proxy->enum_cmt_changed(id);
case idb_event::enum_created:
id = va_arg(va, enum_t);
return proxy->enum_created(id);
case idb_event::enum_deleted:
id = va_arg(va, enum_t);
return proxy->enum_deleted(id);
case idb_event::enum_bf_changed:
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id);
case idb_event::enum_cmt_changed:
id = va_arg(va, enum_t);
return proxy->enum_cmt_changed(id);
#ifdef NO_OBSOLETE_FUNCS
case idb_event::enum_member_created:
case idb_event::enum_member_created:
#else
case idb_event::enum_const_created:
case idb_event::enum_const_created:
#endif
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_created(id, cid);
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_created(id, cid);
#ifdef NO_OBSOLETE_FUNCS
case idb_event::enum_member_deleted:
case idb_event::enum_member_deleted:
#else
case idb_event::enum_const_deleted:
case idb_event::enum_const_deleted:
#endif
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_deleted(id, cid);
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_deleted(id, cid);
case idb_event::struc_created:
struc_id = va_arg(va, tid_t);
return proxy->struc_created(struc_id);
case idb_event::struc_created:
struc_id = va_arg(va, tid_t);
return proxy->struc_created(struc_id);
case idb_event::struc_deleted:
struc_id = va_arg(va, tid_t);
return proxy->struc_deleted(struc_id);
case idb_event::struc_deleted:
struc_id = va_arg(va, tid_t);
return proxy->struc_deleted(struc_id);
case idb_event::struc_renamed:
sptr = va_arg(va, struc_t *);
return proxy->struc_renamed(sptr);
case idb_event::struc_renamed:
sptr = va_arg(va, struc_t *);
return proxy->struc_renamed(sptr);
case idb_event::struc_expanded:
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr);
case idb_event::struc_expanded:
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr);
case idb_event::struc_cmt_changed:
struc_id = va_arg(va, tid_t);
return proxy->struc_cmt_changed(struc_id);
case idb_event::struc_cmt_changed:
struc_id = va_arg(va, tid_t);
return proxy->struc_cmt_changed(struc_id);
case idb_event::struc_member_created:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_created(sptr, mptr);
case idb_event::struc_member_created:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_created(sptr, mptr);
case idb_event::struc_member_deleted:
sptr = va_arg(va, struc_t *);
member_id = va_arg(va, tid_t);
ea = va_arg(va, ea_t);
return proxy->struc_member_deleted(sptr, member_id, ea);
case idb_event::struc_member_deleted:
sptr = va_arg(va, struc_t *);
member_id = va_arg(va, tid_t);
ea = va_arg(va, ea_t);
return proxy->struc_member_deleted(sptr, member_id, ea);
case idb_event::struc_member_renamed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_renamed(sptr, mptr);
case idb_event::struc_member_renamed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_renamed(sptr, mptr);
case idb_event::struc_member_changed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr);
case idb_event::struc_member_changed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr);
case idb_event::thunk_func_created:
pfn = va_arg(va, func_t *);
return proxy->thunk_func_created(pfn);
case idb_event::thunk_func_created:
pfn = va_arg(va, func_t *);
return proxy->thunk_func_created(pfn);
case idb_event::func_tail_appended:
pfn = va_arg(va, func_t *);
tail = va_arg(va, func_t *);
return proxy->func_tail_appended(pfn, tail);
case idb_event::func_tail_appended:
pfn = va_arg(va, func_t *);
tail = va_arg(va, func_t *);
return proxy->func_tail_appended(pfn, tail);
case idb_event::func_tail_removed:
pfn = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->func_tail_removed(pfn, ea);
case idb_event::func_tail_removed:
pfn = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->func_tail_removed(pfn, ea);
case idb_event::tail_owner_changed:
tail = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea);
case idb_event::tail_owner_changed:
tail = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea);
case idb_event::func_noret_changed:
pfn = va_arg(va, func_t *);
return proxy->func_noret_changed(pfn);
case idb_event::func_noret_changed:
pfn = va_arg(va, func_t *);
return proxy->func_noret_changed(pfn);
case idb_event::segm_added:
seg = va_arg(va, segment_t *);
return proxy->segm_added(seg);
case idb_event::segm_added:
seg = va_arg(va, segment_t *);
return proxy->segm_added(seg);
case idb_event::segm_deleted:
ea = va_arg(va, ea_t);
return proxy->segm_deleted(ea);
case idb_event::segm_deleted:
ea = va_arg(va, ea_t);
return proxy->segm_deleted(ea);
case idb_event::segm_start_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg);
case idb_event::segm_start_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg);
case idb_event::segm_end_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg);
case idb_event::segm_end_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg);
case idb_event::segm_moved:
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t);
size = va_arg(va, asize_t);
return proxy->segm_moved(ea, ea2, size);
case idb_event::segm_moved:
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t);
size = va_arg(va, asize_t);
return proxy->segm_moved(ea, ea2, size);
}
}
catch (Swig::DirectorException &e)

View File

@ -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>

View File

@ -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;
}
//-------------------------------------------------------------------------
/*

View File

@ -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

View File

@ -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)

View File

@ -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
&& !find_by_form(NULL, NULL, form)
&& !find_by_view(NULL, NULL, view)
&& !find_by_py_view(NULL, NULL, py_view));
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, 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);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_CLICK,
"iii",
event->x, event->y, event->state));
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();
}

View File

@ -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;

View File

@ -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 %{

View File

@ -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;

View File

@ -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;

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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;
@ -1425,152 +1452,161 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
try {
switch (notification_code)
{
case idb_event::byte_patched:
ea = va_arg(va, ea_t);
return proxy->byte_patched(ea);
case idb_event::byte_patched:
ea = va_arg(va, ea_t);
return proxy->byte_patched(ea);
case idb_event::cmt_changed:
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int);
return proxy->cmt_changed(ea, repeatable_cmt);
#if 0
case idb_event::ti_changed:
ea = va_arg(va, ea_t);
type = va_arg(va, type_t *);
fnames = va_arg(va, fnames);
return proxy->ti_changed(ea, type, fnames);
case idb_event::cmt_changed:
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int);
return proxy->cmt_changed(ea, repeatable_cmt);
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);
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);
return proxy->op_type_changed(ea, n);
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::enum_created:
id = va_arg(va, enum_t);
return proxy->enum_created(id);
case idb_event::ti_changed:
ea = va_arg(va, ea_t);
type = va_arg(va, type_t *);
fnames = va_arg(va, p_list *);
return proxy->ti_changed(ea, type, fnames);
case idb_event::enum_deleted:
id = va_arg(va, enum_t);
return proxy->enum_deleted(id);
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, p_list *);
return proxy->op_ti_changed(ea, n, type, fnames);
case idb_event::enum_bf_changed:
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id);
case idb_event::op_type_changed:
ea = va_arg(va, ea_t);
n = va_arg(va, int);
return proxy->op_type_changed(ea, n);
case idb_event::enum_cmt_changed:
id = va_arg(va, enum_t);
return proxy->enum_cmt_changed(id);
case idb_event::enum_created:
id = va_arg(va, enum_t);
return proxy->enum_created(id);
case idb_event::enum_deleted:
id = va_arg(va, enum_t);
return proxy->enum_deleted(id);
case idb_event::enum_bf_changed:
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id);
case idb_event::enum_cmt_changed:
id = va_arg(va, enum_t);
return proxy->enum_cmt_changed(id);
#ifdef NO_OBSOLETE_FUNCS
case idb_event::enum_member_created:
case idb_event::enum_member_created:
#else
case idb_event::enum_const_created:
case idb_event::enum_const_created:
#endif
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_created(id, cid);
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_created(id, cid);
#ifdef NO_OBSOLETE_FUNCS
case idb_event::enum_member_deleted:
case idb_event::enum_member_deleted:
#else
case idb_event::enum_const_deleted:
case idb_event::enum_const_deleted:
#endif
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_deleted(id, cid);
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_deleted(id, cid);
case idb_event::struc_created:
struc_id = va_arg(va, tid_t);
return proxy->struc_created(struc_id);
case idb_event::struc_created:
struc_id = va_arg(va, tid_t);
return proxy->struc_created(struc_id);
case idb_event::struc_deleted:
struc_id = va_arg(va, tid_t);
return proxy->struc_deleted(struc_id);
case idb_event::struc_deleted:
struc_id = va_arg(va, tid_t);
return proxy->struc_deleted(struc_id);
case idb_event::struc_renamed:
sptr = va_arg(va, struc_t *);
return proxy->struc_renamed(sptr);
case idb_event::struc_renamed:
sptr = va_arg(va, struc_t *);
return proxy->struc_renamed(sptr);
case idb_event::struc_expanded:
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr);
case idb_event::struc_expanded:
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr);
case idb_event::struc_cmt_changed:
struc_id = va_arg(va, tid_t);
return proxy->struc_cmt_changed(struc_id);
case idb_event::struc_cmt_changed:
struc_id = va_arg(va, tid_t);
return proxy->struc_cmt_changed(struc_id);
case idb_event::struc_member_created:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_created(sptr, mptr);
case idb_event::struc_member_created:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_created(sptr, mptr);
case idb_event::struc_member_deleted:
sptr = va_arg(va, struc_t *);
member_id = va_arg(va, tid_t);
ea = va_arg(va, ea_t);
return proxy->struc_member_deleted(sptr, member_id, ea);
case idb_event::struc_member_deleted:
sptr = va_arg(va, struc_t *);
member_id = va_arg(va, tid_t);
ea = va_arg(va, ea_t);
return proxy->struc_member_deleted(sptr, member_id, ea);
case idb_event::struc_member_renamed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_renamed(sptr, mptr);
case idb_event::struc_member_renamed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_renamed(sptr, mptr);
case idb_event::struc_member_changed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr);
case idb_event::struc_member_changed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr);
case idb_event::thunk_func_created:
pfn = va_arg(va, func_t *);
return proxy->thunk_func_created(pfn);
case idb_event::thunk_func_created:
pfn = va_arg(va, func_t *);
return proxy->thunk_func_created(pfn);
case idb_event::func_tail_appended:
pfn = va_arg(va, func_t *);
tail = va_arg(va, func_t *);
return proxy->func_tail_appended(pfn, tail);
case idb_event::func_tail_appended:
pfn = va_arg(va, func_t *);
tail = va_arg(va, func_t *);
return proxy->func_tail_appended(pfn, tail);
case idb_event::func_tail_removed:
pfn = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->func_tail_removed(pfn, ea);
case idb_event::func_tail_removed:
pfn = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->func_tail_removed(pfn, ea);
case idb_event::tail_owner_changed:
tail = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea);
case idb_event::tail_owner_changed:
tail = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea);
case idb_event::func_noret_changed:
pfn = va_arg(va, func_t *);
return proxy->func_noret_changed(pfn);
case idb_event::func_noret_changed:
pfn = va_arg(va, func_t *);
return proxy->func_noret_changed(pfn);
case idb_event::segm_added:
seg = va_arg(va, segment_t *);
return proxy->segm_added(seg);
case idb_event::segm_added:
seg = va_arg(va, segment_t *);
return proxy->segm_added(seg);
case idb_event::segm_deleted:
ea = va_arg(va, ea_t);
return proxy->segm_deleted(ea);
case idb_event::segm_deleted:
ea = va_arg(va, ea_t);
return proxy->segm_deleted(ea);
case idb_event::segm_start_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg);
case idb_event::segm_start_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg);
case idb_event::segm_end_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg);
case idb_event::segm_end_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg);
case idb_event::segm_moved:
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t);
size = va_arg(va, asize_t);
return proxy->segm_moved(ea, ea2, size);
case idb_event::segm_moved:
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t);
size = va_arg(va, asize_t);
return proxy->segm_moved(ea, ea2, size);
}
}
catch (Swig::DirectorException &e)

View File

@ -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)>
%}

View File

@ -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;

View File

@ -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;
}
//-------------------------------------------------------------------------
/*

View File

@ -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);
}
}

View File

@ -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)
%}

View File

@ -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 %{

View File

@ -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

View File

@ -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)
{

View File

@ -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)

View File

@ -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
&& !find_by_form(NULL, NULL, form)
&& !find_by_view(NULL, NULL, view)
&& !find_by_py_view(NULL, NULL, py_view));
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, 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);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_CLICK,
"iii",
event->x, event->y, event->state));
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:

View File

@ -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;