IDA Pro 6.5 support

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

Various bugfixes:
- fixed various memory leaks
- asklong/askaddr/asksel (and corresponding idc.py functions) were returning results truncated to 32 bits in IDA64
- fix wrong documentation for idc.SizeOf
- GetFloat/GetDouble functions did not take into account endianness of the processor
- idaapi.NO_PROCESS was not defined, and was causing GetProcessPid() to fail
- idc.py: insert escape characters to string parameter when call Eval()
- idc.SaveFile/savefile were always overwriting an existing file instead of writing only the new data
- PluginForm.Close() wasn't passing its arguments to the delegate function, resulting in an error.
This commit is contained in:
elias.bachaalany@gmail.com 2013-12-30 01:34:23 +00:00
parent c88a77e809
commit 78c79f85b9
77 changed files with 8952 additions and 5320 deletions

View File

@ -8,8 +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 Elias Bachaalany.
It is primarily maintained by Arnaud Diederen.
* Elias Bachaalany - http://0xeb.wordpress.com/
Current project owner and maintainer
* Ero Carrera - http://dkbza.org/

91
Scripts/callstack_test.py Normal file
View File

@ -0,0 +1,91 @@
import sys
import os
def __sys(cmd, fmt=None, echo=True):
"""Executes a string of OS commands and returns the a list of tuples (return code,command executed)"""
if not fmt:
fmt = {}
r = []
for cmd in [x for x in (cmd % fmt).split("\n") if len(x)]:
if echo:
print ">>>", cmd
r.append((os.system(cmd), cmd))
return r
body = r"""/// Autogenerated file
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <windows.h>
void want_break(int n)
{
printf("do you want to DebugBreak in func%d()?", n);
char ch = _toupper(_getch());
printf("\n");
if (ch == 'Y')
DebugBreak();
else if (ch == 'X')
ExitProcess(n);
}
%FUNCS%
int main(int /*argc*/, char * /*argv[]*/)
{
func1();
return 0;
}
"""
funcs_body = []
func_body = r"""
void func%(n)d()
{
printf("%(ident)senter %(n)d\n");%(pause)s
func%(n1)d();
printf("%(ident)sleave %(n)d\n");
}
"""
if len(sys.argv) < 2:
print "usage: gen nb_calls pause_frequency"
sys.exit(0)
n = int(sys.argv[1])
if n < 1:
print "at least one call should be passed!"
sys.exit(1)
m = int(sys.argv[2])
func_params = {'n': 0, 'n1': 0, 'ident': '', 'pause' : ''}
for i in xrange(1, n + 1):
func_params['n'] = i
func_params['n1'] = i+1
func_params['ident'] = " " * i
func_params['pause'] = ("\n want_break(%d);" % i) if (i % m) == 0 else ''
funcs_body.append(func_body % func_params)
funcs_body.append(r"""
void func%(n)d()
{
printf("that's it #%(n)d!\n");
}
""" % {'n':i+1})
funcs_body.reverse()
# write the file
body = body.replace('%FUNCS%', ''.join(funcs_body))
f = file('src.cpp', 'w')
f.write(body)
f.close()
__sys("""
if exist src.exe del src.exe
bcc32 src
if exist src.exe move src.exe src_bcc.exe
if exist src.obj del src.obj
cl32 src.cpp /Zi /Od
""")

View File

@ -24,7 +24,7 @@ from distutils import sysconfig
VERBOSE = True
IDA_MAJOR_VERSION = 6
IDA_MINOR_VERSION = 4
IDA_MINOR_VERSION = 5
if 'IDA' in os.environ:
IDA_SDK = os.environ['IDA']
@ -35,8 +35,8 @@ else:
# IDAPython version
VERSION_MAJOR = 1
VERSION_MINOR = 5
VERSION_PATCH = 6
VERSION_MINOR = 6
VERSION_PATCH = 0
# Determine Python version
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@ -50,7 +50,7 @@ S_WITH_HEXRAYS = 'with-hexrays'
S_NO_OPT = 'no-opt'
# Swig command-line parameters
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__ -DNO_OBSOLETE_FUNCS'
SWIG_OPTIONS = '-modern -python -threads -c++ -w451 -shadow -D__GNUC__'
# Common macros for all compilations
COMMON_MACROS = [
@ -169,8 +169,8 @@ def parse_options(args):
with_hexrays = '--' + S_WITH_HEXRAYS in sys.argv
return {
S_EA64: ea64,
S_WITH_HEXRAYS: with_hexrays,
S_EA64: ea64,
S_WITH_HEXRAYS: with_hexrays,
S_NO_OPT: no_opt
}
@ -335,9 +335,9 @@ def build_distribution(manifest, distrootdir, ea64, nukeold):
# -----------------------------------------------------------------------
def build_plugin(
platform,
idasdkdir,
plugin_name,
platform,
idasdkdir,
plugin_name,
options):
# Get the arguments
@ -401,7 +401,7 @@ def build_plugin(
platform_macros.append("PLUGINFIX")
# Turn off obsolete functions
platform_macros.append("NO_OBSOLETE_FUNCS")
#platform_macros.append("NO_OBSOLETE_FUNCS")
# Build the wrapper from the interface files
ea64flag = ea64 and "-D__EA64__" or ""
@ -467,17 +467,17 @@ def build_binary_package(options, nukeold):
platform_string)
# Build the plugin
build_plugin(platform_string, IDA_SDK, plugin_name, options)
# Build the binary distribution
binmanifest = []
if nukeold:
binmanifest.extend(BINDIST_MANIFEST)
if not ea64 or nukeold:
binmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py", "idaapi.py"])
binmanifest.append((plugin_name, "plugins"))
build_distribution(binmanifest, BINDISTDIR, ea64, nukeold)

View File

@ -15,11 +15,11 @@ def raw_main(p=True):
for ns in xrange(0, q.nsucc(n)):
if p:
print " %d->%d" % (n, q.succ(n, ns))
print "SUCC: %d->%d" % (n, q.succ(n, ns))
for ns in xrange(0, q.npred(n)):
if p:
print " %d->%d" % (n, q.pred(n, ns))
print "PRED: %d->%d" % (n, q.pred(n, ns))
# -----------------------------------------------------------------------
# Using the class

114
examples/ex_idagraph.py Normal file
View File

@ -0,0 +1,114 @@
# -----------------------------------------------------------------------
# This is an example illustrating how to manipulate an existing IDA-provided
# view (and thus its graph), in Python.
# (c) Hex-Rays
#
from idaapi import IDAViewWrapper
from time import sleep
import threading
class Worker(threading.Thread):
def __init__(self, w):
threading.Thread.__init__(self)
self.w = w
def req_SetCurrentRendererType(self, switch_to):
w = self.w
def f():
print "Switching.."
w.SetCurrentRendererType(switch_to)
idaapi.execute_sync(f, idaapi.MFF_FAST)
def req_SetNodeInfo(self, node, info, flags):
w = self.w
def f():
print "Setting node info.."
w.SetNodeInfo(node, info, flags)
idaapi.execute_sync(f, idaapi.MFF_FAST)
def req_DelNodesInfos(self, *nodes):
w = self.w
def f():
print "Deleting nodes infos.."
w.DelNodesInfos(*nodes)
idaapi.execute_sync(f, idaapi.MFF_FAST)
def run(self):
# Note, in order to leave the UI available
# to the user, we'll perform UI operations
# in this thread.
#
# But.
#
# Qt expects that all UI operations be performed from
# the main thread. Therefore, we'll have to use
# 'idaapi.execute_sync' to send requests to the main thread.
# Switch back & forth to & from graph view
for i in xrange(3):
self.req_SetCurrentRendererType(idaapi.TCCRT_FLAT)
sleep(1)
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
sleep(1)
# Go to graph view, and set the first node's color
self.req_SetCurrentRendererType(idaapi.TCCRT_GRAPH)
ni = idaapi.node_info_t()
ni.bg_color = 0x00ff00ff
ni.frame_color = 0x0000ff00
self.req_SetNodeInfo(0, ni, idaapi.NIF_BG_COLOR|idaapi.NIF_FRAME_COLOR)
sleep(3)
# This was fun. But let's revert it.
self.req_DelNodesInfos(0)
sleep(3)
print "Done."
class MyIDAViewWrapper(IDAViewWrapper):
# A wrapper around the standard IDA view wrapper.
# We'll react to some events and print the parameters
# that were sent to us, that's all.
def __init__(self, viewName):
IDAViewWrapper.__init__(self, viewName)
# Helper function, to be called by "On*" event handlers.
# This will print all the arguments that were passed!
def printPrevFrame(self):
import inspect
stack = inspect.stack()
frame, _, _, _, _, _ = stack[1]
args, _, _, values = inspect.getargvalues(frame)
print "EVENT: %s: args=%s" % (
inspect.getframeinfo(frame)[2],
[(i, values[i]) for i in args[1:]])
def OnViewKeydown(self, key, state):
self.printPrevFrame()
def OnViewClick(self, x, y, state):
self.printPrevFrame()
def OnViewDblclick(self, x, y, state):
self.printPrevFrame()
def OnViewSwitched(self, rt):
self.printPrevFrame()
def OnViewMouseOver(self, x, y, state, over_type, over_data):
self.printPrevFrame()
viewName = "IDA View-A"
w = MyIDAViewWrapper(viewName)
if w.Bind():
print "Succesfully bound to %s" % viewName
# We'll launch the sequence of operations in another thread,
# so that sleep() calls don't freeze the UI
worker = Worker(w)
worker.start()
else:
print "Couldn't bind to view %s. Is it available?" % viewName

View File

@ -1,27 +1,27 @@
import idaapi
def main():
if not idaapi.init_hexrays_plugin():
return False
if not idaapi.init_hexrays_plugin():
return False
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
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
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();
idaapi.term_hexrays_plugin();

View File

@ -5,9 +5,9 @@ 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
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
"""
@ -21,23 +21,23 @@ 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:
@ -47,39 +47,39 @@ class hexrays_callback_info(object):
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)
@ -87,15 +87,15 @@ class hexrays_callback_info(object):
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
@ -103,48 +103,48 @@ class hexrays_callback_info(object):
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:
@ -152,40 +152,40 @@ class hexrays_callback_info(object):
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():
@ -193,3 +193,4 @@ if idaapi.init_hexrays_plugin():
idaapi.install_hexrays_callback(i.event_callback)
else:
print 'invert-if: hexrays is not available.'

View File

@ -3,7 +3,7 @@
ALERT_AUTO_SCRIPTS = 1
// Remove current directory from import search path
REMOVE_CWD_SYS_PATH = 0
REMOVE_CWD_SYS_PATH = 1
// Script timeout (in seconds)
// (A value of 0 disables the timeout)

File diff suppressed because it is too large Load Diff

View File

@ -260,6 +260,9 @@ NEF_FLAT = idaapi.NEF_FLAT # Autocreated FLAT group (PE)
def IsString(var): raise NotImplementedError, "this function is not needed in Python"
def IsLong(var): raise NotImplementedError, "this function is not needed in Python"
def IsFloat(var): raise NotImplementedError, "this function is not needed in Python"
def IsFunc(var): raise NotImplementedError, "this function is not needed in Python"
def IsPvoid(var): raise NotImplementedError, "this function is not needed in Python"
def IsInt64(var): raise NotImplementedError, "this function is not needed in Python"
def MK_FP(seg, off):
"""
@ -1159,7 +1162,11 @@ REFINFO_NOBASE = 0x80 # offset base is a number
# that base have be any value
# nb: base xrefs are created only if base
# points to the middle of a segment
REFINFO_SUBTRACT = 0x0100 # the reference value is subtracted from
# the base value instead of (as usual)
# being added to it
REFINFO_SIGNEDOP = 0x0200 # the operand value is sign-extended (only
# supported for REF_OFF8/16/32/64)
def OpSeg(ea, n):
"""
@ -1865,24 +1872,28 @@ def Qword(ea):
def GetFloat(ea):
"""
Get value of a floating point number (4 bytes)
This function assumes number stored using IEEE format
and in the same endianness as integers.
@param ea: linear address
@return: float
"""
tmp = idaapi.get_many_bytes(ea, 4)
tmp = struct.pack("I", Dword(ea))
return struct.unpack("f", tmp)[0]
def GetDouble(ea):
"""
Get value of a floating point number (8 bytes)
This function assumes number stored using IEEE format
and in the same endianness as integers.
@param ea: linear address
@return: double
"""
tmp = idaapi.get_many_bytes(ea, 8)
tmp = struct.pack("Q", Qword(ea))
return struct.unpack("d", tmp)[0]
@ -2165,23 +2176,46 @@ def Demangle(name, disable_mask):
return idaapi.demangle_name(name, disable_mask)
def GetDisasmEx(ea, flags):
"""
Get disassembly line
@param ea: linear address of instruction
@param flags: combination of the GENDSM_ flags, or 0
@return: "" - could not decode instruction at the specified location
@note: this function may not return exactly the same mnemonics
as you see on the screen.
"""
text = idaapi.generate_disasm_line(ea, flags)
if text:
return idaapi.tag_remove(text)
else:
return ""
# flags for GetDisasmEx
# generate a disassembly line as if
# there is an instruction at 'ea'
GENDSM_FORCE_CODE = idaapi.GENDSM_FORCE_CODE
# if the instruction consists of several lines,
# produce all of them (useful for parallel instructions)
GENDSM_MULTI_LINE = idaapi.GENDSM_MULTI_LINE
def GetDisasm(ea):
"""
Get disassembly line
@param ea: linear address of instruction
@return: "" - no instruction at the specified location
@return: "" - could not decode instruction at the specified location
@note: this function may not return exactly the same mnemonics
as you see on the screen.
"""
text = idaapi.generate_disasm_line(ea)
if text:
return idaapi.tag_remove(text)
else:
return ""
return GetDisasmEx(ea, 0)
def GetMnem(ea):
"""
@ -2475,9 +2509,9 @@ def ChangeConfig(directive):
@param directive: directives to process, for example: PACK_DATABASE=2
@note: If the directives are erroneous, a fatal error will be generated.
The changes will be effective only for the current session.
The settings are permanent: effective for the current session and the next ones
"""
return Eval('ChangeConfig("%s")' % directive)
return Eval('ChangeConfig("%s")' % idaapi.str2user(directive))
# The following functions allow you to set/get common parameters.
@ -3279,7 +3313,7 @@ def SegName(ea):
return name
def AddSeg(startea, endea, base, use32, align, comb):
def AddSegEx(startea, endea, base, use32, align, comb, flags):
"""
Create a new segment
@ -3294,6 +3328,7 @@ def AddSeg(startea, endea, base, use32, align, comb):
@param use32: 0: 16bit segment, 1: 32bit segment, 2: 64bit segment
@param align: segment alignment. see below for alignment values
@param comb: segment combination. see below for combination values.
@param flags: combination of ADDSEG_... bits
@return: 0-failed, 1-ok
"""
@ -3304,8 +3339,27 @@ def AddSeg(startea, endea, base, use32, align, comb):
s.bitness = use32
s.align = align
s.comb = comb
return idaapi.add_segm_ex(s, "", "", idaapi.ADDSEG_NOSREG)
return idaapi.add_segm_ex(s, "", "", flags)
ADDSEG_NOSREG = idaapi.ADDSEG_NOSREG # set all default segment register values
# to BADSELs
# (undefine all default segment registers)
ADDSEG_OR_DIE = idaapi. ADDSEG_OR_DIE # qexit() if can't add a segment
ADDSEG_NOTRUNC = idaapi.ADDSEG_NOTRUNC # don't truncate the new segment at the beginning
# of the next segment if they overlap.
# destroy/truncate old segments instead.
ADDSEG_QUIET = idaapi.ADDSEG_QUIET # silent mode, no "Adding segment..." in the messages window
ADDSEG_FILLGAP = idaapi.ADDSEG_FILLGAP # If there is a gap between the new segment
# and the previous one, and this gap is less
# than 64K, then fill the gap by extending the
# previous segment and adding .align directive
# to it. This way we avoid gaps between segments.
# Too many gaps lead to a virtual array failure.
# It can not hold more than ~1000 gaps.
ADDSEG_SPARSE = idaapi.ADDSEG_SPARSE # Use sparse storage method for the new segment
def AddSeg(startea, endea, base, use32, align, comb):
return AddSegEx(startea, endea, base, use32, align, comb, ADDSEG_NOSREG)
def DelSeg(ea, flags):
"""
@ -3889,7 +3943,7 @@ def SaveFile(filepath, pos, ea, size):
@return: 0 - error, 1 - ok
"""
of = idaapi.fopenWB(filepath)
of = idaapi.fopenM(filepath)
if of:
retval = idaapi.base2file(of, pos, ea, ea+size)
@ -5369,10 +5423,10 @@ def AddStrucMember(sid, name, offset, flag, typeid, nbytes, target=-1, tdelta=0,
"""
if isOff0(flag):
return Eval('AddStrucMember(%d, "%s", %d, %d, %d, %d, %d, %d, %d);' % (sid, name, offset, flag, typeid, nbytes,
return Eval('AddStrucMember(%d, "%s", %d, %d, %d, %d, %d, %d, %d);' % (sid, idaapi.str2user(name), offset, flag, typeid, nbytes,
target, tdelta, reftype))
else:
return Eval('AddStrucMember(%d, "%s", %d, %d, %d, %d);' % (sid, name, offset, flag, typeid, nbytes))
return Eval('AddStrucMember(%d, "%s", %d, %d, %d, %d);' % (sid, idaapi.str2user(name), offset, flag, typeid, nbytes))
STRUC_ERROR_MEMBER_NAME = -1 # already has member with this name (bad name)
@ -6799,10 +6853,10 @@ def GetType(ea):
def SizeOf(typestr):
"""
Returns the size of the type. It is equivalent to IDC's sizeof().
Use name, tp, fld = idc.ParseType() ; Sizeof(fld) to retrieve the size
Use name, tp, fld = idc.ParseType() ; SizeOf(tp) to retrieve the size
@return: -1 if typestring is not valid otherwise the size of the type
"""
return idaapi.get_type_size0(idaapi.cvar.idati, typestr)
return idaapi.calc_type_size(idaapi.cvar.idati, typestr)
def GetTinfo(ea):
"""
@ -6813,6 +6867,15 @@ def GetTinfo(ea):
"""
return idaapi.idc_get_type_raw(ea)
def GetLocalTinfo(ordinal):
"""
Get local type information as 'typeinfo' object
@param ordinal: slot number (1...NumberOfLocalTypes)
@return: None on failure, or (type, fields, name) tuple.
"""
return idaapi.idc_get_local_type_raw(ordinal)
def GuessType(ea):
"""
Guess type of function/variable
@ -6823,6 +6886,37 @@ def GuessType(ea):
"""
return idaapi.idc_guess_type(ea)
TINFO_GUESSED = 0x0000 # this is a guessed type
TINFO_DEFINITE = 0x0001 # this is a definite type
TINFO_DELAYFUNC = 0x0002 # if type is a function and no function exists at ea,
# schedule its creation and argument renaming to
# auto-analysis otherwise try to create it immediately
def ApplyType(ea, py_type, flags = TINFO_DEFINITE):
"""
Apply the specified type to the address
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param py_type: typeinfo tuple (type, fields) as GetTinfo() returns
or tuple (name, type, fields) as ParseType() returns
or None
if specified as None, then the
item associated with 'ea' will be deleted.
@param ea: the address of the object
@param flags: combination of TINFO_... constants or 0
@return: Boolean
"""
if py_type != None:
if len(py_type) == 3:
pt = py_type[1:] # skip name component
else:
pt = py_type
return idaapi.apply_type(idaapi.cvar.idati, pt[0], pt[1], ea, flags)
if idaapi.has_ti(ea):
idaapi.del_tinfo(ea)
return True
return False
def SetType(ea, newtype):
"""
@ -6837,11 +6931,10 @@ def SetType(ea, newtype):
@return: 1-ok, 0-failed.
"""
if newtype is not '':
return idaapi.apply_cdecl2(idaapi.cvar.idati, ea, newtype)
if idaapi.has_ti(ea):
idaapi.del_tinfo(ea)
return True
return False
pt = ParseType(newtype, 0)[1:]
else:
pt = None
return ApplyType(ea, pt, TINFO_DEFINITE)
def ParseType(inputtype, flags):
"""
@ -6852,6 +6945,8 @@ def ParseType(inputtype, flags):
@return: None on failure or (name, type, fields) tuple
"""
if len(inputtype) != 0 and inputtype[-1] != ';':
inputtype = inputtype + ';'
return idaapi.idc_parse_decl(idaapi.cvar.idati, inputtype, flags)
def ParseTypes(inputtype, flags = 0):
@ -6874,6 +6969,9 @@ PT_PAK2 = 0x0020 # #pragma pack(2)
PT_PAK4 = 0x0030 # #pragma pack(4)
PT_PAK8 = 0x0040 # #pragma pack(8)
PT_PAK16 = 0x0050 # #pragma pack(16)
PT_HIGH = 0x0080 # assume high level prototypes
# (with hidden args, etc)
PT_LOWER = 0x0100 # lower the function prototypes
def GetMaxLocalType():
@ -6903,17 +7001,14 @@ def SetLocalType(ordinal, input, flags):
def GetLocalType(ordinal, flags):
"""
Retrieve a local type declaration
@param ordinal: slot number (1...NumberOfLocalTypes)
@param flags: any of PRTYPE_* constants
@return: local type as a C declaration or ""
@note: This function can return types strings up to 64KiB. Use idaapi.idc_get_local_type()
for larger types.
"""
res,str = idaapi.idc_get_local_type(ordinal, flags, 2**16)
return str
(type, fields) = GetLocalTinfo(ordinal)
if type:
name = GetLocalTypeName(ordinal)
return idaapi.idc_print_type(type, fields, name, flags)
return ""
PRTYPE_1LINE = 0x0000 # print to one line
PRTYPE_MULTI = 0x0001 # print to many lines
@ -7313,7 +7408,7 @@ def SendDbgCommand(cmd):
An exception will be raised if the debugger is not running or the current debugger does not export
the 'SendDbgCommand' IDC command.
"""
s = Eval('SendDbgCommand("%s");' % cmd)
s = Eval('SendDbgCommand("%s");' % idaapi.str2user(cmd))
if s.startswith("IDC_FAILURE"):
raise Exception, "Debugger command is available only when the debugger is active!"
return s
@ -7806,10 +7901,11 @@ BPTATTR_SIZE = 2 # size of the breakpoint (undefined for software breakpoint
BPTATTR_TYPE = 3
# Breakpoint types:
BPT_EXEC = 0 # Hardware: Execute instruction
BPT_WRITE = 1 # Hardware: Write access
BPT_RDWR = 3 # Hardware: Read/write access
BPT_SOFT = 4 # Software breakpoint
BPT_WRITE = 1 # Hardware: Write access
BPT_RDWR = 3 # Hardware: Read/write access
BPT_SOFT = 4 # Software breakpoint
BPT_EXEC = 8 # Hardware: Execute instruction
BPT_DEFAULT = (BPT_SOFT|BPT_EXEC); # Choose bpt type automaticaly
BPTATTR_COUNT = 4
BPTATTR_FLAGS = 5
@ -7921,7 +8017,7 @@ def AddBptEx(ea, size, bpttype):
def AddBpt(ea):
return AddBptEx(ea, 0, BPT_SOFT)
return AddBptEx(ea, 0, BPT_DEFAULT)
def DelBpt(ea):
@ -8019,12 +8115,13 @@ def LoadTraceFile(filename):
Load a previously recorded binary trace file
@param filename: trace file
"""
return idaapi.load_trace_file(filename, None)
return idaapi.load_trace_file(filename)
def SaveTraceFile(filename, description):
"""
Save current trace to a binary trace file
@param filename: trace file
@param description: trace description
"""
return idaapi.save_trace_file(filename, description)

View File

@ -29,10 +29,8 @@
#define S_IDAAPI_EXECSCRIPT "IDAPython_ExecScript"
#define S_IDAAPI_COMPLETION "IDAPython_Completion"
#define S_IDAAPI_FORMATEXC "IDAPython_FormatExc"
//------------------------------------------------------------------------
// Vector of PyObject*
typedef qvector<PyObject *> ppyobject_vec_t;
#define S_IDAAPI_LOADPROCMOD "IDAPython_LoadProcMod"
#define S_IDAAPI_UNLOADPROCMOD "IDAPython_UnLoadProcMod"
//------------------------------------------------------------------------
// PyIdc conversion object IDs
@ -58,7 +56,7 @@ typedef qvector<PyObject *> ppyobject_vec_t;
#define CIP_FAILED -1 // Conversion error
#define CIP_IMMUTABLE 0 // Immutable object passed. Will not update the object but no error occured
#define CIP_OK 1 // Success
#define CIP_OK_NODECREF 2 // Success but do not decrement its reference
#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
@ -66,10 +64,12 @@ typedef qvector<PyObject *> ppyobject_vec_t;
#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); \
@ -77,10 +77,12 @@ typedef qvector<PyObject *> ppyobject_vec_t;
} \
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)); \
}
@ -91,47 +93,183 @@ typedef qvector<PyObject *> ppyobject_vec_t;
#endif // __PYWRAPS__
//---------------------------------------------------------------------------
class CGilStateAuto
class gil_lock_t
{
private:
PyGILState_STATE state;
public:
CGilStateAuto()
gil_lock_t()
{
state = PyGILState_Ensure();
}
~CGilStateAuto()
~gil_lock_t()
{
PyGILState_Release(state);
}
};
// Declare a variable to acquire/release the GIL
#define PYW_GIL_AUTO_ENSURE CGilStateAuto GIL_STATE_AUTO
#define PYW_GIL_GET gil_lock_t lock;
// Macros to acquire/release GIL in a given scope
#define PYW_GIL_ENSURE_N(name) PyGILState_STATE gil_state##name = PyGILState_Ensure()
#define PYW_GIL_RELEASE_N(name) PyGILState_Release(gil_state##name)
#ifdef _DEBUG
#define GIL_CHKCONDFAIL (PyGILState_GetThisThreadState() != _PyThreadState_Current)
#else
#define GIL_CHKCONDFAIL (((debug & IDA_DEBUG_PLUGIN) == IDA_DEBUG_PLUGIN) \
&& PyGILState_GetThisThreadState() != _PyThreadState_Current)
#endif
#define PYW_GIL_CHECK_LOCKED_SCOPE() \
do \
{ \
if ( GIL_CHKCONDFAIL ) \
{ \
msg("*** WARNING: Code at %s:%d should have the GIL, but apparently doesn't ***\n", \
__FILE__, __LINE__); \
if ( under_debugger ) \
BPT; \
} \
} while ( false )
#define PYW_GIL_ENSURE PYW_GIL_ENSURE_N(_)
#define PYW_GIL_RELEASE PYW_GIL_RELEASE_N(_)
//------------------------------------------------------------------------
// All the exported functions from PyWraps are forward declared here
insn_t *insn_t_get_clink(PyObject *self);
op_t *op_t_get_clink(PyObject *self);
// Returns a reference to a class
PyObject *get_idaapi_attr(const char *attr);
//-------------------------------------------------------------------------
// The base for a reference. Will automatically increase the reference
// counter for the object when it is assigned from another ref_t,
// and decrease the reference counter when destroyed.
// This is meant to be used whenever possible, in order to prevent
// situations where, e.g., a given code path is taken and we return from
// a function without first decreasing the reference counter.
//
// Note: You should never, ever have to Py_[INCREF|DECREF] the 'o' object yourself.
// Note: These simple ref_t cannot be created with a PyObject* directly
// (that would be the role of 'newref_t'/'borref_t' below.)
// In other words: simple 'ref_t' instances are never created from the
// result of calling the CPython API. They are only used when in
// idapython land.
// In yet other words: the CPython API only deals in terms of
// 'New references' and 'Borrowed references'. Those are implemented,
// respectively, by the 'newref_t' and 'borref_t' classes below.
// This 'ref_t' is only used for internal handling.
struct ref_t
{
PyObject *o;
// Returns a reference to a class by its ID
PyObject *get_idaapi_attr_by_id(const int class_id);
ref_t() : o(NULL) {}
ref_t(const ref_t &other) : o(other.o) { incref(); }
~ref_t() { decref(); }
ref_t &operator=(const ref_t &other)
{
decref();
o = other.o;
incref();
return *this;
}
void incref() const { if ( o != NULL ) Py_INCREF(o); }
void decref() const { if ( o != NULL ) Py_DECREF(o); }
bool operator==(PyObject *other) const { return o == other; }
bool operator!=(PyObject *other) const { return ! ((*this) == other); }
bool operator==(const ref_t &other) const { return o == other.o; }
bool operator!=(const ref_t &other) const { return ! ((*this) == other); }
// operator PyObject *() const { return o; }
// PyObject *operator ->() const { return o; }
// PyObject &operator *() const { return *o; }
//protected:
};
//-------------------------------------------------------------------------
// A 'new' reference. Typically used when the CPython implementation returns
// a PyObject* whose refcnt was already increased, and that the caller is
// responsible for releasing.
//
// This implements the 'New reference' idea at http://docs.python.org/2/c-api/intro.html:
// ---
// "When a function passes ownership of a reference on to its caller,
// the caller is said to receive a new reference"
// ---
// E.g., from "PyObject_GetAttrString"'s doc:
// ---
// "Return value: New reference.
// Retrieve an attribute named attr_name from object o[...]"
// ---
struct newref_t : public ref_t
{
newref_t(); // No.
newref_t(const newref_t &other); // No.
newref_t &operator=(const newref_t &other); // No.
newref_t(PyObject *_o)
{
#ifdef _DEBUG
QASSERT(30409, _o == NULL || _o->ob_refcnt >= 1);
#endif
o = _o;
}
};
//-------------------------------------------------------------------------
// A 'borrowed' reference. Typically used when the CPython implementation returns
// a PyObject* whose ownership is _not_ transferred to the caller.
// Therefore, and since the caller wants to make sure the object is not
// released while it is using it, it must first increase the reference count,
// and then decrease it.
//
// This is similar to the simpler 'ref_t' in that it first increases, and then
// decreases the reference count. The difference is that 'borref_t' instances
// can be created with a PyObject*, while 'ref_t' instances cannot (by design).
//
// This implements the 'Borrowed reference' idea at http://docs.python.org/2/c-api/intro.html:
// ---
// "When no ownership is transferred, the caller is said to borrow the reference.
// Nothing needs to be done for a borrowed reference."
// ---
struct borref_t : public ref_t
{
borref_t(); // No.
borref_t(const newref_t &other); // No.
borref_t &operator=(const newref_t &other); // No.
borref_t(PyObject *_o)
{
o = _o;
incref(); // ~ref_t() will decref(), so we need to incref.
}
};
//------------------------------------------------------------------------
// Vector of ref_t
struct ref_vec_t : public qvector<ref_t>
{
void to_pyobject_pointers(qvector<PyObject*> *out)
{
size_t n = size();
out->resize(n);
for ( size_t i = 0; i < n; ++i )
out->at(i) = at(i).o;
}
};
// Returns a new reference to a class
// Return value: New reference.
ref_t get_idaapi_attr(const char *attr);
// Returns a new reference to a class by its ID
// Return value: New reference.
ref_t get_idaapi_attr_by_id(const int class_id);
// Tries to import a module and swallows the exception if it fails and returns NULL
PyObject *PyW_TryImportModule(const char *name);
// Return value: New reference.
ref_t PyW_TryImportModule(const char *name);
// Tries to get an attribute and swallows the exception if it fails and returns NULL
PyObject *PyW_TryGetAttrString(PyObject *py_var, const char *attr);
ref_t PyW_TryGetAttrString(PyObject *py_var, const char *attr);
// Returns the linked object (void *) from a PyObject
void *pyobj_get_clink(PyObject *pyobj);
@ -160,17 +298,17 @@ bool PyW_GetError(char *buf, size_t bufsz, bool clear_err = true);
bool PyW_ShowCbErr(const char *cb_name);
// Utility function to create a class instance whose constructor takes zero arguments
PyObject *create_idaapi_class_instance0(const char *clsname);
ref_t create_idaapi_class_instance0(const char *clsname);
// Utility function to create linked class instances
PyObject *create_idaapi_linked_class_instance(const char *clsname, void *lnk);
ref_t create_idaapi_linked_class_instance(const char *clsname, void *lnk);
// Returns the string representation of a PyObject
bool PyW_ObjectToString(PyObject *obj, qstring *out);
// Utility function to convert a python object to an IDC object
// and sets a python exception on failure.
bool convert_pyobj_to_idc_exc(PyObject *py_obj, idc_value_t *idc_obj);
bool pyvar_to_idcvar_or_error(const ref_t &py_obj, idc_value_t *idc_obj);
// Creates and initializes an IDC exception
error_t PyW_CreateIdcException(idc_value_t *res, const char *msg);
@ -179,38 +317,38 @@ error_t PyW_CreateIdcException(idc_value_t *res, const char *msg);
// Conversion functions
//
bool pyw_convert_idc_args(
const idc_value_t args[],
int nargs,
ppyobject_vec_t &pargs,
boolvec_t *decref,
char *errbuf = NULL,
size_t errbufsize = 0);
void pyw_free_idc_args(
ppyobject_vec_t &pargs,
boolvec_t *decref = NULL);
const idc_value_t args[],
int nargs,
ref_vec_t &pargs,
bool as_tupple,
char *errbuf = NULL,
size_t errbufsize = 0);
// Converts Python variable to IDC variable
// gvar_sn is used in case the Python object was a created from a call to idcvar_to_pyvar and the IDC object was a VT_REF
int pyvar_to_idcvar(
PyObject *py_var,
idc_value_t *idc_var,
int *gvar_sn = NULL);
const ref_t &py_var,
idc_value_t *idc_var,
int *gvar_sn = NULL);
// Converts from IDC to Python
// We support converting VT_REF IDC variable types
int idcvar_to_pyvar(
const idc_value_t &idc_var,
PyObject **py_var);
ref_t *py_var);
// Walks a Python list or Sequence and calls the callback
Py_ssize_t pyvar_walk_list(
PyObject *py_list,
int (idaapi *cb)(PyObject *py_item, Py_ssize_t index, void *ud) = NULL,
void *ud = NULL);
const ref_t &py_list,
int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud) = NULL,
void *ud = NULL);
Py_ssize_t pyvar_walk_list(
PyObject *py_list,
int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud) = NULL,
void *ud = NULL);
// Converts an intvec_t to a Python list object
PyObject *PyW_IntVecToPyList(const intvec_t &intvec);
ref_t PyW_IntVecToPyList(const intvec_t &intvec);
// Converts an Python list to an intvec
bool PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec);
@ -233,4 +371,4 @@ bool pywraps_check_autoscripts(char *buf, size_t bufsize);
bool init_pywraps();
void deinit_pywraps();
#endif
#endif

View File

@ -1,125 +1,2 @@
@echo off
rem Please use the same tag for the same .i file
rem That means if many insertions are going to happen in one given .i file then don't use more than code marking tag
set PY=c:\python27\python.exe
echo.
echo -------- DEPLOY started --------------------------------------------------
echo.
rem --------------------------------------------------------------------------
echo Deploying idaapi (common functions, notifywhen)
%PY% deploy.py py_idaapi py_cvt.hpp,py_idaapi.hpp,py_idaapi.py,py_notifywhen.hpp,py_notifywhen.py ..\swig\idaapi.i
rem --------------------------------------------------------------------------
echo Deploying Graph
%PY% deploy.py py_graph py_graph.hpp,py_graph.py ..\swig\graph.i
rem --------------------------------------------------------------------------
echo Deploying custview
%PY% deploy.py py_custviewer py_custview.py,py_custview.hpp ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying plgform
%PY% deploy.py py_plgform py_plgform.hpp,py_plgform.py ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying expr
%PY% deploy.py py_expr py_expr.hpp,py_expr.py ..\swig\expr.i
rem --------------------------------------------------------------------------
echo Deploying cli
%PY% deploy.py py_cli py_cli.py,py_cli.hpp ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying Loader
%PY% deploy.py py_loader py_loader.hpp ..\swig\loader.i
rem --------------------------------------------------------------------------
echo Deploying kernwin, choose2, askusingform
%PY% deploy.py py_kernwin py_kernwin.hpp,py_kernwin.py,py_choose.hpp,py_choose2.hpp,py_choose2.py,py_askusingform.hpp,py_askusingform.py ..\swig\kernwin.i
rem --------------------------------------------------------------------------
echo Deploying idd
%PY% deploy.py py_idd py_dbg.hpp,py_appcall.py ..\swig\idd.i
rem --------------------------------------------------------------------------
echo Deploying nalt
%PY% deploy.py py_nalt py_nalt.hpp,py_nalt.py ..\swig\nalt.i
rem --------------------------------------------------------------------------
echo Deploying dbg
%PY% deploy.py py_dbg py_dbg.hpp ..\swig\dbg.i
rem --------------------------------------------------------------------------
echo Deploying linput/diskio
%PY% deploy.py py_diskio py_linput.hpp,py_diskio.hpp,py_diskio.py ..\swig\diskio.i
rem --------------------------------------------------------------------------
echo Deploying name
%PY% deploy.py py_name py_name.hpp,py_name.py ..\swig\name.i
rem --------------------------------------------------------------------------
echo Deploying qfile
%PY% deploy.py py_qfile py_qfile.hpp ..\swig\fpro.i
rem --------------------------------------------------------------------------
echo Deploying bytes
%PY% deploy.py py_bytes py_bytes.hpp,py_custdata.py,py_custdata.hpp ..\swig\bytes.i
rem --------------------------------------------------------------------------
echo Deploying typeinf
%PY% deploy.py py_typeinf py_typeinf.hpp ..\swig\typeinf.i
rem --------------------------------------------------------------------------
echo Deploying gdl
%PY% deploy.py py_gdl py_gdl.py ..\swig\gdl.i
rem --------------------------------------------------------------------------
echo Deploying ua
%PY% deploy.py py_ua py_ua.hpp,py_ua.py ..\swig\ua.i
rem --------------------------------------------------------------------------
echo Deploying idp
%PY% deploy.py py_idp py_idp.hpp ..\swig\idp.i
rem --------------------------------------------------------------------------
echo Deploying lines
%PY% deploy.py py_lines py_lines.hpp,py_lines.py ..\swig\lines.i
rem --------------------------------------------------------------------------
echo Deploying pc_win32_appcall
%PY% deploy.py appcalltest py_appcall.py ..\..\..\tests\input\pc_win32_appcall.pe.hints
rem --------------------------------------------------------------------------
echo Deploying ex_custdata example
%PY% deploy.py ex_custdata ..\examples\ex_custdata.py ..\..\..\tests\input\pc_win32_custdata1.pe.hints
rem --------------------------------------------------------------------------
echo Deploying ex_formchooser
%PY% deploy.py ex_formchooser py_askusingform.py ..\..\formchooser\formchooser.py
rem --------------------------------------------------------------------------
echo Deploying ex_askusingform
%PY% deploy.py ex_askusingform py_askusingform.py ..\examples\ex_askusingform.py
rem --------------------------------------------------------------------------
echo Deploying ex_cli example
%PY% deploy.py ex_cli_ex1 py_cli.py ..\examples\ex_cli.py
rem --------------------------------------------------------------------------
echo Deploying ex_expr example
%PY% deploy.py ex_expr py_expr.py ..\examples\ex_expr.py
rem --------------------------------------------------------------------------
echo Deploying ex_custview.py example
%PY% deploy.py py_custviewerex1 py_custview.py ..\examples\ex_custview.py
rem --------------------------------------------------------------------------
echo.
echo -------- DEPLOY finished -------------------------------------------------
echo.
:end
c:\python27\python.exe deploy_all.py

