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