View File

@ -13,7 +13,13 @@ def make_re(tag, mod_name, prefix):
s = '%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s</%(tag)s\(%(m)s\)>' % {'m': mod_name, 'tag': tag, 'p': prefix}
return (s, re.compile(s, re.DOTALL))
def convert_path(path_in):
parts = path_in.split('/')
return os.sep.join(parts)
def deploy(mod_name, src_files, dest_file, silent = True):
dest_file = convert_path(dest_file)
src_files = map(convert_path, src_files)
# create regular expressions
templates = (
('pycode', make_re('pycode', mod_name, '#')),
@ -88,4 +94,5 @@ def main(argv = None):
deploy(mod_name, src_files, dest_file)
#main(['', 'py_graph', 'py_graph.hpp,py_graph.py', 'graph.i'])
main()
if __name__ == '__main__':
main()

194
pywraps/deploy_all.py Normal file
View File

@ -0,0 +1,194 @@
# Please use the same tag for the same .i file
# That means if many insertions are going to happen in one
# given .i file then don't use more than code marking tag
print "\n-------- DEPLOY started --------------------------------------------------\n"
deploys = {
"idaapi (common functions, notifywhen)" : {
"tag" : "py_idaapi",
"src" : ["py_cvt.hpp", "py_idaapi.hpp", "py_idaapi.py", "py_notifywhen.hpp", "py_notifywhen.py"],
"tgt" : "../swig/idaapi.i"
},
"View (common)" : {
"tag" : "py_view_base",
"src" : ["py_view_base.hpp", "py_view_base.py"],
"tgt" : "../swig/view.i"
},
"IDAView" : {
"tag" : "py_idaview",
"src" : ["py_idaview.hpp", "py_idaview.py"],
"tgt" : "../swig/view.i"
},
"Graph" : {
"tag" : "py_graph",
"src" : ["py_graph.hpp", "py_graph.py"],
"tgt" : "../swig/graph.i"
},
"custview" : {
"tag" : "py_custviewer",
"src" : ["py_custview.py","py_custview.hpp"],
"tgt" : "../swig/kernwin.i"
},
"plgform" : {
"tag" : "py_plgform",
"src" : ["py_plgform.hpp","py_plgform.py"],
"tgt" : "../swig/kernwin.i"
},
"expr" : {
"tag" : "py_expr",
"src" : ["py_expr.hpp","py_expr.py"],
"tgt" : "../swig/expr.i"
},
"cli" : {
"tag" : "py_cli",
"src" : ["py_cli.py","py_cli.hpp"],
"tgt" : "../swig/kernwin.i"
},
"Loader" : {
"tag" : "py_loader",
"src" : ["py_loader.hpp"],
"tgt" : "../swig/loader.i"
},
"kernwin, choose2, askusingform" : {
"tag" : "py_kernwin",
"src" : ["py_kernwin.hpp","py_kernwin.py","py_choose.hpp","py_choose2.hpp","py_choose2.py","py_askusingform.hpp","py_askusingform.py"],
"tgt" : "../swig/kernwin.i"
},
"idd" : {
"tag" : "py_idd",
"src" : ["py_dbg.hpp","py_appcall.py"],
"tgt" : "../swig/idd.i"
},
"idd (python)" : {
"tag" : "py_idd_2",
"src" : ["py_dbg.py"],
"tgt" : "../swig/idd.i"
},
"nalt" : {
"tag" : "py_nalt",
"src" : ["py_nalt.hpp","py_nalt.py"],
"tgt" : "../swig/nalt.i"
},
"dbg" : {
"tag" : "py_dbg",
"src" : ["py_dbg.hpp"],
"tgt" : "../swig/dbg.i"
},
"linput/diskio" : {
"tag" : "py_diskio",
"src" : ["py_linput.hpp","py_diskio.hpp","py_diskio.py"],
"tgt" : "../swig/diskio.i"
},
"name" : {
"tag" : "py_name",
"src" : ["py_name.hpp","py_name.py"],
"tgt" : "../swig/name.i"
},
"qfile" : {
"tag" : "py_qfile",
"src" : ["py_qfile.hpp"],
"tgt" : "../swig/fpro.i"
},
"bytes" : {
"tag" : "py_bytes",
"src" : ["py_bytes.hpp","py_custdata.py","py_custdata.hpp"],
"tgt" : "../swig/bytes.i"
},
"typeinf" : {
"tag" : "py_typeinf",
"src" : ["py_typeinf.hpp","py_typeinf.py"],
"tgt" : "../swig/typeinf.i"
},
"gdl" : {
"tag" : "py_gdl",
"src" : ["py_gdl.py"],
"tgt" : "../swig/gdl.i"
},
"ua" : {
"tag" : "py_ua",
"src" : ["py_ua.hpp","py_ua.py"],
"tgt" : "../swig/ua.i"
},
"idp" : {
"tag" : "py_idp",
"src" : ["py_idp.hpp"],
"tgt" : "../swig/idp.i"
},
"lines" : {
"tag" : "py_lines",
"src" : ["py_lines.hpp","py_lines.py"],
"tgt" : "../swig/lines.i"
},
"pc_win32_appcall" : {
"tag" : "appcalltest",
"src" : ["py_appcall.py"],
"tgt" : "../../../tests/input/pc_win32_appcall.pe.hints"
},
"ex_custdata example" : {
"tag" : "ex_custdata",
"src" : ["../examples/ex_custdata.py"],
"tgt" : "../../../tests/input/pc_win32_custdata1.pe.hints"
},
"ex_formchooser" : {
"tag" : "ex_formchooser",
"src" : ["py_askusingform.py"],
"tgt" : "../../formchooser/formchooser.py"
},
"ex_askusingform" : {
"tag" : "ex_askusingform",
"src" : ["py_askusingform.py"],
"tgt" : "../examples/ex_askusingform.py"
},
"ex_cli example" : {
"tag" : "ex_cli_ex1",
"src" : ["py_cli.py"],
"tgt" : "../examples/ex_cli.py"
},
"ex_expr example" : {
"tag" : "ex_expr",
"src" : ["py_expr.py"],
"tgt" : "../examples/ex_expr.py"
},
"ex_custview.py example" : {
"tag" : "py_custviewerex1",
"src" : ["py_custview.py"],
"tgt" : "../examples/ex_custview.py"
}
}
import deploy
for name in deploys:
data = deploys[name]
print "Deploying %s" % name
deploy.deploy(data["tag"], data["src"], data["tgt"])

View File

@ -58,7 +58,8 @@ static PyObject *ex_pytoidc(
return NULL;
idc_value_t v;
int sn = 0;
if ( pyvar_to_idcvar(self, &v, &sn) < CIP_OK )
borref_t self_ref(self);
if ( pyvar_to_idcvar(self_ref, &v, &sn) < CIP_OK )
Py_RETURN_NONE;
Py_RETURN_TRUE;
}
@ -75,4 +76,4 @@ static PyMethodDef py_methods_dbg[] =
{"pytoidc", ex_pytoidc, METH_VARARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */
};
DRIVER_INIT_METHODS(dbg);
DRIVER_INIT_METHODS(dbg);

View File

@ -162,7 +162,7 @@ class Appcall_callable__(object):
def __get_size(self):
if self.__type == None:
return -1
r = _idaapi.get_type_size0(_idaapi.cvar.idati, self.__type)
r = _idaapi.calc_type_size(_idaapi.cvar.idati, self.__type)
if not r:
return -1
return r
@ -658,6 +658,46 @@ def test_pck_bv():
return 1
# -----------------------------------------------------------------------
def test_local_types():
(type, fields) = GetLocalTinfo(1)
if not type:
return -1
decl = GetLocalType(1, PRTYPE_MULTI)
if decl != "enum\n"\
+ "{\n"\
+ " FEATURE_OBJECT_CACHING = 0x0,\n"\
+ " FEATURE_ZONE_ELEVATION = 0x1,\n"\
+ " FEATURE_MIME_HANDLING = 0x2,\n"\
+ " FEATURE_MIME_SNIFFING = 0x3,\n"\
+ " FEATURE_WINDOW_RESTRICTIONS = 0x4,\n"\
+ " FEATURE_WEBOC_POPUPMANAGEMENT = 0x5,\n"\
+ " FEATURE_BEHAVIORS = 0x6,\n"\
+ " FEATURE_DISABLE_MK_PROTOCOL = 0x7,\n"\
+ " FEATURE_LOCALMACHINE_LOCKDOWN = 0x8,\n"\
+ " FEATURE_SECURITYBAND = 0x9,\n"\
+ " FEATURE_RESTRICT_ACTIVEXINSTALL = 0xA,\n"\
+ " FEATURE_VALIDATE_NAVIGATE_URL = 0xB,\n"\
+ " FEATURE_RESTRICT_FILEDOWNLOAD = 0xC,\n"\
+ " FEATURE_ADDON_MANAGEMENT = 0xD,\n"\
+ " FEATURE_PROTOCOL_LOCKDOWN = 0xE,\n"\
+ " FEATURE_HTTP_USERNAME_PASSWORD_DISABLE = 0xF,\n"\
+ " FEATURE_SAFE_BINDTOOBJECT = 0x10,\n"\
+ " FEATURE_UNC_SAVEDFILECHECK = 0x11,\n"\
+ " FEATURE_GET_URL_DOM_FILEPATH_UNENCODED = 0x12,\n"\
+ " FEATURE_TABBED_BROWSING = 0x13,\n"\
+ " FEATURE_SSLUX = 0x14,\n"\
+ " FEATURE_DISABLE_NAVIGATION_SOUNDS = 0x15,\n"\
+ " FEATURE_DISABLE_LEGACY_COMPRESSION = 0x16,\n"\
+ " FEATURE_FORCE_ADDR_AND_STATUS = 0x17,\n"\
+ " FEATURE_XMLHTTP = 0x18,\n"\
+ " FEATURE_DISABLE_TELNET_PROTOCOL = 0x19,\n"\
+ " FEATURE_FEEDS = 0x1A,\n"\
+ " FEATURE_BLOCK_INPUT_PROMPTS = 0x1B,\n"\
+ " FEATURE_ENTRY_COUNT = 0x1C,\n"\
+ "} _tagINTERNETFEATURELIST\n":
print "decl = " + decl
return -2
return 1
# various tests
def test1(stage):
# call a method that takes a string buffer and appends a dot to its end
@ -891,7 +931,7 @@ def test_exec_throw():
# -----------------------------------------------------------------------
# all the tests that take zero parameters
tests0 = (test_gpa, test_pck_idb_raw, test_pck_bv_raw,
test_unpack_raw, test_pck_idb, test_pck_bv,
test_unpack_raw, test_pck_idb, test_pck_bv, test_local_types,
test_enum_files, test2, test_exec_throw, test_loaddll)
test_log = None # test log file

View File

@ -142,6 +142,7 @@ static PyObject *formchgcbfa_get_field_value(
size_t sz)
{
DECLARE_FORM_ACTIONS;
PYW_GIL_CHECK_LOCKED_SCOPE();
switch ( ft )
{
case 8:
@ -213,7 +214,9 @@ static PyObject *formchgcbfa_get_field_value(
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
(*it)--;
return PyW_IntVecToPyList(intvec);
ref_t l(PyW_IntVecToPyList(intvec));
l.incref();
return l.o;
}
break;
}
@ -276,6 +279,7 @@ static bool formchgcbfa_set_field_value(
PyObject *py_val)
{
DECLARE_FORM_ACTIONS;
PYW_GIL_CHECK_LOCKED_SCOPE();
switch ( ft )
{

View File

@ -5,20 +5,17 @@
//------------------------------------------------------------------------
static bool idaapi py_testf_cb(flags_t flags, void *ud)
{
PyObject *py_flags = PyLong_FromUnsignedLong(flags);
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags, NULL);
PYW_GIL_RELEASE;
bool ret = result != NULL && PyObject_IsTrue(result);
Py_XDECREF(result);
Py_XDECREF(py_flags);
return ret;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_flags(PyLong_FromUnsignedLong(flags));
newref_t result(PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags.o, NULL));
return result != NULL && PyObject_IsTrue(result.o);
}
//------------------------------------------------------------------------
// Wraps the (next|prev)that()
static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_callable) )
return BADADDR;
else
@ -33,20 +30,17 @@ static int idaapi py_visit_patched_bytes_cb(
uint32 v,
void *ud)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunction(
(PyObject *)ud,
PY_FMT64 "iII",
pyul_t(ea),
fpos,
o,
v);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallFunction(
(PyObject *)ud,
PY_FMT64 "iII",
pyul_t(ea),
fpos,
o,
v));
PyW_ShowCbErr("visit_patched_bytes");
int ret = (py_result != NULL && PyInt_Check(py_result)) ? PyInt_AsLong(py_result) : 0;
Py_XDECREF(py_result);
return ret;
return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0;
}
//</code(py_bytes)>
//------------------------------------------------------------------------
@ -74,6 +68,7 @@ def visit_patched_bytes(ea1, ea2, callable):
*/
static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_callable) )
return 0;
else
@ -122,29 +117,23 @@ def get_many_bytes(ea, size):
*/
static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
if ( size <= 0 )
break;
// Allocate memory via Python
PyObject *py_buf = PyString_FromStringAndSize(NULL, Py_ssize_t(size));
newref_t py_buf(PyString_FromStringAndSize(NULL, Py_ssize_t(size)));
if ( py_buf == NULL )
break;
// Read bytes
bool ok = get_many_bytes(ea, PyString_AsString(py_buf), size);
if ( !get_many_bytes(ea, PyString_AsString(py_buf.o), size) )
Py_RETURN_NONE;
// If failed, dispose the Python string
if ( !ok )
{
Py_DECREF(py_buf);
py_buf = Py_None;
Py_INCREF(py_buf);
}
return py_buf;
py_buf.incref();
return py_buf.o;
} while ( false );
Py_RETURN_NONE;
}
@ -195,9 +184,11 @@ static PyObject *py_get_ascii_contents2(
}
if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' )
used_size--;
PyObject *py_buf = PyString_FromStringAndSize((const char *)buf, used_size);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_buf(PyString_FromStringAndSize((const char *)buf, used_size));
qfree(buf);
return py_buf;
py_buf.incref();
return py_buf.o;
}
//---------------------------------------------------------------------------
/*

View File

@ -6,45 +6,35 @@
//---------------------------------------------------------------------------
uint32 idaapi choose_sizer(void *self)
{
PyObject *pyres;
uint32 res;
PYW_GIL_ENSURE;
pyres = PyObject_CallMethod((PyObject *)self, "sizer", "");
PYW_GIL_RELEASE;
res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod((PyObject *)self, "sizer", ""));
return PyInt_AsLong(pyres.o);
}
//---------------------------------------------------------------------------
char *idaapi choose_getl(void *self, uint32 n, char *buf)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
(PyObject *)self,
"getl",
"l",
n);
PYW_GIL_RELEASE;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
(PyObject *)self,
"getl",
"l",
n));
const char *res;
if (pyres == NULL || (res = PyString_AsString(pyres)) == NULL )
if (pyres == NULL || (res = PyString_AsString(pyres.o)) == NULL )
qstrncpy(buf, "<Empty>", MAXSTR);
else
qstrncpy(buf, res, MAXSTR);
Py_XDECREF(pyres);
return buf;
}
//---------------------------------------------------------------------------
void idaapi choose_enter(void *self, uint32 n)
{
PYW_GIL_ENSURE;
Py_XDECREF(PyObject_CallMethod((PyObject *)self, "enter", "l", n));
PYW_GIL_RELEASE;
PYW_GIL_GET;
newref_t res(PyObject_CallMethod((PyObject *)self, "enter", "l", n));
}
//---------------------------------------------------------------------------
@ -57,8 +47,9 @@ uint32 choose_choose(
int deflt,
int icon)
{
PyObject *pytitle = PyObject_GetAttrString((PyObject *)self, "title");
const char *title = pytitle != NULL ? PyString_AsString(pytitle) : "Choose";
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t pytitle(PyObject_GetAttrString((PyObject *)self, "title"));
const char *title = pytitle != NULL ? PyString_AsString(pytitle.o) : "Choose";
int r = choose(
flags,
@ -79,9 +70,9 @@ uint32 choose_choose(
NULL, /* destroy */
NULL, /* popup_names */
NULL);/* get_icon */
Py_XDECREF(pytitle);
return r;
}
//</inline(py_kernwin)>
#endif // __PY_CHOOSE__
#endif // __PY_CHOOSE__

View File

@ -11,8 +11,8 @@
#define thisdecl py_choose2_t *_this = thisobj
#define MENU_COMMAND_CB(id) \
static uint32 idaapi s_menu_command_##id(void *obj, uint32 n) \
{ \
return thisobj->on_command(id, int(n)); \
{ \
return thisobj->on_command(id, int(n)); \
}
//------------------------------------------------------------------------
@ -100,6 +100,9 @@ private:
//------------------------------------------------------------------------
static int idaapi ui_cb(void *obj, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
// UI callback to handle chooser items with attributes
if ( notification_code != ui_get_chooser_item_attrs )
return 0;
@ -209,6 +212,9 @@ private:
void on_get_line(int lineno, char * const *line_arr)
{
// Called from s_getl, which itself can be called from the kernel. Ensure GIL
PYW_GIL_GET;
// Get headers?
if ( lineno == 0 )
{
@ -224,64 +230,51 @@ private:
line_arr[i][0] = '\0';
// Call Python
PYW_GIL_ENSURE;
PyObject *list = PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t list(PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1));
if ( list == NULL )
return;
// Go over the List returned by Python and convert to C strings
for ( int i=ncols-1; i>=0; i-- )
{
PyObject *item = PyList_GetItem(list, Py_ssize_t(i));
borref_t item(PyList_GetItem(list.o, Py_ssize_t(i)));
if ( item == NULL )
continue;
const char *str = PyString_AsString(item);
const char *str = PyString_AsString(item.o);
if ( str != NULL )
qstrncpy(line_arr[i], str, MAXSTR);
}
Py_DECREF(list);
}
size_t on_get_size()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL);
PYW_GIL_RELEASE;
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL));
if ( pyres == NULL )
return 0;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res;
return PyInt_AsLong(pyres.o);
}
void on_refreshed()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL));
}
void on_select(const intvec_t &intvec)
{
PYW_GIL_ENSURE;
PyObject *py_list = PyW_IntVecToPyList(intvec);
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_SELECT, "O", py_list);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
Py_XDECREF(py_list);
PYW_GIL_GET;
ref_t py_list(PyW_IntVecToPyList(intvec));
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_SELECT, "O", py_list.o));
}
void on_close()
{
// Call Python
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL));
// Delete this instance if none modal and not embedded
if ( !is_modal() && get_embedded() == NULL )
@ -290,123 +283,96 @@ private:
int on_delete_line(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_DELETE_LINE,
"i",
lineno - 1);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res + 1;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_DELETE_LINE,
"i",
lineno - 1));
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o) + 1;
}
int on_refresh(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_REFRESH,
"i",
lineno - 1);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_DECREF(pyres);
return res + 1;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_REFRESH,
"i",
lineno - 1));
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o) + 1;
}
void on_insert_line()
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_INSERT_LINE, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_INSERT_LINE, NULL));
}
void on_enter(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_SELECT_LINE,
"i",
lineno - 1);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_SELECT_LINE,
"i",
lineno - 1));
}
void on_edit_line(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_EDIT_LINE,
"i",
lineno - 1);
PYW_GIL_RELEASE;
Py_XDECREF(pyres);
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_EDIT_LINE,
"i",
lineno - 1));
}
int on_command(int cmd_id, int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_COMMAND,
"ii",
lineno - 1,
cmd_id);
PYW_GIL_RELEASE;
if ( pyres==NULL )
return lineno;
size_t res = PyInt_AsLong(pyres);
Py_XDECREF(pyres);
return res;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_COMMAND,
"ii",
lineno - 1,
cmd_id));
return pyres == NULL ? lineno : PyInt_AsLong(pyres.o);
}
int on_get_icon(int lineno)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
self,
(char *)S_ON_GET_ICON,
"i",
lineno - 1);
PYW_GIL_RELEASE;
size_t res = PyInt_AsLong(pyres);
Py_XDECREF(pyres);
return res;
PYW_GIL_GET;
newref_t pyres(
PyObject_CallMethod(
self,
(char *)S_ON_GET_ICON,
"i",
lineno - 1));
return PyInt_AsLong(pyres.o);
}
void on_get_line_attr(int lineno, chooser_item_attrs_t *attr)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1);
PYW_GIL_RELEASE;
if ( pyres == NULL )
return;
if ( PyList_Check(pyres) )
PYW_GIL_GET;
newref_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1));
if ( pyres != NULL )
{
PyObject *item;
if ( (item = PyList_GetItem(pyres, 0)) != NULL )
attr->color = PyInt_AsLong(item);
if ( (item = PyList_GetItem(pyres, 1)) != NULL )
attr->flags = PyInt_AsLong(item);
if ( PyList_Check(pyres.o) )
{
PyObject *item;
if ( (item = PyList_GetItem(pyres.o, 0)) != NULL )
attr->color = PyInt_AsLong(item);
if ( (item = PyList_GetItem(pyres.o, 1)) != NULL )
attr->flags = PyInt_AsLong(item);
}
}
Py_XDECREF(pyres);
}
public:
@ -496,7 +462,7 @@ public:
// Adjust the title
ptitle = title_buf;
// Adjust the caption
p = strtok(NULL, delimiter);
caption += (p - temp);
@ -507,12 +473,12 @@ public:
}
if ( !add_chooser_command(
ptitle,
caption,
menu_cbs[menu_cb_idx],
menu_index,
icon,
flags))
ptitle,
caption,
menu_cbs[menu_cb_idx],
menu_index,
icon,
flags))
{
return -1;
}
@ -525,83 +491,71 @@ public:
// Otherwise the chooser window is created and displayed
int create(PyObject *self)
{
PyObject *attr;
PYW_GIL_CHECK_LOCKED_SCOPE();
// Get flags
attr = PyW_TryGetAttrString(self, S_FLAGS);
if ( attr == NULL )
ref_t flags_attr(PyW_TryGetAttrString(self, S_FLAGS));
if ( flags_attr == NULL )
return -1;
flags = PyInt_Check(attr) != 0 ? PyInt_AsLong(attr) : 0;
Py_DECREF(attr);
flags = PyInt_Check(flags_attr.o) != 0 ? PyInt_AsLong(flags_attr.o) : 0;
// Get the title
if ( !PyW_GetStringAttr(self, S_TITLE, &title) )
return -1;
// Get columns
attr = PyW_TryGetAttrString(self, "cols");
if ( attr == NULL )
ref_t cols_attr(PyW_TryGetAttrString(self, "cols"));
if ( cols_attr == NULL )
return -1;
// Get col count
int ncols = int(PyList_Size(attr));
int ncols = int(PyList_Size(cols_attr.o));
// Get cols caption and widthes
cols.qclear();
for ( int i=0; i<ncols; i++ )
{
// get list item: [name, width]
PyObject *list = PyList_GetItem(attr, i);
PyObject *v = PyList_GetItem(list, 0);
borref_t list(PyList_GetItem(cols_attr.o, i));
borref_t v(PyList_GetItem(list.o, 0));
// Extract string
const char *str = v == NULL ? "" : PyString_AsString(v);
const char *str = v == NULL ? "" : PyString_AsString(v.o);
cols.push_back(str);
// Extract width
int width;
v = PyList_GetItem(list, 1);
borref_t v2(PyList_GetItem(list.o, 1));
// No width? Guess width from column title
if ( v == NULL )
if ( v2 == NULL )
width = strlen(str);
else
width = PyInt_AsLong(v);
width = PyInt_AsLong(v2.o);
widths.push_back(width);
}
Py_DECREF(attr);
// Get *deflt
int deflt = -1;
attr = PyW_TryGetAttrString(self, "deflt");
if ( attr != NULL )
{
deflt = PyInt_AsLong(attr);
Py_DECREF(attr);
}
ref_t deflt_attr(PyW_TryGetAttrString(self, "deflt"));
if ( deflt_attr != NULL )
deflt = PyInt_AsLong(deflt_attr.o);
// Get *icon
int icon = -1;
if ( (attr = PyW_TryGetAttrString(self, "icon")) != NULL )
{
icon = PyInt_AsLong(attr);
Py_DECREF(attr);
}
ref_t icon_attr(PyW_TryGetAttrString(self, "icon"));
if ( icon_attr != NULL )
icon = PyInt_AsLong(icon_attr.o);
// Get *x1,y1,x2,y2
int pts[4];
static const char *pt_attrs[qnumber(pts)] = {"x1", "y1", "x2", "y2"};
for ( size_t i=0; i < qnumber(pts); i++ )
{
if ( (attr = PyW_TryGetAttrString(self, pt_attrs[i])) == NULL )
{
ref_t pt_attr(PyW_TryGetAttrString(self, pt_attrs[i]));
if ( pt_attr == NULL )
pts[i] = -1;
}
else
{
pts[i] = PyInt_AsLong(attr);
Py_DECREF(attr);
}
pts[i] = PyInt_AsLong(pt_attr.o);
}
// Check what callbacks we have
@ -628,10 +582,8 @@ public:
cb_flags = 0;
for ( int i=0; i<qnumber(callbacks); i++ )
{
attr = attr = PyW_TryGetAttrString(self, callbacks[i].name);
bool have_cb = attr != NULL && PyCallable_Check(attr) != 0;
Py_XDECREF(attr);
ref_t cb_attr(PyW_TryGetAttrString(self, callbacks[i].name));
bool have_cb = cb_attr != NULL && PyCallable_Check(cb_attr.o) != 0;
if ( have_cb )
{
cb_flags |= callbacks[i].have;
@ -646,19 +598,18 @@ public:
// Get *popup names
// An array of 4 strings: ("Insert", "Delete", "Edit", "Refresh"
attr = PyW_TryGetAttrString(self, S_POPUP_NAMES);
if ( (attr != NULL)
&& PyList_Check(attr)
&& PyList_Size(attr) == POPUP_NAMES_COUNT )
ref_t pn_attr(PyW_TryGetAttrString(self, S_POPUP_NAMES));
if ( (pn_attr != NULL)
&& PyList_Check(pn_attr.o)
&& PyList_Size(pn_attr.o) == POPUP_NAMES_COUNT )
{
popup_names = new const char *[POPUP_NAMES_COUNT];
for ( int i=0; i<POPUP_NAMES_COUNT; i++ )
{
const char *str = PyString_AsString(PyList_GetItem(attr, i));
const char *str = PyString_AsString(PyList_GetItem(pn_attr.o, i));
popup_names[i] = qstrdup(str);
}
}
Py_XDECREF(attr);
// Adjust flags (if needed)
if ( (cb_flags & CHOOSE2_HAVE_GETATTR) != 0 )
@ -672,8 +623,8 @@ public:
install_hooks(true);
// Check if *embedded
attr = PyW_TryGetAttrString(self, S_EMBEDDED);
if ( attr != NULL && PyObject_IsTrue(attr) == 1 )
ref_t emb_attr(PyW_TryGetAttrString(self, S_EMBEDDED));
if ( emb_attr != NULL && PyObject_IsTrue(emb_attr.o) == 1 )
{
// Create an embedded chooser structure
embedded = new chooser_info_t();
@ -710,7 +661,6 @@ public:
embedded->refresh = NULL;
}
}
Py_XDECREF(attr);
// Create the chooser (if not embedded)
int r;
@ -873,6 +823,8 @@ void choose2_activate(PyObject *self)
//------------------------------------------------------------------------
PyObject *choose2_get_embedded_selection(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_choose2_t *c2 = choose2_find_instance(self);
chooser_info_t *embedded;
@ -886,13 +838,17 @@ PyObject *choose2_get_embedded_selection(PyObject *self)
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
(*it)--;
return PyW_IntVecToPyList(intvec);
ref_t ret(PyW_IntVecToPyList(intvec));
ret.incref();
return ret.o;
}
//------------------------------------------------------------------------
// Return the C instances as 64bit numbers
PyObject *choose2_get_embedded(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_choose2_t *c2 = choose2_find_instance(self);
chooser_info_t *embedded;
@ -945,12 +901,12 @@ PyObject *choose2_get_embedded_selection(PyObject *self);
static void NT_CDECL choose2_test_embedded(chooser_info_t *embedded)
{
msg("cb=%d -> looks %valid\n",
embedded->cb,
msg("cb=%d -> looks %valid\n",
embedded->cb,
embedded->cb == sizeof(chooser_info_t) ? "" : "in");
}
static size_t choose2_get_test_embedded()
{
return (size_t)choose2_test_embedded;
}
#endif // __PY_CHOOSE2__
#endif // __PY_CHOOSE2__

View File

@ -37,17 +37,17 @@ private:
static py_cli_t *py_clis[MAX_PY_CLI];
static const py_cli_cbs_t py_cli_cbs[MAX_PY_CLI];
//--------------------------------------------------------------------------
#define IMPL_PY_CLI_CB(CBN) \
#define IMPL_PY_CLI_CB(CBN) \
static bool idaapi s_keydown##CBN(qstring *line, int *p_x, int *p_sellen, int *vk_key, int shift) \
{ \
{ \
return py_clis[CBN]->on_keydown(line, p_x, p_sellen, vk_key, shift); \
} \
static bool idaapi s_execute_line##CBN(const char *line) \
{ \
return py_clis[CBN]->on_execute_line(line); \
} \
} \
static bool idaapi s_execute_line##CBN(const char *line) \
{ \
return py_clis[CBN]->on_execute_line(line); \
} \
static bool idaapi s_complete_line##CBN(qstring *completion, const char *prefix, int n, const char *line, int x) \
{ \
{ \
return py_clis[CBN]->on_complete_line(completion, prefix, n, line, x); \
}
@ -62,18 +62,15 @@ private:
// Returns: true-executed line, false-ask for more lines
bool on_execute_line(const char *line)
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_EXECUTE_LINE,
"s",
line);
PYW_GIL_RELEASE;
bool ok = result != NULL && PyObject_IsTrue(result);
PYW_GIL_GET;
newref_t result(
PyObject_CallMethod(
self,
(char *)S_ON_EXECUTE_LINE,
"s",
line));
PyW_ShowCbErr(S_ON_EXECUTE_LINE);
Py_XDECREF(result);
return ok;
return result != NULL && PyObject_IsTrue(result.o);
}
//--------------------------------------------------------------------------
@ -95,41 +92,45 @@ private:
int *vk_key,
int shift)
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_KEYDOWN,
"siiHi",
line->c_str(),
*p_x,
*p_sellen,
*vk_key,
shift);
PYW_GIL_RELEASE;
PYW_GIL_GET;
newref_t result(
PyObject_CallMethod(
self,
(char *)S_ON_KEYDOWN,
"siiHi",
line->c_str(),
*p_x,
*p_sellen,
*vk_key,
shift));
bool ok = result != NULL && PyTuple_Check(result);
bool ok = result != NULL && PyTuple_Check(result.o);
PyW_ShowCbErr(S_ON_KEYDOWN);
if ( ok )
{
Py_ssize_t sz = PyTuple_Size(result);
Py_ssize_t sz = PyTuple_Size(result.o);
PyObject *item;
if ( sz > 0 && (item = PyTuple_GetItem(result, 0)) != NULL && PyString_Check(item) )
*line = PyString_AsString(item);
if ( sz > 1 && (item = PyTuple_GetItem(result, 1)) != NULL && PyInt_Check(item) )
*p_x = PyInt_AsLong(item);
if ( sz > 2 && (item = PyTuple_GetItem(result, 2)) != NULL && PyInt_Check(item) )
*p_sellen = PyInt_AsLong(item);
if ( sz > 3 && (item = PyTuple_GetItem(result, 3)) != NULL && PyInt_Check(item) )
*vk_key = PyInt_AsLong(item) & 0xffff;
#define GET_TUPLE_ENTRY(col, PyThingy, AsThingy, out) \
do \
{ \
if ( sz > col ) \
{ \
borref_t _r(PyTuple_GetItem(result.o, col)); \
if ( _r != NULL && PyThingy##_Check(_r.o) ) \
*out = PyThingy##_##AsThingy(_r.o); \
} \
} while ( false )
GET_TUPLE_ENTRY(0, PyString, AsString, line);
GET_TUPLE_ENTRY(1, PyInt, AsLong, p_x);
GET_TUPLE_ENTRY(2, PyInt, AsLong, p_sellen);
GET_TUPLE_ENTRY(3, PyInt, AsLong, vk_key);
*vk_key &= 0xffff;
#undef GET_TUPLE_ENTRY
}
Py_XDECREF(result);
return ok;
}
@ -140,41 +141,41 @@ private:
// Returns: true if generated a new completion
// This callback is optional
bool on_complete_line(
qstring *completion,
const char *prefix,
int n,
const char *line,
int x)
qstring *completion,
const char *prefix,
int n,
const char *line,
int x)
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
self,
(char *)S_ON_COMPLETE_LINE,
"sisi",
prefix,
n,
line,
x);
PYW_GIL_RELEASE;
bool ok = result != NULL && PyString_Check(result);
PYW_GIL_GET;
newref_t result(
PyObject_CallMethod(
self,
(char *)S_ON_COMPLETE_LINE,
"sisi",
prefix,
n,
line,
x));
bool ok = result != NULL && PyString_Check(result.o);
PyW_ShowCbErr(S_ON_COMPLETE_LINE);
if ( ok )
*completion = PyString_AsString(result);
Py_XDECREF(result);
*completion = PyString_AsString(result.o);
return ok;
}
// Private ctor (use bind())
py_cli_t()
{
py_cli_t()
{
}
public:
//---------------------------------------------------------------------------
static int bind(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
int cli_idx;
// Find an empty slot
for ( cli_idx = 0; cli_idx < MAX_PY_CLI; ++cli_idx )
@ -183,7 +184,7 @@ public:
break;
}
py_cli_t *py_cli = NULL;
do
do
{
// No free slots?
if ( cli_idx >= MAX_PY_CLI )
@ -197,14 +198,12 @@ public:
py_cli->cli.size = sizeof(cli_t);
// Store 'flags'
if ( (attr = PyW_TryGetAttrString(py_obj, S_FLAGS)) == NULL )
{
py_cli->cli.flags = 0;
}
else
{
py_cli->cli.flags = PyLong_AsLong(attr);
Py_DECREF(attr);
ref_t flags_attr(PyW_TryGetAttrString(py_obj, S_FLAGS));
if ( flags_attr == NULL )
py_cli->cli.flags = 0;
else
py_cli->cli.flags = PyLong_AsLong(flags_attr.o);
}
// Store 'sname'
@ -256,9 +255,12 @@ public:
py_cli_t *py_cli = py_clis[cli_idx];
remove_command_interpreter(&py_cli->cli);
Py_DECREF(py_cli->self);
delete py_cli;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_DECREF(py_cli->self);
delete py_cli;
}
py_clis[cli_idx] = NULL;
@ -280,12 +282,12 @@ const py_cli_cbs_t py_cli_t::py_cli_cbs[MAX_PY_CLI] =
//<inline(py_cli)>
static int py_install_command_interpreter(PyObject *py_obj)
{
{
return py_cli_t::bind(py_obj);
}
static void py_remove_command_interpreter(int cli_idx)
{
{
py_cli_t::unbind(cli_idx);
}
//</inline(py_cli)>

View File

@ -18,20 +18,18 @@ class py_custom_data_type_t
size_t nbytes) // size of the future item
{
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_MAY_CREATE_AT,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(nbytes));
PYW_GIL_RELEASE;
PYW_GIL_GET;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_MAY_CREATE_AT,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(nbytes)));
PyW_ShowCbErr(S_MAY_CREATE_AT);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
// !=NULL means variable size datatype
@ -42,24 +40,23 @@ class py_custom_data_type_t
ea_t ea, // address of the item
asize_t maxsize) // maximal size of the item
{
PYW_GIL_GET;
// Returns: 0-no such item can be created/displayed
// this callback is required only for varsize datatypes
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_CALC_ITEM_SIZE,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(maxsize));
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_CALC_ITEM_SIZE,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(maxsize)));
if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL )
return 0;
uint64 num = 0;
PyW_GetNumber(py_result, &num);
Py_XDECREF(py_result);
PyW_GetNumber(py_result.o, &num);
return asize_t(num);
}
@ -77,6 +74,8 @@ public:
int register_dt(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Already registered?
if ( dtid >= 0 )
return dtid;
@ -85,9 +84,10 @@ public:
dt.cbsize = sizeof(dt);
dt.ud = this;
PyObject *py_attr = NULL;
do
{
ref_t py_attr;
// name
if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) )
break;
@ -108,30 +108,27 @@ public:
// value_size
py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE);
if ( py_attr != NULL && PyInt_Check(py_attr) )
dt.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
dt.value_size = PyInt_AsLong(py_attr.o);
py_attr = ref_t();
// props
py_attr = PyW_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL && PyInt_Check(py_attr) )
dt.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
dt.props = PyInt_AsLong(py_attr.o);
py_attr = ref_t();
// may_create_at
py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
dt.may_create_at = s_may_create_at;
Py_XDECREF(py_attr);
py_attr = ref_t();
// calc_item_size
py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
dt.calc_item_size = s_calc_item_size;
Py_XDECREF(py_attr);
// Clear attribute
py_attr = NULL;
py_attr = ref_t();
// Now try to register
dtid = register_custom_data_type(&dt);
@ -142,20 +139,16 @@ public:
Py_INCREF(py_obj);
py_self = py_obj;
py_attr = PyInt_FromLong(dtid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
// Done with attribute
py_attr = NULL;
py_attr = newref_t(PyInt_FromLong(dtid));
PyObject_SetAttrString(py_obj, S_ID, py_attr.o);
} while ( false );
Py_XDECREF(py_attr);
return dtid;
}
bool unregister_dt()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dtid < 0 )
return true;
@ -195,44 +188,41 @@ private:
int operand_num, // current operand number
int dtid) // custom data type id
{
PYW_GIL_GET;
// Build a string from the buffer
PyObject *py_value = PyString_FromStringAndSize(
(const char *)value,
Py_ssize_t(size));
newref_t py_value(PyString_FromStringAndSize(
(const char *)value,
Py_ssize_t(size)));
if ( py_value == NULL )
return false;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value,
pyul_t(current_ea),
operand_num,
dtid);
PYW_GIL_RELEASE;
// Done with the string
Py_DECREF(py_value);
newref_t py_result(PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value.o,
pyul_t(current_ea),
operand_num,
dtid));
// Error while calling the function?
if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL )
return false;
bool ok = false;
if ( PyString_Check(py_result) )
if ( PyString_Check(py_result.o) )
{
Py_ssize_t len;
char *buf;
if ( out != NULL && PyString_AsStringAndSize(py_result, &buf, &len) != -1 )
if ( out != NULL && PyString_AsStringAndSize(py_result.o, &buf, &len) != -1 )
{
out->qclear();
out->append(buf, len);
}
ok = true;
}
Py_DECREF(py_result);
return ok;
}
@ -244,16 +234,17 @@ private:
int operand_num, // current operand number (-1 if unknown)
qstring *errstr) // buffer for error message
{
PYW_GIL_GET;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num);
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num));
// Error while calling the function?
if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL)
@ -263,15 +254,14 @@ private:
do
{
// We expect a tuple(bool, string|None)
if ( !PyTuple_Check(py_result) || PyTuple_Size(py_result) != 2 )
if ( !PyTuple_Check(py_result.o) || PyTuple_Size(py_result.o) != 2 )
break;
// Borrow references
PyObject *py_bool = PyTuple_GetItem(py_result, 0);
PyObject *py_val = PyTuple_GetItem(py_result, 1);
borref_t py_bool(PyTuple_GetItem(py_result.o, 0));
borref_t py_val(PyTuple_GetItem(py_result.o, 1));
// Get return code from Python
ok = PyObject_IsTrue(py_bool);
ok = PyObject_IsTrue(py_bool.o);
// We expect None or the value (depending on probe)
if ( ok )
@ -282,7 +272,7 @@ private:
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_val, &buf, &len) != -1 )
if ( PyString_AsStringAndSize(py_val.o, &buf, &len) != -1 )
{
value->qclear();
value->append(buf, len);
@ -292,16 +282,15 @@ private:
else
{
// Make sure the user returned (False, String)
if ( py_bool != Py_False || !PyString_Check(py_val) )
if ( py_bool.o != Py_False || !PyString_Check(py_val.o) )
{
*errstr = "Invalid return value returned from the Python callback!";
break;
}
// Get the error message
*errstr = PyString_AsString(py_val);
*errstr = PyString_AsString(py_val.o);
}
} while ( false );
Py_DECREF(py_result);
return ok;
}
@ -313,19 +302,18 @@ private:
// xrefs from the current item.
// this callback may be missing.
{
PYW_GIL_GET;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_ANALYZE,
PY_FMT64 "i",
pyul_t(current_ea),
operand_num);
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_ANALYZE,
PY_FMT64 "i",
pyul_t(current_ea),
operand_num));
PyW_ShowCbErr(S_ANALYZE);
Py_XDECREF(py_result);
}
public:
py_custom_data_format_t()
@ -334,9 +322,9 @@ public:
py_self = NULL;
}
const char *get_name() const
{
return df_name.c_str();
const char *get_name() const
{
return df_name.c_str();
}
int register_df(int dtid, PyObject *py_obj)
@ -348,10 +336,12 @@ public:
memset(&df, 0, sizeof(df));
df.cbsize = sizeof(df);
df.ud = this;
PyObject *py_attr = NULL;
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
ref_t py_attr;
// name
if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) )
break;
@ -363,9 +353,8 @@ public:
// props
py_attr = PyW_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.props = PyInt_AsLong(py_attr.o);
// hotkey
if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) )
@ -373,36 +362,28 @@ public:
// value_size
py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.value_size = PyInt_AsLong(py_attr.o);
// text_width
py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.text_width = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.text_width = PyInt_AsLong(py_attr.o);
// print cb
py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
df.print = s_print;
Py_XDECREF(py_attr);
// scan cb
py_attr = PyW_TryGetAttrString(py_obj, S_SCAN);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
df.scan = s_scan;
Py_XDECREF(py_attr);
// analyze cb
py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
df.analyze = s_analyze;
Py_XDECREF(py_attr);
// Done with attribute
py_attr = NULL;
// Now try to register
dfid = register_custom_data_format(dtid, &df);
@ -414,19 +395,16 @@ public:
py_self = py_obj;
// Update the format ID
py_attr = PyInt_FromLong(dfid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
py_attr = NULL;
py_attr = newref_t(PyInt_FromLong(dfid));
PyObject_SetAttrString(py_obj, S_ID, py_attr.o);
} while ( false );
Py_XDECREF(py_attr);
return dfid;
}
bool unregister_df(int dtid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Never registered?
if ( dfid < 0 )
return true;
@ -490,6 +468,8 @@ static py_custom_data_format_list_t py_df_list;
//------------------------------------------------------------------------
static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("{s:" PY_FMT64 ",s:i,s:i,s:s,s:s,s:s,s:s}",
S_VALUE_SIZE, pyul_t(dt->value_size),
S_PROPS, dt->props,
@ -503,6 +483,8 @@ static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
//------------------------------------------------------------------------
static PyObject *py_data_format_to_py_dict(const data_format_t *df)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("{s:i,s:i,s:i,s:" PY_FMT64 ",s:s,s:s,s:s}",
S_PROPS, df->props,
S_CBSIZE, df->cbsize,
@ -668,6 +650,7 @@ def get_custom_data_format(dtid, dfid):
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_format(int dtid, int fid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
const data_format_t *df = get_custom_data_format(dtid, fid);
if ( df == NULL )
Py_RETURN_NONE;
@ -688,6 +671,7 @@ def get_custom_data_type(dtid):
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_type(int dtid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
const data_type_t *dt = get_custom_data_type(dtid);
if ( dt == NULL )
Py_RETURN_NONE;

View File

@ -168,6 +168,7 @@ private:
static bool idaapi s_popup_cb(void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_popup();
}
@ -179,6 +180,7 @@ private:
if ( it == _global_popup_map.end() )
return false;
PYW_GIL_GET;
return it->second.cv->on_popup_menu(it->second.menu_id);
}
@ -188,6 +190,7 @@ private:
int shift,
void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_keydown(vk_key, shift);
}
@ -195,6 +198,7 @@ private:
// The popup menu is being constructed
static void idaapi s_cv_popup(TCustomControl * /*cv*/, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
_this->on_popup();
}
@ -202,6 +206,7 @@ private:
// The user clicked
static bool idaapi s_cv_click(TCustomControl * /*cv*/, int shift, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_click(shift);
}
@ -209,6 +214,7 @@ private:
// The user double clicked
static bool idaapi s_cv_dblclick(TCustomControl * /*cv*/, int shift, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_dblclick(shift);
}
@ -216,6 +222,7 @@ private:
// Cursor position has been changed
static void idaapi s_cv_curpos(TCustomControl * /*cv*/, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
_this->on_curpos_changed();
}
@ -223,6 +230,8 @@ private:
//--------------------------------------------------------------------------
static int idaapi s_ui_cb(void *ud, int code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
switch ( code )
{
@ -243,11 +252,12 @@ private:
TForm *form = va_arg(va, TForm *);
if ( _this->_form != form )
break;
unhook_from_notification_point(HT_UI, s_ui_cb, _this);
_this->on_close();
_this->on_post_close();
}
// fallthrough...
case ui_term:
unhook_from_notification_point(HT_UI, s_ui_cb, _this);
_this->on_close();
_this->on_post_close();
break;
}
@ -541,6 +551,8 @@ private:
// Convert a tuple (String, [color, [bgcolor]]) to a simpleline_t
static bool py_to_simpleline(PyObject *py, simpleline_t &sl)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_Check(py) )
{
sl.line = PyString_AsString(py);
@ -570,37 +582,29 @@ private:
//
virtual bool on_click(int shift)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift));
PyW_ShowCbErr(S_ON_CLICK);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
// OnDblClick
virtual bool on_dblclick(int shift)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift));
PyW_ShowCbErr(S_ON_DBL_CLICK);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
// OnCurorPositionChanged
virtual void on_curpos_changed()
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, NULL);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, NULL));
PyW_ShowCbErr(S_ON_CURSOR_POS_CHANGED);
Py_XDECREF(py_result);
}
//--------------------------------------------------------------------------
@ -610,12 +614,9 @@ private:
// Call the close method if it is there and the object is still bound
if ( (features & HAVE_CLOSE) != 0 && py_self != NULL )
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, NULL);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLOSE, NULL));
PyW_ShowCbErr(S_ON_CLOSE);
Py_XDECREF(py_result);
// Cleanup
Py_DECREF(py_self);
@ -627,36 +628,31 @@ private:
// OnKeyDown
virtual bool on_keydown(int vk_key, int shift)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_KEYDOWN,
"ii",
vk_key,
shift);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_KEYDOWN,
"ii",
vk_key,
shift));
PyW_ShowCbErr(S_ON_KEYDOWN);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
// OnPopupShow
virtual bool on_popup()
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP,
NULL);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP,
NULL));
PyW_ShowCbErr(S_ON_POPUP);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
@ -664,28 +660,22 @@ private:
virtual bool on_hint(place_t *place, int *important_lines, qstring &hint)
{
size_t ln = data.to_lineno(place);
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_HINT,
PY_FMT64,
pyul_t(ln));
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_HINT,
PY_FMT64,
pyul_t(ln)));
PyW_ShowCbErr(S_ON_HINT);
bool ok = py_result != NULL && PyTuple_Check(py_result) && PyTuple_Size(py_result) == 2;
bool ok = py_result != NULL && PyTuple_Check(py_result.o) && PyTuple_Size(py_result.o) == 2;
if ( ok )
{
// Borrow references
PyObject *py_nlines = PyTuple_GetItem(py_result, 0);
PyObject *py_hint = PyTuple_GetItem(py_result, 1);
if ( important_lines != NULL )
*important_lines = PyInt_AsLong(py_nlines);
hint = PyString_AsString(py_hint);
*important_lines = PyInt_AsLong(PyTuple_GetItem(py_result.o, 0));
hint = PyString_AsString(PyTuple_GetItem(py_result.o, 1));
}
Py_XDECREF(py_result);
return ok;
}
@ -693,18 +683,15 @@ private:
// OnPopupMenuClick
virtual bool on_popup_menu(size_t menu_id)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP_MENU,
PY_FMT64,
pyul_t(menu_id));
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallMethod(
py_self,
(char *)S_ON_POPUP_MENU,
PY_FMT64,
pyul_t(menu_id)));
PyW_ShowCbErr(S_ON_POPUP_MENU);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
//--------------------------------------------------------------------------
@ -776,6 +763,7 @@ public:
place_t *pl;
int x, y;
pl = get_place(mouse, &x, &y);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( pl == NULL )
Py_RETURN_NONE;
return Py_BuildValue("(" PY_FMT64 "ii)", pyul_t(data.to_lineno(pl)), x, y);
@ -786,6 +774,7 @@ public:
PyObject *get_line(size_t nline)
{
simpleline_t *r = data.get_line(nline);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( r == NULL )
Py_RETURN_NONE;
return Py_BuildValue("(sII)", r->line.c_str(), (unsigned int)r->color, (unsigned int)r->bgcolor);
@ -835,6 +824,8 @@ public:
{S_ON_DBL_CLICK, HAVE_DBLCLICK},
{S_ON_CURSOR_POS_CHANGED, HAVE_CURPOS}
};
PYW_GIL_CHECK_LOCKED_SCOPE();
for ( size_t i=0; i<qnumber(cbtable); i++ )
{
if ( PyObject_HasAttrString(py_link, cbtable[i].cb_name) )
@ -892,6 +883,7 @@ public:
PyObject *py_get_selection()
{
size_t x1, y1, x2, y2;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !get_selection(&x1, &y1, &x2, &y2) )
Py_RETURN_NONE;
return Py_BuildValue("(" PY_FMT64 PY_FMT64 PY_FMT64 PY_FMT64 ")", pyul_t(x1), pyul_t(y1), pyul_t(x2), pyul_t(y2));
@ -899,6 +891,7 @@ public:
static py_simplecustview_t *get_this(PyObject *py_this)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_Check(py_this) ? (py_simplecustview_t *) PyCObject_AsVoidPtr(py_this) : NULL;
}
@ -920,6 +913,7 @@ public:
//
PyObject *pyscv_init(PyObject *py_link, const char *title)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_simplecustview_t *_this = new py_simplecustview_t();
bool ok = _this->init(py_link, title);
if ( !ok )
@ -964,6 +958,7 @@ bool pyscv_refresh_current(PyObject *py_this)
PyObject *pyscv_get_current_line(PyObject *py_this, bool mouse, bool notags)
{
DECL_THIS;
PYW_GIL_CHECK_LOCKED_SCOPE();
const char *line;
if ( _this == NULL || (line = _this->get_current_line(mouse, notags)) == NULL )
Py_RETURN_NONE;
@ -1024,7 +1019,10 @@ PyObject *pyscv_get_line(PyObject *py_this, size_t nline)
{
DECL_THIS;
if ( _this == NULL )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
return _this->get_line(nline);
}
@ -1034,7 +1032,10 @@ PyObject *pyscv_get_pos(PyObject *py_this, bool mouse)
{
DECL_THIS;
if ( _this == NULL )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
return _this->get_pos(mouse);
}
@ -1044,6 +1045,7 @@ PyObject *pyscv_clear_lines(PyObject *py_this)
DECL_THIS;
if ( _this != NULL )
_this->clear();
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
@ -1081,7 +1083,10 @@ PyObject *pyscv_get_selection(PyObject *py_this)
{
DECL_THIS;
if ( _this == NULL )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
return _this->py_get_selection();
}
@ -1089,6 +1094,7 @@ PyObject *pyscv_get_selection(PyObject *py_this)
PyObject *pyscv_get_current_word(PyObject *py_this, bool mouse)
{
DECL_THIS;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( _this != NULL )
{
qstring word;

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,8 @@ static bool dbg_can_query()
//-------------------------------------------------------------------------
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_list = PyList_New(areas.size());
meminfo_vec_t::const_iterator it, it_end(areas.end());
Py_ssize_t i = 0;
@ -42,6 +44,8 @@ PyObject *py_appcall(
PyObject *py_fields,
PyObject *arg_list)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyList_Check(arg_list) )
return NULL;
@ -57,11 +61,11 @@ PyObject *py_appcall(
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
borref_t py_item(PyList_GetItem(arg_list, i));
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
qstring s;
PyW_ObjectToString(py_item, &s);
PyW_ObjectToString(py_item.o, &s);
msg("obj[%d]->%s\n", int(i), s.c_str());
}
// Convert it
@ -81,6 +85,10 @@ PyObject *py_appcall(
return NULL;
}
error_t ret;
idc_value_t idc_result;
Py_BEGIN_ALLOW_THREADS;
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("input variables:\n"
@ -96,8 +104,7 @@ PyObject *py_appcall(
}
// Do Appcall
idc_value_t idc_result;
error_t ret = appcall(
ret = appcall(
func_ea,
tid,
(type_t *)type,
@ -106,16 +113,17 @@ PyObject *py_appcall(
idc_args.begin(),
&idc_result);
Py_END_ALLOW_THREADS;
if ( ret != eOk )
{
// An exception was thrown?
if ( ret == eExecThrow )
{
// Convert the result (which is a debug_event) into a Python object
PyObject *py_appcall_exc(NULL);
ref_t py_appcall_exc;
idcvar_to_pyvar(idc_result, &py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc);
Py_DECREF(py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc.o);
return NULL;
}
// An error in the Appcall? (or an exception but AppCallOptions/DEBEV is not set)
@ -145,7 +153,7 @@ PyObject *py_appcall(
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
borref_t py_item(PyList_GetItem(arg_list, i));
// We convert arguments but fail only on fatal errors
// (we ignore failure because of immutable objects)
if ( idcvar_to_pyvar(idc_args[i], &py_item) == CIP_FAILED )
@ -155,13 +163,13 @@ PyObject *py_appcall(
}
}
// Convert the result from IDC back to Python
PyObject *py_result(NULL);
ref_t py_result;
if ( idcvar_to_pyvar(idc_result, &py_result) <= CIP_IMMUTABLE )
{
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC return value to Python return value");
return NULL;
}
QASSERT(30413, py_result.o->ob_refcnt == 1);
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("return var:\n"
@ -170,7 +178,8 @@ PyObject *py_appcall(
VarPrint(&s, &idc_result);
msg("%s\n-----------\n", s.c_str());
}
return py_result;
py_result.incref();
return py_result.o;
}
//</code(py_idd)>
@ -193,6 +202,8 @@ def dbg_get_registers():
*/
static PyObject *dbg_get_registers()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dbg == NULL )
Py_RETURN_NONE;
@ -251,6 +262,8 @@ def dbg_get_thread_sreg_base(tid, sreg_value):
*/
static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) )
Py_RETURN_NONE;
ea_t answer;
@ -277,6 +290,8 @@ def dbg_read_memory(ea, sz):
*/
static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 ea, sz;
if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) )
Py_RETURN_NONE;
@ -314,6 +329,8 @@ def dbg_write_memory(ea, buffer):
*/
static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 ea;
if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) )
Py_RETURN_NONE;
@ -338,6 +355,8 @@ def dbg_get_name():
*/
static PyObject *dbg_get_name()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dbg == NULL )
Py_RETURN_NONE;
else
@ -359,15 +378,19 @@ def dbg_get_memory_info():
*/
static PyObject *dbg_get_memory_info()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() )
Py_RETURN_NONE;
// Invalidate memory
meminfo_vec_t areas;
Py_BEGIN_ALLOW_THREADS;
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
meminfo_vec_t areas;
get_dbg_memory_info(&areas);
Py_END_ALLOW_THREADS;
return meminfo_vec_t_to_py(areas);
}
@ -459,6 +482,7 @@ static PyObject *refresh_debugger_memory()
// Invalidate the cache
isEnabled(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
@ -466,74 +490,78 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
public:
virtual ~DBG_Hooks() { unhook(); };
virtual ~DBG_Hooks() { unhook(); }
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); };
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); };
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); }
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); }
/* Hook functions to be overridden in Python */
virtual void dbg_process_start(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
asize_t size) {}
virtual void dbg_process_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
int exit_code) {}
virtual void dbg_process_attach(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
asize_t size) {}
virtual void dbg_process_detach(pid_t pid,
thid_t tid,
ea_t ea) { };
ea_t ea) {}
virtual void dbg_thread_start(pid_t pid,
thid_t tid,
ea_t ea) { };
ea_t ea) {}
virtual void dbg_thread_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
int exit_code) {}
virtual void dbg_library_load(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
asize_t size) {}
virtual void dbg_library_unload(pid_t pid,
thid_t tid,
ea_t ea,
char *libname) { };
char *libname) {}
virtual void dbg_information(pid_t pid,
thid_t tid,
ea_t ea,
char *info) { };
char *info) {}
virtual int dbg_exception(pid_t pid,
thid_t tid,
ea_t ea,
int code,
bool can_cont,
ea_t exc_ea,
char *info) { return 0; };
virtual void dbg_suspend_process(void) { };
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; };
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; };
char *info) { return 0; }
virtual void dbg_suspend_process(void) {}
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; }
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; }
virtual void dbg_request_error(int failed_command,
int failed_dbg_notification) { };
virtual void dbg_step_into(void) { };
virtual void dbg_step_over(void) { };
virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) { };
virtual void dbg_step_until_ret(void) { };
int failed_dbg_notification) {}
virtual void dbg_step_into(void) {}
virtual void dbg_step_over(void) {}
virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) {}
virtual void dbg_step_until_ret(void) {}
};
int idaapi DBG_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class DBG_Hooks *proxy = (class DBG_Hooks *)ud;
debug_event_t *event;
int code = 0;
try
{
switch (notification_code)

7
pywraps/py_dbg.py Normal file
View File

@ -0,0 +1,7 @@
#<pycode(py_idd_2)>
NO_PROCESS = 0xFFFFFFFF
NO_THREAD = 0
#</pycode(py_idd_2)>

View File

@ -5,17 +5,17 @@
//--------------------------------------------------------------------------
int idaapi py_enumerate_files_cb(const char *file, void *ud)
{
PyObject *py_file = PyString_FromString(file);
PYW_GIL_ENSURE;
PyObject *py_ret = PyObject_CallFunctionObjArgs(
(PyObject *)ud,
py_file,
NULL);
PYW_GIL_RELEASE;
int r = (py_ret == NULL || !PyNumber_Check(py_ret)) ? 1 /* stop enumeration on failure */ : PyInt_AsLong(py_ret);
Py_XDECREF(py_file);
Py_XDECREF(py_ret);
return r;
// No need to 'PYW_GIL_GET' here, as this is called synchronously
// and from the same thread as the one that executes
// 'py_enumerate_files'.
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_file(PyString_FromString(file));
newref_t py_ret(
PyObject_CallFunctionObjArgs(
(PyObject *)ud,
py_file.o,
NULL));
return (py_ret == NULL || !PyNumber_Check(py_ret.o)) ? 1 /* stop enum on failure */ : PyInt_AsLong(py_ret.o);
}
//</code(py_diskio)>
@ -31,7 +31,7 @@ def enumerate_files(path, fname, callback):
@param callback: a callable object that takes the filename as
its first argument and it returns 0 to continue
enumeration or non-zero to stop enumeration.
@return:
@return:
None in case of script errors
tuple(code, fname) : If the callback returns non-zero
"""
@ -40,6 +40,8 @@ def enumerate_files(path, fname, callback):
*/
PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
if ( !PyString_Check(path) || !PyString_Check(fname) || !PyCallable_Check(callback) )

View File

@ -9,10 +9,12 @@ struct py_idcfunc_ctx_t
int nargs;
py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_INCREF(py_func);
}
~py_idcfunc_ctx_t()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_DECREF(py_func);
}
};
@ -26,25 +28,25 @@ static error_t py_call_idc_func(
// Convert IDC arguments to Python list
py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx;
int cvt;
ppyobject_vec_t pargs;
char errbuf[MAXSTR];
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, NULL, errbuf, sizeof(errbuf)) )
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_vec_t pargs;
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, true, errbuf, sizeof(errbuf)) )
{
// Error during conversion? Create an IDC exception
return PyW_CreateIdcException(r, errbuf);
}
// Call the Python function
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallObject(
ctx->py_func,
pargs.empty() ? NULL : pargs[0]);
newref_t py_result(PyObject_CallObject(
ctx->py_func,
pargs.empty() ? NULL : pargs[0].o));
error_t err;
if ( PyW_GetError(errbuf, sizeof(errbuf)) )
{
err = PyW_CreateIdcException(r, errbuf);
Py_XDECREF(py_result);
}
else
{
@ -55,13 +57,7 @@ static error_t py_call_idc_func(
err = PyW_CreateIdcException(r, "ERROR: bad return value");
else
err = eOk;
if ( cvt != CIP_OK_NODECREF )
Py_XDECREF(py_result);
}
PYW_GIL_RELEASE;
// Free the converted args
pyw_free_idc_args(pargs);
return err;
}
@ -153,4 +149,4 @@ bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize)
}
//</inline(py_expr)>
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#<pycode(py_graph)>
class GraphViewer(object):
class GraphViewer(CustomIDAMemo):
"""This class wraps the user graphing facility provided by the graph.hpp file"""
def __init__(self, title, close_open = False):
"""
@ -52,12 +52,6 @@ class GraphViewer(object):
"""
_idaapi.pyg_close(self)
def Refresh(self):
"""
Refreshes the graph. This causes the OnRefresh() to be called
"""
_idaapi.pyg_refresh(self)
def Show(self):
"""
Shows an existing graph or creates a new one
@ -166,4 +160,4 @@ class GraphViewer(object):
# """
# print "command:", cmd_id
#</pydoc>
#</pycode(py_graph)>
#</pycode(py_graph)>

View File

@ -53,11 +53,23 @@ static const char S_ON_GETTEXT[] = "OnGetText";
static const char S_ON_ACTIVATE[] = "OnActivate";
static const char S_ON_DEACTIVATE[] = "OnDeactivate";
static const char S_ON_SELECT[] = "OnSelect";
static const char S_ON_CREATING_GROUP[] = "OnCreatingGroup";
static const char S_ON_DELETING_GROUP[] = "OnDeletingGroup";
static const char S_ON_GROUP_VISIBILITY[] = "OnGroupVisibility";
static const char S_M_EDGES[] = "_edges";
static const char S_M_NODES[] = "_nodes";
static const char S_M_THIS[] = "_this";
static const char S_M_TITLE[] = "_title";
static const char S_CLINK_NAME[] = "__clink__";
static const char S_ON_VIEW_ACTIVATED[] = "OnViewActivated";
static const char S_ON_VIEW_DEACTIVATED[] = "OnViewDeactivated";
static const char S_ON_VIEW_KEYDOWN[] = "OnViewKeydown";
static const char S_ON_VIEW_CLICK[] = "OnViewClick";
static const char S_ON_VIEW_DBLCLICK[] = "OnViewDblclick";
static const char S_ON_VIEW_CURPOS[] = "OnViewCurpos";
static const char S_ON_VIEW_SWITCHED[] = "OnViewSwitched";
static const char S_ON_VIEW_MOUSE_OVER[] = "OnViewMouseOver";
#ifdef __PYWRAPS__
static const char S_PY_IDAAPI_MODNAME[] = "__main__";
@ -66,7 +78,7 @@ static const char S_PY_IDAAPI_MODNAME[] = S_IDAAPI_MODNAME;
#endif
//------------------------------------------------------------------------
static PyObject *py_cvt_helper_module = NULL;
static ref_t py_cvt_helper_module;
static bool pywraps_initialized = false;
//---------------------------------------------------------------------------
@ -155,19 +167,16 @@ static error_t idaapi idc_py_invoke0(
idc_value_t *argv,
idc_value_t *res)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *pyfunc = (PyObject *) argv[0].pvoid;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(pyfunc, NULL);
PYW_GIL_RELEASE;
Py_XDECREF(py_result);
newref_t py_result(PyObject_CallFunctionObjArgs(pyfunc, NULL));
// Report Python error as IDC exception
qstring err;
error_t err_code = eOk;
if ( PyW_GetError(&err) )
return PyW_CreateIdcException(res, err.c_str());
return eOk;
err_code = PyW_CreateIdcException(res, err.c_str());
return err_code;
}
//------------------------------------------------------------------------
@ -223,8 +232,11 @@ void deinit_pywraps()
return;
pywraps_initialized = false;
Py_XDECREF(py_cvt_helper_module);
py_cvt_helper_module = NULL;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
py_cvt_helper_module = ref_t(); // Deref.
}
// Unregister the IDC PyInvoke0 method (helper function for add_idc_hotkey())
set_idc_func_ex(S_PYINVOKE0, NULL, idc_py_invoke0_args, 0);
@ -232,47 +244,34 @@ void deinit_pywraps()
//------------------------------------------------------------------------
// Utility function to create a class instance whose constructor takes zero arguments
PyObject *create_idaapi_class_instance0(const char *clsname)
ref_t create_idaapi_class_instance0(const char *clsname)
{
PyObject *py_cls = get_idaapi_attr(clsname);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_cls(get_idaapi_attr(clsname));
if ( py_cls == NULL )
return NULL;
return ref_t();
PYW_GIL_ENSURE;
PyObject *py_obj = PyObject_CallFunctionObjArgs(py_cls, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_cls);
ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL));
if ( PyW_GetError() || py_obj == NULL )
{
Py_XDECREF(py_obj);
Py_RETURN_NONE;
}
py_obj = ref_t();
return py_obj;
}
//------------------------------------------------------------------------
// Utility function to create linked class instances
PyObject *create_idaapi_linked_class_instance(
ref_t create_idaapi_linked_class_instance(
const char *clsname,
void *lnk)
{
PyObject *py_cls = get_idaapi_attr(clsname);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_cls(get_idaapi_attr(clsname));
if ( py_cls == NULL )
return NULL;
PyObject *py_lnk = PyCObject_FromVoidPtr(lnk, NULL);
PYW_GIL_ENSURE;
PyObject *py_obj = PyObject_CallFunctionObjArgs(py_cls, py_lnk, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_cls);
Py_DECREF(py_lnk);
return ref_t();
newref_t py_lnk(PyCObject_FromVoidPtr(lnk, NULL));
ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, py_lnk.o, NULL));
if ( PyW_GetError() || py_obj == NULL )
{
Py_XDECREF(py_obj);
py_obj = NULL;
}
py_obj = ref_t();
return py_obj;
}
@ -280,10 +279,10 @@ PyObject *create_idaapi_linked_class_instance(
// Gets a class type reference in idaapi
// With the class type reference we can create a new instance of that type
// This function takes a reference to the idaapi module and keeps the reference
PyObject *get_idaapi_attr_by_id(const int class_id)
ref_t get_idaapi_attr_by_id(const int class_id)
{
if ( class_id >= PY_CLSID_LAST || py_cvt_helper_module == NULL )
return NULL;
return ref_t();
// Some class names. The array is parallel with the PY_CLSID_xxx consts
static const char *class_names[]=
@ -292,16 +291,18 @@ PyObject *get_idaapi_attr_by_id(const int class_id)
"object_t",
"PyIdc_cvt_refclass__"
};
return PyObject_GetAttrString(py_cvt_helper_module, class_names[class_id]);
PYW_GIL_CHECK_LOCKED_SCOPE();
return newref_t(PyObject_GetAttrString(py_cvt_helper_module.o, class_names[class_id]));
}
//------------------------------------------------------------------------
// Gets a class reference by name
PyObject *get_idaapi_attr(const char *attrname)
ref_t get_idaapi_attr(const char *attrname)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return py_cvt_helper_module == NULL
? NULL
: PyW_TryGetAttrString(py_cvt_helper_module, attrname);
? ref_t()
: PyW_TryGetAttrString(py_cvt_helper_module.o, attrname);
}
//------------------------------------------------------------------------
@ -311,41 +312,39 @@ bool PyW_GetStringAttr(
const char *attr_name,
qstring *str)
{
PyObject *py_attr = PyW_TryGetAttrString(py_obj, attr_name);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_attr(PyW_TryGetAttrString(py_obj, attr_name));
if ( py_attr == NULL )
return false;
bool ok = PyString_Check(py_attr) != 0;
bool ok = PyString_Check(py_attr.o) != 0;
if ( ok )
*str = PyString_AsString(py_attr);
*str = PyString_AsString(py_attr.o);
Py_DECREF(py_attr);
return ok;
}
//------------------------------------------------------------------------
// Returns an attribute or NULL
// No errors will be set if the attribute did not exist
PyObject *PyW_TryGetAttrString(PyObject *py_obj, const char *attr)
ref_t PyW_TryGetAttrString(PyObject *py_obj, const char *attr)
{
if ( !PyObject_HasAttrString(py_obj, attr) )
return NULL;
else
return PyObject_GetAttrString(py_obj, attr);
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t o;
if ( PyObject_HasAttrString(py_obj, attr) )
o = newref_t(PyObject_GetAttrString(py_obj, attr));
return o;
}
//------------------------------------------------------------------------
// Tries to import a module and clears the exception on failure
PyObject *PyW_TryImportModule(const char *name)
ref_t PyW_TryImportModule(const char *name)
{
PYW_GIL_ENSURE;
PyObject *result = PyImport_ImportModule(name);
PYW_GIL_RELEASE;
if ( result != NULL )
return result;
if ( PyErr_Occurred() )
PyErr_Clear();
return NULL;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t result(PyImport_ImportModule(name));
if ( result == NULL && PyErr_Occurred() )
PyErr_Clear();
return result;
}
//-------------------------------------------------------------------------
@ -358,144 +357,158 @@ PyObject *PyW_TryImportModule(const char *name)
// And because of that we are confused as to whether to convert to 32 or 64
bool PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var)
{
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
return false;
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
do
{
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
{
rc = false;
break;
}
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
idc_var->set_long(l);
return true;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
l = (long) PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() )
{
idc_var->set_long(l);
return true;
}
PyErr_Clear();
idc_var->set_int64(PyLong_AsLongLong(py_var));
return true;
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
idc_var->set_long(l);
break;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
l = (long) PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() )
{
idc_var->set_long(l);
break;
}
PyErr_Clear();
idc_var->set_int64(PyLong_AsLongLong(py_var));
} while ( false );
return rc;
}
//-------------------------------------------------------------------------
// Parses a Python object as a long or long long
bool PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64)
{
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
return false;
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
#define SETNUM(numexpr, is64_expr) \
do \
{ \
if ( num != NULL ) \
*num = numexpr; \
if ( is_64 != NULL ) \
*is_64 = is64_expr; \
} while ( false )
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
do
{
if ( num != NULL )
*num = uint64(l);
if ( is_64 != NULL )
*is_64 = false;
return true;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() )
{
if ( num != NULL )
*num = uint64(ul);
if ( is_64 != NULL )
*is_64 = false;
return true;
}
PyErr_Clear();
// Try to parse as int64
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if ( !PyErr_Occurred() )
{
if ( num != NULL )
*num = uint64(ll);
if ( is_64 != NULL )
*is_64 = true;
return true;
}
PyErr_Clear();
// Try to parse as uint64
unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var);
PyObject *err = PyErr_Occurred();
if ( err == NULL )
{
if ( num != NULL )
*num = uint64(ull);
if ( is_64 != NULL )
*is_64 = true;
return true;
}
// Negative number? _And_ it with uint64(-1)
bool ok = false;
if ( err == PyExc_TypeError )
{
PyObject *py_mask = Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull);
PyObject *py_num = PyNumber_And(py_var, py_mask);
if ( py_num != NULL && py_mask != NULL )
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
{
PyErr_Clear();
ull = PyLong_AsUnsignedLongLong(py_num);
if ( !PyErr_Occurred() )
rc = false;
break;
}
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(l), false);
break;
}
// Clear last error
PyErr_Clear();
// Can be fit into a C unsigned long?
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(ul), false);
break;
}
PyErr_Clear();
// Try to parse as int64
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(ll), true);
break;
}
PyErr_Clear();
// Try to parse as uint64
unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var);
PyObject *err = PyErr_Occurred();
if ( err == NULL )
{
SETNUM(uint64(ull), true);
break;
}
// Negative number? _And_ it with uint64(-1)
rc = false;
if ( err == PyExc_TypeError )
{
newref_t py_mask(Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull));
newref_t py_num(PyNumber_And(py_var, py_mask.o));
if ( py_num != NULL && py_mask != NULL )
{
if ( num != NULL )
*num = uint64(ull);
if ( is_64 != NULL )
*is_64 = true;
ok = true;
PyErr_Clear();
ull = PyLong_AsUnsignedLongLong(py_num.o);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(ull), true);
rc = true;
}
}
}
Py_XDECREF(py_num);
Py_XDECREF(py_mask);
}
PyErr_Clear();
return ok;
PyErr_Clear();
} while ( false );
return rc;
#undef SETNUM
}
//-------------------------------------------------------------------------
// Checks if a given object is of sequence type
bool PyW_IsSequenceType(PyObject *obj)
{
if ( !PySequence_Check(obj) )
return false;
Py_ssize_t sz = PySequence_Size(obj);
if ( sz == -1 || PyErr_Occurred() != NULL )
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
do
{
PyErr_Clear();
return false;
}
return true;
if ( !PySequence_Check(obj) )
{
rc = false;
break;
}
Py_ssize_t sz = PySequence_Size(obj);
if ( sz == -1 || PyErr_Occurred() != NULL )
{
PyErr_Clear();
rc = false;
break;
}
} while ( false );
return rc;
}
//-------------------------------------------------------------------------
// Returns the string representation of an object
bool PyW_ObjectToString(PyObject *obj, qstring *out)
{
PyObject *py_str = PyObject_Str(obj);
if ( py_str != NULL )
{
*out = PyString_AsString(py_str);
Py_DECREF(py_str);
return true;
}
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_str(PyObject_Str(obj));
bool ok = py_str != NULL;
if ( ok )
*out = PyString_AsString(py_str.o);
else
{
out->qclear();
return false;
}
return ok;
}
//--------------------------------------------------------------------------
@ -503,6 +516,8 @@ bool PyW_ObjectToString(PyObject *obj, qstring *out)
// exception string
bool PyW_GetError(qstring *out, bool clear_err)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() == NULL )
return false;
@ -523,23 +538,18 @@ bool PyW_GetError(qstring *out, bool clear_err)
PyErr_Restore(err_type, err_value, err_traceback);
// Resolve FormatExc()
PyObject *py_fmtexc = get_idaapi_attr(S_IDAAPI_FORMATEXC);
ref_t py_fmtexc(get_idaapi_attr(S_IDAAPI_FORMATEXC));
// Helper there?
if ( py_fmtexc != NULL )
{
// Call helper
PYW_GIL_ENSURE;
py_ret = PyObject_CallFunctionObjArgs(
py_fmtexc,
py_fmtexc.o,
err_type,
err_value,
err_traceback,
NULL);
PYW_GIL_RELEASE;
// Dispose helper reference
Py_DECREF(py_fmtexc);
}
// Clear the error
@ -576,6 +586,8 @@ bool PyW_GetError(qstring *out, bool clear_err)
//-------------------------------------------------------------------------
bool PyW_GetError(char *buf, size_t bufsz, bool clear_err)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstring s;
if ( !PyW_GetError(&s, clear_err) )
return false;
@ -589,6 +601,8 @@ bool PyW_GetError(char *buf, size_t bufsz, bool clear_err)
// This method is used to display errors that occurred in a callback
bool PyW_ShowCbErr(const char *cb_name)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
static qstring err_str;
if ( !PyW_GetError(&err_str) )
return false;
@ -600,10 +614,11 @@ bool PyW_ShowCbErr(const char *cb_name)
//---------------------------------------------------------------------------
void *pyobj_get_clink(PyObject *pyobj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Try to query the link attribute
PyObject *attr = PyW_TryGetAttrString(pyobj, S_CLINK_NAME);
void *t = attr != NULL && PyCObject_Check(attr) ? PyCObject_AsVoidPtr(attr) : NULL;
Py_XDECREF(attr);
ref_t attr(PyW_TryGetAttrString(pyobj, S_CLINK_NAME));
void *t = attr != NULL && PyCObject_Check(attr.o) ? PyCObject_AsVoidPtr(attr.o) : NULL;
return t;
}
@ -624,8 +639,10 @@ def parse_command_line(cmdline):
*/
static PyObject *py_parse_command_line(const char *cmdline)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t args;
if ( parse_command_line2(cmdline, &args, NULL) == 0 )
if ( parse_command_line3(cmdline, &args, NULL, LP_PATH_WITH_ARGS) == 0 )
Py_RETURN_NONE;
PyObject *py_list = PyList_New(args.size());
@ -727,6 +744,7 @@ static bool qstrvec_t_assign(PyObject *self, PyObject *other)
static PyObject *qstrvec_t_addressof(PyObject *self, size_t idx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t *sv = qstrvec_t_get_clink(self);
if ( sv == NULL || idx >= sv->size() )
Py_RETURN_NONE;
@ -751,6 +769,7 @@ static bool qstrvec_t_from_list(
PyObject *self,
PyObject *py_list)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t *sv = qstrvec_t_get_clink(self);
return sv == NULL ? false : PyW_PyListToStrVec(py_list, *sv);
}
@ -763,6 +782,7 @@ static size_t qstrvec_t_size(PyObject *self)
static PyObject *qstrvec_t_get(PyObject *self, size_t idx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstrvec_t *sv = qstrvec_t_get_clink(self);
if ( sv == NULL || idx >= sv->size() )
Py_RETURN_NONE;

View File

@ -18,6 +18,36 @@ import os
import sys
import bisect
import __builtin__
import imp
def require(modulename):
"""
Load, or reload a module.
When under heavy development, a user's tool might consist of multiple
modules. If those are imported using the standard 'import' mechanism,
there is no guarantee that the Python implementation will re-read
and re-evaluate the module's Python code. In fact, it usually doesn't.
What should be done instead is 'reload()'-ing that module.
This is a simple helper function that will do just that: In case the
module doesn't exist, it 'import's it, and if it does exist,
'reload()'s it.
For more information, see: <http://www.hexblog.com/?p=749>.
"""
if modulename in sys.modules.keys():
reload(sys.modules[modulename])
else:
import importlib
import inspect
m = importlib.import_module(modulename)
frame_obj, filename, line_number, function_name, lines, index = inspect.stack()[1]
importer_module = inspect.getmodule(frame_obj)
if importer_module is None: # No importer module; called from command line
importer_module = sys.modules['__main__']
setattr(importer_module, modulename, m)
sys.modules[modulename] = m
# -----------------------------------------------------------------------
@ -403,11 +433,7 @@ def IDAPython_ExecScript(script, g):
if len(scriptpath) and scriptpath not in sys.path:
sys.path.append(scriptpath)
# Save the argv, path, I/O and base modules for later cleanup
argv = sys.argv
path = sys.path
stdio = [sys.stdin, sys.stdout, sys.stderr]
basemodules = sys.modules.copy()
sys.argv = [ script ]
# Adjust the __file__ path in the globals we pass to the script
@ -421,18 +447,65 @@ def IDAPython_ExecScript(script, g):
PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc())
print(PY_COMPILE_ERR)
finally:
# Restore the globals to the state before the script was run
# Restore state
g['__file__'] = old__file__
sys.argv = argv
sys.path = path
sys.stdin, sys.stdout, sys.stderr = stdio
# Clean up the modules loaded by the script
for module in sys.modules.keys():
if not module in basemodules:
del sys.modules[module]
return PY_COMPILE_ERR
# ------------------------------------------------------------
def IDAPython_LoadProcMod(script, g):
"""
Load processor module.
"""
pname = g['__name__'] if g and g.has_key("__name__") else '__main__'
parent = sys.modules[pname]
scriptpath, scriptname = os.path.split(script)
if len(scriptpath) and scriptpath not in sys.path:
sys.path.append(scriptpath)
procmod_name = os.path.splitext(scriptname)[0]
procobj = None
fp = None
try:
fp, pathname, description = imp.find_module(procmod_name)
procmod = imp.load_module(procmod_name, fp, pathname, description)
if parent:
setattr(parent, procmod_name, procmod)
# export attrs from parent to processor module
parent_attrs = getattr(parent, '__all__',
(attr for attr in dir(parent) if not attr.startswith('_')))
for pa in parent_attrs:
setattr(procmod, pa, getattr(parent, pa))
# instantiate processor object
if getattr(procmod, 'PROCESSOR_ENTRY', None):
procobj = procmod.PROCESSOR_ENTRY()
PY_COMPILE_ERR = None
except Exception as e:
PY_COMPILE_ERR = "%s\n%s" % (str(e), traceback.format_exc())
print(PY_COMPILE_ERR)
finally:
if fp: fp.close()
sys.path.remove(scriptpath)
return (PY_COMPILE_ERR, procobj)
# ------------------------------------------------------------
def IDAPython_UnLoadProcMod(script, g):
"""
Unload processor module.
"""
pname = g['__name__'] if g and g.has_key("__name__") else '__main__'
parent = sys.modules[pname]
scriptname = os.path.split(script)[1]
procmod_name = os.path.splitext(scriptname)[0]
if getattr(parent, procmod_name, None):
delattr(parent, procmod_name)
del sys.modules[procmod_name]
PY_COMPILE_ERR = None
return PY_COMPILE_ERR
# ----------------------------------------------------------------------

75
pywraps/py_idaview.hpp Normal file
View File

@ -0,0 +1,75 @@
#ifndef __PY_IDA_VIEW__
#define __PY_IDA_VIEW__
//<code(py_idaview)>
class py_idaview_t : public py_customidamemo_t
{
typedef py_customidamemo_t inherited;
public:
static bool Bind(PyObject *self);
};
//-------------------------------------------------------------------------
bool py_idaview_t::Bind(PyObject *self)
{
// Already a py_idaview_t associated to this object?
py_idaview_t *_this = view_extract_this<py_idaview_t>(self);
if ( _this != NULL )
return false;
qstring title;
if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) )
return false;
// Get the IDAView associated to this TForm
TForm *tform = find_tform(title.c_str());
if ( tform == NULL )
return false;
TCustomControl *v = get_tform_idaview(tform);
if ( v == NULL )
return false;
// Get unique py_idaview_t associated to that tform
py_idaview_t *py_view;
TCustomControl *found_view;
if ( lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) )
{
// If we have a py_idaview_t for that form, ensure it has
// the expected view.
QASSERT(30451, found_view == v);
}
else
{
py_view = new py_idaview_t();
lookup_info.add(tform, v, py_view);
}
// Finally, bind:
// py_idaview_t <=> IDAViewWrapper
// py_idaview_t => TCustomControl
bool ok = py_view->bind(self, v);
if ( ok )
{
ok = py_view->collect_pyobject_callbacks(self);
if ( !ok )
delete py_view;
}
return ok;
}
//-------------------------------------------------------------------------
bool pyidag_bind(PyObject *self)
{
return py_idaview_t::Bind(self);
}
//</code(py_idaview)>
//--------------------------------------------------------------------------
//<inline(py_idaview)>
bool pyidag_bind(PyObject *self);
//</inline(py_idaview)>
#endif // __PY_IDA_VIEW__

16
pywraps/py_idaview.py Normal file
View File

@ -0,0 +1,16 @@
#<pycode(py_idaview)>
class IDAViewWrapper(CustomIDAMemo):
"""This class wraps access to native IDA views. See kernwin.hpp file"""
def __init__(self, title):
"""
Constructs the IDAViewWrapper object around the view
whose title is 'title'.
@param title: The title of the existing IDA view. E.g., 'IDA View-A'
"""
self._title = title
def Bind(self):
return _idaapi.pyidag_bind(self)
#</pycode(py_idaview)>

View File

@ -33,12 +33,17 @@ static PyObject *AssembleLine(
{
int inslen;
char buf[MAXSTR];
bool ok = false;
if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
{
return PyString_FromStringAndSize(buf, inslen);
ok = true;
}
Py_RETURN_NONE;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return PyString_FromStringAndSize(buf, inslen);
else
Py_RETURN_NONE;
}
//---------------------------------------------------------------------------
@ -66,17 +71,20 @@ bool assemble(
{
int inslen;
char buf[MAXSTR];
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = false;
Py_BEGIN_ALLOW_THREADS;
if (ph.notify != NULL)
{
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
if (inslen > 0)
{
patch_many_bytes(ea, buf, inslen);
return true;
rc = true;
}
}
return false;
Py_END_ALLOW_THREADS;
return rc;
}
//-------------------------------------------------------------------------
@ -318,6 +326,7 @@ def ph_get_instruc():
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start);
for ( const instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end;
p != end;
@ -341,10 +350,10 @@ def ph_get_regnames():
static PyObject *ph_get_regnames()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
return py_result;
}
@ -372,6 +381,10 @@ static PyObject *ph_get_operand_info(
ea_t ea,
int n)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool ok = false;
idd_opinfo_t opinf;
Py_BEGIN_ALLOW_THREADS;
do
{
if ( dbg == NULL || n == - 1 )
@ -386,7 +399,6 @@ static PyObject *ph_get_operand_info(
break;
// Call the processor module
idd_opinfo_t opinf;
if ( ph.notify(ph.get_operand_info,
ea,
n,
@ -397,14 +409,19 @@ static PyObject *ph_get_operand_info(
{
break;
}
return Py_BuildValue("(i" PY_FMT64 "Kii)",
opinf.modified,
opinf.ea,
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
ok = true;
} while (false);
Py_RETURN_NONE;
Py_END_ALLOW_THREADS;
if ( ok )
return Py_BuildValue("(i" PY_FMT64 "Kii)",
opinf.modified,
opinf.ea,
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
@ -785,6 +802,7 @@ public:
bool /*use32*/,
const char * /*line*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
};
@ -847,6 +865,8 @@ public:
//-------------------------------------------------------------------------
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
IDP_Hooks *proxy = (IDP_Hooks *)ud;
int ret = 0;
try
@ -868,16 +888,16 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
case processor_t::custom_outop:
{
op_t *op = va_arg(va, op_t *);
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
ref_t py_obj(create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op));
if ( py_obj == NULL )
break;
ret = proxy->custom_outop(py_obj) ? 2 : 0;
Py_XDECREF(py_obj);
ret = proxy->custom_outop(py_obj.o) ? 2 : 0;
break;
}
case processor_t::custom_mnem:
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_ret = proxy->custom_mnem();
if ( py_ret != NULL && PyString_Check(py_ret) )
{
@ -1009,6 +1029,7 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
// Extract user buffer (we hardcode the MAXSTR size limit)
uchar *bin = va_arg(va, uchar *);
// Call python
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line);
if ( py_buffer != NULL && PyString_Check(py_buffer) )
{
@ -1328,6 +1349,7 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in IDP Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
@ -1337,6 +1359,9 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
//---------------------------------------------------------------------------
int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
ea_t ea, ea2;
bool repeatable_cmt;
@ -1508,10 +1533,9 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in IDB Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if (PyErr_Occurred())
{
PyErr_Print();
}
}
return 0;
}

View File

@ -24,6 +24,8 @@ def register_timer(interval, callback):
*/
static PyObject *py_register_timer(int interval, PyObject *py_callback)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( py_callback == NULL || !PyCallable_Check(py_callback) )
Py_RETURN_NONE;
@ -32,17 +34,15 @@ static PyObject *py_register_timer(int interval, PyObject *py_callback)
{
static int idaapi callback(void *ud)
{
PYW_GIL_GET;
py_timer_ctx_t *ctx = (py_timer_ctx_t *)ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(ctx->pycallback, NULL);
int ret = py_result == NULL ? -1 : PyLong_AsLong(py_result);
Py_XDECREF(py_result);
PYW_GIL_RELEASE;
newref_t py_result(PyObject_CallFunctionObjArgs(ctx->pycallback, NULL));
int ret = py_result == NULL ? -1 : PyLong_AsLong(py_result.o);
// Timer has been unregistered?
if ( ret == -1 )
{
// Fee the context
// Free the context
Py_DECREF(ctx->pycallback);
delete ctx;
}
@ -83,6 +83,8 @@ def unregister_timer(timer_obj):
*/
static PyObject *py_unregister_timer(PyObject *py_timerctx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( py_timerctx == NULL || !PyCObject_Check(py_timerctx) )
Py_RETURN_FALSE;
@ -111,6 +113,7 @@ def choose_idasgn():
static PyObject *py_choose_idasgn()
{
char *name = choose_idasgn();
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( name == NULL )
{
Py_RETURN_NONE;
@ -140,6 +143,7 @@ static PyObject *py_get_highlighted_identifier(int flags = 0)
{
char buf[MAXSTR];
bool ok = get_highlighted_identifier(buf, sizeof(buf), flags);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !ok )
Py_RETURN_NONE;
else
@ -157,6 +161,7 @@ static int py_load_custom_icon_data(PyObject *data, const char *format)
{
Py_ssize_t len;
char *s;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_AsStringAndSize(data, &s, &len) == -1 )
return 0;
else
@ -191,6 +196,7 @@ def asktext(max_text, defval, prompt):
*/
PyObject *py_asktext(int max_text, const char *defval, const char *prompt)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( max_text <= 0 )
Py_RETURN_NONE;
@ -231,6 +237,26 @@ ea_t py_str2ea(const char *str, ea_t screenEA = BADADDR)
return ok ? ea : BADADDR;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def str2user(str):
"""
Insert C-style escape characters to string
@return: new string with escape characters inserted
"""
pass
#</pydoc>
*/
PyObject *py_str2user(const char *str)
{
qstring qstr(str);
qstring retstr;
qstr2user(&retstr, qstr);
return PyString_FromString(retstr.c_str());
}
//------------------------------------------------------------------------
/*
#<pydoc>
@ -265,6 +291,7 @@ def del_menu_item(menu_ctx):
*/
static bool py_del_menu_item(PyObject *py_ctx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_ctx) )
return false;
@ -297,6 +324,7 @@ def del_hotkey(ctx):
*/
bool py_del_hotkey(PyObject *pyctx)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(pyctx) )
return false;
@ -327,6 +355,7 @@ def add_hotkey(hotkey, pyfunc):
*/
PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Make sure a callable was passed
if ( !PyCallable_Check(pyfunc) )
return NULL;
@ -414,6 +443,7 @@ static PyObject *py_add_menu_item(
PyObject *pyfunc,
PyObject *args)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool no_args;
// No slash in the menu path?
@ -512,55 +542,55 @@ def execute_sync(callable, reqf):
//------------------------------------------------------------------------
static int py_execute_sync(PyObject *py_callable, int reqf)
{
// Not callable?
if ( !PyCallable_Check(py_callable) )
return -1;
struct py_exec_request_t: exec_request_t
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc = -1;
// Callable?
if ( PyCallable_Check(py_callable) )
{
PyObject *py_callable;
bool no_wait;
virtual int idaapi execute()
struct py_exec_request_t : exec_request_t
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callable, NULL);
int r = py_result == NULL || !PyInt_Check(py_result) ? -1 : PyInt_AsLong(py_result);
Py_XDECREF(py_result);
PYW_GIL_RELEASE;
ref_t py_callable;
virtual int idaapi execute()
{
PYW_GIL_GET;
newref_t py_result(PyObject_CallFunctionObjArgs(py_callable.o, NULL));
int ret = py_result == NULL || !PyInt_Check(py_result.o)
? -1
: PyInt_AsLong(py_result.o);
// if the requesting thread decided not to wait for the request to
// complete, we have to self-destroy, nobody else will do it
if ( (code & MFF_NOWAIT) != 0 )
delete this;
return ret;
}
py_exec_request_t(PyObject *pyc)
{
// No need to GIL-ensure here, since this is created
// within the py_execute_sync() scope.
py_callable = borref_t(pyc);
}
virtual ~py_exec_request_t()
{
// Need to GIL-ensure here, since this might be called
// from the main thread.
PYW_GIL_GET;
py_callable = ref_t(); // Release callable
}
};
py_exec_request_t *req = new py_exec_request_t(py_callable);
// Free this request
if ( no_wait )
delete this;
return r;
}
py_exec_request_t(PyObject *pyc, bool no_wait):
py_callable(pyc), no_wait(no_wait)
{
// Take reference to the callable
Py_INCREF(py_callable);
}
virtual ~py_exec_request_t()
{
// Release callable
Py_XDECREF(py_callable);
}
};
bool no_wait = (reqf & MFF_NOWAIT) != 0;
// Allocate a request
py_exec_request_t *req = new py_exec_request_t(py_callable, no_wait);
// Execute it
int r = execute_sync(*req, reqf);
// Delete only if NOWAIT was not specified
// (Otherwise the request will delete itself)
if ( !no_wait )
delete req;
return r;
// Release GIL before executing, or if this is running in the
// non-main thread, this will wait on the req.sem, while the main
// thread might be waiting for the GIL to be available.
Py_BEGIN_ALLOW_THREADS;
rc = execute_sync(*req, reqf);
Py_END_ALLOW_THREADS;
// destroy the request once it is finished. exception: NOWAIT requests
// will be handled in the future, so do not destroy them yet!
if ( (reqf & MFF_NOWAIT) == 0 )
delete req;
}
return rc;
}
//------------------------------------------------------------------------
@ -585,23 +615,22 @@ static bool py_execute_ui_requests(PyObject *py_list)
struct py_ui_request_t: public ui_request_t
{
private:
ppyobject_vec_t py_callables;
ref_vec_t py_callables;
size_t py_callable_idx;
static int idaapi s_py_list_walk_cb(
PyObject *py_item,
Py_ssize_t index,
void *ud)
const ref_t &py_item,
Py_ssize_t index,
void *ud)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Not callable? Terminate iteration
if ( !PyCallable_Check(py_item) )
if ( !PyCallable_Check(py_item.o) )
return CIP_FAILED;
// Append this callable and increment its reference
py_ui_request_t *_this = (py_ui_request_t *)ud;
_this->py_callables.push_back(py_item);
Py_INCREF(py_item);
return CIP_OK;
}
public:
@ -611,14 +640,13 @@ static bool py_execute_ui_requests(PyObject *py_list)
virtual bool idaapi run()
{
// Get callable
PyObject *py_callable = py_callables.at(py_callable_idx);
PYW_GIL_GET;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callable, NULL);
bool reschedule = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
PYW_GIL_RELEASE;
// Get callable
ref_t py_callable = py_callables.at(py_callable_idx);
bool reschedule;
newref_t py_result(PyObject_CallFunctionObjArgs(py_callable.o, NULL));
reschedule = py_result != NULL && PyObject_IsTrue(py_result.o);
// No rescheduling? Then advance to the next callable
if ( !reschedule )
@ -640,13 +668,7 @@ static bool py_execute_ui_requests(PyObject *py_list)
virtual idaapi ~py_ui_request_t()
{
// Release all callables
for ( ppyobject_vec_t::const_iterator it=py_callables.begin();
it != py_callables.end();
++it )
{
Py_XDECREF(*it);
}
py_callables.clear();
}
};
@ -809,6 +831,7 @@ public:
virtual PyObject *get_ea_hint(ea_t /*ea*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
};
};
@ -821,6 +844,8 @@ public:
//---------------------------------------------------------------------------
int idaapi UI_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
UI_Hooks *proxy = (UI_Hooks *)ud;
int ret = 0;
try
@ -857,6 +882,7 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
char *_buf;
Py_ssize_t _len;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_str = proxy->get_ea_hint(ea);
if ( py_str != NULL
&& PyString_Check(py_str)
@ -872,6 +898,7 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in UI Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
@ -881,15 +908,15 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
//------------------------------------------------------------------------
bool idaapi py_menu_item_callback(void *userdata)
{
PYW_GIL_GET;
// userdata is a tuple of ( func, args )
// func and args are borrowed references from userdata
PyObject *func = PyTuple_GET_ITEM(userdata, 0);
PyObject *args = PyTuple_GET_ITEM(userdata, 1);
// Call the python function
PYW_GIL_ENSURE;
PyObject *result = PyEval_CallObject(func, args);
PYW_GIL_RELEASE;
newref_t result(PyEval_CallObject(func, args));
// We cannot raise an exception in the callback, just print it.
if ( result == NULL )
@ -898,10 +925,8 @@ bool idaapi py_menu_item_callback(void *userdata)
return false;
}
bool ret = PyObject_IsTrue(result) != 0;
Py_DECREF(result);
return ret;
return PyObject_IsTrue(result.o) != 0;
}
//</code(py_kernwin)>
#endif
#endif

View File

@ -12,10 +12,12 @@ static void idaapi s_py_get_user_defined_prefix(
char *buf,
size_t bufsize)
{
PyObject *py_ret = PyObject_CallFunction(
py_get_user_defined_prefix,
PY_FMT64 "iis" PY_FMT64,
ea, lnnum, indent, line, bufsize);
PYW_GIL_GET;
newref_t py_ret(
PyObject_CallFunction(
py_get_user_defined_prefix,
PY_FMT64 "iis" PY_FMT64,
ea, lnnum, indent, line, bufsize));
// Error? Display it
// No error? Copy the buffer
@ -23,14 +25,13 @@ static void idaapi s_py_get_user_defined_prefix(
{
Py_ssize_t py_len;
char *py_str;
if ( PyString_AsStringAndSize(py_ret, &py_str, &py_len) != -1 )
if ( PyString_AsStringAndSize(py_ret.o, &py_str, &py_len) != -1 )
{
memcpy(buf, py_str, qmin(bufsize, py_len));
if ( py_len < bufsize )
buf[py_len] = '\0';
}
}
Py_XDECREF(py_ret);
}
//</code(py_lines)>
@ -65,6 +66,7 @@ def set_user_defined_prefix(width, callback):
*/
static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( width == 0 || pycb == Py_None )
{
// Release old callback reference
@ -110,6 +112,7 @@ def tag_remove(colstr):
*/
PyObject *py_tag_remove(const char *instr)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
size_t sz = strlen(instr);
char *buf = new char[sz + 5];
if ( buf == NULL )
@ -135,6 +138,7 @@ PyObject *py_tag_addr(ea_t ea)
{
char buf[100];
tag_addr(buf, buf + sizeof(buf), ea);
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(buf);
}
@ -180,6 +184,7 @@ PyObject *py_generate_disassembly(
bool as_stack,
bool notags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( max_lines <= 0 )
Py_RETURN_NONE;
@ -188,7 +193,7 @@ PyObject *py_generate_disassembly(
int lnnum;
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
PyObject *py_tuple = PyTuple_New(nlines);
newref_t py_tuple(PyTuple_New(nlines));
for ( int i=0; i<nlines; i++ )
{
const char *s = lines[i];
@ -199,13 +204,11 @@ PyObject *py_generate_disassembly(
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0];
}
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
PyTuple_SetItem(py_tuple.o, i, PyString_FromString(s));
qfree(lines[i]);
}
delete [] lines;
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
Py_DECREF(py_tuple);
return py_result;
return Py_BuildValue("(iO)", lnnum, py_tuple.o);
}
//</inline(py_lines)>
#endif

View File

@ -110,6 +110,7 @@ private:
//--------------------------------------------------------------------------
void _from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
this->set_linput((linput_t *)PyCObject_AsVoidPtr(pycobject));
}
@ -133,6 +134,7 @@ public:
//--------------------------------------------------------------------------
loader_input_t(PyObject *pycobject = NULL): li(NULL), own(OWN_NONE), __idc_cvt_id__(PY_ICID_OPAQUE)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( pycobject != NULL && PyCObject_Check(pycobject) )
_from_cobject(pycobject);
}
@ -143,11 +145,13 @@ public:
if ( li == NULL )
return;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
if ( own == OWN_CREATE )
close_linput(li);
else if ( own == OWN_FROM_FP )
unmake_linput(li);
Py_END_ALLOW_THREADS;
li = NULL;
own = OWN_NONE;
}
@ -162,14 +166,17 @@ public:
bool open(const char *filename, bool remote = false)
{
close();
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
li = open_linput(filename, remote);
if ( li == NULL )
return false;
// Save file name
fn = filename;
own = OWN_CREATE;
return true;
if ( li != NULL )
{
// Save file name
fn = filename;
own = OWN_CREATE;
}
Py_END_ALLOW_THREADS;
return li != NULL;
}
//--------------------------------------------------------------------------
@ -193,6 +200,7 @@ public:
// This method can be used to pass a linput_t* from C code
static loader_input_t *from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(pycobject) )
return NULL;
loader_input_t *l = new loader_input_t();
@ -203,14 +211,18 @@ public:
//--------------------------------------------------------------------------
static loader_input_t *from_fp(FILE *fp)
{
PYW_GIL_GET;
loader_input_t *l = NULL;
Py_BEGIN_ALLOW_THREADS;
linput_t *fp_li = make_linput(fp);
if ( fp_li == NULL )
return NULL;
loader_input_t *l = new loader_input_t();
l->own = OWN_FROM_FP;
l->fn.sprnt("<FILE * %p>", fp);
l->li = fp_li;
if ( fp_li != NULL )
{
l = new loader_input_t();
l->own = OWN_FROM_FP;
l->fn.sprnt("<FILE * %p>", fp);
l->li = fp_li;
}
Py_END_ALLOW_THREADS;
return l;
}
@ -223,37 +235,55 @@ public:
//--------------------------------------------------------------------------
bool open_memory(ea_t start, asize_t size = 0)
{
linput_t *l = create_memory_linput(start, size);
if ( l == NULL )
return false;
close();
li = l;
fn = "<memory>";
own = OWN_CREATE;
return true;
PYW_GIL_GET;
linput_t *l;
Py_BEGIN_ALLOW_THREADS;
l = create_memory_linput(start, size);
if ( l != NULL )
{
close();
li = l;
fn = "<memory>";
own = OWN_CREATE;
}
Py_END_ALLOW_THREADS;
return l != NULL;
}
//--------------------------------------------------------------------------
int32 seek(int32 pos, int whence = SEEK_SET)
{
return qlseek(li, pos, whence);
int32 r;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
r = qlseek(li, pos, whence);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
int32 tell()
{
return qltell(li);
int32 r;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
r = qltell(li);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
PyObject *getz(size_t sz, int32 fpos = -1)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(sz + 5);
if ( buf == NULL )
break;
Py_BEGIN_ALLOW_THREADS;
qlgetz(li, fpos, buf, sz);
Py_END_ALLOW_THREADS;
PyObject *ret = PyString_FromString(buf);
free(buf);
return ret;
@ -264,12 +294,17 @@ public:
//--------------------------------------------------------------------------
PyObject *gets(size_t len)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(len + 5);
if ( buf == NULL )
break;
if ( qlgets(buf, len, li) == NULL )
bool ok;
Py_BEGIN_ALLOW_THREADS;
ok = qlgets(buf, len, li) != NULL;
Py_END_ALLOW_THREADS;
if ( !ok )
{
free(buf);
break;
@ -284,12 +319,16 @@ public:
//--------------------------------------------------------------------------
PyObject *read(size_t size)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
ssize_t r = qlread(li, buf, size);
ssize_t r;
Py_BEGIN_ALLOW_THREADS;
r = qlread(li, buf, size);
Py_END_ALLOW_THREADS;
if ( r == -1 )
{
free(buf);
@ -311,12 +350,16 @@ public:
//--------------------------------------------------------------------------
PyObject *readbytes(size_t size, bool big_endian)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = lreadbytes(li, buf, size, big_endian);
int r;
Py_BEGIN_ALLOW_THREADS;
r = lreadbytes(li, buf, size, big_endian);
Py_END_ALLOW_THREADS;
if ( r == -1 )
{
free(buf);
@ -332,25 +375,38 @@ public:
//--------------------------------------------------------------------------
int file2base(int32 pos, ea_t ea1, ea_t ea2, int patchable)
{
return ::file2base(li, pos, ea1, ea2, patchable);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = ::file2base(li, pos, ea1, ea2, patchable);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 size()
{
return qlsize(li);
int32 rc;
Py_BEGIN_ALLOW_THREADS;
rc = qlsize(li);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
PyObject *filename()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qlgetc(li);
PYW_GIL_CHECK_LOCKED_SCOPE();
int ch;
Py_BEGIN_ALLOW_THREADS;
ch = qlgetc(li);
Py_END_ALLOW_THREADS;
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);

View File

@ -25,8 +25,11 @@ static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1)
{
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
return 0;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
return 0;
}
return mem2base((void *)buf, ea, ea+len, fpos);
}
@ -47,6 +50,7 @@ def load_plugin(name):
static PyObject *py_load_plugin(const char *name)
{
plugin_t *r = load_plugin(name);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( r == NULL )
Py_RETURN_NONE;
else
@ -67,10 +71,20 @@ def run_plugin(plg):
*/
static bool py_run_plugin(PyObject *plg, int arg)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(plg) )
{
return false;
}
else
return run_plugin((plugin_t *)PyCObject_AsVoidPtr(plg), arg);
{
plugin_t *p = (plugin_t *)PyCObject_AsVoidPtr(plg);
bool rc;
Py_BEGIN_ALLOW_THREADS;
rc = run_plugin(p, arg);
Py_END_ALLOW_THREADS;
return rc;
}
}
//</inline(py_loader)>

View File

@ -21,53 +21,35 @@ static int idaapi py_import_enum_cb(
if ( name == NULL )
name = get_true_name(BADADDR, ea, name_buf, sizeof(name_buf));
PyObject *py_name;
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_name;
if ( name == NULL )
{
py_name = Py_None;
Py_INCREF(Py_None);
}
py_name = borref_t(Py_None);
else
{
py_name = PyString_FromString(name);
}
py_name = newref_t(PyString_FromString(name));
PyObject *py_ord = Py_BuildValue(PY_FMT64, pyul_t(ord));
PyObject *py_ea = Py_BuildValue(PY_FMT64, pyul_t(ea));
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(
(PyObject *)param,
py_ea,
py_name,
py_ord,
NULL);
PYW_GIL_RELEASE;
int r = py_result != NULL && PyObject_IsTrue(py_result) ? 1 : 0;
Py_DECREF(py_ea);
Py_DECREF(py_name);
Py_DECREF(py_ord);
Py_XDECREF(py_result);
return r;
newref_t py_ord(Py_BuildValue(PY_FMT64, pyul_t(ord)));
newref_t py_ea(Py_BuildValue(PY_FMT64, pyul_t(ea)));
newref_t py_result(
PyObject_CallFunctionObjArgs(
(PyObject *)param,
py_ea.o,
py_name.o,
py_ord.o,
NULL));
return py_result != NULL && PyObject_IsTrue(py_result.o) ? 1 : 0;
}
//-------------------------------------------------------------------------
switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyObject_HasAttrString(self, S_CLINK_NAME) )
return NULL;
switch_info_ex_t *r;
PyObject *attr = PyObject_GetAttrString(self, S_CLINK_NAME);
if ( PyCObject_Check(attr) )
r = (switch_info_ex_t *) PyCObject_AsVoidPtr(attr);
else
r = NULL;
Py_DECREF(attr);
return r;
newref_t attr(PyObject_GetAttrString(self, S_CLINK_NAME));
return PyCObject_Check(attr.o) ? ((switch_info_ex_t *) PyCObject_AsVoidPtr(attr.o)) : NULL;
}
//</code(py_nalt)>
@ -86,10 +68,11 @@ def get_import_module_name(path, fname, callback):
*/
static PyObject *py_get_import_module_name(int mod_index)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
char buf[MAXSTR];
if ( !get_import_module_name(mod_index, buf, sizeof(buf)) )
Py_RETURN_NONE;
return PyString_FromString(buf);
}
@ -108,14 +91,16 @@ def get_switch_info_ex(ea):
PyObject *py_get_switch_info_ex(ea_t ea)
{
switch_info_ex_t *ex = new switch_info_ex_t();
PyObject *py_obj;
if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0
ref_t py_obj;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0
|| (py_obj = create_idaapi_linked_class_instance(S_PY_SWIEX_CLSNAME, ex)) == NULL )
{
delete ex;
Py_RETURN_NONE;
}
return py_obj;
py_obj.incref();
return py_obj.o;
}
//-------------------------------------------------------------------------
@ -129,7 +114,7 @@ def create_switch_xrefs(insn_ea, si):
will call it for switch tables
Note: Custom switch information are not supported yet.
@param insn_ea: address of the 'indirect jump' instruction
@param si: switch information
@ -157,7 +142,7 @@ idaman bool ida_export py_create_switch_xrefs(
def create_switch_table(insn_ea, si):
"""
Create switch table from the switch information
@param insn_ea: address of the 'indirect jump' instruction
@param si: switch information
@ -173,7 +158,7 @@ idaman bool ida_export py_create_switch_table(
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
if ( swi == NULL )
return false;
create_switch_table(insn_ea, swi);
return true;
}
@ -232,9 +217,9 @@ def enum_import_names(mod_index, callback):
*/
static int py_enum_import_names(int mod_index, PyObject *py_cb)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_cb) )
return -1;
return enum_import_names(mod_index, py_import_enum_cb, py_cb);
}
@ -242,12 +227,14 @@ static int py_enum_import_names(int mod_index, PyObject *py_cb)
static PyObject *switch_info_ex_t_create()
{
switch_info_ex_t *inst = new switch_info_ex_t();
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(inst, NULL);
}
//---------------------------------------------------------------------------
static bool switch_info_ex_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
switch_info_ex_t *inst = (switch_info_ex_t *) PyCObject_AsVoidPtr(py_obj);
@ -273,6 +260,7 @@ static bool switch_info_ex_t_assign(PyObject *self, PyObject *other)
static PyObject *switch_info_ex_t_get_regdtyp(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("b", (char)link->regdtyp);
@ -282,12 +270,14 @@ static void switch_info_ex_t_set_regdtyp(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->regdtyp = (char)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_flags2(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->flags2);
@ -297,12 +287,14 @@ static void switch_info_ex_t_set_flags2(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->flags2 = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_jcases(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->jcases);
@ -312,12 +304,14 @@ static void switch_info_ex_t_set_jcases(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->jcases = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_regnum(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", (int)link->regnum);
@ -327,12 +321,14 @@ static void switch_info_ex_t_set_regnum(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->regnum = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_flags(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (ushort)link->flags);
@ -342,12 +338,14 @@ static void switch_info_ex_t_set_flags(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->flags = (uint16)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_ncases(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (uint16)link->ncases);
@ -357,12 +355,14 @@ static void switch_info_ex_t_set_ncases(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->ncases = (ushort)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_defjump(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->defjump);
@ -372,6 +372,7 @@ static void switch_info_ex_t_set_defjump(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 v(0); PyW_GetNumber(value, &v);
link->defjump = (pyul_t)v;
}
@ -388,6 +389,7 @@ static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 v(0); PyW_GetNumber(value, &v);
link->jumps = (pyul_t)v;
}
@ -395,6 +397,7 @@ static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_elbase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->elbase);
@ -405,6 +408,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->elbase = (pyul_t)v;
}
@ -412,6 +416,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_startea(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->startea);
@ -422,6 +427,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->startea = (pyul_t)v;
}
@ -429,6 +435,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_custom(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->custom);
@ -439,6 +446,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->custom = (pyul_t)v;
}
@ -446,6 +454,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_ind_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->ind_lowcase);
@ -456,6 +465,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->ind_lowcase = (pyul_t)v;
}
@ -463,6 +473,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_values_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->values);
@ -473,6 +484,7 @@ static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->values = (pyul_t)v;
}

View File

@ -5,16 +5,19 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
{
// Get debug names
ea_name_vec_t names;
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_BEGIN_ALLOW_THREADS;
get_debug_names(ea1, ea2, names);
Py_END_ALLOW_THREADS;
PyObject *dict = Py_BuildValue("{}");
if (dict == NULL)
return NULL;
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
if (dict != NULL)
{
PyDict_SetItem(dict,
Py_BuildValue(PY_FMT64, it->ea),
PyString_FromString(it->name.c_str()));
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
{
PyDict_SetItem(dict,
Py_BuildValue(PY_FMT64, it->ea),
PyString_FromString(it->name.c_str()));
}
}
return dict;
}

View File

@ -8,7 +8,7 @@
//------------------------------------------------------------------------
class pywraps_notify_when_t
{
ppyobject_vec_t table[NW_EVENTSCNT];
ref_vec_t table[NW_EVENTSCNT];
qstring err;
bool in_notify;
struct notify_when_args_t
@ -22,6 +22,8 @@ class pywraps_notify_when_t
//------------------------------------------------------------------------
static int idaapi idp_callback(void *ud, int event_id, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud;
switch ( event_id )
{
@ -60,32 +62,29 @@ class pywraps_notify_when_t
//------------------------------------------------------------------------
void register_callback(int slot, PyObject *py_callable)
{
ppyobject_vec_t &tbl = table[slot];
ppyobject_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, py_callable);
borref_t callable_ref(py_callable);
ref_vec_t &tbl = table[slot];
ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref);
// Already added
if ( it != it_end )
return;
// Increment reference
Py_INCREF(py_callable);
// Insert the element
tbl.push_back(py_callable);
tbl.push_back(callable_ref);
}
//------------------------------------------------------------------------
void unregister_callback(int slot, PyObject *py_callable)
{
ppyobject_vec_t &tbl = table[slot];
ppyobject_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, py_callable);
borref_t callable_ref(py_callable);
ref_vec_t &tbl = table[slot];
ref_vec_t::iterator it_end = tbl.end(), it = std::find(tbl.begin(), it_end, callable_ref);
// Not found?
if ( it == it_end )
return;
// Decrement reference
Py_DECREF(py_callable);
// Delete the element
tbl.erase(it);
}
@ -101,11 +100,11 @@ public:
bool deinit()
{
// Uninstall all objects
ppyobject_vec_t::iterator it, it_end;
ref_vec_t::iterator it, it_end;
for ( int slot=0; slot<NW_EVENTSCNT; slot++ )
{
for ( it = table[slot].begin(), it_end = table[slot].end(); it!=it_end; ++it )
unregister_callback(slot, *it);
unregister_callback(slot, it->o);
}
// ...and remove the notification
return unhook_from_notification_point(HT_IDP, idp_callback, this);
@ -154,6 +153,8 @@ public:
//------------------------------------------------------------------------
bool notify_va(int slot, va_list va)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Sanity bounds check!
if ( slot < 0 || slot >= NW_EVENTSCNT )
return false;
@ -161,42 +162,38 @@ public:
bool ok = true;
in_notify = true;
int old = slot == NW_OPENIDB_SLOT ? va_arg(va, int) : 0;
for (ppyobject_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end();
it != it_end;
++it)
{
// Form the notification code
PyObject *py_code = PyInt_FromLong(1 << slot);
PyObject *py_result(NULL);
switch ( slot )
for (ref_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end();
it != it_end;
++it)
{
case NW_CLOSEIDB_SLOT:
case NW_INITIDA_SLOT:
case NW_TERMIDA_SLOT:
// Form the notification code
newref_t py_code(PyInt_FromLong(1 << slot));
ref_t py_result;
switch ( slot )
{
PYW_GIL_ENSURE;
py_result = PyObject_CallFunctionObjArgs(*it, py_code, NULL);
PYW_GIL_RELEASE;
break;
case NW_CLOSEIDB_SLOT:
case NW_INITIDA_SLOT:
case NW_TERMIDA_SLOT:
{
py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, NULL));
break;
}
case NW_OPENIDB_SLOT:
{
newref_t py_old(PyInt_FromLong(old));
py_result = newref_t(PyObject_CallFunctionObjArgs(it->o, py_code.o, py_old.o, NULL));
}
break;
}
case NW_OPENIDB_SLOT:
if ( PyW_GetError(&err) || py_result == NULL )
{
PyObject *py_old = PyInt_FromLong(old);
PYW_GIL_ENSURE;
py_result = PyObject_CallFunctionObjArgs(*it, py_code, py_old, NULL);
PYW_GIL_RELEASE;
Py_DECREF(py_old);
PyErr_Clear();
warning("notify_when(): Error occured while notifying object.\n%s", err.c_str());
ok = false;
}
break;
}
Py_DECREF(py_code);
if ( PyW_GetError(&err) || py_result == NULL )
{
PyErr_Clear();
warning("notify_when(): Error occured while notifying object.\n%s", err.c_str());
ok = false;
}
Py_XDECREF(py_result);
}
in_notify = false;
@ -211,6 +208,7 @@ public:
}
delayed_notify_when_list.qclear();
}
return ok;
}
@ -247,6 +245,10 @@ bool pywraps_nw_notify(int slot, ...)
if ( g_nw == NULL )
return false;
// Appears to be called from 'driver_notifywhen.cpp', which
// itself is called from possibly non-python code.
// I.e., we must acquire the GIL.
PYW_GIL_GET;
va_list va;
va_start(va, slot);
bool ok = g_nw->notify_va(slot, va);
@ -261,11 +263,11 @@ bool pywraps_nw_term()
{
if ( g_nw == NULL )
return true;
// If could not deinitialize then return w/o stopping nw
if ( !g_nw->deinit() )
return false;
// Cleanup
delete g_nw;
g_nw = NULL;
@ -296,6 +298,7 @@ def notify_when(when, callback):
*/
static bool notify_when(int when, PyObject *py_callable)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( g_nw == NULL || !PyCallable_Check(py_callable) )
return false;
return g_nw->notify_when(when, py_callable);

View File

@ -6,11 +6,14 @@
class plgform_t
{
private:
PyObject *py_obj;
ref_t py_obj;
TForm *form;
static int idaapi s_callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
plgform_t *_this = (plgform_t *)ud;
if ( notification_code == ui_tform_visible )
{
@ -21,15 +24,12 @@ private:
// G: HWND
// We wrap and pass as a CObject in the hope that a Python UI framework
// can unwrap a CObject and get the hwnd/widget back
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_obj,
(char *)S_ON_CREATE, "O",
PyCObject_FromVoidPtr(form, NULL));
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_obj.o,
(char *)S_ON_CREATE, "O",
PyCObject_FromVoidPtr(form, NULL)));
PyW_ShowCbErr(S_ON_CREATE);
Py_XDECREF(py_result);
}
}
else if ( notification_code == ui_tform_invisible )
@ -37,16 +37,14 @@ private:
TForm *form = va_arg(va, TForm *);
if ( form == _this->form )
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_obj,
(char *)S_ON_CLOSE, "O",
PyCObject_FromVoidPtr(form, NULL));
PYW_GIL_RELEASE;
PyW_ShowCbErr(S_ON_CLOSE);
Py_XDECREF(py_result);
{
newref_t py_result(
PyObject_CallMethod(
_this->py_obj.o,
(char *)S_ON_CLOSE, "O",
PyCObject_FromVoidPtr(form, NULL)));
PyW_ShowCbErr(S_ON_CLOSE);
}
_this->unhook();
}
}
@ -59,11 +57,12 @@ private:
form = NULL;
// Call DECREF at last, since it may trigger __del__
Py_XDECREF(py_obj);
PYW_GIL_CHECK_LOCKED_SCOPE();
py_obj = ref_t();
}
public:
plgform_t(): py_obj(NULL), form(NULL)
plgform_t(): form(NULL)
{
}
@ -98,8 +97,7 @@ public:
return false;
}
py_obj = obj;
Py_INCREF(obj);
py_obj = borref_t(obj);
if ( is_idaq() )
options |= FORM_QWIDGET;
@ -117,6 +115,7 @@ public:
static PyObject *create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new plgform_t(), destroy);
}
@ -129,7 +128,7 @@ public:
//<inline(py_plgform)>
//---------------------------------------------------------------------------
#define DECL_PLGFORM plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link);
#define DECL_PLGFORM PYW_GIL_CHECK_LOCKED_SCOPE(); plgform_t *plgform = (plgform_t *) PyCObject_AsVoidPtr(py_link);
static PyObject *plgform_new()
{
return plgform_t::create();
@ -155,4 +154,4 @@ static void plgform_close(
#undef DECL_PLGFORM
//</inline(py_plgform)>
#endif // __PY_PLGFORM__
#endif // __PY_PLGFORM__

View File

@ -59,6 +59,19 @@ class PluginForm(object):
@param ctx: Context. Reference to a module that already imported QtGui module
"""
if form is None:
return None
if type(form).__name__ == "SwigPyObject":
# Since 'form' is a SwigPyObject, we first need to convert it to a PyCObject.
# However, there's no easy way of doing it, so we'll use a rather brutal approach:
# converting the SwigPyObject to a 'long' (will go through 'SwigPyObject_long',
# that will return the pointer's value as a long), and then convert that value
# back to a pointer into a PyCObject.
ptr_l = long(form)
from ctypes import pythonapi, c_void_p, py_object
pythonapi.PyCObject_FromVoidPtr.restype = py_object
pythonapi.PyCObject_AsVoidPtr.argtypes = [c_void_p, c_void_p]
form = pythonapi.PyCObject_FromVoidPtr(ptr_l, 0)
return ctx.QtGui.QWidget.FromCObject(form)
@ -89,7 +102,7 @@ class PluginForm(object):
@return: None
"""
return _idaapi.plgform_close(self.__clink__)
return _idaapi.plgform_close(self.__clink__, options)
FORM_SAVE = 0x1
"""Save state in desktop config"""
@ -105,4 +118,4 @@ class PluginForm(object):
#</pycode(py_plgform)>
plg = PluginForm()
plg.Show("This is it")
plg.Show("This is it")

View File

@ -102,6 +102,7 @@ private:
}
inline void _from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
_from_fp((FILE *)PyCObject_AsVoidPtr(pycobject));
}
public:
@ -119,7 +120,12 @@ public:
own = true;
fn.qclear();
__idc_cvt_id__ = PY_ICID_OPAQUE;
if ( pycobject != NULL && PyCObject_Check(pycobject) )
bool ok;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
ok = pycobject != NULL && PyCObject_Check(pycobject);
}
if ( ok )
_from_cobject(pycobject);
}
@ -135,7 +141,11 @@ public:
if ( fp == NULL )
return;
if ( own )
{
Py_BEGIN_ALLOW_THREADS;
qfclose(fp);
Py_END_ALLOW_THREADS;
}
fp = NULL;
own = true;
}
@ -150,7 +160,9 @@ public:
bool open(const char *filename, const char *mode)
{
close();
Py_BEGIN_ALLOW_THREADS;
fp = qfopen(filename, mode);
Py_END_ALLOW_THREADS;
if ( fp == NULL )
return false;
// Save file name
@ -181,7 +193,11 @@ public:
//--------------------------------------------------------------------------
static qfile_t *tmpfile()
{
return from_fp(qtmpfile());
FILE *fp;
Py_BEGIN_ALLOW_THREADS;
fp = qtmpfile();
Py_END_ALLOW_THREADS;
return from_fp(fp);
}
//--------------------------------------------------------------------------
@ -193,13 +209,21 @@ public:
//--------------------------------------------------------------------------
int seek(int32 offset, int whence = SEEK_SET)
{
return qfseek(fp, offset, whence);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfseek(fp, offset, whence);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 tell()
{
return qftell(fp);
int32 rc;
Py_BEGIN_ALLOW_THREADS;
rc = qftell(fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
@ -210,12 +234,17 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = freadbytes(fp, buf, size, big_endian);
PYW_GIL_CHECK_LOCKED_SCOPE();
int r;
Py_BEGIN_ALLOW_THREADS;
r = freadbytes(fp, buf, size, big_endian);
Py_END_ALLOW_THREADS;
if ( r != 0 )
{
free(buf);
break;
}
PyObject *ret = PyString_FromStringAndSize(buf, r);
free(buf);
return ret;
@ -231,7 +260,11 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = qfread(fp, buf, size);
PYW_GIL_CHECK_LOCKED_SCOPE();
int r;
Py_BEGIN_ALLOW_THREADS;
r = qfread(fp, buf, size);
Py_END_ALLOW_THREADS;
if ( r <= 0 )
{
free(buf);
@ -252,7 +285,12 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
if ( qfgets(buf, size, fp) == NULL )
PYW_GIL_CHECK_LOCKED_SCOPE();
char *p;
Py_BEGIN_ALLOW_THREADS;
p = qfgets(buf, size, fp);
Py_END_ALLOW_THREADS;
if ( p == NULL )
{
free(buf);
break;
@ -267,50 +305,87 @@ public:
//--------------------------------------------------------------------------
int writebytes(PyObject *py_buf, bool big_endian)
{
int sz = PyString_GET_SIZE(py_buf);
void *buf = (void *)PyString_AS_STRING(py_buf);
return fwritebytes(fp, buf, sz, big_endian);
Py_ssize_t sz;
void *buf;
PYW_GIL_CHECK_LOCKED_SCOPE();
sz = PyString_GET_SIZE(py_buf);
buf = (void *)PyString_AS_STRING(py_buf);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = fwritebytes(fp, buf, int(sz), big_endian);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int write(PyObject *py_buf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_buf) )
return 0;
return qfwrite(fp, (void *)PyString_AS_STRING(py_buf), PyString_GET_SIZE(py_buf));
// Just so that there is no risk that the buffer returned by
// 'PyString_AS_STRING' gets deallocated within the
// Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_buf_ref(py_buf);
void *p = (void *)PyString_AS_STRING(py_buf);
Py_ssize_t sz = PyString_GET_SIZE(py_buf);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfwrite(fp, p, sz);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int puts(const char *str)
{
return qfputs(str, fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfputs(str, fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 size()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
int32 r;
Py_BEGIN_ALLOW_THREADS;
int pos = qfseek(fp, 0, SEEK_END);
int32 r = qftell(fp);
r = qftell(fp);
qfseek(fp, pos, SEEK_SET);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
int flush()
{
return qflush(fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qflush(fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
PyObject *filename()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qfgetc(fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int ch;
Py_BEGIN_ALLOW_THREADS;
ch = qfgetc(fp);
Py_END_ALLOW_THREADS;
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
@ -319,7 +394,12 @@ public:
//--------------------------------------------------------------------------
int put_char(char chr)
{
return qfputc(chr, fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfputc(chr, fp);
Py_END_ALLOW_THREADS;
return rc;
}
};
//</inline(py_qfile)>

View File

@ -5,22 +5,26 @@
//-------------------------------------------------------------------------
PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
{
qtype fields, type;
tinfo_t tif;
qstring name;
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
if ( !ok )
Py_RETURN_NONE;
qtype fields, type;
bool ok = parse_decl2(ti, decl, &name, &tif, flags);
if ( ok )
ok = tif.serialize(&type, &fields, NULL, SUDT_FAST);
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_type_size0(ti, tp):
def calc_type_size(ti, tp):
"""
Returns the size of a type
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@ -32,25 +36,69 @@ def get_type_size0(ti, tp):
pass
#</pydoc>
*/
PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
PyObject *py_calc_type_size(const til_t *ti, PyObject *tp)
{
if ( !PyString_Check(tp) )
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_Check(tp) )
{
// To avoid release of 'data' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t tpref(tp);
const type_t *data = (type_t *)PyString_AsString(tp);
size_t sz;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
tif.deserialize(ti, &data, NULL, NULL);
sz = tif.get_size();
Py_END_ALLOW_THREADS;
if ( sz != BADSIZE )
return PyInt_FromLong(sz);
Py_RETURN_NONE;
}
else
{
PyErr_SetString(PyExc_ValueError, "String expected!");
return NULL;
}
size_t sz = get_type_size0(ti, (type_t *)PyString_AsString(tp));
if ( sz == BADSIZE )
Py_RETURN_NONE;
return PyInt_FromLong(sz);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def print_type(ea, on_line):
def apply_type(ti, ea, tp_name, py_type, py_fields, flags)
"""
Apply the specified type to the address
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param py_type: type string
@param py_fields: type fields
@param ea: the address of the object
@param flags: combination of TINFO_... constants or 0
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_t ea, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
const type_t *type = (const type_t *) PyString_AsString(py_type);
const p_list *fields = (const p_list *) PyString_AsString(py_fields);
bool rc;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
rc = tif.deserialize(ti, &type, &fields, NULL) && apply_tinfo2(ea, tif, flags);
Py_END_ALLOW_THREADS;
return rc;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def print_type(ea, one_line):
"""
Returns the type of an item
@return:
@ -62,14 +110,13 @@ def print_type(ea, on_line):
*/
static PyObject *py_print_type(ea_t ea, bool one_line)
{
char buf[MAXSTR];
if ( print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI) )
{
qstrncat(buf, ";", sizeof(buf));
char buf[64*MAXSTR];
int flags = PRTYPE_SEMI | (one_line ? PRTYPE_1LINE : PRTYPE_MULTI);
bool ok = print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return PyString_FromString(buf);
}
else
Py_RETURN_NONE;
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
@ -90,17 +137,24 @@ PyObject *py_unpack_object_from_idb(
ea_t ea,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Unpack
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
idc_value_t idc_obj;
error_t err = unpack_object_from_idb(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = unpack_object_from_idb(
&idc_obj,
ti,
type,
@ -108,22 +162,21 @@ PyObject *py_unpack_object_from_idb(
ea,
NULL,
pio_flags);
Py_END_ALLOW_THREADS;
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
ref_t py_ret;
err = idcvar_to_pyvar(idc_obj, &py_ret);
// Conversion failed?
if ( err != CIP_OK )
return Py_BuildValue("(ii)", 0, err);
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
Py_DECREF(py_ret);
return py_result;
else
return Py_BuildValue("(iO)", 1, py_ret.o);
}
//-------------------------------------------------------------------------
@ -152,12 +205,17 @@ PyObject *py_unpack_object_from_bv(
PyObject *py_bytes,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) && !PyString_Check(py_bytes) )
{
PyErr_SetString(PyExc_ValueError, "Incorrect argument type!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
@ -168,29 +226,30 @@ PyObject *py_unpack_object_from_bv(
memcpy(bytes.begin(), PyString_AsString(py_bytes), bytes.size());
idc_value_t idc_obj;
error_t err = unpack_object_from_bv(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = unpack_object_from_bv(
&idc_obj,
ti,
type,
fields,
bytes,
pio_flags);
Py_END_ALLOW_THREADS;
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
ref_t py_ret;
err = idcvar_to_pyvar(idc_obj, &py_ret);
// Conversion failed?
if ( err != CIP_OK )
return Py_BuildValue("(ii)", 0, err);
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
Py_DECREF(py_ret);
return py_result;
return Py_BuildValue("(iO)", 1, py_ret.o);
}
//-------------------------------------------------------------------------
@ -218,6 +277,7 @@ PyObject *py_pack_object_to_idb(
ea_t ea,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
@ -226,15 +286,24 @@ PyObject *py_pack_object_to_idb(
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
borref_t py_obj_ref(py_obj);
if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) )
return NULL;
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
type_t *type = (type_t *)PyString_AsString(py_type);
p_list *fields = (p_list *)PyString_AsString(py_fields);
// Pack
error_t err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags);
// error_t err;
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags);
Py_END_ALLOW_THREADS;
return PyInt_FromLong(err);
}
@ -265,6 +334,7 @@ PyObject *py_pack_object_to_bv(
ea_t base_ea,
int pio_flags=0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
@ -273,16 +343,23 @@ PyObject *py_pack_object_to_bv(
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
borref_t py_obj_ref(py_obj);
if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) )
return NULL;
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
type_t *type = (type_t *)PyString_AsString(py_type);
p_list *fields = (p_list *)PyString_AsString(py_fields);
// Pack
relobj_t bytes;
error_t err = pack_object_to_bv(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = pack_object_to_bv(
&idc_obj,
ti,
type,
@ -290,19 +367,172 @@ PyObject *py_pack_object_to_bv(
&bytes,
NULL,
pio_flags);
do
{
if ( err != eOk )
break;
if ( !bytes.relocate(base_ea, inf.mf) )
{
if ( err == eOk && !bytes.relocate(base_ea, inf.mf) )
err = -1;
break;
}
Py_END_ALLOW_THREADS;
if ( err == eOk )
return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size());
} while ( false );
return Py_BuildValue("(ii)", 0, err);
else
return Py_BuildValue("(ii)", 0, err);
}
//-------------------------------------------------------------------------
/* Parse types from a string or file. See ParseTypes() in idc.py */
int idc_parse_types(const char *input, int flags)
{
int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT;
if ((flags & 1) != 0)
hti |= HTI_FIL;
return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti);
}
//-------------------------------------------------------------------------
PyObject *py_idc_get_type_raw(ea_t ea)
{
qtype type, fields;
bool ok = get_tinfo(ea, &type, &fields);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str());
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
PyObject *py_idc_get_local_type_raw(int ordinal)
{
const type_t *type;
const p_list *fields;
bool ok = get_numbered_type(idati, ordinal, &type, &fields);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(ss)", (char *)type, (char *)fields);
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
char *idc_guess_type(ea_t ea, char *buf, size_t bufsize)
{
tinfo_t tif;
if ( guess_tinfo2(ea, &tif) )
{
qstring out;
if ( tif.print(&out) )
return qstrncpy(buf, out.begin(), bufsize);
}
return NULL;
}
//-------------------------------------------------------------------------
char *idc_get_type(ea_t ea, char *buf, size_t bufsize)
{
tinfo_t tif;
if ( get_tinfo2(ea, &tif) )
{
qstring out;
if ( tif.print(&out) )
{
qstrncpy(buf, out.c_str(), bufsize);
return buf;
}
}
return NULL;
}
//-------------------------------------------------------------------------
int idc_set_local_type(int ordinal, const char *dcl, int flags)
{
if (dcl == NULL || dcl[0] == '\0')
{
if ( !del_numbered_type(idati, ordinal) )
return 0;
}
else
{
tinfo_t tif;
qstring name;
if ( !parse_decl2(idati, dcl, &name, &tif, flags) )
return 0;
if ( ordinal <= 0 )
{
if ( !name.empty() )
ordinal = get_type_ordinal(idati, name.begin());
if ( ordinal <= 0 )
ordinal = alloc_type_ordinal(idati);
}
if ( tif.set_numbered_type(idati, ordinal, 0, name.c_str()) != TERR_OK )
return 0;
}
return ordinal;
}
//-------------------------------------------------------------------------
int idc_get_local_type(int ordinal, int flags, char *buf, size_t maxsize)
{
tinfo_t tif;
if ( !tif.get_numbered_type(idati, ordinal) )
{
buf[0] = 0;
return false;
}
qstring res;
const char *name = get_numbered_type_name(idati, ordinal);
if ( !tif.print(&res, name, flags, 2, 40) )
{
buf[0] = 0;
return false;
}
qstrncpy(buf, res.begin(), maxsize);
return true;
}
//-------------------------------------------------------------------------
PyObject *idc_print_type(PyObject *py_type, PyObject *py_fields, const char *name, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
qstring res;
const type_t *type = (type_t *)PyString_AsString(py_type);
const p_list *fields = (p_list *)PyString_AsString(py_fields);
bool ok;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
ok = tif.deserialize(idati, &type, &fields, NULL)
&& tif.print(&res, name, flags, 2, 40);
Py_END_ALLOW_THREADS;
if ( ok )
return PyString_FromString(res.begin());
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize)
{
const char *name = get_numbered_type_name(idati, ordinal);
if ( name == NULL )
return false;
qstrncpy(buf, name, bufsize);
return true;
}
//</inline(py_typeinf)>
#endif

15
pywraps/py_typeinf.py Normal file
View File

@ -0,0 +1,15 @@
#<pycode(py_typeinf)>
def get_type_size0(ti, tp):
"""
DEPRECATED. Please use calc_type_size instead
Returns the size of a type
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param tp: type string
@return:
- None on failure
- The size of the type
"""
return calc_type_size(ti, tp)
#</pycode(py_typeinf)>

View File

@ -35,6 +35,8 @@ def init_output_buffer(size = MAXSTR):
*/
PyObject *py_init_output_buffer(size_t size = MAXSTR)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Let Python allocate a writable string buffer for us
PyObject *py_str = PyString_FromStringAndSize(NULL, size);
if ( py_str == NULL )
@ -73,6 +75,7 @@ PyObject *py_decode_preceding_insn(ea_t ea)
{
bool farref;
ea_t r = decode_preceding_insn(ea, &farref);
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0);
}
@ -117,6 +120,7 @@ def get_stkvar(op, v):
*/
PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v;
if ( op == NULL || !PyW_GetNumber(py_v, &v) )
@ -150,6 +154,7 @@ def add_stkvar3(op, v, flags):
*/
bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v;
return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true;
@ -192,11 +197,24 @@ bool py_apply_type_to_stkarg(
const char *name)
{
uint64 v;
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type))
{
return false;
}
else
return apply_type_to_stkarg(*op, uval_t(v), (type_t *) PyString_AsString(py_type), name);
{
const type_t *t = (type_t *) PyString_AsString(py_type);
tinfo_t tif;
tif.deserialize(idati, &t);
borref_t br(py_op);
bool rc;
Py_BEGIN_ALLOW_THREADS;
rc = apply_tinfo_to_stkarg(*op, uval_t(v), tif, name);
Py_END_ALLOW_THREADS;
return rc;
}
}
//-------------------------------------------------------------------------
@ -213,6 +231,7 @@ def OutImmChar(op, outflags = 0):
*/
static void py_OutImmChar(PyObject *x)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(x);
if ( op != NULL )
OutImmChar(*op);
@ -233,6 +252,7 @@ def ua_stkvar2(op, outflags = 0):
*/
static bool py_ua_stkvar2(PyObject *x, adiff_t v, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(x);
return op == NULL ? false : ua_stkvar2(*op, v, flags);
}
@ -252,6 +272,7 @@ def ua_add_off_drefs(op, type):
*/
ea_t py_ua_add_off_drefs(PyObject *py_op, dref_t type)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs(*op, type);
}
@ -270,6 +291,7 @@ def ua_add_off_drefs2(op, type, outf):
*/
ea_t py_ua_add_off_drefs2(PyObject *py_op, dref_t type, int outf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs2(*op, type, outf);
}
@ -295,6 +317,7 @@ bool py_out_name_expr(
ea_t ea,
PyObject *py_off)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v(0);
adiff_t off;
@ -302,13 +325,14 @@ bool py_out_name_expr(
off = adiff_t(v);
else
off = BADADDR;
return op == NULL ? false : out_name_expr(*op, ea, off);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( i < 0 || i >= UA_MAXOP || !PyCObject_Check(py_insn_lnk) )
Py_RETURN_NONE;
@ -322,18 +346,21 @@ static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i)
//-------------------------------------------------------------------------
static PyObject *insn_t_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new insn_t(), NULL);
}
//-------------------------------------------------------------------------
static PyObject *op_t_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new op_t(), NULL);
}
//-------------------------------------------------------------------------
static bool op_t_assign(PyObject *self, PyObject *other)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *lhs = op_t_get_clink(self);
op_t *rhs = op_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
@ -346,6 +373,7 @@ static bool op_t_assign(PyObject *self, PyObject *other)
//-------------------------------------------------------------------------
static bool insn_t_assign(PyObject *self, PyObject *other)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *lhs = insn_t_get_clink(self);
insn_t *rhs = insn_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
@ -358,6 +386,7 @@ static bool insn_t_assign(PyObject *self, PyObject *other)
//-------------------------------------------------------------------------
static bool op_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
@ -370,6 +399,7 @@ static bool op_t_destroy(PyObject *py_obj)
//-------------------------------------------------------------------------
static bool insn_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
@ -381,13 +411,16 @@ static bool insn_t_destroy(PyObject *py_obj)
// Returns a C link to the global 'cmd' variable
static PyObject *py_get_global_cmd_link()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(&::cmd, NULL);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_is_canon_insn(int itype)
{
if ( ph.is_canon_insn(itype) )
bool ok = ph.is_canon_insn(itype);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@ -396,13 +429,17 @@ static PyObject *insn_t_is_canon_insn(int itype)
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_feature(int itype)
{
return Py_BuildValue("I", ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0);
uint32 v = ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("I", v);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_mnem(int itype)
{
if ( ph.is_canon_insn(itype) )
bool ok = ph.is_canon_insn(itype);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name);
else
Py_RETURN_NONE;
@ -411,6 +448,7 @@ static PyObject *insn_t_get_canon_mnem(int itype)
//-------------------------------------------------------------------------
static PyObject *insn_t_get_cs(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -419,10 +457,11 @@ static PyObject *insn_t_get_cs(PyObject *self)
static void insn_t_set_cs(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyW_GetNumber(value, &v);
link->cs = ea_t(v);
@ -430,6 +469,7 @@ static void insn_t_set_cs(PyObject *self, PyObject *value)
static PyObject *insn_t_get_ip(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -438,6 +478,7 @@ static PyObject *insn_t_get_ip(PyObject *self)
static void insn_t_set_ip(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -448,6 +489,7 @@ static void insn_t_set_ip(PyObject *self, PyObject *value)
static PyObject *insn_t_get_ea(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -456,6 +498,7 @@ static PyObject *insn_t_get_ea(PyObject *self)
static void insn_t_set_ea(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -466,6 +509,7 @@ static void insn_t_set_ea(PyObject *self, PyObject *value)
static PyObject *insn_t_get_itype(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -474,6 +518,7 @@ static PyObject *insn_t_get_itype(PyObject *self)
static void insn_t_set_itype(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -482,6 +527,7 @@ static void insn_t_set_itype(PyObject *self, PyObject *value)
static PyObject *insn_t_get_size(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -490,6 +536,7 @@ static PyObject *insn_t_get_size(PyObject *self)
static void insn_t_set_size(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -498,6 +545,7 @@ static void insn_t_set_size(PyObject *self, PyObject *value)
static PyObject *insn_t_get_auxpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -506,6 +554,7 @@ static PyObject *insn_t_get_auxpref(PyObject *self)
static void insn_t_set_auxpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -514,6 +563,7 @@ static void insn_t_set_auxpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_segpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -522,6 +572,7 @@ static PyObject *insn_t_get_segpref(PyObject *self)
static void insn_t_set_segpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -530,6 +581,7 @@ static void insn_t_set_segpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_insnpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -538,6 +590,7 @@ static PyObject *insn_t_get_insnpref(PyObject *self)
static void insn_t_set_insnpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -546,6 +599,7 @@ static void insn_t_set_insnpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_flags(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -554,6 +608,7 @@ static PyObject *insn_t_get_flags(PyObject *self)
static void insn_t_set_flags(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -563,6 +618,7 @@ static void insn_t_set_flags(PyObject *self, PyObject *value)
//-------------------------------------------------------------------------
static PyObject *op_t_get_n(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -579,6 +635,7 @@ static void op_t_set_n(PyObject *self, PyObject *value)
static PyObject *op_t_get_type(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -587,6 +644,7 @@ static PyObject *op_t_get_type(PyObject *self)
static void op_t_set_type(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -595,6 +653,7 @@ static void op_t_set_type(PyObject *self, PyObject *value)
static PyObject *op_t_get_offb(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -603,6 +662,7 @@ static PyObject *op_t_get_offb(PyObject *self)
static void op_t_set_offb(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -611,6 +671,7 @@ static void op_t_set_offb(PyObject *self, PyObject *value)
static PyObject *op_t_get_offo(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -619,6 +680,7 @@ static PyObject *op_t_get_offo(PyObject *self)
static void op_t_set_offo(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -627,6 +689,7 @@ static void op_t_set_offo(PyObject *self, PyObject *value)
static PyObject *op_t_get_flags(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -635,6 +698,7 @@ static PyObject *op_t_get_flags(PyObject *self)
static void op_t_set_flags(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -643,6 +707,7 @@ static void op_t_set_flags(PyObject *self, PyObject *value)
static PyObject *op_t_get_dtyp(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -651,6 +716,7 @@ static PyObject *op_t_get_dtyp(PyObject *self)
static void op_t_set_dtyp(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -659,6 +725,7 @@ static void op_t_set_dtyp(PyObject *self, PyObject *value)
static PyObject *op_t_get_reg_phrase(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -666,6 +733,7 @@ static PyObject *op_t_get_reg_phrase(PyObject *self)
}
static void op_t_set_reg_phrase(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -674,6 +742,7 @@ static void op_t_set_reg_phrase(PyObject *self, PyObject *value)
static PyObject *op_t_get_value(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -682,6 +751,7 @@ static PyObject *op_t_get_value(PyObject *self)
static void op_t_set_value(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -690,6 +760,7 @@ static void op_t_set_value(PyObject *self, PyObject *value)
static PyObject *op_t_get_addr(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -698,6 +769,7 @@ static PyObject *op_t_get_addr(PyObject *self)
static void op_t_set_addr(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -708,6 +780,7 @@ static void op_t_set_addr(PyObject *self, PyObject *value)
static PyObject *op_t_get_specval(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -716,6 +789,7 @@ static PyObject *op_t_get_specval(PyObject *self)
static void op_t_set_specval(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -726,6 +800,7 @@ static void op_t_set_specval(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag1(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -734,6 +809,7 @@ static PyObject *op_t_get_specflag1(PyObject *self)
static void op_t_set_specflag1(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -742,6 +818,7 @@ static void op_t_set_specflag1(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag2(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -750,6 +827,7 @@ static PyObject *op_t_get_specflag2(PyObject *self)
static void op_t_set_specflag2(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -758,6 +836,7 @@ static void op_t_set_specflag2(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag3(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -766,6 +845,7 @@ static PyObject *op_t_get_specflag3(PyObject *self)
static void op_t_set_specflag3(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -774,6 +854,7 @@ static void op_t_set_specflag3(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag4(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -782,6 +863,7 @@ static PyObject *op_t_get_specflag4(PyObject *self)
static void op_t_set_specflag4(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;

810
pywraps/py_view_base.hpp Normal file
View File

@ -0,0 +1,810 @@
#ifndef __PY_VIEW_BASE__
#define __PY_VIEW_BASE__
//<code(py_view_base)>
//#define PYGDBG_ENABLED
#ifdef PYGDBG_ENABLED
#define PYGLOG(...) msg(__VA_ARGS__)
#else
#define PYGLOG(...)
#endif
//-------------------------------------------------------------------------
class py_customidamemo_t;
class lookup_info_t
{
public:
void add(TForm *form, TCustomControl *view, py_customidamemo_t *py_view)
{
QASSERT(0, form != NULL && view != NULL && py_view != NULL
&& !find_by_form(NULL, NULL, form)
&& !find_by_view(NULL, NULL, view)
&& !find_by_py_view(NULL, NULL, py_view));
entry_t &e = entries.push_back();
e.form = form;
e.view = view;
e.py_view = py_view;
}
#define FIND_BY__BODY(crit, res1, res2) \
{ \
for ( entries_t::const_iterator it = entries.begin(); it != entries.end(); ++it ) \
{ \
const entry_t &e = *it; \
if ( e.crit == crit ) \
{ \
if ( out_##res1 != NULL ) \
*out_##res1 = e.res1; \
if ( out_##res2 != NULL ) \
*out_##res2 = e.res2; \
return true; \
} \
} \
return false; \
}
bool find_by_form(TCustomControl **out_view, py_customidamemo_t **out_py_view, const TForm *form) const FIND_BY__BODY(form, view, py_view);
bool find_by_view(TForm **out_form, py_customidamemo_t **out_py_view, const TCustomControl *view) const FIND_BY__BODY(view, form, py_view);
bool find_by_py_view(TForm **out_form, TCustomControl **out_view, const py_customidamemo_t *py_view) const FIND_BY__BODY(py_view, view, form);
#undef FIND_BY__BODY
bool del_by_py_view(const py_customidamemo_t *py_view)
{
for ( entries_t::iterator it = entries.begin(); it != entries.end(); ++it )
{
if ( it->py_view == py_view )
{
entries.erase(it);
return true;
}
}
return false;
}
private:
struct entry_t
{
TForm *form;
TCustomControl *view;
py_customidamemo_t *py_view;
};
typedef qvector<entry_t> entries_t;
entries_t entries;
};
//-------------------------------------------------------------------------
template <typename T>
T *view_extract_this(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_this(PyW_TryGetAttrString(self, S_M_THIS));
if ( py_this == NULL || !PyCObject_Check(py_this.o) )
return NULL;
return (T*) PyCObject_AsVoidPtr(py_this.o);
}
//-------------------------------------------------------------------------
class py_customidamemo_t
{
void convert_node_info(
node_info_t *out,
uint32 *out_flags,
ref_t py_nodeinfo)
{
if ( out_flags != NULL )
*out_flags = 0;
#define COPY_PROP(checker, converter, pname, flag) \
do \
{ \
newref_t pname(PyObject_GetAttrString(py_nodeinfo.o, #pname)); \
if ( pname != NULL && checker(pname.o) ) \
{ \
out->pname = converter(pname.o); \
if ( out_flags != NULL ) \
*out_flags |= flag; \
} \
} while ( false )
#define COPY_ULONG_PROP(pname, flag) COPY_PROP(PyNumber_Check, PyLong_AsUnsignedLong, pname, flag)
#define COPY_STRING_PROP(pname, flag) COPY_PROP(PyString_Check, PyString_AsString, pname, flag)
COPY_ULONG_PROP(bg_color, NIF_BG_COLOR);
COPY_ULONG_PROP(frame_color, NIF_FRAME_COLOR);
COPY_ULONG_PROP(ea, NIF_EA);
COPY_STRING_PROP(text, NIF_TEXT);
#undef COPY_STRING_PROP
#undef COPY_ULONG_PROP
#undef COPY_PROP
}
enum
{
GRBASE_HAVE_VIEW_ACTIVATED = 0x001,
GRBASE_HAVE_VIEW_DEACTIVATED = 0x002,
GRBASE_HAVE_KEYDOWN = 0x004,
GRBASE_HAVE_POPUP = 0x008,
GRBASE_HAVE_VIEW_CLICK = 0x010,
GRBASE_HAVE_VIEW_DBLCLICK = 0x020,
GRBASE_HAVE_VIEW_CURPOS = 0x040,
GRBASE_HAVE_CLOSE = 0x080,
GRBASE_HAVE_VIEW_SWITCHED = 0x100,
GRBASE_HAVE_VIEW_MOUSE_OVER = 0x200,
};
static void ensure_view_callbacks_installed();
int cb_flags;
protected:
ref_t self;
TCustomControl *view;
// This is called after having modified the
// node properties in the IDB. In case an
// implementation is performing some caching,
// this is a chance to update that cache.
// If 'ni' is NULL, then the node info was deleted.
virtual void node_info_modified(
int /*n*/,
const node_info_t * /*ni*/,
uint32 /*flags*/) {}
struct callback_id_t
{
qstring name;
int have;
};
struct callbacks_ids_t : public qvector<callback_id_t>
{
void add(const char *_n, int _h)
{
callback_id_t &o = push_back();
o.name = _n;
o.have = _h;
}
};
callbacks_ids_t cbids;
bool collect_pyobject_callbacks(PyObject *self);
virtual void collect_class_callbacks_ids(callbacks_ids_t *out);
// Bi-directionally bind/unbind the Python object and this controller.
bool bind(PyObject *_self, TCustomControl *view);
void unbind();
static lookup_info_t lookup_info;
public:
py_customidamemo_t();
virtual ~py_customidamemo_t();
virtual void refresh()
{
refresh_viewer(view);
}
void set_node_info(PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags);
void set_nodes_infos(PyObject *dict);
PyObject *get_node_info(PyObject *py_node_idx);
void del_nodes_infos(PyObject *py_nodes);
PyObject *get_current_renderer_type();
void set_current_renderer_type(PyObject *py_rto);
PyObject *create_groups(PyObject *groups_infos);
PyObject *delete_groups(PyObject *groups, PyObject *new_current);
PyObject *set_groups_visibility(PyObject *groups, PyObject *expand, PyObject *new_current);
// View events
void on_view_activated();
void on_view_deactivated();
void on_view_keydown(int key, int state);
void on_view_popup();
void on_view_click(const view_mouse_event_t *event);
void on_view_dblclick(const view_mouse_event_t *event);
void on_view_curpos();
void on_view_close();
void on_view_switched(tcc_renderer_type_t rt);
void on_view_mouse_over(const view_mouse_event_t *event);
inline bool has_callback(int flag) { return (cb_flags & flag) != 0; }
};
//-------------------------------------------------------------------------
py_customidamemo_t::py_customidamemo_t()
: self(newref_t(NULL)),
view(NULL)
{
PYGLOG("%p: py_customidamemo_t()\n", this);
ensure_view_callbacks_installed();
}
//-------------------------------------------------------------------------
py_customidamemo_t::~py_customidamemo_t()
{
PYGLOG("%p: ~py_customidamemo_t()\n", this);
unbind();
lookup_info.del_by_py_view(this);
}
//-------------------------------------------------------------------------
void py_customidamemo_t::ensure_view_callbacks_installed()
{
static bool installed = false;
if ( !installed )
{
struct ida_local lambda_t
{
static int idaapi callback(void * /*ud*/, int code, va_list va)
{
py_customidamemo_t *py_view;
if ( lookup_info.find_by_view(NULL, &py_view, va_arg(va, TCustomControl *)) )
{
PYW_GIL_GET;
switch ( code )
{
case view_activated:
py_view->on_view_activated();
break;
case view_deactivated:
py_view->on_view_deactivated();
break;
case view_keydown:
{
int key = va_arg(va, int);
int state = va_arg(va, int);
py_view->on_view_keydown(key, state);
}
break;
case view_popup:
py_view->on_view_popup();
break;
case view_click:
case view_dblclick:
{
const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*);
if ( code == view_click )
py_view->on_view_click(event);
else
py_view->on_view_dblclick(event);
}
break;
case view_curpos:
py_view->on_view_curpos();
break;
case view_close:
py_view->on_view_close();
delete py_view;
break;
case view_switched:
{
tcc_renderer_type_t rt = (tcc_renderer_type_t) va_arg(va, int);
py_view->on_view_switched(rt);
}
break;
case view_mouse_over:
{
const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*);
py_view->on_view_mouse_over(event);
}
break;
}
}
return 0;
}
};
hook_to_notification_point(HT_VIEW, lambda_t::callback, NULL);
installed = true;
}
}
//-------------------------------------------------------------------------
void py_customidamemo_t::set_node_info(
PyObject *py_node_idx,
PyObject *py_node_info,
PyObject *py_flags)
{
if ( !PyNumber_Check(py_node_idx) || !PyNumber_Check(py_flags) )
return;
borref_t py_idx(py_node_idx);
borref_t py_ni(py_node_info);
borref_t py_fl(py_flags);
node_info_t ni;
convert_node_info(&ni, NULL, py_ni);
int idx = PyInt_AsLong(py_idx.o);
uint32 flgs = PyLong_AsLong(py_fl.o);
viewer_set_node_info(view, idx, ni, flgs);
node_info_modified(idx, &ni, flgs);
}
//-------------------------------------------------------------------------
void py_customidamemo_t::set_nodes_infos(PyObject *dict)
{
if ( !PyDict_Check(dict) )
return;
Py_ssize_t pos = 0;
PyObject *o_key, *o_value;
while ( PyDict_Next(dict, &pos, &o_key, &o_value) )
{
borref_t key(o_key);
borref_t value(o_value);
if ( !PyNumber_Check(key.o) )
continue;
uint32 flags;
node_info_t ni;
convert_node_info(&ni, &flags, value);
int idx = PyInt_AsLong(key.o);
viewer_set_node_info(view, idx, ni, flags);
node_info_modified(idx, &ni, flags);
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::get_node_info(PyObject *py_node_idx)
{
if ( !PyNumber_Check(py_node_idx) )
Py_RETURN_NONE;
node_info_t ni;
if ( !viewer_get_node_info(view, &ni, PyInt_AsLong(py_node_idx)) )
Py_RETURN_NONE;
return Py_BuildValue("(kkks)", ni.bg_color, ni.frame_color, ni.ea, ni.text.c_str());
}
//-------------------------------------------------------------------------
void py_customidamemo_t::del_nodes_infos(PyObject *py_nodes)
{
if ( !PySequence_Check(py_nodes) )
return;
Py_ssize_t sz = PySequence_Size(py_nodes);
for ( Py_ssize_t i = 0; i < sz; ++i )
{
newref_t item(PySequence_GetItem(py_nodes, i));
if ( !PyNumber_Check(item.o) )
continue;
int idx = PyInt_AsLong(item.o);
viewer_del_node_info(view, idx);
node_info_modified(idx, NULL, 0);
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::get_current_renderer_type()
{
tcc_renderer_type_t rt = get_view_renderer_type(view);
return PyLong_FromLong(long(rt));
}
//-------------------------------------------------------------------------
void py_customidamemo_t::set_current_renderer_type(PyObject *py_rto)
{
tcc_renderer_type_t rt = TCCRT_INVALID;
borref_t py_rt(py_rto);
if ( PyNumber_Check(py_rt.o) )
{
rt = tcc_renderer_type_t(PyLong_AsLong(py_rt.o));
set_view_renderer_type(view, rt);
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::create_groups(PyObject *_groups_infos)
{
if ( !PySequence_Check(_groups_infos) )
Py_RETURN_NONE;
borref_t groups_infos(_groups_infos);
groups_crinfos_t gis;
Py_ssize_t sz = PySequence_Size(groups_infos.o);
for ( Py_ssize_t i = 0; i < sz; ++i )
{
newref_t item(PySequence_GetItem(groups_infos.o, i));
if ( !PyDict_Check(item.o) )
continue;
borref_t nodes(PyDict_GetItemString(item.o, "nodes"));
if ( nodes.o == NULL || !PySequence_Check(nodes.o) )
continue;
borref_t text(PyDict_GetItemString(item.o, "text"));
if ( text.o == NULL || !PyString_Check(text.o) )
continue;
group_crinfo_t gi;
Py_ssize_t nodes_cnt = PySequence_Size(nodes.o);
for ( Py_ssize_t k = 0; k < nodes_cnt; ++k )
{
newref_t node(PySequence_GetItem(nodes.o, k));
if ( PyInt_Check(node.o) )
gi.nodes.insert(PyInt_AsLong(node.o));
}
if ( !gi.nodes.empty() )
{
gi.text = PyString_AsString(text.o);
gis.push_back(gi);
}
}
intset_t groups;
if ( gis.empty() || !viewer_create_groups(view, &groups, gis) || groups.empty() )
Py_RETURN_NONE;
PyObject *py_groups = PyList_New(0);
for ( intset_t::const_iterator it = groups.begin(); it != groups.end(); ++it )
PyList_Append(py_groups, PyInt_FromLong(long(*it)));
return py_groups;
}
//-------------------------------------------------------------------------
static void pynodes_to_idanodes(intset_t *idanodes, ref_t pynodes)
{
Py_ssize_t sz = PySequence_Size(pynodes.o);
for ( Py_ssize_t i = 0; i < sz; ++i )
{
newref_t item(PySequence_GetItem(pynodes.o, i));
if ( !PyInt_Check(item.o) )
continue;
idanodes->insert(PyInt_AsLong(item.o));
}
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::delete_groups(PyObject *_groups, PyObject *_new_current)
{
if ( !PySequence_Check(_groups) || !PyNumber_Check(_new_current) )
Py_RETURN_NONE;
borref_t groups(_groups);
borref_t new_current(_new_current);
intset_t ida_groups;
pynodes_to_idanodes(&ida_groups, groups);
if ( ida_groups.empty() )
Py_RETURN_NONE;
if ( viewer_delete_groups(view, ida_groups, int(PyInt_AsLong(new_current.o))) )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
//-------------------------------------------------------------------------
PyObject *py_customidamemo_t::set_groups_visibility(PyObject *_groups, PyObject *_expand, PyObject *_new_current)
{
if ( !PySequence_Check(_groups)
|| !PyBool_Check(_expand)
|| !PyNumber_Check(_new_current) )
Py_RETURN_NONE;
borref_t groups(_groups);
borref_t expand(_expand);
borref_t new_current(_new_current);
intset_t ida_groups;
pynodes_to_idanodes(&ida_groups, groups);
if ( ida_groups.empty() )
Py_RETURN_NONE;
if ( viewer_set_groups_visibility(view, ida_groups, expand.o == Py_True, int(PyInt_AsLong(new_current.o))) )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
//-------------------------------------------------------------------------
bool py_customidamemo_t::bind(PyObject *_self, TCustomControl *view)
{
if ( this->self != NULL || this->view != NULL )
return false;
PYGLOG("%p: py_customidamemo_t::bind(_self=%p, view=%p)\n", this, _self, view);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_cobj(PyCObject_FromVoidPtr(this, NULL));
PyObject_SetAttrString(_self, S_M_THIS, py_cobj.o);
this->self = borref_t(_self);
this->view = view;
return true;
}
//-------------------------------------------------------------------------
void py_customidamemo_t::unbind()
{
if ( self == NULL )
return;
PYGLOG("%p: py_customidamemo_t::unbind(); self.o=%p, view=%p\n", this, self.o, view);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_cobj(PyCObject_FromVoidPtr(NULL, NULL));
PyObject_SetAttrString(self.o, S_M_THIS, py_cobj.o);
self = newref_t(NULL);
view = NULL;
}
//-------------------------------------------------------------------------
void py_customidamemo_t::collect_class_callbacks_ids(callbacks_ids_t *out)
{
out->add(S_ON_VIEW_ACTIVATED, GRBASE_HAVE_VIEW_ACTIVATED);
out->add(S_ON_VIEW_DEACTIVATED, GRBASE_HAVE_VIEW_DEACTIVATED);
out->add(S_ON_VIEW_KEYDOWN, GRBASE_HAVE_KEYDOWN);
out->add(S_ON_POPUP, GRBASE_HAVE_POPUP);
out->add(S_ON_VIEW_CLICK, GRBASE_HAVE_VIEW_CLICK);
out->add(S_ON_VIEW_DBLCLICK, GRBASE_HAVE_VIEW_DBLCLICK);
out->add(S_ON_VIEW_CURPOS, GRBASE_HAVE_VIEW_CURPOS);
out->add(S_ON_CLOSE, GRBASE_HAVE_CLOSE);
out->add(S_ON_VIEW_SWITCHED, GRBASE_HAVE_VIEW_SWITCHED);
out->add(S_ON_VIEW_MOUSE_OVER, GRBASE_HAVE_VIEW_MOUSE_OVER);
}
//-------------------------------------------------------------------------
bool py_customidamemo_t::collect_pyobject_callbacks(PyObject *o)
{
callbacks_ids_t cbids;
collect_class_callbacks_ids(&cbids);
cb_flags = 0;
for ( callbacks_ids_t::const_iterator it = cbids.begin(); it != cbids.end(); ++it )
{
const callback_id_t &cbid = *it;
ref_t attr(PyW_TryGetAttrString(o, cbid.name.c_str()));
int have = cbid.have;
// Mandatory fields not present?
if ( (attr == NULL && have <= 0 )
// Mandatory callback fields present but not callable?
|| (attr != NULL && have >= 0 && PyCallable_Check(attr.o) == 0))
{
return false;
}
if ( have > 0 && attr != NULL )
cb_flags |= have;
}
return true;
}
//-------------------------------------------------------------------------
#define CHK_EVT(flag_needed) \
if ( self == NULL || !has_callback(flag_needed) ) \
return; \
PYW_GIL_CHECK_LOCKED_SCOPE()
#ifdef PYGDBG_ENABLED
#define CHK_RES() PYGLOG("%s: return code: %p\n", __FUNCTION__, result.o)
#else
#define CHK_RES()
#endif
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_activated()
{
CHK_EVT(GRBASE_HAVE_VIEW_ACTIVATED);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_ACTIVATED,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_deactivated()
{
CHK_EVT(GRBASE_HAVE_VIEW_DEACTIVATED);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_DEACTIVATED,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_keydown(int key, int state)
{
CHK_EVT(GRBASE_HAVE_KEYDOWN);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_KEYDOWN,
"ii",
key, state));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_popup()
{
CHK_EVT(GRBASE_HAVE_POPUP);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_POPUP,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_click(const view_mouse_event_t *event)
{
CHK_EVT(GRBASE_HAVE_VIEW_CLICK);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_CLICK,
"iii",
event->x, event->y, event->state));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_dblclick(const view_mouse_event_t *event)
{
CHK_EVT(GRBASE_HAVE_VIEW_DBLCLICK);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_DBLCLICK,
"iii",
event->x, event->y, event->state));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_curpos()
{
CHK_EVT(GRBASE_HAVE_VIEW_CURPOS);
newref_t result(
PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_CURPOS,
NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_close()
{
CHK_EVT(GRBASE_HAVE_CLOSE);
newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_CLOSE, NULL));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_switched(tcc_renderer_type_t rt)
{
CHK_EVT(GRBASE_HAVE_VIEW_SWITCHED);
newref_t result(PyObject_CallMethod(self.o, (char *)S_ON_VIEW_SWITCHED, "i", int(rt)));
CHK_RES();
}
//-------------------------------------------------------------------------
void py_customidamemo_t::on_view_mouse_over(const view_mouse_event_t *event)
{
CHK_EVT(GRBASE_HAVE_VIEW_MOUSE_OVER);
if ( event->rtype == TCCRT_GRAPH || event->rtype == TCCRT_PROXIMITY )
{
const selection_item_t *item = event->location.item;
int icode;
ref_t tuple;
if ( item != NULL )
{
if ( item->is_node )
{
icode = 1;
tuple = newref_t(Py_BuildValue("(i)", item->node));
}
else
{
icode = 2;
tuple = newref_t(Py_BuildValue("(ii)", item->elp.e.src, item->elp.e.dst));
}
}
else
{
icode = 0;
tuple = newref_t(Py_BuildValue("()"));
}
newref_t result(PyObject_CallMethod(
self.o,
(char *)S_ON_VIEW_MOUSE_OVER,
"iiiiO",
event->x, event->y, event->state, icode, tuple.o));
CHK_RES();
}
}
#undef CHK_RES
#undef CHK_EVT
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
#define GET_THIS() py_customidamemo_t *_this = view_extract_this<py_customidamemo_t>(self)
#define CHK_THIS() \
GET_THIS(); \
if ( _this == NULL ) \
return
#define CHK_THIS_OR_NONE() \
GET_THIS(); \
if ( _this == NULL ) \
Py_RETURN_NONE
//-------------------------------------------------------------------------
void pygc_refresh(PyObject *self)
{
CHK_THIS();
_this->refresh();
}
//-------------------------------------------------------------------------
void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags)
{
CHK_THIS();
_this->set_node_info(py_node_idx, py_node_info, py_flags);
}
//-------------------------------------------------------------------------
void pygc_set_nodes_infos(PyObject *self, PyObject *values)
{
CHK_THIS();
_this->set_nodes_infos(values);
}
//-------------------------------------------------------------------------
PyObject *pygc_get_node_info(PyObject *self, PyObject *py_node_idx)
{
GET_THIS();
if ( _this != NULL )
return _this->get_node_info(py_node_idx);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
void pygc_del_nodes_infos(PyObject *self, PyObject *py_nodes)
{
CHK_THIS();
_this->del_nodes_infos(py_nodes);
}
//-------------------------------------------------------------------------
PyObject *pygc_get_current_renderer_type(PyObject *self)
{
GET_THIS();
if ( _this != NULL )
return _this->get_current_renderer_type();
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt)
{
CHK_THIS();
_this->set_current_renderer_type(py_rt);
}
//-------------------------------------------------------------------------
PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos)
{
CHK_THIS_OR_NONE();
return _this->create_groups(groups_infos);
}
//-------------------------------------------------------------------------
PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current)
{
CHK_THIS_OR_NONE();
return _this->delete_groups(groups, new_current);
}
//-------------------------------------------------------------------------
PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current)
{
CHK_THIS_OR_NONE();
return _this->set_groups_visibility(groups, expand, new_current);
}
#undef CHK_THIS_OR_NONE
#undef CHK_THIS
#undef GET_THIS
//-------------------------------------------------------------------------
lookup_info_t py_customidamemo_t::lookup_info;
//</code(py_view_base)>
//<inline(py_view_base)>
void pygc_refresh(PyObject *self);
void pygc_set_node_info(PyObject *self, PyObject *py_node_idx, PyObject *py_node_info, PyObject *py_flags);
void pygc_set_nodes_infos(PyObject *self, PyObject *values);
PyObject *pygc_get_node_info(PyObject *self, PyObject *py_node_idx);
void pygc_del_nodes_infos(PyObject *self, PyObject *py_nodes);
PyObject *pygc_get_current_renderer_type(PyObject *self);
void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt);
PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos);
PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current);
PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current);
//</inline(py_view_base)>
#endif // __PY_VIEW_BASE__

107
pywraps/py_view_base.py Normal file
View File

@ -0,0 +1,107 @@
#<pycode(py_view_base)>
class CustomIDAMemo(object):
def Refresh(self):
"""
Refreshes the graph. This causes the OnRefresh() to be called
"""
_idaapi.pygc_refresh(self)
def GetCurrentRendererType(self):
return _idaapi.pygc_get_current_renderer_type(self)
def SetCurrentRendererType(self, rtype):
"""
Set the current view's renderer.
@param rtype: The renderer type. Should be one of the idaapi.TCCRT_* values.
"""
_idaapi.pygc_set_current_renderer_type(self, rtype)
def SetNodeInfo(self, node_index, node_info, flags):
"""
Set the properties for the given node.
Example usage (set second nodes's bg color to red):
inst = ...
p = idaapi.node_info_t()
p.bg_color = 0x00ff0000
inst.SetNodeInfo(1, p, idaapi.NIF_BG_COLOR)
@param node_index: The node index.
@param node_info: An idaapi.node_info_t instance.
@param flags: An OR'ed value of NIF_* values.
"""
_idaapi.pygc_set_node_info(self, node_index, node_info, flags)
def SetNodesInfos(self, values):
"""
Set the properties for the given nodes.
Example usage (set first three nodes's bg color to purple):
inst = ...
p = idaapi.node_info_t()
p.bg_color = 0x00ff00ff
inst.SetNodesInfos({0 : p, 1 : p, 2 : p})
@param values: A dictionary of 'int -> node_info_t' objects.
"""
_idaapi.pygc_set_nodes_infos(self, values)
def GetNodeInfo(self, node):
"""
Get the properties for the given node.
@param node: The index of the node.
@return: A tuple (bg_color, frame_color, ea, text), or None.
"""
return _idaapi.pygc_get_node_info(self, node)
def DelNodesInfos(self, *nodes):
"""
Delete the properties for the given node(s).
@param nodes: A list of node IDs
"""
return _idaapi.pygc_del_nodes_infos(self, nodes)
def CreateGroups(self, groups_infos):
"""
Send a request to modify the graph by creating a
(set of) group(s), and perform an animation.
Each object in the 'groups_infos' list must be of the format:
{
"nodes" : [<int>, <int>, <int>, ...] # The list of nodes to group
"text" : <string> # The synthetic text for that group
}
@param groups_infos: A list of objects that describe those groups.
@return: A [<int>, <int>, ...] list of group nodes, or None (failure).
"""
return _idaapi.pygc_create_groups(self, groups_infos)
def DeleteGroups(self, groups, new_current = -1):
"""
Send a request to delete the specified groups in the graph,
and perform an animation.
@param groups: A list of group node numbers.
@param new_current: A node to focus on after the groups have been deleted
@return: True on success, False otherwise.
"""
return _idaapi.pygc_delete_groups(self, groups, new_current)
def SetGroupsVisibility(self, groups, expand, new_current = -1):
"""
Send a request to expand/collapse the specified groups in the graph,
and perform an animation.
@param groups: A list of group node numbers.
@param expand: True to expand the group, False otherwise.
@param new_current: A node to focus on after the groups have been expanded/collapsed.
@return: True on success, False otherwise.
"""
return _idaapi.pygc_set_groups_visibility(self, groups, expand, new_current)
#</pycode(py_view_base)>

View File

@ -90,6 +90,10 @@ class processor_t(object):
# ----------------------------------------------------------------------
BADADDR = 0xFFFFFFFFFFFFFFFFL
# ----------------------------------------------------------------------
UA_MAXOP = 6
o_last = 14
o_void = 0
# ----------------------------------------------------------------------
"""

View File

@ -1,27 +1,17 @@
%ignore sarray;
%ignore lastreq_t;
%ignore AREA_CACHE_SIZE;
%ignore ANODE;
%ignore ANODE2;
%ignore AREA_LONG_COMMENT_TAG;
%ignore area_visitor_t;
%ignore areacb_t_link_dont_load;
%ignore add_area_from_cache;
%ignore areacb_t_valid_push_back;
// Ignore the private members in areacb_t
%ignore areacb_t::areasCode;
%ignore areacb_t::infosize;
%ignore areacb_t::lastreq;
%ignore areacb_t::reserved;
%ignore areacb_t::sa;
%ignore areacb_t::cache;
%ignore areacb_t::allocate;
%ignore areacb_t::search;
%ignore areacb_t::readArea;
%ignore areacb_t::findCache;
%ignore areacb_t::addCache;
%ignore areacb_t::delCache;
%ignore areacb_t::free_cache;
%ignore areacb_t::find_nth_start;
%ignore areacb_t::build_optimizer;
%ignore areacb_t::areas;
%ignore areacb_t::move_area_comment;
%ignore areacb_t::pack_and_write_area;
%ignore areacb_t::move_away;

View File

@ -102,20 +102,17 @@
//------------------------------------------------------------------------
static bool idaapi py_testf_cb(flags_t flags, void *ud)
{
PyObject *py_flags = PyLong_FromUnsignedLong(flags);
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags, NULL);
PYW_GIL_RELEASE;
bool ret = result != NULL && PyObject_IsTrue(result);
Py_XDECREF(result);
Py_XDECREF(py_flags);
return ret;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_flags(PyLong_FromUnsignedLong(flags));
newref_t result(PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags.o, NULL));
return result != NULL && PyObject_IsTrue(result.o);
}
//------------------------------------------------------------------------
// Wraps the (next|prev)that()
static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_callable) )
return BADADDR;
else
@ -130,20 +127,17 @@ static int idaapi py_visit_patched_bytes_cb(
uint32 v,
void *ud)
{
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunction(
(PyObject *)ud,
PY_FMT64 "iII",
pyul_t(ea),
fpos,
o,
v);
PYW_GIL_RELEASE;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
PyObject_CallFunction(
(PyObject *)ud,
PY_FMT64 "iII",
pyul_t(ea),
fpos,
o,
v));
PyW_ShowCbErr("visit_patched_bytes");
int ret = (py_result != NULL && PyInt_Check(py_result)) ? PyInt_AsLong(py_result) : 0;
Py_XDECREF(py_result);
return ret;
return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0;
}
@ -163,20 +157,18 @@ class py_custom_data_type_t
size_t nbytes) // size of the future item
{
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_MAY_CREATE_AT,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(nbytes));
PYW_GIL_RELEASE;
PYW_GIL_GET;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_MAY_CREATE_AT,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(nbytes)));
PyW_ShowCbErr(S_MAY_CREATE_AT);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
return py_result != NULL && PyObject_IsTrue(py_result.o);
}
// !=NULL means variable size datatype
@ -187,24 +179,23 @@ class py_custom_data_type_t
ea_t ea, // address of the item
asize_t maxsize) // maximal size of the item
{
PYW_GIL_GET;
// Returns: 0-no such item can be created/displayed
// this callback is required only for varsize datatypes
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_CALC_ITEM_SIZE,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(maxsize));
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_CALC_ITEM_SIZE,
PY_FMT64 PY_FMT64,
pyul_t(ea),
pyul_t(maxsize)));
if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL )
return 0;
uint64 num = 0;
PyW_GetNumber(py_result, &num);
Py_XDECREF(py_result);
PyW_GetNumber(py_result.o, &num);
return asize_t(num);
}
@ -222,6 +213,8 @@ public:
int register_dt(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Already registered?
if ( dtid >= 0 )
return dtid;
@ -230,9 +223,10 @@ public:
dt.cbsize = sizeof(dt);
dt.ud = this;
PyObject *py_attr = NULL;
do
{
ref_t py_attr;
// name
if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) )
break;
@ -253,30 +247,27 @@ public:
// value_size
py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE);
if ( py_attr != NULL && PyInt_Check(py_attr) )
dt.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
dt.value_size = PyInt_AsLong(py_attr.o);
py_attr = ref_t();
// props
py_attr = PyW_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL && PyInt_Check(py_attr) )
dt.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
dt.props = PyInt_AsLong(py_attr.o);
py_attr = ref_t();
// may_create_at
py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
dt.may_create_at = s_may_create_at;
Py_XDECREF(py_attr);
py_attr = ref_t();
// calc_item_size
py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
dt.calc_item_size = s_calc_item_size;
Py_XDECREF(py_attr);
// Clear attribute
py_attr = NULL;
py_attr = ref_t();
// Now try to register
dtid = register_custom_data_type(&dt);
@ -287,20 +278,16 @@ public:
Py_INCREF(py_obj);
py_self = py_obj;
py_attr = PyInt_FromLong(dtid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
// Done with attribute
py_attr = NULL;
py_attr = newref_t(PyInt_FromLong(dtid));
PyObject_SetAttrString(py_obj, S_ID, py_attr.o);
} while ( false );
Py_XDECREF(py_attr);
return dtid;
}
bool unregister_dt()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dtid < 0 )
return true;
@ -340,44 +327,41 @@ private:
int operand_num, // current operand number
int dtid) // custom data type id
{
PYW_GIL_GET;
// Build a string from the buffer
PyObject *py_value = PyString_FromStringAndSize(
(const char *)value,
Py_ssize_t(size));
newref_t py_value(PyString_FromStringAndSize(
(const char *)value,
Py_ssize_t(size)));
if ( py_value == NULL )
return false;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value,
pyul_t(current_ea),
operand_num,
dtid);
PYW_GIL_RELEASE;
// Done with the string
Py_DECREF(py_value);
newref_t py_result(PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value.o,
pyul_t(current_ea),
operand_num,
dtid));
// Error while calling the function?
if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL )
return false;
bool ok = false;
if ( PyString_Check(py_result) )
if ( PyString_Check(py_result.o) )
{
Py_ssize_t len;
char *buf;
if ( out != NULL && PyString_AsStringAndSize(py_result, &buf, &len) != -1 )
if ( out != NULL && PyString_AsStringAndSize(py_result.o, &buf, &len) != -1 )
{
out->qclear();
out->append(buf, len);
}
ok = true;
}
Py_DECREF(py_result);
return ok;
}
@ -389,16 +373,17 @@ private:
int operand_num, // current operand number (-1 if unknown)
qstring *errstr) // buffer for error message
{
PYW_GIL_GET;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num);
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num));
// Error while calling the function?
if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL)
@ -408,15 +393,14 @@ private:
do
{
// We expect a tuple(bool, string|None)
if ( !PyTuple_Check(py_result) || PyTuple_Size(py_result) != 2 )
if ( !PyTuple_Check(py_result.o) || PyTuple_Size(py_result.o) != 2 )
break;
// Borrow references
PyObject *py_bool = PyTuple_GetItem(py_result, 0);
PyObject *py_val = PyTuple_GetItem(py_result, 1);
borref_t py_bool(PyTuple_GetItem(py_result.o, 0));
borref_t py_val(PyTuple_GetItem(py_result.o, 1));
// Get return code from Python
ok = PyObject_IsTrue(py_bool);
ok = PyObject_IsTrue(py_bool.o);
// We expect None or the value (depending on probe)
if ( ok )
@ -427,7 +411,7 @@ private:
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_val, &buf, &len) != -1 )
if ( PyString_AsStringAndSize(py_val.o, &buf, &len) != -1 )
{
value->qclear();
value->append(buf, len);
@ -437,16 +421,15 @@ private:
else
{
// Make sure the user returned (False, String)
if ( py_bool != Py_False || !PyString_Check(py_val) )
if ( py_bool.o != Py_False || !PyString_Check(py_val.o) )
{
*errstr = "Invalid return value returned from the Python callback!";
break;
}
// Get the error message
*errstr = PyString_AsString(py_val);
*errstr = PyString_AsString(py_val.o);
}
} while ( false );
Py_DECREF(py_result);
return ok;
}
@ -458,19 +441,18 @@ private:
// xrefs from the current item.
// this callback may be missing.
{
PYW_GIL_GET;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_ANALYZE,
PY_FMT64 "i",
pyul_t(current_ea),
operand_num);
PYW_GIL_RELEASE;
newref_t py_result(
PyObject_CallMethod(
_this->py_self,
(char *)S_ANALYZE,
PY_FMT64 "i",
pyul_t(current_ea),
operand_num));
PyW_ShowCbErr(S_ANALYZE);
Py_XDECREF(py_result);
}
public:
py_custom_data_format_t()
@ -479,9 +461,9 @@ public:
py_self = NULL;
}
const char *get_name() const
{
return df_name.c_str();
const char *get_name() const
{
return df_name.c_str();
}
int register_df(int dtid, PyObject *py_obj)
@ -493,10 +475,12 @@ public:
memset(&df, 0, sizeof(df));
df.cbsize = sizeof(df);
df.ud = this;
PyObject *py_attr = NULL;
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
ref_t py_attr;
// name
if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) )
break;
@ -508,9 +492,8 @@ public:
// props
py_attr = PyW_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.props = PyInt_AsLong(py_attr.o);
// hotkey
if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) )
@ -518,36 +501,28 @@ public:
// value_size
py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.value_size = PyInt_AsLong(py_attr.o);
// text_width
py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH);
if ( py_attr != NULL && PyInt_Check(py_attr) )
df.text_width = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
if ( py_attr != NULL && PyInt_Check(py_attr.o) )
df.text_width = PyInt_AsLong(py_attr.o);
// print cb
py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
df.print = s_print;
Py_XDECREF(py_attr);
// scan cb
py_attr = PyW_TryGetAttrString(py_obj, S_SCAN);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
df.scan = s_scan;
Py_XDECREF(py_attr);
// analyze cb
py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
if ( py_attr != NULL && PyCallable_Check(py_attr.o) )
df.analyze = s_analyze;
Py_XDECREF(py_attr);
// Done with attribute
py_attr = NULL;
// Now try to register
dfid = register_custom_data_format(dtid, &df);
@ -559,19 +534,16 @@ public:
py_self = py_obj;
// Update the format ID
py_attr = PyInt_FromLong(dfid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
py_attr = NULL;
py_attr = newref_t(PyInt_FromLong(dfid));
PyObject_SetAttrString(py_obj, S_ID, py_attr.o);
} while ( false );
Py_XDECREF(py_attr);
return dfid;
}
bool unregister_df(int dtid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Never registered?
if ( dfid < 0 )
return true;
@ -635,6 +607,8 @@ static py_custom_data_format_list_t py_df_list;
//------------------------------------------------------------------------
static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("{s:" PY_FMT64 ",s:i,s:i,s:s,s:s,s:s,s:s}",
S_VALUE_SIZE, pyul_t(dt->value_size),
S_PROPS, dt->props,
@ -648,6 +622,8 @@ static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
//------------------------------------------------------------------------
static PyObject *py_data_format_to_py_dict(const data_format_t *df)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("{s:i,s:i,s:i,s:" PY_FMT64 ",s:s,s:s,s:s}",
S_PROPS, df->props,
S_CBSIZE, df->cbsize,
@ -684,6 +660,7 @@ def visit_patched_bytes(ea1, ea2, callable):
*/
static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_callable) )
return 0;
else
@ -732,29 +709,23 @@ def get_many_bytes(ea, size):
*/
static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
if ( size <= 0 )
break;
// Allocate memory via Python
PyObject *py_buf = PyString_FromStringAndSize(NULL, Py_ssize_t(size));
newref_t py_buf(PyString_FromStringAndSize(NULL, Py_ssize_t(size)));
if ( py_buf == NULL )
break;
// Read bytes
bool ok = get_many_bytes(ea, PyString_AsString(py_buf), size);
if ( !get_many_bytes(ea, PyString_AsString(py_buf.o), size) )
Py_RETURN_NONE;
// If failed, dispose the Python string
if ( !ok )
{
Py_DECREF(py_buf);
py_buf = Py_None;
Py_INCREF(py_buf);
}
return py_buf;
py_buf.incref();
return py_buf.o;
} while ( false );
Py_RETURN_NONE;
}
@ -805,9 +776,11 @@ static PyObject *py_get_ascii_contents2(
}
if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' )
used_size--;
PyObject *py_buf = PyString_FromStringAndSize((const char *)buf, used_size);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_buf(PyString_FromStringAndSize((const char *)buf, used_size));
qfree(buf);
return py_buf;
py_buf.incref();
return py_buf.o;
}
//---------------------------------------------------------------------------
/*
@ -987,6 +960,7 @@ def get_custom_data_format(dtid, dfid):
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_format(int dtid, int fid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
const data_format_t *df = get_custom_data_format(dtid, fid);
if ( df == NULL )
Py_RETURN_NONE;
@ -1007,6 +981,7 @@ def get_custom_data_type(dtid):
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_type(int dtid)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
const data_type_t *dt = get_custom_data_type(dtid);
if ( dt == NULL )
Py_RETURN_NONE;

View File

@ -25,7 +25,14 @@ typedef struct
%rename (get_manual_regions) py_get_manual_regions;
%ignore set_manual_regions;
%ignore inform_idc_about_debthread;
%ignore is_dbgmem_valid;
// We want ALL wrappers around what is declared in dbg.hpp
// to release the GIL when calling into the IDA api: those
// might be very long operations, that even require some
// network traffic.
%thread;
%include "dbg.hpp"
%nothread;
%ignore DBG_Callback;
%feature("director") DBG_Hooks;
@ -112,6 +119,7 @@ static PyObject *refresh_debugger_memory()
// Invalidate the cache
isEnabled(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
@ -119,74 +127,78 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
public:
virtual ~DBG_Hooks() { unhook(); };
virtual ~DBG_Hooks() { unhook(); }
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); };
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); };
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); }
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); }
/* Hook functions to be overridden in Python */
virtual void dbg_process_start(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
asize_t size) {}
virtual void dbg_process_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
int exit_code) {}
virtual void dbg_process_attach(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
asize_t size) {}
virtual void dbg_process_detach(pid_t pid,
thid_t tid,
ea_t ea) { };
ea_t ea) {}
virtual void dbg_thread_start(pid_t pid,
thid_t tid,
ea_t ea) { };
ea_t ea) {}
virtual void dbg_thread_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
int exit_code) {}
virtual void dbg_library_load(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
asize_t size) {}
virtual void dbg_library_unload(pid_t pid,
thid_t tid,
ea_t ea,
char *libname) { };
char *libname) {}
virtual void dbg_information(pid_t pid,
thid_t tid,
ea_t ea,
char *info) { };
char *info) {}
virtual int dbg_exception(pid_t pid,
thid_t tid,
ea_t ea,
int code,
bool can_cont,
ea_t exc_ea,
char *info) { return 0; };
virtual void dbg_suspend_process(void) { };
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; };
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; };
char *info) { return 0; }
virtual void dbg_suspend_process(void) {}
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; }
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; }
virtual void dbg_request_error(int failed_command,
int failed_dbg_notification) { };
virtual void dbg_step_into(void) { };
virtual void dbg_step_over(void) { };
virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) { };
virtual void dbg_step_until_ret(void) { };
int failed_dbg_notification) {}
virtual void dbg_step_into(void) {}
virtual void dbg_step_over(void) {}
virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) {}
virtual void dbg_step_until_ret(void) {}
};
int idaapi DBG_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class DBG_Hooks *proxy = (class DBG_Hooks *)ud;
debug_event_t *event;
int code = 0;
try
{
switch (notification_code)

View File

@ -49,17 +49,17 @@
//--------------------------------------------------------------------------
int idaapi py_enumerate_files_cb(const char *file, void *ud)
{
PyObject *py_file = PyString_FromString(file);
PYW_GIL_ENSURE;
PyObject *py_ret = PyObject_CallFunctionObjArgs(
(PyObject *)ud,
py_file,
NULL);
PYW_GIL_RELEASE;
int r = (py_ret == NULL || !PyNumber_Check(py_ret)) ? 1 /* stop enumeration on failure */ : PyInt_AsLong(py_ret);
Py_XDECREF(py_file);
Py_XDECREF(py_ret);
return r;
// No need to 'PYW_GIL_GET' here, as this is called synchronously
// and from the same thread as the one that executes
// 'py_enumerate_files'.
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_file(PyString_FromString(file));
newref_t py_ret(
PyObject_CallFunctionObjArgs(
(PyObject *)ud,
py_file.o,
NULL));
return (py_ret == NULL || !PyNumber_Check(py_ret.o)) ? 1 /* stop enum on failure */ : PyInt_AsLong(py_ret.o);
}
//</code(py_diskio)>
%}
@ -173,6 +173,7 @@ private:
//--------------------------------------------------------------------------
void _from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
this->set_linput((linput_t *)PyCObject_AsVoidPtr(pycobject));
}
@ -196,6 +197,7 @@ public:
//--------------------------------------------------------------------------
loader_input_t(PyObject *pycobject = NULL): li(NULL), own(OWN_NONE), __idc_cvt_id__(PY_ICID_OPAQUE)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( pycobject != NULL && PyCObject_Check(pycobject) )
_from_cobject(pycobject);
}
@ -206,11 +208,13 @@ public:
if ( li == NULL )
return;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
if ( own == OWN_CREATE )
close_linput(li);
else if ( own == OWN_FROM_FP )
unmake_linput(li);
Py_END_ALLOW_THREADS;
li = NULL;
own = OWN_NONE;
}
@ -225,14 +229,17 @@ public:
bool open(const char *filename, bool remote = false)
{
close();
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
li = open_linput(filename, remote);
if ( li == NULL )
return false;
// Save file name
fn = filename;
own = OWN_CREATE;
return true;
if ( li != NULL )
{
// Save file name
fn = filename;
own = OWN_CREATE;
}
Py_END_ALLOW_THREADS;
return li != NULL;
}
//--------------------------------------------------------------------------
@ -256,6 +263,7 @@ public:
// This method can be used to pass a linput_t* from C code
static loader_input_t *from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(pycobject) )
return NULL;
loader_input_t *l = new loader_input_t();
@ -266,14 +274,18 @@ public:
//--------------------------------------------------------------------------
static loader_input_t *from_fp(FILE *fp)
{
PYW_GIL_GET;
loader_input_t *l = NULL;
Py_BEGIN_ALLOW_THREADS;
linput_t *fp_li = make_linput(fp);
if ( fp_li == NULL )
return NULL;
loader_input_t *l = new loader_input_t();
l->own = OWN_FROM_FP;
l->fn.sprnt("<FILE * %p>", fp);
l->li = fp_li;
if ( fp_li != NULL )
{
l = new loader_input_t();
l->own = OWN_FROM_FP;
l->fn.sprnt("<FILE * %p>", fp);
l->li = fp_li;
}
Py_END_ALLOW_THREADS;
return l;
}
@ -286,37 +298,55 @@ public:
//--------------------------------------------------------------------------
bool open_memory(ea_t start, asize_t size = 0)
{
linput_t *l = create_memory_linput(start, size);
if ( l == NULL )
return false;
close();
li = l;
fn = "<memory>";
own = OWN_CREATE;
return true;
PYW_GIL_GET;
linput_t *l;
Py_BEGIN_ALLOW_THREADS;
l = create_memory_linput(start, size);
if ( l != NULL )
{
close();
li = l;
fn = "<memory>";
own = OWN_CREATE;
}
Py_END_ALLOW_THREADS;
return l != NULL;
}
//--------------------------------------------------------------------------
int32 seek(int32 pos, int whence = SEEK_SET)
{
return qlseek(li, pos, whence);
int32 r;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
r = qlseek(li, pos, whence);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
int32 tell()
{
return qltell(li);
int32 r;
PYW_GIL_GET;
Py_BEGIN_ALLOW_THREADS;
r = qltell(li);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
PyObject *getz(size_t sz, int32 fpos = -1)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(sz + 5);
if ( buf == NULL )
break;
Py_BEGIN_ALLOW_THREADS;
qlgetz(li, fpos, buf, sz);
Py_END_ALLOW_THREADS;
PyObject *ret = PyString_FromString(buf);
free(buf);
return ret;
@ -327,12 +357,17 @@ public:
//--------------------------------------------------------------------------
PyObject *gets(size_t len)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(len + 5);
if ( buf == NULL )
break;
if ( qlgets(buf, len, li) == NULL )
bool ok;
Py_BEGIN_ALLOW_THREADS;
ok = qlgets(buf, len, li) != NULL;
Py_END_ALLOW_THREADS;
if ( !ok )
{
free(buf);
break;
@ -347,12 +382,16 @@ public:
//--------------------------------------------------------------------------
PyObject *read(size_t size)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
ssize_t r = qlread(li, buf, size);
ssize_t r;
Py_BEGIN_ALLOW_THREADS;
r = qlread(li, buf, size);
Py_END_ALLOW_THREADS;
if ( r == -1 )
{
free(buf);
@ -374,12 +413,16 @@ public:
//--------------------------------------------------------------------------
PyObject *readbytes(size_t size, bool big_endian)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = lreadbytes(li, buf, size, big_endian);
int r;
Py_BEGIN_ALLOW_THREADS;
r = lreadbytes(li, buf, size, big_endian);
Py_END_ALLOW_THREADS;
if ( r == -1 )
{
free(buf);
@ -395,25 +438,38 @@ public:
//--------------------------------------------------------------------------
int file2base(int32 pos, ea_t ea1, ea_t ea2, int patchable)
{
return ::file2base(li, pos, ea1, ea2, patchable);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = ::file2base(li, pos, ea1, ea2, patchable);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 size()
{
return qlsize(li);
int32 rc;
Py_BEGIN_ALLOW_THREADS;
rc = qlsize(li);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
PyObject *filename()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qlgetc(li);
PYW_GIL_CHECK_LOCKED_SCOPE();
int ch;
Py_BEGIN_ALLOW_THREADS;
ch = qlgetc(li);
Py_END_ALLOW_THREADS;
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
@ -432,7 +488,7 @@ def enumerate_files(path, fname, callback):
@param callback: a callable object that takes the filename as
its first argument and it returns 0 to continue
enumeration or non-zero to stop enumeration.
@return:
@return:
None in case of script errors
tuple(code, fname) : If the callback returns non-zero
"""
@ -441,6 +497,8 @@ def enumerate_files(path, fname, callback):
*/
PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
do
{
if ( !PyString_Check(path) || !PyString_Check(fname) || !PyCallable_Check(callback) )

View File

@ -74,10 +74,12 @@ struct py_idcfunc_ctx_t
int nargs;
py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_INCREF(py_func);
}
~py_idcfunc_ctx_t()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_DECREF(py_func);
}
};
@ -91,25 +93,25 @@ static error_t py_call_idc_func(
// Convert IDC arguments to Python list
py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx;
int cvt;
ppyobject_vec_t pargs;
char errbuf[MAXSTR];
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, NULL, errbuf, sizeof(errbuf)) )
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_vec_t pargs;
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, true, errbuf, sizeof(errbuf)) )
{
// Error during conversion? Create an IDC exception
return PyW_CreateIdcException(r, errbuf);
}
// Call the Python function
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallObject(
ctx->py_func,
pargs.empty() ? NULL : pargs[0]);
newref_t py_result(PyObject_CallObject(
ctx->py_func,
pargs.empty() ? NULL : pargs[0].o));
error_t err;
if ( PyW_GetError(errbuf, sizeof(errbuf)) )
{
err = PyW_CreateIdcException(r, errbuf);
Py_XDECREF(py_result);
}
else
{
@ -120,13 +122,7 @@ static error_t py_call_idc_func(
err = PyW_CreateIdcException(r, "ERROR: bad return value");
else
err = eOk;
if ( cvt != CIP_OK_NODECREF )
Py_XDECREF(py_result);
}
PYW_GIL_RELEASE;
// Free the converted args
pyw_free_idc_args(pargs);
return err;
}

View File

@ -100,6 +100,7 @@ private:
}
inline void _from_cobject(PyObject *pycobject)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
_from_fp((FILE *)PyCObject_AsVoidPtr(pycobject));
}
public:
@ -117,7 +118,12 @@ public:
own = true;
fn.qclear();
__idc_cvt_id__ = PY_ICID_OPAQUE;
if ( pycobject != NULL && PyCObject_Check(pycobject) )
bool ok;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
ok = pycobject != NULL && PyCObject_Check(pycobject);
}
if ( ok )
_from_cobject(pycobject);
}
@ -133,7 +139,11 @@ public:
if ( fp == NULL )
return;
if ( own )
{
Py_BEGIN_ALLOW_THREADS;
qfclose(fp);
Py_END_ALLOW_THREADS;
}
fp = NULL;
own = true;
}
@ -148,7 +158,9 @@ public:
bool open(const char *filename, const char *mode)
{
close();
Py_BEGIN_ALLOW_THREADS;
fp = qfopen(filename, mode);
Py_END_ALLOW_THREADS;
if ( fp == NULL )
return false;
// Save file name
@ -179,7 +191,11 @@ public:
//--------------------------------------------------------------------------
static qfile_t *tmpfile()
{
return from_fp(qtmpfile());
FILE *fp;
Py_BEGIN_ALLOW_THREADS;
fp = qtmpfile();
Py_END_ALLOW_THREADS;
return from_fp(fp);
}
//--------------------------------------------------------------------------
@ -191,13 +207,21 @@ public:
//--------------------------------------------------------------------------
int seek(int32 offset, int whence = SEEK_SET)
{
return qfseek(fp, offset, whence);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfseek(fp, offset, whence);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 tell()
{
return qftell(fp);
int32 rc;
Py_BEGIN_ALLOW_THREADS;
rc = qftell(fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
@ -208,12 +232,17 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = freadbytes(fp, buf, size, big_endian);
PYW_GIL_CHECK_LOCKED_SCOPE();
int r;
Py_BEGIN_ALLOW_THREADS;
r = freadbytes(fp, buf, size, big_endian);
Py_END_ALLOW_THREADS;
if ( r != 0 )
{
free(buf);
break;
}
PyObject *ret = PyString_FromStringAndSize(buf, r);
free(buf);
return ret;
@ -229,7 +258,11 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
int r = qfread(fp, buf, size);
PYW_GIL_CHECK_LOCKED_SCOPE();
int r;
Py_BEGIN_ALLOW_THREADS;
r = qfread(fp, buf, size);
Py_END_ALLOW_THREADS;
if ( r <= 0 )
{
free(buf);
@ -250,7 +283,12 @@ public:
char *buf = (char *) malloc(size + 5);
if ( buf == NULL )
break;
if ( qfgets(buf, size, fp) == NULL )
PYW_GIL_CHECK_LOCKED_SCOPE();
char *p;
Py_BEGIN_ALLOW_THREADS;
p = qfgets(buf, size, fp);
Py_END_ALLOW_THREADS;
if ( p == NULL )
{
free(buf);
break;
@ -265,50 +303,87 @@ public:
//--------------------------------------------------------------------------
int writebytes(PyObject *py_buf, bool big_endian)
{
int sz = PyString_GET_SIZE(py_buf);
void *buf = (void *)PyString_AS_STRING(py_buf);
return fwritebytes(fp, buf, sz, big_endian);
Py_ssize_t sz;
void *buf;
PYW_GIL_CHECK_LOCKED_SCOPE();
sz = PyString_GET_SIZE(py_buf);
buf = (void *)PyString_AS_STRING(py_buf);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = fwritebytes(fp, buf, int(sz), big_endian);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int write(PyObject *py_buf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_buf) )
return 0;
return qfwrite(fp, (void *)PyString_AS_STRING(py_buf), PyString_GET_SIZE(py_buf));
// Just so that there is no risk that the buffer returned by
// 'PyString_AS_STRING' gets deallocated within the
// Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_buf_ref(py_buf);
void *p = (void *)PyString_AS_STRING(py_buf);
Py_ssize_t sz = PyString_GET_SIZE(py_buf);
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfwrite(fp, p, sz);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int puts(const char *str)
{
return qfputs(str, fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfputs(str, fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
int32 size()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
int32 r;
Py_BEGIN_ALLOW_THREADS;
int pos = qfseek(fp, 0, SEEK_END);
int32 r = qftell(fp);
r = qftell(fp);
qfseek(fp, pos, SEEK_SET);
Py_END_ALLOW_THREADS;
return r;
}
//--------------------------------------------------------------------------
int flush()
{
return qflush(fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qflush(fp);
Py_END_ALLOW_THREADS;
return rc;
}
//--------------------------------------------------------------------------
PyObject *filename()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(fn.c_str());
}
//--------------------------------------------------------------------------
PyObject *get_char()
{
int ch = qfgetc(fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int ch;
Py_BEGIN_ALLOW_THREADS;
ch = qfgetc(fp);
Py_END_ALLOW_THREADS;
if ( ch == EOF )
Py_RETURN_NONE;
return Py_BuildValue("c", ch);
@ -317,7 +392,12 @@ public:
//--------------------------------------------------------------------------
int put_char(char chr)
{
return qfputc(chr, fp);
PYW_GIL_CHECK_LOCKED_SCOPE();
int rc;
Py_BEGIN_ALLOW_THREADS;
rc = qfputc(chr, fp);
Py_END_ALLOW_THREADS;
return rc;
}
};
//</inline(py_qfile)>

View File

@ -17,6 +17,8 @@
%ignore write_stkpnts;
%ignore del_stkpnts;
%ignore rename_frame;
%ignore _set_frame_size;
%ignore add_empty_frame;
%ignore get_stkvar;
%rename (get_stkvar) py_get_stkvar;

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
#pragma SWIG nowarn=454 // Setting a pointer/reference variable may leak memory
#define _STD_BEGIN
#define typename
#define typename
%{
#include "hexrays.hpp"
@ -177,9 +177,9 @@ typedef intvec_t eavec_t;// vector of addresses
%template(history_t) qstack<history_item_t>;
typedef int iterator_word;
/* no support for nested classes in swig means we need to wrap
/* no support for nested classes in swig means we need to wrap
this iterator and do some magic...
to use it, call qlist< cinsn_t >::begin() which will return the
proper iterator type which can then be used to get the current item.
*/
@ -246,27 +246,25 @@ void qswap(cinsn_t &a, cinsn_t &b);
%{
//---------------------------------------------------------------------
static int hexrays_python_call(PyObject *fct, PyObject *args)
static int hexrays_python_call(ref_t fct, ref_t args)
{
PyObject *resultobj;
PYW_GIL_GET;
int result;
int ecode1 = 0 ;
resultobj = PyEval_CallObject(fct, args);
if (resultobj == NULL)
newref_t resultobj(PyEval_CallObject(fct.o, args.o));
if ( resultobj == NULL )
{
msg("IDAPython: Hex-rays python callback raised an exception.\n");
// we can't do much else than clear the exception since this was not called from Python.
// XXX: print stack trace?
PyErr_Clear();
return 0;
}
ecode1 = SWIG_AsVal_int(resultobj, &result);
Py_DECREF(resultobj);
ecode1 = SWIG_AsVal_int(resultobj.o, &result);
if (SWIG_IsOK(ecode1))
return result;
@ -277,22 +275,22 @@ static int hexrays_python_call(PyObject *fct, PyObject *args)
//---------------------------------------------------------------------
static bool idaapi __python_custom_viewer_popup_item_callback(void *ud)
{
PYW_GIL_GET;
int ret;
PyObject *fct = (PyObject *)ud;
ret = hexrays_python_call(fct, NULL);
borref_t fct((PyObject *)ud);
newref_t nil(NULL);
ret = hexrays_python_call(fct, nil);
return ret ? true : false;
}
//---------------------------------------------------------------------
static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_list va)
{
PYW_GIL_GET;
int ret;
PyObject *fct = (PyObject *)ud;
void *argp = NULL;
PyObject *args = NULL;
borref_t fct((PyObject *)ud);
switch(event)
{
case hxe_maturity:
@ -302,13 +300,9 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
{
cfunc_t *arg0 = va_arg(va, cfunc_t *);
ctree_maturity_t arg1 = va_argi(va, ctree_maturity_t);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 );
args = Py_BuildValue("(iOi)", event, arg0obj, arg1);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 ));
newref_t args(Py_BuildValue("(iOi)", event, arg0obj.o, arg1));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_interr:
@ -316,31 +310,23 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
///< int errcode
{
int arg0 = va_argi(va, int);
args = Py_BuildValue("(ii)", event, arg0);
newref_t args(Py_BuildValue("(ii)", event, arg0));
ret = hexrays_python_call(fct, args);
Py_DECREF(args);
}
break;
case hxe_print_func:
///< Printing ctree and generating text.
///< cfunc_t *cfunc
///< vc_printer_t *vp
///< cfunc_t *cfunc
///< vc_printer_t *vp
///< Returns: 1 if text has been generated by the plugin
{
cfunc_t *arg0 = va_arg(va, cfunc_t *);
vc_printer_t *arg1 = va_arg(va, vc_printer_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 );
PyObject *arg1obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg1), SWIGTYPE_p_vc_printer_t, 0 );
args = Py_BuildValue("(iOO)", event, arg0obj, arg1obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 ));
newref_t arg1obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg1), SWIGTYPE_p_vc_printer_t, 0 ));
newref_t args(Py_BuildValue("(iOO)", event, arg0obj.o, arg1obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_XDECREF(arg1obj);
Py_DECREF(args);
}
break;
@ -350,13 +336,9 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
///< vdui_t *vu
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_switch_pseudocode:
@ -366,28 +348,20 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
///< vdui_t *vu
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_refresh_pseudocode:
///< Existing pseudocode text has been refreshed.
///< vdui_t *vu
///< vdui_t *vu
///< See also hxe_text_ready, which happens earlier
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_close_pseudocode:
@ -395,32 +369,24 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
///< vdui_t *vu
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_keyboard:
///< Keyboard has been hit.
///< vdui_t *vu
///< int key_code (VK_...)
///< int shift_state
///< vdui_t *vu
///< int key_code (VK_...)
///< int shift_state
///< Should return: 1 if the event has been handled
{
vdui_t *arg0 = va_arg(va, vdui_t *);
int arg1 = va_argi(va, int);
int arg2 = va_argi(va, int);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iOii)", event, arg0obj, arg1, arg2);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iOii)", event, arg0obj.o, arg1, arg2));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_right_click:
@ -428,30 +394,22 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
///< vdui_t *vu
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_double_click:
///< Mouse double click.
///< vdui_t *vu
///< int shift_state
///< vdui_t *vu
///< int shift_state
///< Should return: 1 if the event has been handled
{
vdui_t *arg0 = va_arg(va, vdui_t *);
int arg1 = va_argi(va, int);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iOi)", event, arg0obj, arg1);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iOi)", event, arg0obj.o, arg1));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_curpos:
@ -460,51 +418,39 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
///< vdui_t *vu
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_create_hint:
///< Create a hint for the current item.
///< vdui_t *vu
///< qstring *result_hint
///< int *implines
///< Possible return values:
///< 0: the event has not been handled
///< vdui_t *vu
///< qstring *result_hint
///< int *implines
///< Possible return values:
///< 0: the event has not been handled
///< 1: hint has been created (should set *implines to nonzero as well)
///< 2: hint has been created but the standard hints must be
///< appended by the decompiler
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
case hxe_text_ready:
///< Decompiled text is ready.
///< vdui_t *vu
///< vdui_t *vu
///< This event can be used to modify the output text (sv).
///< The text uses regular color codes (see lines.hpp)
///< COLOR_ADDR is used to store pointers to ctree elements
{
vdui_t *arg0 = va_arg(va, vdui_t *);
PyObject *arg0obj = SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 );
args = Py_BuildValue("(iO)", event, arg0obj);
newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 ));
newref_t args(Py_BuildValue("(iO)", event, arg0obj.o));
ret = hexrays_python_call(fct, args);
Py_XDECREF(arg0obj);
Py_DECREF(args);
}
break;
default:
@ -512,7 +458,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_
ret = 0;
break;
}
return ret;
}
@ -550,37 +496,40 @@ void __add_custom_viewer_popup_item(
const char *hotkey,
PyObject *custom_viewer_popup_item_callback)
{
Py_INCREF(custom_viewer_popup_item_callback);
add_custom_viewer_popup_item(custom_viewer, title, hotkey, __python_custom_viewer_popup_item_callback, custom_viewer_popup_item_callback);
PYW_GIL_GET;
Py_INCREF(custom_viewer_popup_item_callback);
add_custom_viewer_popup_item(custom_viewer, title, hotkey, __python_custom_viewer_popup_item_callback, custom_viewer_popup_item_callback);
};
//---------------------------------------------------------------------
bool __install_hexrays_callback(PyObject *hx_cblist_callback)
{
if (install_hexrays_callback(__hexrays_python_callback, hx_cblist_callback))
{
Py_INCREF(hx_cblist_callback);
return true;
}
return false;
PYW_GIL_GET;
if (install_hexrays_callback(__hexrays_python_callback, hx_cblist_callback))
{
Py_INCREF(hx_cblist_callback);
return true;
}
return false;
}
//---------------------------------------------------------------------
int __remove_hexrays_callback(PyObject *hx_cblist_callback)
{
int result, i;
result = remove_hexrays_callback(__hexrays_python_callback, hx_cblist_callback);
for (i=0;i<result;i++)
Py_DECREF(hx_cblist_callback);
PYW_GIL_GET;
int result, i;
result = remove_hexrays_callback(__hexrays_python_callback, hx_cblist_callback);
for (i=0;i<result;i++)
Py_DECREF(hx_cblist_callback);
return result;
return result;
}
%}
//---------------------------------------------------------------------
%define %python_callback_in(CB)
%typemap(check) CB {
if (!PyCallable_Check($1))
if (!PyCallable_Check($1))
{
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
return NULL;
@ -602,10 +551,10 @@ hexrays_failure_t.__str__ = lambda self: str(self.str)
# ---------------------------------------------------------------------
class DecompilationFailure(Exception):
""" Raised on a decompilation error.
The associated hexrays_failure_t object is stored in the
'info' member of this exception. """
def __init__(self, info):
Exception.__init__(self, 'Decompilation failed: %s' % (str(info), ))
self.info = info
@ -620,15 +569,15 @@ def decompile(ea, hf=None):
func = ea
else:
raise RuntimeError('arg 1 of decompile expects either ea_t or cfunc_t argument')
if hf is None:
hf = hexrays_failure_t()
ptr = _decompile(func, hf)
if ptr.__deref__() is None:
raise DecompilationFailure(hf)
return ptr
# ---------------------------------------------------------------------
@ -674,7 +623,7 @@ def _vectors_iterator(self):
yield self[i]
for cls in [cinsnptrvec_t, ctree_items_t, uvalvec_t, \
intvec_t, boolvec_t, hexwarns_t, \
history_t, strvec_t, qvector_lvar_t,
history_t, strvec_t, qvector_lvar_t,
qvector_carg_t, qvector_ccase_t
]:
cls.__getitem__ = cls.at
@ -683,12 +632,12 @@ for cls in [cinsnptrvec_t, ctree_items_t, uvalvec_t, \
def citem_to_specific_type(self):
""" cast the citem_t object to its more specific type, either cexpr_t or cinsn_t. """
if self.op >= cot_empty and self.op <= cot_last:
return self.cexpr
elif self.op >= cit_empty and self.op < cit_end:
return self.cinsn
raise RuntimeError('unknown op type %s' % (repr(self.op), ))
citem_t.to_specific_type = property(citem_to_specific_type)
@ -711,129 +660,129 @@ cexpr_t.opname = property(property_op_to_typename)
def cexpr_operands(self):
""" return a dictionary with the operands of a cexpr_t. """
if self.op >= cot_comma and self.op <= cot_asgumod or \
self.op >= cot_lor and self.op <= cot_fdiv or \
self.op == cot_idx:
return {'x': self.x, 'y': self.y}
elif self.op == cot_tern:
return {'x': self.x, 'y': self.y, 'z': self.z}
elif self.op in [cot_fneg, cot_neg, cot_sizeof] or \
self.op >= cot_lnot and self.op <= cot_predec:
return {'x': self.x}
elif self.op == cot_cast:
return {'type': self.type, 'x': self.x}
elif self.op == cot_call:
return {'x': self.x, 'a': self.a}
elif self.op in [cot_memref, cot_memptr]:
return {'x': self.x, 'm': self.m}
elif self.op == cot_num:
return {'n': self.n}
elif self.op == cot_fnum:
return {'fpc': self.fpc}
elif self.op == cot_str:
return {'string': self.string}
elif self.op == cot_obj:
return {'obj_ea': self.obj_ea}
elif self.op == cot_var:
return {'v': self.v}
elif self.op == cot_helper:
return {'helper': self.helper}
raise RuntimeError('unknown op type %s' % self.opname)
cexpr_t.operands = property(cexpr_operands)
def cinsn_details(self):
""" return the details pointer for the cinsn_t object depending on the value of its op member. \
this is one of the cblock_t, cif_t, etc. objects. """
if self.op not in self.op_to_typename:
raise RuntimeError('unknown item->op type')
opname = self.opname
if opname == 'empty':
return self
if opname in ['break', 'continue']:
return None
return getattr(self, 'c' + opname)
cinsn_t.details = property(cinsn_details)
def cblock_iter(self):
iter = self.begin()
for i in range(self.size()):
yield iter.cur
iter.next()
return
cblock_t.__iter__ = cblock_iter
cblock_t.__len__ = cblock_t.size
# cblock.find(cinsn_t) -> returns the iterator positioned at the given item
def cblock_find(self, item):
iter = self.begin()
for i in range(self.size()):
if iter.cur == item:
return iter
iter.next()
return
cblock_t.find = cblock_find
# cblock.index(cinsn_t) -> returns the index of the given item
def cblock_index(self, item):
iter = self.begin()
for i in range(self.size()):
if iter.cur == item:
return i
iter.next()
return
cblock_t.index = cblock_index
# cblock.at(int) -> returns the item at the given index index
def cblock_at(self, index):
iter = self.begin()
for i in range(self.size()):
if i == index:
return iter.cur
iter.next()
return
cblock_t.at = cblock_at
# cblock.remove(cinsn_t)
def cblock_remove(self, item):
iter = self.find(item)
self.erase(iter)
return
cblock_t.remove = cblock_remove
# cblock.insert(index, cinsn_t)
def cblock_insert(self, index, item):
pos = self.at(index)
iter = self.find(pos)
self.insert(iter, item)
return
cblock_t.insert = cblock_insert
@ -848,13 +797,13 @@ cfuncptr_t.__str__ = lambda self: str(self.__deref__())
def cfunc_typestring(self):
""" Get the function's return type typestring object. The full prototype \
can be obtained via typestring._print() method. """
ts = typestring()
qt = qtype()
result = self.get_func_type(ts, qt)
if not result: return
return ts
cfunc_t.typestring = property(cfunc_typestring)
cfuncptr_t.typestring = property(lambda self: self.__deref__().typestring)
@ -1000,18 +949,18 @@ def _map_setdefault(self, key, default=None):
return default
def _map_as_dict(maptype, name, keytype, valuetype):
maptype.keytype = keytype
maptype.valuetype = valuetype
for fctname in ['begin', 'end', 'first', 'second', 'next', \
'find', 'insert', 'erase', 'clear', 'size']:
fct = getattr(_idaapi, name + '_' + fctname)
setattr(maptype, '__' + fctname, fct)
maptype.__len__ = maptype.size
maptype.__getitem__ = maptype.at
maptype.begin = lambda self, *args: self.__begin(self, *args)
maptype.end = lambda self, *args: self.__end(self, *args)
maptype.first = lambda self, *args: self.__first(*args)

View File

@ -1,9 +1,16 @@
// Ignore kernel-only symbols
%ignore dual_text_options_t;
%ignore idainfo::init;
%ignore idainfo::init_netnode;
%ignore idainfo::precheck_idb_version;
%ignore idainfo::retrieve;
%ignore idainfo::read;
%ignore idainfo::write;
%ignore idainfo::convert_va_format;
%ignore idainfo::upgrade_approved;
%ignore idainfo::will_upgrade;
%ignore idainfo::approve_upgrade;
%ignore idainfo::show_progress;
%ignore idainfo::align_short_demnames;
%ignore idainfo::align_strtype;
%ignore idainfo::align_long_demnames;

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,12 @@
%clear(char dtyp);
%pythoncode %{
#<pycode(py_idd_2)>
NO_PROCESS = 0xFFFFFFFF
NO_THREAD = 0
#</pycode(py_idd_2)>
%}
%{
//<code(py_idd)>
@ -28,6 +34,8 @@ static bool dbg_can_query()
//-------------------------------------------------------------------------
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_list = PyList_New(areas.size());
meminfo_vec_t::const_iterator it, it_end(areas.end());
Py_ssize_t i = 0;
@ -56,6 +64,8 @@ PyObject *py_appcall(
PyObject *py_fields,
PyObject *arg_list)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyList_Check(arg_list) )
return NULL;
@ -71,11 +81,11 @@ PyObject *py_appcall(
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
borref_t py_item(PyList_GetItem(arg_list, i));
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
qstring s;
PyW_ObjectToString(py_item, &s);
PyW_ObjectToString(py_item.o, &s);
msg("obj[%d]->%s\n", int(i), s.c_str());
}
// Convert it
@ -95,6 +105,10 @@ PyObject *py_appcall(
return NULL;
}
error_t ret;
idc_value_t idc_result;
Py_BEGIN_ALLOW_THREADS;
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("input variables:\n"
@ -110,8 +124,7 @@ PyObject *py_appcall(
}
// Do Appcall
idc_value_t idc_result;
error_t ret = appcall(
ret = appcall(
func_ea,
tid,
(type_t *)type,
@ -120,16 +133,17 @@ PyObject *py_appcall(
idc_args.begin(),
&idc_result);
Py_END_ALLOW_THREADS;
if ( ret != eOk )
{
// An exception was thrown?
if ( ret == eExecThrow )
{
// Convert the result (which is a debug_event) into a Python object
PyObject *py_appcall_exc(NULL);
ref_t py_appcall_exc;
idcvar_to_pyvar(idc_result, &py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc);
Py_DECREF(py_appcall_exc);
PyErr_SetObject(PyExc_OSError, py_appcall_exc.o);
return NULL;
}
// An error in the Appcall? (or an exception but AppCallOptions/DEBEV is not set)
@ -159,7 +173,7 @@ PyObject *py_appcall(
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
borref_t py_item(PyList_GetItem(arg_list, i));
// We convert arguments but fail only on fatal errors
// (we ignore failure because of immutable objects)
if ( idcvar_to_pyvar(idc_args[i], &py_item) == CIP_FAILED )
@ -169,13 +183,13 @@ PyObject *py_appcall(
}
}
// Convert the result from IDC back to Python
PyObject *py_result(NULL);
ref_t py_result;
if ( idcvar_to_pyvar(idc_result, &py_result) <= CIP_IMMUTABLE )
{
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC return value to Python return value");
return NULL;
}
QASSERT(30413, py_result.o->ob_refcnt == 1);
if ( (debug & IDA_DEBUG_APPCALL) != 0 )
{
msg("return var:\n"
@ -184,7 +198,8 @@ PyObject *py_appcall(
VarPrint(&s, &idc_result);
msg("%s\n-----------\n", s.c_str());
}
return py_result;
py_result.incref();
return py_result.o;
}
//</code(py_idd)>
%}
@ -212,6 +227,8 @@ def dbg_get_registers():
*/
static PyObject *dbg_get_registers()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dbg == NULL )
Py_RETURN_NONE;
@ -270,6 +287,8 @@ def dbg_get_thread_sreg_base(tid, sreg_value):
*/
static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) )
Py_RETURN_NONE;
ea_t answer;
@ -296,6 +315,8 @@ def dbg_read_memory(ea, sz):
*/
static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 ea, sz;
if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) )
Py_RETURN_NONE;
@ -333,6 +354,8 @@ def dbg_write_memory(ea, buffer):
*/
static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 ea;
if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) )
Py_RETURN_NONE;
@ -357,6 +380,8 @@ def dbg_get_name():
*/
static PyObject *dbg_get_name()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( dbg == NULL )
Py_RETURN_NONE;
else
@ -378,15 +403,19 @@ def dbg_get_memory_info():
*/
static PyObject *dbg_get_memory_info()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !dbg_can_query() )
Py_RETURN_NONE;
// Invalidate memory
meminfo_vec_t areas;
Py_BEGIN_ALLOW_THREADS;
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
meminfo_vec_t areas;
get_dbg_memory_info(&areas);
Py_END_ALLOW_THREADS;
return meminfo_vec_t_to_py(areas);
}
@ -611,7 +640,7 @@ class Appcall_callable__(object):
def __get_size(self):
if self.__type == None:
return -1
r = _idaapi.get_type_size0(_idaapi.cvar.idati, self.__type)
r = _idaapi.calc_type_size(_idaapi.cvar.idati, self.__type)
if not r:
return -1
return r

View File

@ -35,6 +35,7 @@
%ignore _py_getreg;
%ignore free_processor_module;
%ignore read_config_file;
%ignore cfg_compiler_changed;
%ignore gen_idb_event;
@ -74,12 +75,17 @@ static PyObject *AssembleLine(
{
int inslen;
char buf[MAXSTR];
bool ok = false;
if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
{
return PyString_FromStringAndSize(buf, inslen);
ok = true;
}
Py_RETURN_NONE;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return PyString_FromStringAndSize(buf, inslen);
else
Py_RETURN_NONE;
}
//---------------------------------------------------------------------------
@ -107,17 +113,20 @@ bool assemble(
{
int inslen;
char buf[MAXSTR];
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = false;
Py_BEGIN_ALLOW_THREADS;
if (ph.notify != NULL)
{
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
if (inslen > 0)
{
patch_many_bytes(ea, buf, inslen);
return true;
rc = true;
}
}
return false;
Py_END_ALLOW_THREADS;
return rc;
}
//-------------------------------------------------------------------------
@ -359,6 +368,7 @@ def ph_get_instruc():
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start);
for ( const instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end;
p != end;
@ -382,10 +392,10 @@ def ph_get_regnames():
static PyObject *ph_get_regnames()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
return py_result;
}
@ -413,6 +423,10 @@ static PyObject *ph_get_operand_info(
ea_t ea,
int n)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool ok = false;
idd_opinfo_t opinf;
Py_BEGIN_ALLOW_THREADS;
do
{
if ( dbg == NULL || n == - 1 )
@ -427,7 +441,6 @@ static PyObject *ph_get_operand_info(
break;
// Call the processor module
idd_opinfo_t opinf;
if ( ph.notify(ph.get_operand_info,
ea,
n,
@ -438,14 +451,19 @@ static PyObject *ph_get_operand_info(
{
break;
}
return Py_BuildValue("(i" PY_FMT64 "Kii)",
opinf.modified,
opinf.ea,
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
ok = true;
} while (false);
Py_RETURN_NONE;
Py_END_ALLOW_THREADS;
if ( ok )
return Py_BuildValue("(i" PY_FMT64 "Kii)",
opinf.modified,
opinf.ea,
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
@ -826,6 +844,7 @@ public:
bool /*use32*/,
const char * /*line*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
};
@ -889,6 +908,8 @@ public:
//-------------------------------------------------------------------------
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
IDP_Hooks *proxy = (IDP_Hooks *)ud;
int ret = 0;
try
@ -910,16 +931,16 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
case processor_t::custom_outop:
{
op_t *op = va_arg(va, op_t *);
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
ref_t py_obj(create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op));
if ( py_obj == NULL )
break;
ret = proxy->custom_outop(py_obj) ? 2 : 0;
Py_XDECREF(py_obj);
ret = proxy->custom_outop(py_obj.o) ? 2 : 0;
break;
}
case processor_t::custom_mnem:
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_ret = proxy->custom_mnem();
if ( py_ret != NULL && PyString_Check(py_ret) )
{
@ -1051,6 +1072,7 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
// Extract user buffer (we hardcode the MAXSTR size limit)
uchar *bin = va_arg(va, uchar *);
// Call python
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line);
if ( py_buffer != NULL && PyString_Check(py_buffer) )
{
@ -1370,6 +1392,7 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in IDP Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
@ -1379,6 +1402,9 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
//---------------------------------------------------------------------------
int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
ea_t ea, ea2;
bool repeatable_cmt;
@ -1550,10 +1576,9 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
catch (Swig::DirectorException &e)
{
msg("Exception in IDB Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if (PyErr_Occurred())
{
PyErr_Print();
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -85,10 +85,12 @@ static void idaapi s_py_get_user_defined_prefix(
char *buf,
size_t bufsize)
{
PyObject *py_ret = PyObject_CallFunction(
py_get_user_defined_prefix,
PY_FMT64 "iis" PY_FMT64,
ea, lnnum, indent, line, bufsize);
PYW_GIL_GET;
newref_t py_ret(
PyObject_CallFunction(
py_get_user_defined_prefix,
PY_FMT64 "iis" PY_FMT64,
ea, lnnum, indent, line, bufsize));
// Error? Display it
// No error? Copy the buffer
@ -96,14 +98,13 @@ static void idaapi s_py_get_user_defined_prefix(
{
Py_ssize_t py_len;
char *py_str;
if ( PyString_AsStringAndSize(py_ret, &py_str, &py_len) != -1 )
if ( PyString_AsStringAndSize(py_ret.o, &py_str, &py_len) != -1 )
{
memcpy(buf, py_str, qmin(bufsize, py_len));
if ( py_len < bufsize )
buf[py_len] = '\0';
}
}
Py_XDECREF(py_ret);
}
//</code(py_lines)>
%}
@ -138,6 +139,7 @@ def set_user_defined_prefix(width, callback):
*/
static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( width == 0 || pycb == Py_None )
{
// Release old callback reference
@ -183,6 +185,7 @@ def tag_remove(colstr):
*/
PyObject *py_tag_remove(const char *instr)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
size_t sz = strlen(instr);
char *buf = new char[sz + 5];
if ( buf == NULL )
@ -208,6 +211,7 @@ PyObject *py_tag_addr(ea_t ea)
{
char buf[100];
tag_addr(buf, buf + sizeof(buf), ea);
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyString_FromString(buf);
}
@ -253,6 +257,7 @@ PyObject *py_generate_disassembly(
bool as_stack,
bool notags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( max_lines <= 0 )
Py_RETURN_NONE;
@ -261,7 +266,7 @@ PyObject *py_generate_disassembly(
int lnnum;
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
PyObject *py_tuple = PyTuple_New(nlines);
newref_t py_tuple(PyTuple_New(nlines));
for ( int i=0; i<nlines; i++ )
{
const char *s = lines[i];
@ -272,13 +277,11 @@ PyObject *py_generate_disassembly(
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0];
}
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
PyTuple_SetItem(py_tuple.o, i, PyString_FromString(s));
qfree(lines[i]);
}
delete [] lines;
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
Py_DECREF(py_tuple);
return py_result;
return Py_BuildValue("(iO)", lnnum, py_tuple.o);
}
//</inline(py_lines)>

View File

@ -68,6 +68,7 @@
%ignore IDP_DESC_START;
%ignore IDP_DESC_END;
%ignore get_idp_desc;
%ignore get_idp_descs;
%ignore init_fileregions;
%ignore term_fileregions;
%ignore save_fileregions;
@ -108,6 +109,8 @@
%ignore is_in_loader;
%ignore get_ids_filename;
%ignore is_embedded_dbfile_ext;
%ignore cpp_namespaces;
%ignore max_trusted_idb_count;
%ignore mem2base;
%rename (mem2base) py_mem2base;
@ -147,8 +150,11 @@ static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1)
{
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
return 0;
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_AsStringAndSize(py_mem, &buf, &len) == -1 )
return 0;
}
return mem2base((void *)buf, ea, ea+len, fpos);
}
@ -169,6 +175,7 @@ def load_plugin(name):
static PyObject *py_load_plugin(const char *name)
{
plugin_t *r = load_plugin(name);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( r == NULL )
Py_RETURN_NONE;
else
@ -189,10 +196,20 @@ def run_plugin(plg):
*/
static bool py_run_plugin(PyObject *plg, int arg)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(plg) )
{
return false;
}
else
return run_plugin((plugin_t *)PyCObject_AsVoidPtr(plg), arg);
{
plugin_t *p = (plugin_t *)PyCObject_AsVoidPtr(plg);
bool rc;
Py_BEGIN_ALLOW_THREADS;
rc = run_plugin(p, arg);
Py_END_ALLOW_THREADS;
return rc;
}
}
//</inline(py_loader)>

View File

@ -35,53 +35,35 @@ static int idaapi py_import_enum_cb(
if ( name == NULL )
name = get_true_name(BADADDR, ea, name_buf, sizeof(name_buf));
PyObject *py_name;
PYW_GIL_CHECK_LOCKED_SCOPE();
ref_t py_name;
if ( name == NULL )
{
py_name = Py_None;
Py_INCREF(Py_None);
}
py_name = borref_t(Py_None);
else
{
py_name = PyString_FromString(name);
}
py_name = newref_t(PyString_FromString(name));
PyObject *py_ord = Py_BuildValue(PY_FMT64, pyul_t(ord));
PyObject *py_ea = Py_BuildValue(PY_FMT64, pyul_t(ea));
PYW_GIL_ENSURE;
PyObject *py_result = PyObject_CallFunctionObjArgs(
(PyObject *)param,
py_ea,
py_name,
py_ord,
NULL);
PYW_GIL_RELEASE;
int r = py_result != NULL && PyObject_IsTrue(py_result) ? 1 : 0;
Py_DECREF(py_ea);
Py_DECREF(py_name);
Py_DECREF(py_ord);
Py_XDECREF(py_result);
return r;
newref_t py_ord(Py_BuildValue(PY_FMT64, pyul_t(ord)));
newref_t py_ea(Py_BuildValue(PY_FMT64, pyul_t(ea)));
newref_t py_result(
PyObject_CallFunctionObjArgs(
(PyObject *)param,
py_ea.o,
py_name.o,
py_ord.o,
NULL));
return py_result != NULL && PyObject_IsTrue(py_result.o) ? 1 : 0;
}
//-------------------------------------------------------------------------
switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyObject_HasAttrString(self, S_CLINK_NAME) )
return NULL;
switch_info_ex_t *r;
PyObject *attr = PyObject_GetAttrString(self, S_CLINK_NAME);
if ( PyCObject_Check(attr) )
r = (switch_info_ex_t *) PyCObject_AsVoidPtr(attr);
else
r = NULL;
Py_DECREF(attr);
return r;
newref_t attr(PyObject_GetAttrString(self, S_CLINK_NAME));
return PyCObject_Check(attr.o) ? ((switch_info_ex_t *) PyCObject_AsVoidPtr(attr.o)) : NULL;
}
//</code(py_nalt)>
%}
@ -108,10 +90,11 @@ def get_import_module_name(path, fname, callback):
*/
static PyObject *py_get_import_module_name(int mod_index)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
char buf[MAXSTR];
if ( !get_import_module_name(mod_index, buf, sizeof(buf)) )
Py_RETURN_NONE;
return PyString_FromString(buf);
}
@ -130,14 +113,16 @@ def get_switch_info_ex(ea):
PyObject *py_get_switch_info_ex(ea_t ea)
{
switch_info_ex_t *ex = new switch_info_ex_t();
PyObject *py_obj;
if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0
ref_t py_obj;
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0
|| (py_obj = create_idaapi_linked_class_instance(S_PY_SWIEX_CLSNAME, ex)) == NULL )
{
delete ex;
Py_RETURN_NONE;
}
return py_obj;
py_obj.incref();
return py_obj.o;
}
//-------------------------------------------------------------------------
@ -151,7 +136,7 @@ def create_switch_xrefs(insn_ea, si):
will call it for switch tables
Note: Custom switch information are not supported yet.
@param insn_ea: address of the 'indirect jump' instruction
@param si: switch information
@ -179,7 +164,7 @@ idaman bool ida_export py_create_switch_xrefs(
def create_switch_table(insn_ea, si):
"""
Create switch table from the switch information
@param insn_ea: address of the 'indirect jump' instruction
@param si: switch information
@ -195,7 +180,7 @@ idaman bool ida_export py_create_switch_table(
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
if ( swi == NULL )
return false;
create_switch_table(insn_ea, swi);
return true;
}
@ -254,9 +239,9 @@ def enum_import_names(mod_index, callback):
*/
static int py_enum_import_names(int mod_index, PyObject *py_cb)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCallable_Check(py_cb) )
return -1;
return enum_import_names(mod_index, py_import_enum_cb, py_cb);
}
@ -264,12 +249,14 @@ static int py_enum_import_names(int mod_index, PyObject *py_cb)
static PyObject *switch_info_ex_t_create()
{
switch_info_ex_t *inst = new switch_info_ex_t();
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(inst, NULL);
}
//---------------------------------------------------------------------------
static bool switch_info_ex_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
switch_info_ex_t *inst = (switch_info_ex_t *) PyCObject_AsVoidPtr(py_obj);
@ -295,6 +282,7 @@ static bool switch_info_ex_t_assign(PyObject *self, PyObject *other)
static PyObject *switch_info_ex_t_get_regdtyp(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("b", (char)link->regdtyp);
@ -304,12 +292,14 @@ static void switch_info_ex_t_set_regdtyp(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->regdtyp = (char)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_flags2(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->flags2);
@ -319,12 +309,14 @@ static void switch_info_ex_t_set_flags2(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->flags2 = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_jcases(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->jcases);
@ -334,12 +326,14 @@ static void switch_info_ex_t_set_jcases(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->jcases = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_regnum(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", (int)link->regnum);
@ -349,12 +343,14 @@ static void switch_info_ex_t_set_regnum(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->regnum = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_flags(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (ushort)link->flags);
@ -364,12 +360,14 @@ static void switch_info_ex_t_set_flags(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->flags = (uint16)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_ncases(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (uint16)link->ncases);
@ -379,12 +377,14 @@ static void switch_info_ex_t_set_ncases(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
link->ncases = (ushort)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_defjump(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->defjump);
@ -394,6 +394,7 @@ static void switch_info_ex_t_set_defjump(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 v(0); PyW_GetNumber(value, &v);
link->defjump = (pyul_t)v;
}
@ -410,6 +411,7 @@ static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value)
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
PYW_GIL_CHECK_LOCKED_SCOPE();
uint64 v(0); PyW_GetNumber(value, &v);
link->jumps = (pyul_t)v;
}
@ -417,6 +419,7 @@ static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_elbase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->elbase);
@ -427,6 +430,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->elbase = (pyul_t)v;
}
@ -434,6 +438,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_startea(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->startea);
@ -444,6 +449,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->startea = (pyul_t)v;
}
@ -451,6 +457,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_custom(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->custom);
@ -461,6 +468,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->custom = (pyul_t)v;
}
@ -468,6 +476,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_ind_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->ind_lowcase);
@ -478,6 +487,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->ind_lowcase = (pyul_t)v;
}
@ -485,6 +495,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
static PyObject *switch_info_ex_t_get_values_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->values);
@ -495,6 +506,7 @@ static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value)
if ( link == NULL )
return;
uint64 v(0);
PYW_GIL_CHECK_LOCKED_SCOPE();
PyW_GetNumber(value, &v);
link->values = (pyul_t)v;
}

View File

@ -39,16 +39,19 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
{
// Get debug names
ea_name_vec_t names;
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_BEGIN_ALLOW_THREADS;
get_debug_names(ea1, ea2, names);
Py_END_ALLOW_THREADS;
PyObject *dict = Py_BuildValue("{}");
if (dict == NULL)
return NULL;
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
if (dict != NULL)
{
PyDict_SetItem(dict,
Py_BuildValue(PY_FMT64, it->ea),
PyString_FromString(it->name.c_str()));
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
{
PyDict_SetItem(dict,
Py_BuildValue(PY_FMT64, it->ea),
PyString_FromString(it->name.c_str()));
}
}
return dict;
}

View File

@ -69,10 +69,12 @@
%ignore netnode::set_close_flag;
%ignore netnode::reserve_nodes;
%ignore netnode::validate;
%ignore netnode::upgrade16;
%ignore netnode::upgrade;
%ignore netnode::compress;
%ignore netnode::inited;
%ignore netnode::init;
%ignore netnode::can_write;
%ignore netnode::flush;
%ignore netnode::get_linput;
%ignore netnode::term;

View File

@ -98,7 +98,8 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
%ignore BELOW_NORMAL_PRIORITY_CLASS;
%ignore parse_command_line;
%ignore parse_command_line2;
%rename (parse_command_line2) py_parse_command_line;
%ignore parse_command_line3;
%rename (parse_command_line3) py_parse_command_line;
%ignore qgetenv;
%ignore qsetenv;
%ignore qctime;
@ -126,13 +127,6 @@ public:
const char *c_str() const { return self->c_str(); }
};
//---------------------------------------------------------------------
// for obscure reasons swig can't get past this one on its own, it needs a dummy declaration.
class strvec_t {
public:
qstring& at(int _idx) { return self->at(_idx).line; }
size_t size() const { return self->size(); }
};
class qtype {
public:

View File

@ -19,6 +19,43 @@
%ignore is_ephemeral_segm;
%ignore correct_address;
%{
void segment_t_startEA_set(segment_t *segm, ea_t newea)
{
if ( getseg(segm->startEA) == segm )
{
PyErr_SetString(PyExc_AttributeError, "Can't modify startEA, please use set_segm_start() instead");
}
else
{
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 )
{
PyErr_SetString(PyExc_AttributeError, "Can't modify endEA, please use set_segm_end() instead");
}
else
{
segm->endEA = newea;
}
}
ea_t segment_t_endEA_get(segment_t *segm)
{
return segm->endEA;
}
%}
%extend segment_t
{
ea_t startEA;
ea_t endEA;
}
%include "segment.hpp"
%inline %{

View File

@ -1,14 +1,14 @@
// Ignore kernel-only symbols
%ignore createSRarea;
%ignore killSRareas;
%ignore delSRarea;
%ignore splitSRarea;
%ignore SRareaStart;
%ignore SRareaEnd;
%ignore create_srarea;
%ignore kill_srareras;
%ignore del_srarea;
%ignore break_srarea;
%ignore set_srarea_start;
%ignore set_srarea_end;
%ignore repairSRarea;
%ignore SRinit;
%ignore SRterm;
%ignore SRsave;
%ignore init_srarea;
%ignore term_srarea;
%ignore save_srarea;
#define R_es 29
#define R_cs 30

View File

@ -44,6 +44,7 @@
}
%typemap(argout) (TYPEMAP,SIZE) {
Py_XDECREF(resultobj);
if (result > 0)
{
resultobj = PyString_FromString($1);
@ -91,6 +92,7 @@
/* REMOVING ssize_t return value in $symname */
}
%typemap(argout) (TYPEMAP,SIZE) {
Py_XDECREF(resultobj);
if (result > 0)
{
resultobj = PyString_FromStringAndSize((char *)$1, result);
@ -117,6 +119,7 @@
/* REMOVING ssize_t return value in $symname */
}
%typemap(argout) (TYPEMAP,SIZE) {
Py_XDECREF(resultobj);
if (result)
{
resultobj = PyString_FromStringAndSize((char *)$1, *$2);
@ -151,3 +154,32 @@
}
$1 = ea_t($1_temp);
}
//-------------------------------------------------------------------------
// Convert qstring
%typemap(in) qstring*
{
char *buf;
Py_ssize_t length;
int success = PyString_AsStringAndSize($input, &buf, &length);
if ( success > -1 )
{
$1 = new qstring(buf, length);
}
}
%typemap(freearg) qstring*
{
delete $1;
}
%typemap(out) qstring*
{
$result = PyString_FromStringAndSize($1->c_str(), $1->length());
}
#ifdef __EA64__
%apply longlong *INOUT { sval_t *value };
%apply ulonglong *INOUT { ea_t *addr };
%apply ulonglong *INOUT { sel_t *sel };
#else
%apply int *INOUT { sval_t *value };
%apply unsigned int *INOUT { ea_t *addr };
%apply unsigned int *INOUT { sel_t *sel };
#endif

View File

@ -49,6 +49,8 @@
%ignore til_add_macro;
%ignore til_next_macro;
%ignore parse_subtype;
%ignore calc_type_size;
%ignore get_type_size;
%ignore get_type_size0;
%ignore skip_type;
@ -62,6 +64,7 @@
%ignore print_type;
%ignore show_type;
%ignore show_plist;
%ignore show_bytes;
%ignore skip_function_arg_names;
%ignore perform_funcarg_conversion;
%ignore get_argloc_info;
@ -85,11 +88,17 @@
%ignore get_named_type_size;
%ignore decorate_name;
%ignore decorate_name3;
%ignore gen_decorate_name;
%ignore calc_bare_name;
%ignore calc_bare_name3;
%ignore calc_cpp_name;
%ignore calc_c_cpp_name;
%ignore calc_c_cpp_name3;
%ignore predicate_t;
%ignore local_predicate_t;
%ignore tinfo_predicate_t;
%ignore local_tinfo_predicate_t;
%ignore choose_named_type;
%ignore get_default_align;
%ignore align_size;
@ -123,6 +132,8 @@
%rename (apply_type_to_stkarg) py_apply_type_to_stkarg;
%ignore print_type;
%rename (print_type) py_print_type;
%rename (calc_type_size) py_calc_type_size;
%rename (apply_type) py_apply_type;
%ignore use_regarg_type_cb;
%ignore set_op_type_t;
@ -143,29 +154,17 @@
%ignore extend_sign;
// Kernel-only symbols
%ignore init_til;
%ignore save_til;
%ignore term_til;
%ignore determine_til;
%ignore sync_from_til;
%ignore get_tilpath;
%ignore autoload_til;
%ignore get_idainfo_by_type;
%ignore apply_callee_type;
%ignore propagate_stkargs;
%ignore build_anon_type_name;
%ignore type_names;
%ignore get_compiler_id;
%ignore reloc_info_t;
%ignore relobj_t;
%ignore regobj_t;
%ignore build_func_type;
%ignore append_type_name;
%ignore for_all_types_ex;
%ignore fix_idb_type;
%ignore pdb2ti;
%ignore process_sdacl_padding;
%ignore enum_type_data_t::is_signed;
%ignore enum_type_data_t::is_unsigned;
%ignore enum_type_data_t::get_sign;
%ignore bitfield_type_data_t::serialize;
%ignore func_type_data_t::serialize;
%ignore func_type_data_t::deserialize;
%ignore enum_type_data_t::get_enum_base_type;
%ignore enum_type_data_t::deserialize_enum;
%ignore valstr_deprecated_t;
%ignore valinfo_deprecated_t;
%include "typeinf.hpp"
@ -174,6 +173,7 @@
%rename (load_til) load_til_wrap;
%rename (get_type_size0) py_get_type_size0;
%rename (idc_get_type_raw) py_idc_get_type_raw;
%rename (idc_get_local_type_raw) py_idc_get_local_type_raw;
%rename (unpack_object_from_idb) py_unpack_object_from_idb;
%rename (unpack_object_from_bv) py_unpack_object_from_bv;
%rename (pack_object_to_idb) py_pack_object_to_idb;
@ -183,22 +183,26 @@
//-------------------------------------------------------------------------
PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
{
qtype fields, type;
tinfo_t tif;
qstring name;
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
if ( !ok )
Py_RETURN_NONE;
qtype fields, type;
bool ok = parse_decl2(ti, decl, &name, &tif, flags);
if ( ok )
ok = tif.serialize(&type, &fields, NULL, SUDT_FAST);
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.c_str(),
(char *)fields.c_str());
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_type_size0(ti, tp):
def calc_type_size(ti, tp):
"""
Returns the size of a type
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@ -210,25 +214,69 @@ def get_type_size0(ti, tp):
pass
#</pydoc>
*/
PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
PyObject *py_calc_type_size(const til_t *ti, PyObject *tp)
{
if ( !PyString_Check(tp) )
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyString_Check(tp) )
{
// To avoid release of 'data' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t tpref(tp);
const type_t *data = (type_t *)PyString_AsString(tp);
size_t sz;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
tif.deserialize(ti, &data, NULL, NULL);
sz = tif.get_size();
Py_END_ALLOW_THREADS;
if ( sz != BADSIZE )
return PyInt_FromLong(sz);
Py_RETURN_NONE;
}
else
{
PyErr_SetString(PyExc_ValueError, "String expected!");
return NULL;
}
size_t sz = get_type_size0(ti, (type_t *)PyString_AsString(tp));
if ( sz == BADSIZE )
Py_RETURN_NONE;
return PyInt_FromLong(sz);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def print_type(ea, on_line):
def apply_type(ti, ea, tp_name, py_type, py_fields, flags)
"""
Apply the specified type to the address
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param py_type: type string
@param py_fields: type fields
@param ea: the address of the object
@param flags: combination of TINFO_... constants or 0
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_t ea, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
const type_t *type = (const type_t *) PyString_AsString(py_type);
const p_list *fields = (const p_list *) PyString_AsString(py_fields);
bool rc;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
rc = tif.deserialize(ti, &type, &fields, NULL) && apply_tinfo2(ea, tif, flags);
Py_END_ALLOW_THREADS;
return rc;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def print_type(ea, one_line):
"""
Returns the type of an item
@return:
@ -240,14 +288,13 @@ def print_type(ea, on_line):
*/
static PyObject *py_print_type(ea_t ea, bool one_line)
{
char buf[MAXSTR];
if ( print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI) )
{
qstrncat(buf, ";", sizeof(buf));
char buf[64*MAXSTR];
int flags = PRTYPE_SEMI | (one_line ? PRTYPE_1LINE : PRTYPE_MULTI);
bool ok = print_type2(ea, buf, sizeof(buf), one_line ? PRTYPE_1LINE : PRTYPE_MULTI);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return PyString_FromString(buf);
}
else
Py_RETURN_NONE;
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
@ -268,17 +315,24 @@ PyObject *py_unpack_object_from_idb(
ea_t ea,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Unpack
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
idc_value_t idc_obj;
error_t err = unpack_object_from_idb(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = unpack_object_from_idb(
&idc_obj,
ti,
type,
@ -286,22 +340,21 @@ PyObject *py_unpack_object_from_idb(
ea,
NULL,
pio_flags);
Py_END_ALLOW_THREADS;
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
ref_t py_ret;
err = idcvar_to_pyvar(idc_obj, &py_ret);
// Conversion failed?
if ( err != CIP_OK )
return Py_BuildValue("(ii)", 0, err);
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
Py_DECREF(py_ret);
return py_result;
else
return Py_BuildValue("(iO)", 1, py_ret.o);
}
//-------------------------------------------------------------------------
@ -330,12 +383,17 @@ PyObject *py_unpack_object_from_bv(
PyObject *py_bytes,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) && !PyString_Check(py_bytes) )
{
PyErr_SetString(PyExc_ValueError, "Incorrect argument type!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
@ -346,29 +404,30 @@ PyObject *py_unpack_object_from_bv(
memcpy(bytes.begin(), PyString_AsString(py_bytes), bytes.size());
idc_value_t idc_obj;
error_t err = unpack_object_from_bv(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = unpack_object_from_bv(
&idc_obj,
ti,
type,
fields,
bytes,
pio_flags);
Py_END_ALLOW_THREADS;
// Unpacking failed?
if ( err != eOk )
return Py_BuildValue("(ii)", 0, err);
// Convert
PyObject *py_ret(NULL);
ref_t py_ret;
err = idcvar_to_pyvar(idc_obj, &py_ret);
// Conversion failed?
if ( err != CIP_OK )
return Py_BuildValue("(ii)", 0, err);
PyObject *py_result = Py_BuildValue("(iO)", 1, py_ret);
Py_DECREF(py_ret);
return py_result;
return Py_BuildValue("(iO)", 1, py_ret.o);
}
//-------------------------------------------------------------------------
@ -396,6 +455,7 @@ PyObject *py_pack_object_to_idb(
ea_t ea,
int pio_flags = 0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
@ -404,15 +464,24 @@ PyObject *py_pack_object_to_idb(
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
borref_t py_obj_ref(py_obj);
if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) )
return NULL;
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
type_t *type = (type_t *)PyString_AsString(py_type);
p_list *fields = (p_list *)PyString_AsString(py_fields);
// Pack
error_t err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags);
// error_t err;
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags);
Py_END_ALLOW_THREADS;
return PyInt_FromLong(err);
}
@ -443,6 +512,7 @@ PyObject *py_pack_object_to_bv(
ea_t base_ea,
int pio_flags=0)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
@ -451,16 +521,23 @@ PyObject *py_pack_object_to_bv(
// Convert Python object to IDC object
idc_value_t idc_obj;
if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
borref_t py_obj_ref(py_obj);
if ( !pyvar_to_idcvar_or_error(py_obj_ref, &idc_obj) )
return NULL;
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
// Get type strings
type_t *type = (type_t *) PyString_AsString(py_type);
p_list *fields = (p_list *) PyString_AsString(py_fields);
type_t *type = (type_t *)PyString_AsString(py_type);
p_list *fields = (p_list *)PyString_AsString(py_fields);
// Pack
relobj_t bytes;
error_t err = pack_object_to_bv(
error_t err;
Py_BEGIN_ALLOW_THREADS;
err = pack_object_to_bv(
&idc_obj,
ti,
type,
@ -468,174 +545,212 @@ PyObject *py_pack_object_to_bv(
&bytes,
NULL,
pio_flags);
do
{
if ( err != eOk )
break;
if ( !bytes.relocate(base_ea, inf.mf) )
{
if ( err == eOk && !bytes.relocate(base_ea, inf.mf) )
err = -1;
break;
}
Py_END_ALLOW_THREADS;
if ( err == eOk )
return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size());
} while ( false );
return Py_BuildValue("(ii)", 0, err);
else
return Py_BuildValue("(ii)", 0, err);
}
//</inline(py_typeinf)>
til_t * load_til(const char *tildir, const char *name)
//-------------------------------------------------------------------------
/* Parse types from a string or file. See ParseTypes() in idc.py */
int idc_parse_types(const char *input, int flags)
{
char errbuf[4096];
til_t *res;
int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT;
res = load_til(tildir, name, errbuf, sizeof(errbuf));
if ((flags & 1) != 0)
hti |= HTI_FIL;
if (!res)
return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti);
}
//-------------------------------------------------------------------------
PyObject *py_idc_get_type_raw(ea_t ea)
{
qtype type, fields;
bool ok = get_tinfo(ea, &type, &fields);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str());
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
PyObject *py_idc_get_local_type_raw(int ordinal)
{
const type_t *type;
const p_list *fields;
bool ok = get_numbered_type(idati, ordinal, &type, &fields);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("(ss)", (char *)type, (char *)fields);
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
char *idc_guess_type(ea_t ea, char *buf, size_t bufsize)
{
tinfo_t tif;
if ( guess_tinfo2(ea, &tif) )
{
qstring out;
if ( tif.print(&out) )
return qstrncpy(buf, out.begin(), bufsize);
}
return NULL;
}
//-------------------------------------------------------------------------
char *idc_get_type(ea_t ea, char *buf, size_t bufsize)
{
tinfo_t tif;
if ( get_tinfo2(ea, &tif) )
{
qstring out;
if ( tif.print(&out) )
{
PyErr_SetString(PyExc_RuntimeError, errbuf);
return NULL;
qstrncpy(buf, out.c_str(), bufsize);
return buf;
}
}
return NULL;
}
//-------------------------------------------------------------------------
int idc_set_local_type(int ordinal, const char *dcl, int flags)
{
if (dcl == NULL || dcl[0] == '\0')
{
if ( !del_numbered_type(idati, ordinal) )
return 0;
}
else
{
tinfo_t tif;
qstring name;
if ( !parse_decl2(idati, dcl, &name, &tif, flags) )
return 0;
if ( ordinal <= 0 )
{
if ( !name.empty() )
ordinal = get_type_ordinal(idati, name.begin());
if ( ordinal <= 0 )
ordinal = alloc_type_ordinal(idati);
}
return res;
if ( tif.set_numbered_type(idati, ordinal, 0, name.c_str()) != TERR_OK )
return 0;
}
return ordinal;
}
//-------------------------------------------------------------------------
int idc_get_local_type(int ordinal, int flags, char *buf, size_t maxsize)
{
tinfo_t tif;
if ( !tif.get_numbered_type(idati, ordinal) )
{
buf[0] = 0;
return false;
}
qstring res;
const char *name = get_numbered_type_name(idati, ordinal);
if ( !tif.print(&res, name, flags, 2, 40) )
{
buf[0] = 0;
return false;
}
qstrncpy(buf, res.begin(), maxsize);
return true;
}
//-------------------------------------------------------------------------
PyObject *idc_print_type(PyObject *py_type, PyObject *py_fields, const char *name, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL;
}
// To avoid release of 'type'/'fields' during Py_BEGIN|END_ALLOW_THREADS section.
borref_t py_type_ref(py_type);
borref_t py_fields_ref(py_fields);
qstring res;
const type_t *type = (type_t *)PyString_AsString(py_type);
const p_list *fields = (p_list *)PyString_AsString(py_fields);
bool ok;
Py_BEGIN_ALLOW_THREADS;
tinfo_t tif;
ok = tif.deserialize(idati, &type, &fields, NULL)
&& tif.print(&res, name, flags, 2, 40);
Py_END_ALLOW_THREADS;
if ( ok )
return PyString_FromString(res.begin());
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize)
{
const char *name = get_numbered_type_name(idati, ordinal);
if ( name == NULL )
return false;
qstrncpy(buf, name, bufsize);
return true;
}
//</inline(py_typeinf)>
til_t *load_til(const char *tildir, const char *name)
{
char errbuf[MAXSTR];
til_t *res = load_til(tildir, name, errbuf, sizeof(errbuf));
if ( res == NULL )
PyErr_SetString(PyExc_RuntimeError, errbuf);
return res;
}
%}
%rename (load_til_header) load_til_header_wrap;
%inline %{
til_t * load_til_header_wrap(const char *tildir, const char *name)
til_t *load_til_header_wrap(const char *tildir, const char *name)
{
char errbuf[4096];
til_t *res;
res = load_til_header(tildir, name, errbuf, sizeof(errbuf));;
if (!res)
{
PyErr_SetString(PyExc_RuntimeError, errbuf);
return NULL;
}
return res;
char errbuf[MAXSTR];
til_t *res = load_til_header(tildir, name, errbuf, sizeof(errbuf));;
if ( res == NULL )
PyErr_SetString(PyExc_RuntimeError, errbuf);
return res;
}
%}
%cstring_output_maxsize(char *buf, size_t maxsize);
%inline %{
/* Parse types from a string or file. See ParseTypes() in idc.py */
int idc_parse_types(const char *input, int flags)
{
int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT;
%pythoncode %{
#<pycode(py_typeinf)>
if ((flags & 1) != 0)
hti |= HTI_FIL;
def get_type_size0(ti, tp):
"""
DEPRECATED. Please use calc_type_size instead
Returns the size of a type
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param tp: type string
@return:
- None on failure
- The size of the type
"""
return calc_type_size(ti, tp)
return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti);
}
#</pycode(py_typeinf)>
PyObject *py_idc_get_type_raw(ea_t ea)
{
qtype type, fields;
if (get_tinfo(ea, &type, &fields))
{
return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str());
}
else
{
Py_RETURN_NONE;
}
}
char *idc_get_type(ea_t ea, char *buf, size_t bufsize)
{
qtype type, fnames;
if (get_tinfo(ea, &type, &fnames))
{
int code = print_type_to_one_line(buf, bufsize, idati, type.c_str(),
NULL, NULL, fnames.c_str());
if (code == T_NORMAL)
return buf;
}
return NULL;
}
char *idc_guess_type(ea_t ea, char *buf, size_t bufsize)
{
qtype type, fnames;
if (guess_tinfo(ea, &type, &fnames))
{
int code = print_type_to_one_line(buf, bufsize, idati, type.c_str(),
NULL, NULL, fnames.c_str());
if (code == T_NORMAL)
return buf;
}
return NULL;
}
int idc_set_local_type(int ordinal, const char *dcl, int flags)
{
if (dcl == NULL || dcl[0] == '\0')
{
if (!del_numbered_type(idati, ordinal))
return 0;
}
else
{
qstring name;
qtype type;
qtype fields;
if (!parse_decl(idati, dcl, &name, &type, &fields, flags))
return 0;
if (ordinal <= 0)
{
if (!name.empty())
ordinal = get_type_ordinal(idati, name.c_str());
if (ordinal <= 0)
ordinal = alloc_type_ordinal(idati);
}
if (!set_numbered_type(idati, ordinal, 0, name.c_str(), type.c_str(), fields.c_str()))
return 0;
}
return ordinal;
}
int idc_get_local_type(int ordinal, int flags, char *buf, size_t maxsize)
{
const type_t *type;
const p_list *fields;
if (!get_numbered_type(idati, ordinal, &type, &fields))
{
buf[0] = 0;
return false;
}
qstring res;
const char *name = get_numbered_type_name(idati, ordinal);
if (print_type_to_qstring(&res, NULL, 2, 40, flags, idati, type, name, NULL, fields) <= 0)
{
buf[0] = 0;
return false;
}
qstrncpy(buf, res.c_str(), maxsize);
return true;
}
char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize)
{
const char *name = get_numbered_type_name(idati, ordinal);
if (name == NULL)
return false;
qstrncpy(buf, name, bufsize);
return true;
}
%}

View File

@ -60,6 +60,8 @@ def init_output_buffer(size = MAXSTR):
*/
PyObject *py_init_output_buffer(size_t size = MAXSTR)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Let Python allocate a writable string buffer for us
PyObject *py_str = PyString_FromStringAndSize(NULL, size);
if ( py_str == NULL )
@ -98,6 +100,7 @@ PyObject *py_decode_preceding_insn(ea_t ea)
{
bool farref;
ea_t r = decode_preceding_insn(ea, &farref);
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0);
}
@ -142,6 +145,7 @@ def get_stkvar(op, v):
*/
PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v;
if ( op == NULL || !PyW_GetNumber(py_v, &v) )
@ -175,6 +179,7 @@ def add_stkvar3(op, v, flags):
*/
bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v;
return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true;
@ -217,11 +222,24 @@ bool py_apply_type_to_stkarg(
const char *name)
{
uint64 v;
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type))
{
return false;
}
else
return apply_type_to_stkarg(*op, uval_t(v), (type_t *) PyString_AsString(py_type), name);
{
const type_t *t = (type_t *) PyString_AsString(py_type);
tinfo_t tif;
tif.deserialize(idati, &t);
borref_t br(py_op);
bool rc;
Py_BEGIN_ALLOW_THREADS;
rc = apply_tinfo_to_stkarg(*op, uval_t(v), tif, name);
Py_END_ALLOW_THREADS;
return rc;
}
}
//-------------------------------------------------------------------------
@ -238,6 +256,7 @@ def OutImmChar(op, outflags = 0):
*/
static void py_OutImmChar(PyObject *x)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(x);
if ( op != NULL )
OutImmChar(*op);
@ -258,6 +277,7 @@ def ua_stkvar2(op, outflags = 0):
*/
static bool py_ua_stkvar2(PyObject *x, adiff_t v, int flags)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(x);
return op == NULL ? false : ua_stkvar2(*op, v, flags);
}
@ -277,6 +297,7 @@ def ua_add_off_drefs(op, type):
*/
ea_t py_ua_add_off_drefs(PyObject *py_op, dref_t type)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs(*op, type);
}
@ -295,6 +316,7 @@ def ua_add_off_drefs2(op, type, outf):
*/
ea_t py_ua_add_off_drefs2(PyObject *py_op, dref_t type, int outf)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
return op == NULL ? BADADDR : ua_add_off_drefs2(*op, type, outf);
}
@ -320,6 +342,7 @@ bool py_out_name_expr(
ea_t ea,
PyObject *py_off)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *op = op_t_get_clink(py_op);
uint64 v(0);
adiff_t off;
@ -327,13 +350,14 @@ bool py_out_name_expr(
off = adiff_t(v);
else
off = BADADDR;
return op == NULL ? false : out_name_expr(*op, ea, off);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( i < 0 || i >= UA_MAXOP || !PyCObject_Check(py_insn_lnk) )
Py_RETURN_NONE;
@ -347,18 +371,21 @@ static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i)
//-------------------------------------------------------------------------
static PyObject *insn_t_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new insn_t(), NULL);
}
//-------------------------------------------------------------------------
static PyObject *op_t_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(new op_t(), NULL);
}
//-------------------------------------------------------------------------
static bool op_t_assign(PyObject *self, PyObject *other)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *lhs = op_t_get_clink(self);
op_t *rhs = op_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
@ -371,6 +398,7 @@ static bool op_t_assign(PyObject *self, PyObject *other)
//-------------------------------------------------------------------------
static bool insn_t_assign(PyObject *self, PyObject *other)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *lhs = insn_t_get_clink(self);
insn_t *rhs = insn_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
@ -383,6 +411,7 @@ static bool insn_t_assign(PyObject *self, PyObject *other)
//-------------------------------------------------------------------------
static bool op_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
@ -395,6 +424,7 @@ static bool op_t_destroy(PyObject *py_obj)
//-------------------------------------------------------------------------
static bool insn_t_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCObject_Check(py_obj) )
return false;
@ -406,13 +436,16 @@ static bool insn_t_destroy(PyObject *py_obj)
// Returns a C link to the global 'cmd' variable
static PyObject *py_get_global_cmd_link()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCObject_FromVoidPtr(&::cmd, NULL);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_is_canon_insn(int itype)
{
if ( ph.is_canon_insn(itype) )
bool ok = ph.is_canon_insn(itype);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@ -421,13 +454,17 @@ static PyObject *insn_t_is_canon_insn(int itype)
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_feature(int itype)
{
return Py_BuildValue("I", ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0);
uint32 v = ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
return Py_BuildValue("I", v);
}
//-------------------------------------------------------------------------
static PyObject *insn_t_get_canon_mnem(int itype)
{
if ( ph.is_canon_insn(itype) )
bool ok = ph.is_canon_insn(itype);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( ok )
return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name);
else
Py_RETURN_NONE;
@ -436,6 +473,7 @@ static PyObject *insn_t_get_canon_mnem(int itype)
//-------------------------------------------------------------------------
static PyObject *insn_t_get_cs(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -444,10 +482,11 @@ static PyObject *insn_t_get_cs(PyObject *self)
static void insn_t_set_cs(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyW_GetNumber(value, &v);
link->cs = ea_t(v);
@ -455,6 +494,7 @@ static void insn_t_set_cs(PyObject *self, PyObject *value)
static PyObject *insn_t_get_ip(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -463,6 +503,7 @@ static PyObject *insn_t_get_ip(PyObject *self)
static void insn_t_set_ip(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -473,6 +514,7 @@ static void insn_t_set_ip(PyObject *self, PyObject *value)
static PyObject *insn_t_get_ea(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -481,6 +523,7 @@ static PyObject *insn_t_get_ea(PyObject *self)
static void insn_t_set_ea(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -491,6 +534,7 @@ static void insn_t_set_ea(PyObject *self, PyObject *value)
static PyObject *insn_t_get_itype(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -499,6 +543,7 @@ static PyObject *insn_t_get_itype(PyObject *self)
static void insn_t_set_itype(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -507,6 +552,7 @@ static void insn_t_set_itype(PyObject *self, PyObject *value)
static PyObject *insn_t_get_size(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -515,6 +561,7 @@ static PyObject *insn_t_get_size(PyObject *self)
static void insn_t_set_size(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -523,6 +570,7 @@ static void insn_t_set_size(PyObject *self, PyObject *value)
static PyObject *insn_t_get_auxpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -531,6 +579,7 @@ static PyObject *insn_t_get_auxpref(PyObject *self)
static void insn_t_set_auxpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -539,6 +588,7 @@ static void insn_t_set_auxpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_segpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -547,6 +597,7 @@ static PyObject *insn_t_get_segpref(PyObject *self)
static void insn_t_set_segpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -555,6 +606,7 @@ static void insn_t_set_segpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_insnpref(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -563,6 +615,7 @@ static PyObject *insn_t_get_insnpref(PyObject *self)
static void insn_t_set_insnpref(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -571,6 +624,7 @@ static void insn_t_set_insnpref(PyObject *self, PyObject *value)
static PyObject *insn_t_get_flags(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -579,6 +633,7 @@ static PyObject *insn_t_get_flags(PyObject *self)
static void insn_t_set_flags(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
insn_t *link = insn_t_get_clink(self);
if ( link == NULL )
return;
@ -588,6 +643,7 @@ static void insn_t_set_flags(PyObject *self, PyObject *value)
//-------------------------------------------------------------------------
static PyObject *op_t_get_n(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -604,6 +660,7 @@ static void op_t_set_n(PyObject *self, PyObject *value)
static PyObject *op_t_get_type(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -612,6 +669,7 @@ static PyObject *op_t_get_type(PyObject *self)
static void op_t_set_type(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -620,6 +678,7 @@ static void op_t_set_type(PyObject *self, PyObject *value)
static PyObject *op_t_get_offb(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -628,6 +687,7 @@ static PyObject *op_t_get_offb(PyObject *self)
static void op_t_set_offb(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -636,6 +696,7 @@ static void op_t_set_offb(PyObject *self, PyObject *value)
static PyObject *op_t_get_offo(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -644,6 +705,7 @@ static PyObject *op_t_get_offo(PyObject *self)
static void op_t_set_offo(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -652,6 +714,7 @@ static void op_t_set_offo(PyObject *self, PyObject *value)
static PyObject *op_t_get_flags(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -660,6 +723,7 @@ static PyObject *op_t_get_flags(PyObject *self)
static void op_t_set_flags(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -668,6 +732,7 @@ static void op_t_set_flags(PyObject *self, PyObject *value)
static PyObject *op_t_get_dtyp(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -676,6 +741,7 @@ static PyObject *op_t_get_dtyp(PyObject *self)
static void op_t_set_dtyp(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -684,6 +750,7 @@ static void op_t_set_dtyp(PyObject *self, PyObject *value)
static PyObject *op_t_get_reg_phrase(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -691,6 +758,7 @@ static PyObject *op_t_get_reg_phrase(PyObject *self)
}
static void op_t_set_reg_phrase(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -699,6 +767,7 @@ static void op_t_set_reg_phrase(PyObject *self, PyObject *value)
static PyObject *op_t_get_value(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -707,6 +776,7 @@ static PyObject *op_t_get_value(PyObject *self)
static void op_t_set_value(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -715,6 +785,7 @@ static void op_t_set_value(PyObject *self, PyObject *value)
static PyObject *op_t_get_addr(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -723,6 +794,7 @@ static PyObject *op_t_get_addr(PyObject *self)
static void op_t_set_addr(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -733,6 +805,7 @@ static void op_t_set_addr(PyObject *self, PyObject *value)
static PyObject *op_t_get_specval(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -741,6 +814,7 @@ static PyObject *op_t_get_specval(PyObject *self)
static void op_t_set_specval(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -751,6 +825,7 @@ static void op_t_set_specval(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag1(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -759,6 +834,7 @@ static PyObject *op_t_get_specflag1(PyObject *self)
static void op_t_set_specflag1(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -767,6 +843,7 @@ static void op_t_set_specflag1(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag2(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -775,6 +852,7 @@ static PyObject *op_t_get_specflag2(PyObject *self)
static void op_t_set_specflag2(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -783,6 +861,7 @@ static void op_t_set_specflag2(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag3(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -791,6 +870,7 @@ static PyObject *op_t_get_specflag3(PyObject *self)
static void op_t_set_specflag3(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;
@ -799,6 +879,7 @@ static void op_t_set_specflag3(PyObject *self, PyObject *value)
static PyObject *op_t_get_specflag4(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
@ -807,6 +888,7 @@ static PyObject *op_t_get_specflag4(PyObject *self)
static void op_t_set_specflag4(PyObject *self, PyObject *value)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
op_t *link = op_t_get_clink(self);
if ( link == NULL )
return;

1008
swig/view.i Normal file

File diff suppressed because it is too large Load Diff