IDAPython for IDA 7.3

This commit is contained in:
Arnaud Diederen
2019-06-26 14:37:39 +02:00
parent afca63f19a
commit 7a567eecf0
127 changed files with 104365 additions and 3930 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ A script that tries to determine the call stack
Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
Copyright (c) 1990-2018 Hex-Rays
Copyright (c) 1990-2019 Hex-Rays
ALL RIGHTS RESERVED.
"""
import ida_ua
+1 -1
View File
@@ -2,7 +2,7 @@
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
Copyright (c) 1990-2018 Hex-Rays
Copyright (c) 1990-2019 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2009 Hex-Rays
Copyright (c) 1990-2019 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -13,7 +13,7 @@ The general syntax is:
* To specify in which context the instructions should be assembled, pass asm_where=ea:
find("jmp dword ptr [esp]", asm_where=here())
Copyright (c) 1990-2018 Hex-Rays
Copyright (c) 1990-2019 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -4,7 +4,7 @@ A script that graphs all the exception handlers in a given process
It will be easy to see what thread uses what handler and what handlers are commonly used between threads
Copyright (c) 1990-2018 Hex-Rays
Copyright (c) 1990-2019 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2009 Hex-Rays
Copyright (c) 1990-2019 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@ from __future__ import print_function
# -----------------------------------------------------------------------
# VirusTotal IDA Plugin
# By Elias Bachaalany <elias at hex-rays.com>
# (c) Hex-Rays 2011
# (c) Hex-Rays 2011-2019
#
# Special thanks:
# - VirusTotal team
+2794 -115
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -15,9 +15,6 @@ import idautils
#--------------------------------------------------------------------------
class assemble_idp_hook_t(idaapi.IDP_Hooks):
def __init__(self):
idaapi.IDP_Hooks.__init__(self)
def assemble(self, ea, cs, ip, use32, line):
line = line.strip()
if line == "xor eax, eax":
+16 -11
View File
@@ -15,13 +15,16 @@ class MyUiHook(idaapi.UI_Hooks):
idaapi.UI_Hooks.__init__(self)
self.cmdname = "<no command>"
def preprocess(self, name):
print("IDA preprocessing command: %s" % name)
def _log(self, msg):
print(">>> MyUiHook: %s" % msg)
def preprocess_action(self, name):
self._log("IDA preprocessing command: %s" % name)
self.cmdname = name
return 0
def postprocess(self):
print("IDA finished processing command: %s" % self.cmdname)
def postprocess_action(self):
self._log("IDA finished processing command: %s" % self.cmdname)
return 0
def saving(self):
@@ -30,7 +33,7 @@ class MyUiHook(idaapi.UI_Hooks):
@return: Ignored
"""
print("Saving....")
self._log("Saving....")
def saved(self):
"""
@@ -38,7 +41,7 @@ class MyUiHook(idaapi.UI_Hooks):
@return: Ignored
"""
print("Saved")
self._log("Saved")
def term(self):
"""
@@ -47,7 +50,7 @@ class MyUiHook(idaapi.UI_Hooks):
This callback is best used within the context of a plugin_t with PLUGIN_FIX flags
"""
print("IDA terminated")
self._log("IDA terminated")
def get_ea_hint(self, ea):
"""
@@ -56,21 +59,21 @@ class MyUiHook(idaapi.UI_Hooks):
@param ea: The address
@return: String with the hint or None
"""
print("get_ea_hint(%x)" % ea)
self._log("get_ea_hint(%x)" % ea)
def populating_widget_popup(self, widget, popup, ctx):
"""
The UI is currently populating the widget popup. Now is a good time to
attach actions.
"""
print("populating_widget_popup; title: %s" % (ctx.widget_title,))
self._log("populating_widget_popup; title: %s" % (ctx.widget_title,))
def finish_populating_widget_popup(self, widget, popup, ctx):
"""
The UI is done populating the widget popup. Now is the last chance to
attach actions.
"""
print("finish_populating_widget_popup; title: %s" % (ctx.widget_title,))
self._log("finish_populating_widget_popup; title: %s" % (ctx.widget_title,))
#---------------------------------------------------------------------
@@ -80,12 +83,14 @@ try:
print("UI hook: checking for hook...")
uihook
print("UI hook: unhooking....")
ui_hook_stat2 = ""
uihook.unhook()
del uihook
except:
print("UI hook: not installed, installing now....")
ui_hook_stat = ""
ui_hook_stat2 = "un"
uihook = MyUiHook()
uihook.hook()
print("UI hook %sinstalled. Run the script again to %sinstall" % (ui_hook_stat, ui_hook_stat))
print("UI hook %sinstalled. Run the script again to %sinstall" % (ui_hook_stat, ui_hook_stat2))
+64
View File
@@ -0,0 +1,64 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# It installs a custom microcode optimization rule:
# call !DbgRaiseAssertionFailure <fast:>.0
# =>
# call !DbgRaiseAssertionFailure <fast:"char *" "assertion text">.0
#
# To see this plugin in action please use arm64_brk.i64, in the hexrays sdk
#
# This is a rewrite in Python of the vds10 example that comes with hexrays sdk.
#
import ida_bytes
import ida_range
import ida_kernwin
import ida_hexrays
import ida_typeinf
class nt_assert_optimizer_t(ida_hexrays.optinsn_t):
def func(self, blk, ins):
if self.handle_nt_assert(ins):
return 1
return 0
def handle_nt_assert(self, ins):
# recognize call !DbgRaiseAssertionFailure <fast:>.0
if not ins.is_helper("DbgRaiseAssertionFailure"):
return False
# did we already add an argument?
fi = ins.d.f;
if not fi.args.empty():
return False
# use a comment from the disassembly listing as the call argument
cmt = ida_bytes.get_cmt(ins.ea, False)
if not cmt:
return False
# remove "NT_ASSERT("...")" to make the listing nicer
if cmt.startswith("NT_ASSERT(\""):
cmt = cmt[11:]
if cmt.endswith("\")"):
cmt = cmt[:-2]
# all ok, transform the instruction by adding one more call argument
fa = fi.args.push_back()
fa.t = ida_hexrays.mop_str;
fa.cstr = cmt
fa.type = ida_typeinf.tinfo_t.get_stock(ida_typeinf.STI_PCCHAR) # const char *
fa.size = fa.type.get_size()
return True
if ida_hexrays.init_hexrays_plugin():
optimizer = nt_assert_optimizer_t()
optimizer.install()
else:
print('vds10: Hex-rays is not available.')
+79
View File
@@ -0,0 +1,79 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# It installs a custom block optimization rule:
#
# goto L1 => goto L2
# ...
# L1:
# goto L2
#
# In other words we fix a goto target if it points to a chain of gotos.
# This improves the decompiler output in some cases.
#
# This is a rewrite in Python of the vds11 example that comes with hexrays sdk.
#
import ida_bytes
import ida_range
import ida_kernwin
import ida_hexrays
import ida_typeinf
class goto_optimizer_t(ida_hexrays.optblock_t):
def func(self, blk):
if self.handle_goto_chain(blk):
return 1
return 0
def handle_goto_chain(self, blk):
mgoto = blk.tail
if not mgoto or mgoto.opcode != ida_hexrays.m_goto:
return False
visited = []
t0 = mgoto.l.b
i = t0
mba = blk.mba
# follow the goto chain
while True:
if i in visited:
return False
visited.append(i)
b = mba.get_mblock(i)
m2 = ida_hexrays.getf_reginsn(b.head)
if not m2 or m2.opcode != ida_hexrays.m_goto:
break
i = m2.l.b
if i == t0:
return False # not a chain
# all ok, found a goto chain
mgoto.l.b = i # jump directly to the end of the chain
# fix the successor/predecessor lists
blk.succset[0] = i
mba.get_mblock(i).predset.add(blk.serial)
mba.get_mblock(t0).predset._del(blk.serial)
# since we changed the control flow graph, invalidate the use/def chains.
# stricly speaking it is not really necessary in our plugin because
# we did not move around any microcode operands.
mba.mark_chains_dirty()
# it is a good idea to verify microcode after each change
# however, it may be time consuming, so comment it out eventually
mba.verify(True);
return True
if ida_hexrays.init_hexrays_plugin():
optimizer = goto_optimizer_t()
optimizer.install()
else:
print('vds11: Hex-rays is not available.')
+155
View File
@@ -0,0 +1,155 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# It shows list of direct references to a register from the current
# instruction.
#
# This is a rewrite in Python of the vds12 example that comes with hexrays sdk.
#
import ida_pro
import ida_hexrays
import ida_kernwin
import ida_funcs
import ida_bytes
import ida_lines
def collect_block_xrefs(out, mlist, blk, ins, find_uses):
p = ins
while p and not mlist.empty():
use = blk.build_use_list(p, ida_hexrays.MUST_ACCESS); # things used by the insn
_def = blk.build_def_list(p, ida_hexrays.MUST_ACCESS); # things defined by the insn
plst = use if find_uses else _def
if mlist.has_common(plst):
if not p.ea in out:
out.append(p.ea) # this microinstruction seems to use our operand
mlist.sub(_def)
p = p.next if find_uses else p.prev
def collect_xrefs(out, ctx, mop, mlist, du, find_uses):
# first collect the references in the current block
start = ctx.topins.next if find_uses else ctx.topins.prev;
collect_block_xrefs(out, mlist, ctx.blk, start, find_uses)
# then find references in other blocks
serial = ctx.blk.serial; # block number of the operand
bc = du[serial] # chains of that block
voff = ida_hexrays.voff_t(mop)
ch = bc.get_chain(voff) # chain of the operand
if not ch:
return # odd
for bn in ch:
b = ctx.mba.get_mblock(bn)
ins = b.head if find_uses else b.tail
tmp = ida_hexrays.mlist_t()
tmp.add(mlist)
collect_block_xrefs(out, tmp, b, ins, find_uses)
class xref_chooser_t(ida_kernwin.Choose):
def __init__(self, xrefs, t, n, ea, gco):
ida_kernwin.Choose.__init__(
self,
t,
[["Type", 3], ["Address", 16], ["Instruction", 60]])
self.xrefs = xrefs
self.ndefs = n
self.curr_ea = ea
self.gco = gco
self.items = [ self._make_item(idx) for idx in xrange(len(xrefs)) ]
def OnGetSize(self):
return len(self.items)
def OnGetLine(self, n):
return self.items[n]
def _make_item(self, idx):
ea = self.xrefs[idx]
both_mask = ida_hexrays.GCO_USE|ida_hexrays.GCO_DEF
both = (self.gco.flags & both_mask) == both_mask
if ea == self.curr_ea and both:
type_str = "use/def"
elif idx < self.ndefs:
type_str = "def"
else:
type_str = "use"
insn = ida_lines.generate_disasm_line(ea, ida_lines.GENDSM_REMOVE_TAGS)
return [type_str, "%08x" % ea, insn]
def show_xrefs(ea, gco, xrefs, ndefs):
title = "xrefs to %s at %08x" % (gco.name, ea)
xc = xref_chooser_t(xrefs, title, ndefs, ea, gco)
i = xc.Show(True)
if i >= 0:
ida_kernwin.jumpto(xrefs[i])
if ida_hexrays.init_hexrays_plugin():
ea = ida_kernwin.get_screen_ea()
pfn = ida_funcs.get_func(ea)
w = ida_kernwin.warning
if pfn:
F = ida_bytes.get_flags(ea)
if ida_bytes.is_code(F):
gco = ida_hexrays.gco_info_t()
if ida_hexrays.get_current_operand(gco):
# generate microcode
hf = ida_hexrays.hexrays_failure_t()
mbr = ida_hexrays.mba_ranges_t(pfn)
mba = ida_hexrays.gen_microcode(
mbr,
hf,
None,
ida_hexrays.DECOMP_WARNINGS,
ida_hexrays.MMAT_PREOPTIMIZED)
if mba:
merr = mba.build_graph()
if merr == ida_hexrays.MERR_OK:
ncalls = mba.analyze_calls(ida_hexrays.ACFL_GUESS)
if ncalls < 0:
print("%08x: failed to determine some calling conventions", pfn.start_ea)
mlist = ida_hexrays.mlist_t()
if gco.append_to_list(mlist, mba):
ctx = ida_hexrays.op_parent_info_t()
mop = mba.find_mop(ctx, ea, gco.is_def(), mlist)
if mop:
xrefs = ida_pro.eavec_t()
ndefs = 0
graph = mba.get_graph()
ud = graph.get_ud(ida_hexrays.GC_REGS_AND_STKVARS)
du = graph.get_du(ida_hexrays.GC_REGS_AND_STKVARS)
if gco.is_use():
collect_xrefs(xrefs, ctx, mop, mlist, ud, False)
ndefs = xrefs.size()
if ea not in xrefs:
xrefs.append(ea)
if gco.is_def():
if ea not in xrefs:
xrefs.append(ea)
ndefs = len(xrefs)
collect_xrefs(xrefs, ctx, mop, mlist, du, True)
show_xrefs(ea, gco, xrefs, ndefs)
else:
w("Could not find the operand in the microcode, sorry")
else:
w("Failed to represent %s as microcode list" % gco.name)
else:
w("%08x: %s" % (errea, ida_hexrays.get_merror_desc(merr, mba)))
else:
w("%08x: %s" % (hf.errea, hf.str))
else:
w("Could not find a register or stkvar in the current operand")
else:
w("Please position the cursor on an instruction")
else:
w("Please position the cursor within a function")
else:
print('vds12: Hex-rays is not available.')
+39
View File
@@ -0,0 +1,39 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# It generates microcode for selection and dumps it to the output window.
#
# This is a rewrite in Python of the vds13 example that comes with hexrays sdk.
#
import ida_bytes
import ida_range
import ida_kernwin
import ida_hexrays
if ida_hexrays.init_hexrays_plugin():
sel, sea, eea = ida_kernwin.read_range_selection(None)
w = ida_kernwin.warning
if sel:
F = ida_bytes.get_flags(sea)
if ida_bytes.is_code(F):
hf = ida_hexrays.hexrays_failure_t()
mbr = ida_hexrays.mba_ranges_t()
mbr.ranges.push_back(ida_range.range_t(sea, eea))
mba = ida_hexrays.gen_microcode(mbr, hf, None, ida_hexrays.DECOMP_WARNINGS)
if mba:
print("Successfully generated microcode for 0x%08x..0x%08x\n" % (sea, eea))
vp = ida_hexrays.vd_printer_t()
mba._print(vp)
else:
w("0x%08x: %s" % (hf.errea, hf.str))
else:
w("The selected range must start with an instruction")
else:
w("Please select a range of addresses to analyze")
else:
print('vds13: Hex-rays is not available.')
+142
View File
@@ -0,0 +1,142 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
# It shows how to use "Select offsets" widget (select_udt_by_offset() call).
# This plugin repeats the Alt-Y functionality.
# Usage: place cursor on the union field and press Shift-T
#
# This is a rewrite in Python of the vds17 example that comes with hexrays sdk.
#
import ida_idaapi
import ida_hexrays
# --------------------------------------------------------------------------
class func_stroff_ah_t(ida_kernwin.action_handler_t):
def __init__(self):
ida_kernwin.action_handler_t.__init__(self)
def activate(self, ctx):
# get current item
vu = ida_hexrays.get_widget_vdui(ctx.widget)
vu.get_current_item(idaapi.USE_KEYBOARD)
# check the current item is union field
if not vu.item.is_citem():
return 0
e = vu.item.e
while True:
op = e.op
if op != ida_hexrays.cot_memptr and op != ida_hexrays.cot_memref:
return 0
e = e.x
if op == ida_hexrays.cot_memptr:
if e.type.is_union():
break
else:
if ida_typeinf.remove_pointer(e.type).is_union():
break
if not e.type.is_udt():
return 0
# calculate member's offset
off = 0
e = vu.item.e
while True:
e2 = e.x
tif = ida_typeinf.remove_pointer(e2.type)
if not tif.is_union():
off += e.m
e = e2
if e2.op != ida_hexrays.cot_memptr and e2.op != ida_hexrays.cot_memref:
break
if not e2.type.is_udt():
break
# go up and collect more member references (in order to calculate the final offset)
p = vu.item.e
while True:
p2 = vu.cfunc.body.find_parent_of(p)
if p2.op == ida_hexrays.cot_memptr:
break
if p2.op == ida_hexrays.cot_memref:
e2 = p2
tif = remove_pointer(e2.x.type)
if not tif.is_union():
off += e2.m
p = p2
continue
if p2.op == ida_hexrays.cot_ref:
# handle &a.b + N (this expression may appear if the user previously selected
# a wrong field)
delta = 0
add = vu.cfunc.body.find_parent_of(p2)
if add.op == ida_hexrays.cot_cast:
add = vu.cfunc.body.find_parent_of(add)
if add.op == ida_hexrays.cot_add and add.y.op == ida_hexrays.cot_num:
delta = add.y.numval()
objsize = add.type.get_ptrarr_objsize()
nbytes = delta * objsize
off += nbytes
# we can use the calling helpers like WORD/BYTE/...
# to calculate the more precise offset
# if ( p2->op == cot_call && (e2->exflags & EXFL_LVALUE) != 0 )
break
ea = vu.item.e.ea
# the item itself may be unaddressable.
# TODO: find its addressable parent
if ea == idaapi.BADADDR:
return 0
# prepare the text representation for the item,
# use the neighborhoods of cursor
line = idaapi.tag_remove(ida_kernwin.get_custom_viewer_curline(vu.ct, False))
line_len = len(line)
x = max(0, vu.cpos.x - 10)
l = min(10, line_len - vu.cpos.x) + 10
line = line[x:x+l]
ops = ida_hexrays.ui_stroff_ops_t()
op = ops.push_back()
op.offset = off
op.text = line
class set_union_sel_t(ida_hexrays.ui_stroff_applicator_t):
def __init__(self, eas):
ida_hexrays.ui_stroff_applicator_t.__init__(self)
self.eas = eas
def apply(self, opnum, path):
vu.cfunc.set_user_union_selection(self.eas[opnum], path)
vu.cfunc.save_user_unions()
return True
su = set_union_sel_t([ea])
res = ida_hexrays.select_udt_by_offset(None, ops, su)
if res != 0:
# regenerate ctree
vu.refresh_view(True)
return 1
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET if \
ctx.widget_type == ida_kernwin.BWN_PSEUDOCODE else \
ida_kernwin.AST_DISABLE_FOR_WIDGET
# --------------------------------------------------------------------------
if ida_hexrays.init_hexrays_plugin():
print("Hex-rays version %s has been detected, Structure offsets ready to use" % idaapi.get_hexrays_version())
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
"vds17:strchoose",
"Structure offsets",
func_stroff_ah_t(),
"Shift+T"))
else:
print('vds17: Hex-rays is not available.')
+1
View File
@@ -1,5 +1,6 @@
from __future__ import print_function
import ida_idaapi
import ida_pro
import ida_hexrays
import ida_kernwin
+1
View File
@@ -9,6 +9,7 @@ from __future__ import print_function
import idautils
import idc
import ida_idaapi
import ida_hexrays
import ida_lines
+2 -4
View File
@@ -1,6 +1,6 @@
# Hex-Rays Decompiler project
# Copyright (c) 2007-2018 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample script for Hex-Rays Decompiler usage of udc_filter_t
@@ -10,6 +10,7 @@
#
# It is also added into the right-click menu as "vds8.py:Toggle UDC"
import ida_idaapi
import ida_hexrays
import ida_kernwin
import ida_allins
@@ -64,9 +65,6 @@ class toggle_udc_ah_t(ida_kernwin.action_handler_t):
# --------------------------------------------------------------------------
class my_hooks_t(ida_kernwin.UI_Hooks):
def __init__(self):
ida_kernwin.UI_Hooks.__init__(self)
def populating_widget_popup(self, widget, popup):
if ida_kernwin.get_widget_type(widget) == ida_kernwin.BWN_PSEUDOCODE:
ida_kernwin.attach_action_to_popup(widget, popup, ACTION_NAME)
+1
View File
@@ -7,6 +7,7 @@ If the object under the cursor is:
- an 'if' statement, replace the hint with our own, saying "condition"
"""
import ida_idaapi
import ida_hexrays
class hint_hooks_t(ida_hexrays.Hexrays_Hooks):
+1
View File
@@ -3,6 +3,7 @@ Various hooks for Hexrays Decompiler
"""
from __future__ import print_function
import ida_idaapi
import ida_typeinf
import ida_hexrays
+45
View File
@@ -0,0 +1,45 @@
import ida_hexrays
import ida_typeinf
import idc
class my_modifier_t(ida_hexrays.user_lvar_modifier_t):
def __init__(self, name_prefix="", cmt_prefix="", new_types={}):
ida_hexrays.user_lvar_modifier_t.__init__(self)
self.name_prefix = name_prefix
self.cmt_prefix = cmt_prefix
self.new_types = new_types
def modify_lvars(self, lvars):
def log(msg):
print("modify_lvars: %s" % msg)
log("len(lvars.lvvec) = %d" % len(lvars.lvvec))
log("lvars.lmaps.size() = %d" % lvars.lmaps.size())
log("lvars.stkoff_delta = %d" % lvars.stkoff_delta)
log("lvars.ulv_flags = %x" % lvars.ulv_flags)
for idx, one in enumerate(lvars.lvvec):
def varlog(msg):
log("var #%d: %s" % (idx, msg))
varlog("name = '%s'" % one.name)
varlog("type = '%s'" % one.type._print())
varlog("cmt = '%s'" % one.cmt)
varlog("size = %d" % one.size)
varlog("flags = %x" % one.flags)
new_type = self.new_types.get(one.name)
if new_type:
ida_typeinf.parse_decl(one.type, None, new_type, 0)
one.name = self.name_prefix + one.name
one.cmt = self.cmt_prefix + one.cmt
return True
def modify_function_lvars(name_prefix="patched_", cmt_prefix="(patched) ", new_types={}):
ea = idc.here()
my_mod = my_modifier_t(
name_prefix=name_prefix,
cmt_prefix=cmt_prefix,
new_types=new_types)
ida_hexrays.modify_user_lvars(ea, my_mod)
+2 -1
View File
@@ -10,6 +10,7 @@ global:
PyW_IsSequenceType;
PyW_ObjectToString;
PyW_PyListToEaVec;
PyW_PyListToEa64Vec;
PyW_PyListToSizeVec;
PyW_PyListToStrVec;
PyW_ShowCbErr;
@@ -19,7 +20,6 @@ global:
PyW_TryImportModule;
PyW_register_compiled_form;
PyW_unregister_compiled_form;
add_notify_when;
create_linked_class_instance;
disable_script_timeout;
enable_extlang_python;
@@ -58,6 +58,7 @@ global:
register_module_lifecycle_callbacks;
set_script_timeout;
set_interruptible_state;
setup_new_execution;
til_deregister_python_array_type_data_t_instance;
til_deregister_python_func_type_data_t_instance;
til_deregister_python_ptr_type_data_t_instance;
+2 -1
View File
@@ -10,6 +10,7 @@ EXPORTS
PyW_IsSequenceType
PyW_ObjectToString
PyW_PyListToEaVec
PyW_PyListToEa64Vec
PyW_PyListToSizeVec
PyW_PyListToStrVec
PyW_register_compiled_form
@@ -17,7 +18,6 @@ EXPORTS
PyW_TryGetAttrString
PyW_TryImportModule
PyW_unregister_compiled_form
add_notify_when
create_linked_class_instance
disable_script_timeout
enable_extlang_python
@@ -51,6 +51,7 @@ EXPORTS
pyw_convert_idc_args
set_script_timeout
set_interruptible_state
setup_new_execution
til_deregister_python_array_type_data_t_instance
til_deregister_python_func_type_data_t_instance
til_deregister_python_ptr_type_data_t_instance
+118 -24
View File
@@ -42,8 +42,15 @@ else
endif
ifndef __MKDEP__
I = $(ST_SDK)/
else
# HACK for mkdep to add dependencies for $(F)python$(O)
endif
# HACK HIJACK the $(LIBDIR) variable to point to our staging SDK
ifneq ($(OUT_OF_TREE_BUILD),)
LIBDIR = $(IDA)lib/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(STATSUF)
endif
# HACK for mkdep to add dependencies for $(F)python$(O)
ifdef __MKDEP__
OBJS += $(F)python$(O)
endif
@@ -103,9 +110,14 @@ ifdef DO_IDAMAKE_SIMPLIFY
QGEN_IDC_BC695 = @echo $(call qcolor,gen_idc_bc695) $< && #
QINJECT_PLFM = @echo $(call qcolor,inject_plfm) $< && #
QINJECT_PYDOC = @echo $(call qcolor,inject_pydoc) $$< && #
QINJECT_BASE_HOOKS_FLAGS = @echo $(call qcolor,inject_base_hooks_flags) $< && #
QPATCH_CODEGEN = @echo $(call qcolor,patch_codegen) $$< && #
QPATCH_H_CODEGEN = @echo $(call qcolor,patch_h_codegen) $$< && #
QPATCH_PYTHON_CODEGEN = @echo $(call qcolor,patch_python_codegen) $$< && #
QSWIG = @echo $(call qcolor,swig) $$< && #
QUPATE_SDK = @echo $(call qcolor,update_sdk) $< && #
QUPDATE_SDK = @echo $(call qcolor,update_sdk) $< && #
QSPLIT_HEXRAYS_TEMPLATES = @echo $(call qcolor,split_hexrays_templates) $< && #
QPYDOC_INJECTIONS = @echo $(call qcolor,check_injections) $@ && #
endif
#----------------------------------------------------------------------
@@ -127,6 +139,9 @@ DEPLOY_IDAUTILS_PY=$(DEPLOY_PYDIR)/idautils.py
DEPLOY_IDC_BC695_PY=$(DEPLOY_PYDIR)/idc_bc695.py
DEPLOY_IDAAPI_PY=$(DEPLOY_PYDIR)/idaapi.py
DEPLOY_IDADEX_PY=$(DEPLOY_PYDIR)/idadex.py
ifdef TESTABLE_BUILD
DEPLOY_LUMINA_MODEL_PY=$(DEPLOY_PYDIR)/lumina_model.py
endif
ifeq ($(OUT_OF_TREE_BUILD),)
TEST_IDC=test_idc
IDC_BC695_IDC_SOURCE?=$(DEPLOY_PYDIR)/../idc/idc.idc
@@ -184,6 +199,9 @@ MODULES_NAMES += idp
MODULES_NAMES += kernwin
MODULES_NAMES += lines
MODULES_NAMES += loader
ifdef TESTABLE_BUILD
MODULES_NAMES += lumina
endif
MODULES_NAMES += moves
MODULES_NAMES += nalt
MODULES_NAMES += name
@@ -251,7 +269,8 @@ pyfiles: $(DEPLOY_IDAUTILS_PY) \
$(DEPLOY_IDC_BC695_PY) \
$(DEPLOY_INIT_PY) \
$(DEPLOY_IDAAPI_PY) \
$(DEPLOY_IDADEX_PY)
$(DEPLOY_IDADEX_PY) \
$(DEPLOY_LUMINA_MODEL_PY)
GENHOOKS=tools/genhooks/
@@ -273,6 +292,9 @@ $(DEPLOY_IDAAPI_PY): python/idaapi.py tools/genidaapi.py $(IDAPYTHON_MODULES)
$(DEPLOY_IDADEX_PY): python/idadex.py
$(CP) $? $@
$(DEPLOY_LUMINA_MODEL_PY): python/lumina_model.py
$(CP) $? $@
$(DEPLOY_PYDIR)/lib/%: precompiled/lib/%
cp $< $@
$(Q)chmod +w $@
@@ -306,13 +328,35 @@ $(foreach d,$(sort $(DIRLIST)),$(if $(wildcard $(d)),,$(shell mkdir -p $(d))))
#----------------------------------------------------------------------
# obj/.../idasdk/*.h[pp]
# NOTE: Because we have the following sequence in hexrays.hpp:
# - definition of template "template <class T> struct ivl_tpl"
# - instantiation of template into "typedef ivl_tpl<uval_t> uval_ivl_t;"
# - subclassing of "uval_ivl_t": "struct ivl_t : public uval_ivl_t",
# we are in trouble in our hexrays.i file, because by the time SWiG
# processes "struct ivl_t", it won't have properly instantiated the
# template, leading to the IDAPython proxy class "ivl_t" not subclassing
# "uval_ivl_t". Therefore, we have to split the hexrays.hpp header file
# into two: one that defines the template, and one that instantiates it.
# This way, we can '%import "hexrays_templates.hpp"', then do the SWiG
# template incantation, and finally '%include "hexrays_notemplates.hpp"'
# to actually generate wrappers.
ifeq ($(OUT_OF_TREE_BUILD),)
$(ST_SDK)/%.h: $(IDA_INCLUDE)/%.h
$(QUPATE_SDK)$(PYTHON) ../../bin/update_sdk.py $(FILTER_SDK_FLAGS) -filter-file -input $^ -output $@
$(QUPDATE_SDK) perl ../../etc/sdk/filter_src.pl $^ $@
$(ST_SDK)/%.hpp: $(IDA_INCLUDE)/%.hpp
$(QUPATE_SDK)$(PYTHON) ../../bin/update_sdk.py $(FILTER_SDK_FLAGS) -filter-file -input $^ -output $@
$(QUPDATE_SDK) perl ../../etc/sdk/filter_src.pl $^ $@
HEXRAYS_HPP_SPLIT_DIR:=$(ST_SDK)
else
HEXRAYS_HPP_SPLIT_DIR:=$(F)
endif
$(HEXRAYS_HPP_SPLIT_DIR)/hexrays_notemplates.hpp: $(ST_SDK)/hexrays.hpp tools/split_hexrays_templates.py
$(QSPLIT_HEXRAYS_TEMPLATES)$(PYTHON) tools/split_hexrays_templates.py \
--input $< \
--out-templates $(HEXRAYS_HPP_SPLIT_DIR)/hexrays_templates.hpp \
--out-body=$(HEXRAYS_HPP_SPLIT_DIR)/hexrays_notemplates.hpp
SWIGFLAGS += -I$(HEXRAYS_HPP_SPLIT_DIR)
#----------------------------------------------------------------------
# obj/.../pywraps/*
$(ST_PYW)/%.hpp: pywraps/%.hpp
@@ -329,6 +373,7 @@ $(ST_PYW)/py_idp.hpp: pywraps/py_idp.hpp \
$(GENHOOKS)recipe_idphooks.py \
$(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c IDP_Hooks \
-x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e event_t \
-r int -n 0 -m hookgenIDP -q "processor_t::" \
-R $(GENHOOKS)recipe_idphooks.py
@@ -337,15 +382,17 @@ $(ST_PYW)/py_idp_idbhooks.hpp: pywraps/py_idp_idbhooks.hpp \
$(GENHOOKS)recipe_idbhooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c IDB_Hooks \
-x $(ST_PARSED_HEADERS)/namespaceidb__event.xml -e event_code_t \
-r int -n 0 -m hookgenIDB -q "idb_event::" \
-r void -n 0 -m hookgenIDB -q "idb_event::" \
-R $(GENHOOKS)recipe_idbhooks.py
$(ST_PYW)/py_dbg.hpp: pywraps/py_dbg.hpp \
$(I)dbg.hpp \
$(GENHOOKS)recipe_dbghooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-x $(ST_PARSED_HEADERS)/dbg_8hpp.xml -e dbg_notification_t \
-c DBG_Hooks \
-x $(ST_PARSED_HEADERS)/dbg_8hpp.xml -q "dbg_notification_t::" -e dbg_notification_t \
-r void -n 0 -m hookgenDBG \
-R $(GENHOOKS)recipe_dbghooks.py
$(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \
@@ -353,7 +400,9 @@ $(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \
$(GENHOOKS)recipe_uihooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c UI_Hooks \
-x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e ui_notification_t \
-q "ui_notification_t::" \
-r void -n 0 -m hookgenUI \
-R $(GENHOOKS)recipe_uihooks.py \
-d "ui_dbg_,ui_obsolete" -D "ui:" -s "ui_"
@@ -362,15 +411,19 @@ $(ST_PYW)/py_kernwin_viewhooks.hpp: pywraps/py_kernwin_viewhooks.hpp \
$(GENHOOKS)recipe_viewhooks.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c View_Hooks \
-x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e view_notification_t \
-q "view_notification_t::" \
-r void -n 0 -m hookgenVIEW \
-R $(GENHOOKS)recipe_viewhooks.py
$(ST_PYW)/py_hexrays_hooks.hpp: pywraps/py_hexrays_hooks.hpp \
$(I)hexrays.hpp \
$(HEXRAYS_HPP_SPLIT_DIR)/hexrays_notemplates.hpp \
$(GENHOOKS)recipe_hexrays.py \
$(GENHOOKS)genhooks.py $(PARSED_HEADERS_MARKER) $(MAKEFILE_DEP) | $(SDK_SOURCES)
$(QGENHOOKS)$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \
-c Hexrays_Hooks \
-x $(ST_PARSED_HEADERS)/hexrays_8hpp.xml -e hexrays_event_t \
-q "hexrays_event_t::" \
-r int -n 0 -m hookgenHEXRAYS \
-R $(GENHOOKS)recipe_hexrays.py \
-s "hxe_,lxe_"
@@ -382,8 +435,8 @@ CC_DEFS += $(BC695_CC_DEF)
CC_DEFS += $(DEF_TYPE_TABLE)
CC_DEFS += $(WITH_HEXRAYS_DEF)
CC_DEFS += USE_STANDARD_FILE_FUNCTIONS
CC_DEFS += VER_MAJOR="1"
CC_DEFS += VER_MINOR="7"
CC_DEFS += VER_MAJOR="7"
CC_DEFS += VER_MINOR="3"
CC_DEFS += VER_PATCH="0"
CC_DEFS += __EXPR_SRC
CC_INCP += $(F)
@@ -391,8 +444,23 @@ CC_INCP += $(IDA_INCLUDE)
CC_INCP += $(ST_SWIG)
CC_INCP += .
# suppress warnings
WARNS = $(NOWARNS)
ifdef __UNIX__
# suppress some warnings
# see https://github.com/swig/swig/pull/801
# FIXME: remove these once swig is fixed
CC_WNO += -Wno-shadow
CC_WNO += -Wno-unused-parameter
# FIXME: these should be fixed and removed
CC_WNO += -Wno-attributes
CC_WNO += -Wno-delete-non-virtual-dtor
CC_WNO += -Wno-deprecated-declarations
CC_WNO += -Wno-format-nonliteral
CC_WNO += -Wno-write-strings
ifdef __MAC__
# additional switches for clang
CC_WNO += -Wno-deprecated-register
endif
endif
# disable -pthread in CFLAGS
PTHR_SWITCH =
@@ -403,7 +471,6 @@ NO_OBSOLETE_FUNCS =
#----------------------------------------------------------------------
ifdef TESTABLE_BUILD
SWIGFLAGS+=-DTESTABLE_BUILD
FILTER_SDK_FLAGS+=-testable-build
endif
ST_SWIG_HEADER = $(ST_SWIG)/header.i
@@ -416,12 +483,17 @@ endif
find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $(1)))*.hpp) $(wildcard pywraps/py_$(subst .i,,$(notdir $(1)))*.py)
find-pydoc-patches-deps = $(wildcard tools/inject_pydoc/$(1).py)
find-patch-codegen-deps = $(wildcard tools/patch_codegen/*$(1)*.py)
ADDITIONAL_PYWRAP_DEP_idp=$(ST_PYW)/py_idp.py
$(ST_PYW)/py_idp.py: pywraps/py_idp.py.in tools/inject_plfm.py $(ST_SDK)/idp.hpp
$(QINJECT_PLFM)$(PYTHON) tools/inject_plfm.py -i $< -o $@ -d $(ST_SDK)/idp.hpp
ADDITIONAL_PYWRAP_DEP_idaapi=$(ST_PYW)/py_idaapi.hpp
$(ST_PYW)/py_idaapi.hpp: pywraps/py_idaapi.hpp.in tools/inject_base_hooks_flags.py pywraps.hpp
$(QINJECT_BASE_HOOKS_FLAGS)$(PYTHON) tools/inject_base_hooks_flags.py -i $< -o $@ -f pywraps.hpp
# Some .i files depend on some other .i files in order to be parseable by SWiG
# (e.g., segregs.i imports range.i). Declare the list of such dependencies here
# so they will be picked by the auto-generated rules.
@@ -430,7 +502,7 @@ SWIG_IFACE_dbg=idd
SWIG_IFACE_frame=range
SWIG_IFACE_funcs=range
SWIG_IFACE_gdl=range
SWIG_IFACE_hexrays=typeinf
SWIG_IFACE_hexrays=pro typeinf xref
SWIG_IFACE_idd=range
SWIG_IFACE_segment=range
SWIG_IFACE_segregs=range
@@ -439,6 +511,7 @@ SWIG_IFACE_tryblks=range
MODULE_LIFECYCLE_hexrays=--lifecycle-aware
MODULE_LIFECYCLE_bytes=--lifecycle-aware
MODULE_LIFECYCLE_idaapi=--lifecycle-aware
define make-module-rules
@@ -454,7 +527,7 @@ define make-module-rules
# files.
# ../../bin/x86_linux_gcc/python/ida_$(1).py (note: dep. on .cpp. See note above.)
$(DEPLOY_PYDIR)/ida_$(1).py: $(ST_WRAP)/$(1).cpp $(PARSED_HEADERS_MARKER) $(call find-pydoc-patches-deps,$(1)) | tools/inject_pydoc.py
$(DEPLOY_PYDIR)/ida_$(1).py: $(ST_WRAP)/$(1).cpp $(PARSED_HEADERS_MARKER) $(call find-pydoc-patches-deps,$(1)) $(call find-patch-codegen-deps,$(1)) | tools/inject_pydoc.py
$(QINJECT_PYDOC)$(PYTHON) tools/inject_pydoc.py \
-x $(ST_PARSED_HEADERS) \
-m $(1) \
@@ -477,17 +550,29 @@ define make-module-rules
--xml-doc-directory $(ST_PARSED_HEADERS)
# obj/x86_linux_gcc/wrappers/X.cpp
$(ST_WRAP)/$(1).cpp: $(ST_SWIG)/$(1).i tools/patch_codegen.py $(PATCH_DIRECTORS_SCRIPT) $(PARSED_HEADERS_MARKER) tools/chkapi.py
$(ST_WRAP)/$(1).cpp: $(ST_SWIG)/$(1).i tools/patch_codegen.py tools/patch_python_codegen.py $(PATCH_DIRECTORS_SCRIPT) $(PARSED_HEADERS_MARKER) tools/chkapi.py
$(QSWIG)$(SWIG) -modern $(addprefix -D,$(WITH_HEXRAYS_DEF)) -python -threads -c++ -shadow \
-D__GNUC__ $(SWIGFLAGS) $(addprefix -D,$(DEF64)) -I$(ST_SWIG) \
-outdir $(ST_WRAP) -o $$@ -I$(ST_SDK) $$<
$(Q)$(PYTHON) tools/patch_constants.py --file $(ST_WRAP)/$(1).cpp
-outdir $(ST_WRAP) -o $$@.in1 -oh $(ST_WRAP)/$(1).h -I$(ST_SDK) -DIDAPYTHON_MODULE_$(1)=1 $$<
$(Q)$(PYTHON) tools/patch_constants.py \
--input $(ST_WRAP)/$(1).cpp.in1 \
--output $(ST_WRAP)/$(1).cpp.in2
$(QPATCH_CODEGEN)$(PYTHON) tools/patch_codegen.py \
--apply-valist-patches \
--file $(ST_WRAP)/$(1).cpp \
--input $(ST_WRAP)/$(1).cpp.in2 \
--output $(ST_WRAP)/$(1).cpp \
--module $(1) \
--xml-doc-directory $(ST_PARSED_HEADERS) \
--patches tools/patch_codegen/$(1).py
--patches tools/patch_codegen/$(1).py \
--batch-patches tools/patch_codegen/$(1)_batch.py
$(QPATCH_H_CODEGEN)$(PYTHON) tools/patch_h_codegen.py \
--file $(ST_WRAP)/$(1).h \
--module $(1) \
--patches tools/patch_codegen/$(1)_h.py
$(QPATCH_PYTHON_CODEGEN)$(PYTHON) tools/patch_python_codegen.py \
--file $(ST_WRAP)/ida_$(1).py \
--module $(1) \
--patches tools/patch_codegen/ida_$(1).py
ifdef __NT__
$(PYTHON) $(PATCH_DIRECTORS_SCRIPT) --file $(ST_WRAP)/$(1).h
endif
@@ -505,9 +590,10 @@ vpath %.cpp $(ST_WRAP)
ifdef __NT__
# remove warnings from generated code:
# error C4296: '<': expression is always false
# warning C4647: behavior change: __is_pod(type) has different value in previous versions
# warning C4700: uninitialized local variable 'c_result' used
# warning C4706: assignment within conditional expression
$(X_O): CFLAGS += /wd4296 /wd4700 /wd4706
$(X_O): CFLAGS += /wd4296 /wd4647 /wd4700 /wd4706
endif
# disable -fno-rtti
$(X_O): NORTTI =
@@ -544,7 +630,11 @@ $(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX): $(F)_ida_%$(MODULE_SFX)
$(Q)$(CP) $< $@
#----------------------------------------------------------------------
ifdef TESTABLE_BUILD
API_CONTENTS = api_contents.txt
else
API_CONTENTS = release_api_contents.txt
endif
ST_API_CONTENTS = $(F)$(API_CONTENTS)
.PRECIOUS: $(ST_API_CONTENTS)
@@ -562,7 +652,11 @@ endif
#----------------------------------------------------------------------
# Check that doc injection is stable
ifdef TESTABLE_BUILD
PYDOC_INJECTIONS = pydoc_injections.txt
else
PYDOC_INJECTIONS = release_pydoc_injections.txt
endif
ST_PYDOC_INJECTIONS = $(F)$(PYDOC_INJECTIONS)
.PRECIOUS: $(ST_PYDOC_INJECTIONS)
@@ -572,7 +666,7 @@ ifdef __CODE_CHECKER__
$(Q)touch $@
else
ifeq ($(OUT_OF_TREE_BUILD),)
$(Q)$(IDA_CMD) $(BATCH_SWITCH) -OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO -S"$< $@ $(ST_WRAP)" -t -L$(F)dumpdoc.log >/dev/null
$(QPYDOC_INJECTIONS)$(IDA_CMD) $(BATCH_SWITCH) -OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO -S"$< $@ $(ST_WRAP)" -t -L$(F)dumpdoc.log >/dev/null
$(Q)(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \
(echo "PYDOC INJECTION CHANGED! update $(PYDOC_INJECTIONS) or fix .. what needs fixing" && \
echo "(New API: $(ST_PYDOC_INJECTIONS)) ***" && \
Binary file not shown.
+13713 -968
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -19,4 +19,7 @@ AUTOIMPORT_COMPAT_IDA695 = YES
// Is IDAPython namespace-aware?
// If yes, then plugins, loaders & processor modules will each be loaded
// within their own namespace, preventing namespace pollution.
NAMESPACE_AWARE = YES
NAMESPACE_AWARE = YES
// Should results be printed by 'sys.displayhook'?
REPL_USE_SYS_DISPLAYHOOK = YES
+197 -76
View File
@@ -23,7 +23,10 @@
#endif
#ifdef __MAC__
#include <mach-o/dyld.h>
#undef SEG_DATA // avoid conflict between mach-o/loader.h and segment.hpp
#endif
// Python defines snprintf macro so we need to allow it
#define USE_DANGEROUS_FUNCTIONS
#include <ida.hpp>
#include <idp.hpp>
#include <expr.hpp>
@@ -32,6 +35,13 @@
#include <kernwin.hpp>
#include <ida_highlighter.hpp>
#if defined (PY_MAJOR_VERSION) && (PY_MAJOR_VERSION < 3)
// in Python 2.x many APIs accept char * instead of const char *
GCC_DIAG_OFF(write-strings)
#else
#error remove me once we switch to Python 3
#endif
#include "pywraps.hpp"
#include "pywraps.cpp"
@@ -49,7 +59,8 @@
#define S_IDAPYTHON "IDAPython"
#define S_INIT_PY "init.py"
static const char S_IDC_ARGS_VARNAME[] = "ARGV";
static const char S_IDC_RUNPYTHON_STATEMENT[] = "RunPythonStatement";
static const char S_IDC_EXEC_PYTHON[] = "exec_python";
static const char S_IDC_EVAL_PYTHON[] = "eval_python";
static const char S_IDAPYTHON_DATA_NODE[] = "IDAPython_Data";
//-------------------------------------------------------------------------
@@ -82,6 +93,11 @@ static qstring requested_plugin_path;
// Plugin run() callback
bool idaapi run(size_t);
static PyObject *get_module_globals_from_path(const char *path);
static bool idaapi IDAPython_extlang_eval_expr(
idc_value_t *rv,
ea_t /*current_ea*/,
const char *expr,
qstring *errbuf);
//lint -e818 could be pointer to const
@@ -121,6 +137,7 @@ static bool g_use_local_python = false;
static bool g_autoimport_compat_idaapi = true;
static bool g_autoimport_compat_ida695 = true;
static bool g_namespace_aware = true;
static bool g_repl_use_sys_displayhook = true;
// Allowing the user to interrupt a script is not entirely trivial.
// Imagine the following script, that is run in an IDB that uses
@@ -294,7 +311,8 @@ int execution_t::on_trace(PyObject *obj, _frame *frame, int what, PyObject *arg)
if ( user_cancelled() )
{
LEXEC("on_trace()::INTERRUPTING\n");
PyErr_SetString(PyExc_KeyboardInterrupt, "User interrupted");
if ( PyErr_Occurred() == NULL )
PyErr_SetString(PyExc_KeyboardInterrupt, "User interrupted");
return -1;
}
}
@@ -318,28 +336,25 @@ int execution_t::on_trace(PyObject *obj, _frame *frame, int what, PyObject *arg)
}
//-------------------------------------------------------------------------
//lint -esym(1788, new_execution_t) is referenced only by its constructor or destructor
struct new_execution_t
void ida_export setup_new_execution(
new_execution_t *instance,
bool setup)
{
bool created;
new_execution_t()
if ( setup )
{
created = g_ui_ready && execution.timeout > 0;
if ( created )
instance->created = g_ui_ready && execution.timeout > 0;
if ( instance->created )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
execution.push();
}
}
~new_execution_t()
else
{
if ( created )
{
PYW_GIL_CHECK_LOCKED_SCOPE();
execution.pop();
}
PYW_GIL_CHECK_LOCKED_SCOPE();
execution.pop();
}
};
}
//-------------------------------------------------------------------------
void ida_export set_interruptible_state(bool interruptible)
@@ -403,6 +418,26 @@ static PyObject *get_module_globals(const char *modname=NULL)
return module == NULL ? NULL : PyModule_GetDict(module);
}
//-------------------------------------------------------------------------
static ref_t _get_sys_displayhook()
{
ref_t h;
if ( g_repl_use_sys_displayhook )
{
ref_t py_sys(PyW_TryImportModule("sys"));
if ( py_sys != NULL )
h = PyW_TryGetAttrString(py_sys.o, "displayhook");
}
return h;
}
//-------------------------------------------------------------------------
static const char *bomify(qstring *out)
{
out->insert(0, UTF8_BOM, UTF8_BOM_SZ);
return out->c_str();
}
//------------------------------------------------------------------------
static void PythonEvalOrExec(
const char *str,
@@ -411,7 +446,8 @@ static void PythonEvalOrExec(
// Compile as an expression
PYW_GIL_CHECK_LOCKED_SCOPE();
PyCompilerFlags cf = {0};
newref_t py_code(Py_CompileStringFlags(str, filename, Py_eval_input, &cf));
qstring qstr(str);
newref_t py_code(Py_CompileStringFlags(bomify(&qstr), filename, Py_eval_input, &cf));
if ( py_code == NULL || PyErr_Occurred() )
{
// Not an expression?
@@ -435,7 +471,13 @@ static void PythonEvalOrExec(
}
else
{
if ( py_result.o != Py_None )
ref_t sys_displayhook(_get_sys_displayhook());
if ( sys_displayhook != NULL )
{
//lint -esym(1788, res) is referenced only by its constructor or destructor
newref_t res(PyObject_CallFunctionObjArgs(sys_displayhook.o, py_result.o, NULL));
}
else if ( py_result.o != Py_None )
{
bool ok = false;
if ( PyUnicode_Check(py_result.o) )
@@ -460,6 +502,8 @@ static void PythonEvalOrExec(
}
}
//lint -esym(1788, new_execution_t) is referenced only by its constructor or destructor
//------------------------------------------------------------------------
// Executes a simple string
static bool idaapi IDAPython_extlang_eval_snippet(
@@ -513,7 +557,7 @@ static error_t idaapi idc_runpythonstatement(
static const char idc_runpythonstatement_args[] = { VT_STR, 0 };
static const ext_idcfunc_t idc_runpythonstatement_desc =
{
S_IDC_RUNPYTHON_STATEMENT,
S_IDC_EXEC_PYTHON,
idc_runpythonstatement,
idc_runpythonstatement_args,
NULL,
@@ -521,6 +565,31 @@ static const ext_idcfunc_t idc_runpythonstatement_desc =
0
};
//------------------------------------------------------------------------
// Simple Python expression evaluator for IDC
static error_t idaapi idc_eval_python(
idc_value_t *argv,
idc_value_t *res)
{
qstring errbuf;
const char *snippet = argv[0].c_str();
bool ok = IDAPython_extlang_eval_expr(res, BADADDR, snippet, &errbuf);
if ( !ok )
return throw_idc_exception(res, errbuf.c_str());
return eOk;
}
static const char idc_eval_python_args[] = { VT_STR, 0 };
static const ext_idcfunc_t idc_eval_python_desc =
{
S_IDC_EVAL_PYTHON,
idc_eval_python,
idc_eval_python_args,
NULL,
0,
0
};
//--------------------------------------------------------------------------
static const cfgopt_t opts[] =
{
@@ -530,6 +599,7 @@ static const cfgopt_t opts[] =
cfgopt_t("AUTOIMPORT_COMPAT_IDAAPI", &g_autoimport_compat_idaapi, true),
cfgopt_t("AUTOIMPORT_COMPAT_IDA695", &g_autoimport_compat_ida695, true),
cfgopt_t("NAMESPACE_AWARE", &g_namespace_aware, true),
cfgopt_t("REPL_USE_SYS_DISPLAYHOOK", &g_repl_use_sys_displayhook, true),
};
//-------------------------------------------------------------------------
@@ -829,7 +899,8 @@ static bool idaapi IDAPython_extlang_call_func(
module = PyImport_ImportModule(final_modname);
if ( module == NULL )
{
errbuf->sprnt("couldn't import module %s", final_modname);
if ( errbuf != NULL )
errbuf->sprnt("couldn't import module %s", final_modname);
ok = false;
break;
}
@@ -840,7 +911,8 @@ static bool idaapi IDAPython_extlang_call_func(
PyObject *func = PyDict_GetItemString(globals, funcname);
if ( func == NULL )
{
errbuf->sprnt("undefined function %s", name);
if ( errbuf != NULL )
errbuf->sprnt("undefined function %s", name);
ok = false;
break;
}
@@ -865,13 +937,37 @@ static bool idaapi IDAPython_extlang_call_func(
//-------------------------------------------------------------------------
static void wrap_in_function(qstring *out, const qstring &body, const char *name)
{
out->sprnt("def %s():\n", name);
// dont copy trailing whitespace
int i = body.length()-1;
while ( i >= 0 && qisspace(body.at(i)) )
i--;
out->append(body.substr(0, i+1));
out->replace("\n", "\n ");
qstrvec_t lines;
lines.push_back().sprnt("def %s():\n", name);
qstring buf(body);
while ( !buf.empty() && qisspace(buf.last()) ) // dont copy trailing whitespace(s)
buf.remove_last();
char *ctx;
for ( char *p = qstrtok(buf.begin(), "\n", &ctx);
p != NULL;
p = qstrtok(NULL, "\n", &ctx) )
{
static const char FROM_FUTURE_IMPORT_STMT[] = "from __future__ import";
if ( strneq(p, FROM_FUTURE_IMPORT_STMT, sizeof(FROM_FUTURE_IMPORT_STMT)-1) )
{
lines.insert(lines.begin(), p);
}
else
{
qstring &s = lines.push_back();
s.append(" ", 4);
s.append(p);
}
}
out->qclear();
for ( size_t i = 0; i < lines.size(); ++i )
{
if ( i > 0 )
out->append('\n');
out->append(lines[i]);
}
}
//-------------------------------------------------------------------------
@@ -886,7 +982,11 @@ static bool idaapi IDAPython_extlang_compile_expr(
PyObject *globals = get_module_globals();
bool isfunc = false;
PyCodeObject *code = (PyCodeObject *)Py_CompileString(expr, "<string>", Py_eval_input);
qstring qstr(expr);
PyCodeObject *code = (PyCodeObject *)Py_CompileString(
bomify(&qstr),
"<string>",
Py_eval_input);
if ( code == NULL )
{
// try compiling as a list of statements
@@ -894,6 +994,7 @@ static bool idaapi IDAPython_extlang_compile_expr(
handle_python_error(errbuf);
qstring func;
wrap_in_function(&func, expr, name);
bomify(&func);
code = (PyCodeObject *)Py_CompileString(func.c_str(), "<string>", Py_file_input);
if ( code == NULL )
{
@@ -948,6 +1049,10 @@ static bool idaapi IDAPython_extlang_compile_file(
// Load processor module callback for Python external language evaluator
static bool idaapi IDAPython_extlang_load_procmod(
idc_value_t *procobj,
// hook_cb_t **idp_notifier,
// void **idp_notifier_ud,
// hook_cb_t **idb_notifier,
// void **idb_notifier_ud,
const char *path,
qstring *errbuf)
{
@@ -956,7 +1061,7 @@ static bool idaapi IDAPython_extlang_load_procmod(
{
new_execution_t exec;
PyObject *globals = get_module_globals_from_path(path);
ok = IDAPython_ExecFile(path, globals, errbuf, S_IDAAPI_LOADPROCMOD, procobj, true);
ok = IDAPython_ExecFile(path, globals, errbuf, S_IDAAPI_LOADPROCMOD, procobj, /*want_tuple=*/ true);
}
if ( ok && procobj->is_zero() )
{
@@ -1590,12 +1695,32 @@ void convert_idc_args()
PyObject_SetAttrString(py_mod.o, S_IDC_ARGS_VARNAME, py_args.o);
}
#define DISPATCH_TO_MODULES(Method) \
do \
{ \
for ( size_t i = modules_callbacks.size(); i > 0; --i ) \
modules_callbacks[i-1].Method(); \
} while ( false )
//-------------------------------------------------------------------------
enum module_lifecycle_notification_t
{
mln_init = 0,
mln_term,
mln_closebase
};
static void send_modules_lifecycle_notification(module_lifecycle_notification_t what)
{
PYW_GIL_GET;
for ( size_t i = modules_callbacks.size(); i > 0; --i )
{
const module_callbacks_t &m = modules_callbacks[i-1];
switch ( what )
{
case mln_init: m.init(); break;
case mln_term: m.term(); break;
case mln_closebase: m.closebase(); break;
}
if ( PyErr_Occurred() )
{
msg("Error during module lifecycle notification:\n");
PyErr_Print();
}
}
}
//------------------------------------------------------------------------
//lint -esym(715,va) Symbol not referenced
@@ -1651,7 +1776,7 @@ static ssize_t idaapi on_idb_notification(void *, int code, va_list)
// through all the tinfo_t objects that are embedded in SWIG wrappers,
// (i.e., that were created from Python) and clear those.
til_clear_python_tinfo_t_instances();
DISPATCH_TO_MODULES(closebase);
send_modules_lifecycle_notification(mln_closebase);
break;
}
return 0;
@@ -1734,26 +1859,6 @@ static bool initsite(void)
return true;
}
//-------------------------------------------------------------------------
static void init_ida_modules()
{
// char buf[QMAXPATH];
// // IDA_MODULES must be passed as a define
// qstrncpy(buf, IDA_MODULES, sizeof(buf));
// char *ctx;
// for ( char *module = qstrtok(buf, ",", &ctx);
// module != NULL;
// module = qstrtok(NULL, DELIMITER, &ctx) )
// {
// deb(IDA_DEBUG_PLUGIN, "Initializing \"ida_%s\"\n", module);
// }
// Load the 'ida_idaapi' module, that contains some important bits of code
// ref_t ida_idaapi(PyW_TryImportModule(S_PY_IDA_IDAAPI_MODNAME));
// ref_t sys(PyW_TryImportModule("sys"));
}
//-------------------------------------------------------------------------
// Initialize the Python environment
bool IDAPython_Init(void)
@@ -1862,8 +1967,6 @@ bool IDAPython_Init(void)
if ( !PyEval_ThreadsInitialized() )
PyEval_InitThreads();
init_ida_modules();
#ifdef Py_DEBUG
msg("HexraysPython: Python compiled with DEBUG enabled.\n");
#endif
@@ -1877,11 +1980,7 @@ bool IDAPython_Init(void)
"IDAPYTHON_DYNLOAD_RELPATH = \"ida_%" FMT_Z "\"\n"
"IDAPYTHON_COMPAT_AUTOIMPORT_MODULES = %s\n"
"IDAPYTHON_COMPAT_695_API = %s\n",
VER_MAJOR,
VER_MINOR,
VER_PATCH,
VER_STATUS,
VER_SERIAL,
VER_MAJOR, VER_MINOR, VER_PATCH, VER_STATUS, VER_SERIAL,
g_remove_cwd_sys_path ? "True" : "False",
idadir(NULL),
sizeof(ea_t)*8,
@@ -1927,7 +2026,7 @@ bool IDAPython_Init(void)
}
// Init pywraps and notify_when
if ( !init_pywraps() || !pywraps_nw_init() )
if ( !init_pywraps() )
{
warning("IDAPython: init_pywraps() failed!");
remove_extlang(&extlang_python);
@@ -1938,9 +2037,9 @@ bool IDAPython_Init(void)
PyEval_SetTrace(tracefunc, NULL);
#endif
// Register a RunPythonStatement() function for IDC
// Register a exec_python() function for IDC
add_idc_func(idc_runpythonstatement_desc);
add_idc_func(idc_eval_python_desc);
// A script specified on the command line is run
if ( g_run_when == RUN_ON_INIT )
@@ -1955,7 +2054,8 @@ bool IDAPython_Init(void)
// Enable the CLI by default
enable_python_cli(true);
pywraps_nw_notify(NW_INITIDA_SLOT);
// Let all modules perform possible initialization
send_modules_lifecycle_notification(mln_init);
PyEval_ReleaseThread(PyThreadState_Get());
@@ -1963,6 +2063,27 @@ bool IDAPython_Init(void)
return true;
}
//-------------------------------------------------------------------------
#ifdef TESTABLE_BUILD
// "user-code-leniency" means that, even in TESTABLE_BUILD builds,
// IDAPython will accept that some things are left in an undesirable,
// but recuperable state (e.g., remaining hooks.)
// This should *ONLY* be used for tests that rely on user code that
// is in such a shape that it would require significant changes to
// have it perform proper cleanup, which means that it would have to
// diverge from the original user's code, which means that we
// would have to maintain our own branch of it, which is not
// the best idea of the world, overhead-wise.
static int _is_user_code_lenient = -1;
static bool is_user_code_lenient()
{
if ( _is_user_code_lenient < 0 )
_is_user_code_lenient = qgetenv("IDAPYTHON_USER_CODE_LENIENT");
return _is_user_code_lenient > 0;
}
#endif
//-------------------------------------------------------------------------
// Cleaning up Python
void IDAPython_Term(void)
@@ -1981,7 +2102,7 @@ void IDAPython_Term(void)
}
// Let all modules perform possible de-initialization
DISPATCH_TO_MODULES(term);
send_modules_lifecycle_notification(mln_term);
unhook_from_notification_point(HT_IDB, on_idb_notification);
unhook_from_notification_point(HT_UI, on_ui_notification);
@@ -1989,12 +2110,6 @@ void IDAPython_Term(void)
unhook_from_notification_point(HT_UI, ui_debug_handler_cb);
#endif
// Notify about IDA closing
pywraps_nw_notify(NW_TERMIDA_SLOT);
// De-init notify_when
pywraps_nw_term();
// Remove the CLI
enable_python_cli(false);
@@ -2005,6 +2120,7 @@ void IDAPython_Term(void)
deinit_pywraps();
// Uninstall IDC function
del_idc_func(idc_eval_python_desc.name);
del_idc_func(idc_runpythonstatement_desc.name);
// Shut the interpreter down
@@ -2012,9 +2128,14 @@ void IDAPython_Term(void)
g_instance_initialized = false;
#ifdef TESTABLE_BUILD
// Check that all hooks were unhooked
QASSERT(30509, hook_data_vec.empty());
if ( !is_user_code_lenient() ) // Check that all hooks were unhooked
QASSERT(30509, hook_data_vec.empty());
#endif
for ( size_t i = hook_data_vec.size(); i > 0; --i )
{
const hook_data_t &hd = hook_data_vec[i-1];
idapython_unhook_from_notification_point(hd.type, hd.cb, hd.ud);
}
}
//-------------------------------------------------------------------------
+10 -10
View File
@@ -193,27 +193,27 @@ def XrefsTo(ea, flags=0):
def Threads():
"""Returns all thread IDs"""
"""Returns all thread IDs for the current debugee"""
for i in xrange(0, idc.get_thread_qty()):
yield idc.getn_thread(i)
def Heads(start=None, end=None):
"""
Get a list of heads (instructions or data)
Get a list of heads (instructions or data items)
@param start: start address (default: inf.min_ea)
@param end: end address (default: inf.max_ea)
@return: list of heads between start and end
"""
if not start: start = ida_ida.cvar.inf.min_ea
if not end: end = ida_ida.cvar.inf.max_ea
if start is None: start = ida_ida.cvar.inf.min_ea
if end is None: end = ida_ida.cvar.inf.max_ea
ea = start
if not idc.is_head(ida_bytes.get_flags(ea)):
ea = ida_bytes.next_head(ea, end)
while ea != ida_idaapi.BADADDR:
while ea < end and ea != ida_idaapi.BADADDR:
yield ea
ea = ida_bytes.next_head(ea, end)
@@ -225,15 +225,15 @@ def Functions(start=None, end=None):
@param start: start address (default: inf.min_ea)
@param end: end address (default: inf.max_ea)
@return: list of heads between start and end
@return: list of function entrypoints between start and end
@note: The last function that starts before 'end' is included even
if it extends beyond 'end'. Any function that has its chunks scattered
in multiple segments will be reported multiple times, once in each segment
as they are listed.
"""
if not start: start = ida_ida.cvar.inf.min_ea
if not end: end = ida_ida.cvar.inf.max_ea
if start is None: start = ida_ida.cvar.inf.min_ea
if end is None: end = ida_ida.cvar.inf.max_ea
# find first function head chunk in the range
chunk = ida_funcs.get_fchunk(start)
@@ -303,7 +303,7 @@ def Segments():
def Entries():
"""
Returns a list of entry points
Returns a list of entry points (exports)
@return: List of tuples (index, ordinal, ea, name)
"""
@@ -317,7 +317,7 @@ def Entries():
def FuncItems(start):
"""
Get a list of function items
Get a list of function items (instruction or data items inside function boundaries)
@param start: address of the function
+186 -287
View File
@@ -1473,7 +1473,7 @@ def func_contains(func_ea, ea):
GN_VISIBLE = ida_name.GN_VISIBLE # replace forbidden characters by SUBSTCHAR
GN_COLORED = ida_name.GN_COLORED # return colored name
GN_DEMANGLED = ida_name.GN_DEMANGLED # return demangled name
GN_STRICT = ida_name.GN_STRICT # fail if can not demangle
GN_STRICT = ida_name.GN_STRICT # fail if cannot demangle
GN_SHORT = ida_name.GN_SHORT # use short form of demangled name
GN_LONG = ida_name.GN_LONG # use long form of demangled name
GN_LOCAL = ida_name.GN_LOCAL # try to get local name first; if failed, get global
@@ -1690,13 +1690,46 @@ GetCommentEx = ida_bytes.get_cmt
get_cmt = GetCommentEx
get_forced_operand = ida_bytes.get_forced_operand
STRTYPE_C = ida_nalt.STRTYPE_TERMCHR # C-style ASCII string
STRTYPE_PASCAL = ida_nalt.STRTYPE_PASCAL # Pascal-style ASCII string (length byte)
STRTYPE_LEN2 = ida_nalt.STRTYPE_LEN2 # Pascal-style, length is 2 bytes
STRTYPE_C_16 = ida_nalt.STRTYPE_C_16 # Unicode string
STRTYPE_LEN4 = ida_nalt.STRTYPE_LEN4 # Pascal-style, length is 4 bytes
STRTYPE_LEN2_16 = ida_nalt.STRTYPE_LEN2_16 # Pascal-style Unicode, length is 2 bytes
STRTYPE_LEN4_16 = ida_nalt.STRTYPE_LEN4_16 # Pascal-style Unicode, length is 4 bytes
BPU_1B = ida_nalt.BPU_1B
BPU_2B = ida_nalt.BPU_2B
BPU_4B = ida_nalt.BPU_4B
STRWIDTH_1B = ida_nalt.STRWIDTH_1B
STRWIDTH_2B = ida_nalt.STRWIDTH_2B
STRWIDTH_4B = ida_nalt.STRWIDTH_4B
STRWIDTH_MASK = ida_nalt.STRWIDTH_MASK
STRLYT_TERMCHR = ida_nalt.STRLYT_TERMCHR
STRLYT_PASCAL1 = ida_nalt.STRLYT_PASCAL1
STRLYT_PASCAL2 = ida_nalt.STRLYT_PASCAL2
STRLYT_PASCAL4 = ida_nalt.STRLYT_PASCAL4
STRLYT_MASK = ida_nalt.STRLYT_MASK
STRLYT_SHIFT = ida_nalt.STRLYT_SHIFT
# Character-terminated string. The termination characters
# are kept in the next bytes of string type.
STRTYPE_TERMCHR = ida_nalt.STRTYPE_TERMCHR
# C-style string.
STRTYPE_C = ida_nalt.STRTYPE_C
# Zero-terminated 16bit chars
STRTYPE_C_16 = ida_nalt.STRTYPE_C_16
# Zero-terminated 32bit chars
STRTYPE_C_32 = ida_nalt.STRTYPE_C_32
# Pascal-style, one-byte length prefix
STRTYPE_PASCAL = ida_nalt.STRTYPE_PASCAL
# Pascal-style, 16bit chars, one-byte length prefix
STRTYPE_PASCAL_16 = ida_nalt.STRTYPE_PASCAL_16
# Pascal-style, two-byte length prefix
STRTYPE_LEN2 = ida_nalt.STRTYPE_LEN2
# Pascal-style, 16bit chars, two-byte length prefix
STRTYPE_LEN2_16 = ida_nalt.STRTYPE_LEN2_16
# Pascal-style, four-byte length prefix
STRTYPE_LEN4 = ida_nalt.STRTYPE_LEN4
# Pascal-style, 16bit chars, four-byte length prefix
STRTYPE_LEN4_16 = ida_nalt.STRTYPE_LEN4_16
# alias
STRTYPE_C16 = STRTYPE_C_16
def get_strlit_contents(ea, length = -1, strtype = STRTYPE_C):
"""
@@ -1780,26 +1813,11 @@ def process_config_line(directive):
# The following functions allow you to set/get common parameters.
# Please note that not all parameters can be set directly.
def get_inf_attr(offset):
"""
"""
val = _IDC_GetAttr(ida_ida.cvar.inf, _INFMAP, offset)
if offset == INF_PROCNAME:
# procName is a character array
val = ida_idaapi.as_cstr(val)
return val
def set_inf_attr(offset, value):
if offset == INF_PROCNAME:
raise NotImplementedError("Please use ida_idp.set_processor_type() to change processor")
# We really want to go through IDC's equivalent, because it might
# have side-effects (i.e., send a notification, etc...)
return eval_idc("set_inf_attr(%d, %d)" % (offset, value))
INF_VERSION = 4 # short; Version of database
INF_PROCNAME = 6 # char[8]; Name of current processor
INF_GENFLAGS = 22 # ushort; General flags:
INF_VERSION = 0 # short; Version of database
INF_PROCNAME = 1 # char[8]; Name of current processor
INF_GENFLAGS = 2 # ushort; General flags:
INFFL_AUTO = 0x01 # Autoanalysis is enabled?
INFFL_ALLASM = 0x02 # May use constructs not supported by
# the target assembler
@@ -1809,7 +1827,7 @@ INFFL_READONLY = 0x10 # (internal) temporary interdiction t
INFFL_CHKOPS = 0x20 # check manual operands?
INFFL_NMOPS = 0x40 # allow non-matched operands?
INFFL_GRAPH_VIEW= 0x80 # currently using graph options (\dto{graph})
INF_LFLAGS = 24 # uint32; IDP-dependent flags
INF_LFLAGS = 3 # uint32; IDP-dependent flags
LFLG_PC_FPP = 0x00000001 # decode floating point processor
# instructions?
LFLG_PC_FLAT = 0x00000002 # Flat model?
@@ -1824,9 +1842,10 @@ LFLG_PACK = 0x00000200 # pack the database?
LFLG_COMPRESS = 0x00000400 # compress the database?
LFLG_KERNMODE = 0x00000800 # is kernel mode binary?
INF_CHANGE_COUNTER= 28 # uint32; database change counter; keeps track of byte and segment modifications
INF_DATABASE_CHANGE_COUNT= 4 # uint32; database change counter; keeps track of byte and segment modifications
INF_CHANGE_COUNTER=INF_DATABASE_CHANGE_COUNT
INF_FILETYPE = 32 # short; type of input file (see ida.hpp)
INF_FILETYPE = 5 # short; type of input file (see ida.hpp)
FT_EXE_OLD = 0 # MS DOS EXE File (obsolete)
FT_COM_OLD = 1 # MS DOS COM File (obsolete)
FT_BIN = 2 # Binary File
@@ -1853,12 +1872,12 @@ FT_EXE = 22 # MS DOS EXE File
FT_COM = 23 # MS DOS COM File
FT_AIXAR = 24 # AIX ar library
FT_MACHO = 25 # Mac OS X Mach-O file
INF_OSTYPE = 34 # short; FLIRT: OS type the program is for
INF_OSTYPE = 6 # short; FLIRT: OS type the program is for
OSTYPE_MSDOS= 0x0001
OSTYPE_WIN = 0x0002
OSTYPE_OS2 = 0x0004
OSTYPE_NETW = 0x0008
INF_APPTYPE = 36 # short; FLIRT: Application type
INF_APPTYPE = 7 # short; FLIRT: Application type
APPT_CONSOLE= 0x0001 # console
APPT_GRAPHIC= 0x0002 # graphics
APPT_PROGRAM= 0x0004 # EXE
@@ -1868,10 +1887,10 @@ APPT_1THREAD= 0x0020 # Singlethread
APPT_MTHREAD= 0x0040 # Multithread
APPT_16BIT = 0x0080 # 16 bit application
APPT_32BIT = 0x0100 # 32 bit application
INF_ASMTYPE = 38 # char; target assembler number (0..n)
INF_SPECSEGS = 39
INF_ASMTYPE = 8 # char; target assembler number (0..n)
INF_SPECSEGS = 9
INF_AF = 40 # uint32; Analysis flags:
INF_AF = 10 # uint32; Analysis flags:
AF_CODE = 0x00000001 # Trace execution flow
AF_MARKCODE = 0x00000002 # Mark typical code sequences as code
AF_JUMPTBL = 0x00000004 # Locate and create jump tables
@@ -1910,54 +1929,62 @@ AF_DODATA = 0x20000000 # Coagulate data segs at the final pa
AF_DOCODE = 0x40000000 # Coagulate code segs at the final pass
AF_FINAL = 0x80000000 # Final pass of analysis
INF_AF2 = 44 # uint32; Analysis flags 2
INF_AF2 = 11 # uint32; Analysis flags 2
AF2_DOEH = 0x00000001 # Handle EH information
AF2_DORTTI = 0x00000002 # Handle RTTI information
AF2_MACRO = 0x00000004 # Try to combine several instructions into a macro instruction
INF_BASEADDR = 48 # uval_t; base paragraph of the program
INF_START_SS = 52 # int32; value of SS at the start
INF_START_CS = 56 # int32; value of CS at the start
INF_START_IP = 60 # ea_t; IP register value at the start of
INF_BASEADDR = 12 # uval_t; base paragraph of the program
INF_START_SS = 13 # int32; value of SS at the start
INF_START_CS = 14 # int32; value of CS at the start
INF_START_IP = 15 # ea_t; IP register value at the start of
# program execution
INF_START_EA = 64 # ea_t; Linear address of program entry point
INF_START_SP = 68 # ea_t; SP register value at the start of
INF_START_EA = 16 # ea_t; Linear address of program entry point
INF_START_SP = 17 # ea_t; SP register value at the start of
# program execution
INF_MAIN = 72 # ea_t; address of main()
INF_MIN_EA = 76 # ea_t; The lowest address used
INF_MAIN = 18 # ea_t; address of main()
INF_MIN_EA = 19 # ea_t; The lowest address used
# in the program
INF_MAX_EA = 80 # ea_t; The highest address used
INF_MAX_EA = 20 # ea_t; The highest address used
# in the program - 1
INF_OMIN_EA = 84
INF_OMAX_EA = 88
INF_LOW_OFF = 92 # ea_t; low limit of voids
INF_HIGH_OFF = 96 # ea_t; high limit of voids
INF_MAXREF = 100 # uval_t; max xref depth
INF_START_PRIVRANGE = 104 # uval_t; Range of addresses reserved for internal use.
INF_END_PRIVRANGE = 108 # uval_t; Initially (MAXADDR, MAXADDR+0x100000)
INF_OMIN_EA = 21
INF_OMAX_EA = 22
INF_LOWOFF = 23 # ea_t; low limit of voids
INF_LOW_OFF=INF_LOWOFF
INF_HIGHOFF = 24 # ea_t; high limit of voids
INF_HIGH_OFF=INF_HIGHOFF
INF_MAXREF = 25 # uval_t; max xref depth
INF_PRIVRANGE_START_EA = 27 # uval_t; Range of addresses reserved for internal use.
INF_START_PRIVRANGE=INF_PRIVRANGE_START_EA
INF_PRIVRANGE_END_EA = 28 # uval_t; Initially (MAXADDR, MAXADDR+0x100000)
INF_END_PRIVRANGE=INF_PRIVRANGE_END_EA
INF_NETDELTA = 112 # sval_t; Delta value to be added to all adresses for mapping to netnodes.
INF_NETDELTA = 29 # sval_t; Delta value to be added to all adresses for mapping to netnodes.
# Initially 0.
# CROSS REFERENCES
INF_XREFNUM = 116 # char; Number of references to generate
INF_XREFNUM = 30 # char; Number of references to generate
# 0 - xrefs won't be generated at all
INF_TYPE_XREFS = 117 # char; Number of references to generate
INF_TYPE_XREFNUM = 31 # char; Number of references to generate
# in the struct & enum windows
# 0 - xrefs won't be generated at all
INF_REFCMTS = 118 # uchar; number of comment lines to
INF_TYPE_XREFS=INF_TYPE_XREFNUM
INF_REFCMTNUM = 32 # uchar; number of comment lines to
# generate for refs to ASCII
# string or demangled name
# 0 - such comments won't be
# generated at all
INF_XREFS = 119 # char; xrefs representation:
INF_REFCMTS=INF_REFCMTNUM
INF_XREFFLAG = 33 # char; xrefs representation:
INF_XREFS=INF_XREFFLAG
SW_SEGXRF = 0x01 # show segments in xrefs?
SW_XRFMRK = 0x02 # show xref type marks?
SW_XRFFNC = 0x04 # show function offsets?
SW_XRFVAL = 0x08 # show xref values? (otherwise-"...")
# NAMES
INF_MAX_AUTONAME_LEN = 120 # ushort; max name length (without zero byte)
INF_NAMETYPE = 122 # char; dummy names represenation type
INF_MAX_AUTONAME_LEN = 34 # ushort; max name length (without zero byte)
INF_NAMETYPE = 35 # char; dummy names represenation type
NM_REL_OFF = 0
NM_PTR_OFF = 1
NM_NAM_OFF = 2
@@ -1969,27 +1996,29 @@ NM_EA4 = 7
NM_EA8 = 8
NM_SHORT = 9
NM_SERIAL = 10
INF_SHORT_DN = 124 # int32; short form of demangled names
INF_LONG_DN = 128 # int32; long form of demangled names
INF_SHORT_DEMNAMES = 36 # int32; short form of demangled names
INF_SHORT_DN=INF_SHORT_DEMNAMES
INF_LONG_DEMNAMES = 37 # int32; long form of demangled names
# see demangle.h for definitions
INF_DEMNAMES = 132 # char; display demangled names as:
INF_LONG_DN=INF_LONG_DEMNAMES
INF_DEMNAMES = 38 # char; display demangled names as:
DEMNAM_CMNT = 0 # comments
DEMNAM_NAME = 1 # regular names
DEMNAM_NONE = 2 # don't display
DEMNAM_GCC3 = 4 # assume gcc3 names (valid for gnu compiler)
DEMNAM_FIRST= 8 # override type info
INF_LISTNAMES = 133 # uchar; What names should be included in the list?
INF_LISTNAMES = 39 # uchar; What names should be included in the list?
LN_NORMAL = 0x01 # normal names
LN_PUBLIC = 0x02 # public names
LN_AUTO = 0x04 # autogenerated names
LN_WEAK = 0x08 # weak names
# DISASSEMBLY LISTING DETAILS
INF_INDENT = 134 # char; Indention for instructions
INF_COMMENT = 135 # char; Indention for comments
INF_MARGIN = 136 # ushort; max length of data lines
INF_LENXREF = 138 # ushort; max length of line with xrefs
INF_OUTFLAGS = 140 # uint32; output flags
INF_INDENT = 40 # char; Indention for instructions
INF_COMMENT = 41 # char; Indention for comments
INF_MARGIN = 42 # ushort; max length of data lines
INF_LENXREF = 43 # ushort; max length of line with xrefs
INF_OUTFLAGS = 44 # uint32; output flags
OFLG_SHOW_VOID = 0x0002 # Display void marks?
OFLG_SHOW_AUTO = 0x0004 # Display autoanalysis indicator?
OFLG_GEN_NULL = 0x0010 # Generate empty lines?
@@ -1999,66 +2028,43 @@ OFLG_LZERO = 0x0080 # generate leading zeroes in numbers
OFLG_GEN_ORG = 0x0100 # Generate 'org' directives?
OFLG_GEN_ASSUME= 0x0200 # Generate 'assume' directives?
OFLG_GEN_TRYBLKS = 0x0400 # Generate try/catch directives?
INF_CMTFLAG = 144 # char; comments:
INF_CMTFLG = 45 # char; comments:
INF_CMTFLAG=INF_CMTFLG
SW_RPTCMT = 0x01 # show repeatable comments?
SW_ALLCMT = 0x02 # comment all lines?
SW_NOCMT = 0x04 # no comments at all
SW_LINNUM = 0x08 # show source line numbers
INF_BORDER = 145 # char; Generate borders?
INF_BINPREF = 146 # short; # of instruction bytes to show
INF_LIMITER = 46 # char; Generate borders?
INF_BORDER=INF_LIMITER
INF_BIN_PREFIX_SIZE = 47 # short; # of instruction bytes to show
# in line prefix
INF_PREFFLAG = 148 # char; line prefix type:
INF_BINPREF=INF_BIN_PREFIX_SIZE
INF_PREFFLAG = 48 # char; line prefix type:
PREF_SEGADR = 0x01 # show segment addresses?
PREF_FNCOFF = 0x02 # show function offsets?
PREF_STACK = 0x04 # show stack pointer?
# STRING LITERALS
INF_STRLIT_FLAGS= 149 # uchar; string literal flags
INF_STRLIT_FLAGS= 49 # uchar; string literal flags
STRF_GEN = 0x01 # generate names?
STRF_AUTO = 0x02 # names have 'autogenerated' bit?
STRF_SERIAL = 0x04 # generate serial names?
STRF_COMMENT = 0x10 # generate auto comment for string references?
STRF_SAVECASE = 0x20 # preserve case of strings for identifiers
INF_STRLIT_BREAK= 150 # char; string literal line break symbol
INF_STRLIT_ZEROES= 151 # char; leading zeroes
INF_STRTYPE = 152 # int32; current ascii string type
INF_STRLIT_BREAK= 50 # char; string literal line break symbol
INF_STRLIT_ZEROES= 51 # char; leading zeroes
INF_STRTYPE = 52 # int32; current ascii string type
# is considered as several bytes:
# low byte:
BPU_1B = 1
BPU_2B = 2
BPU_4B = 4
STRWIDTH_1B = 0
STRWIDTH_2B = 1
STRWIDTH_4B = 2
STRWIDTH_MASK = 0x03
STRLYT_TERMCHR = 0
STRLYT_PASCAL1 = 1
STRLYT_PASCAL2 = 2
STRLYT_PASCAL4 = 3
STRLYT_MASK = 0xFC
STRLYT_SHIFT = 2
STRTYPE_TERMCHR = STRWIDTH_1B|STRLYT_TERMCHR<<STRLYT_SHIFT
STRTYPE_C = STRTYPE_TERMCHR
STRTYPE_C16 = STRWIDTH_2B|STRLYT_TERMCHR<<STRLYT_SHIFT
STRTYPE_C_32 = STRWIDTH_4B|STRLYT_TERMCHR<<STRLYT_SHIFT
STRTYPE_PASCAL = STRWIDTH_1B|STRLYT_PASCAL1<<STRLYT_SHIFT
STRTYPE_PASCAL_16 = STRWIDTH_2B|STRLYT_PASCAL1<<STRLYT_SHIFT
STRTYPE_LEN2 = STRWIDTH_1B|STRLYT_PASCAL2<<STRLYT_SHIFT
STRTYPE_LEN2_16 = STRWIDTH_2B|STRLYT_PASCAL2<<STRLYT_SHIFT
STRTYPE_LEN4 = STRWIDTH_1B|STRLYT_PASCAL4<<STRLYT_SHIFT
STRTYPE_LEN4_16 = STRWIDTH_2B|STRLYT_PASCAL4<<STRLYT_SHIFT
INF_STRLIT_PREF = 156 # char[16];ASCII names prefix
INF_STRLIT_SERNUM= 172 # uint32; serial number
INF_STRLIT_PREF = 53 # char[16];ASCII names prefix
INF_STRLIT_SERNUM= 54 # uint32; serial number
# DATA ITEMS
INF_DATATYPES = 176 # int32; data types allowed in data carousel
INF_DATATYPES = 55 # int32; data types allowed in data carousel
# COMPILER
INF_COMPILER = 180 # uchar; compiler
INF_CC_ID = 57 # uchar; compiler
COMP_MASK = 0x0F # mask to apply to get the pure compiler id
COMP_UNK = 0x00 # Unknown
COMP_MS = 0x01 # Visual C++
@@ -2067,16 +2073,26 @@ COMP_WATCOM = 0x03 # Watcom C++
COMP_GNU = 0x06 # GNU C++
COMP_VISAGE = 0x07 # Visual Age C++
COMP_BP = 0x08 # Delphi
INF_MODEL = 181 # uchar; memory model & calling convention
INF_SIZEOF_INT = 182 # uchar; sizeof(int)
INF_SIZEOF_BOOL = 183 # uchar; sizeof(bool)
INF_SIZEOF_ENUM = 184 # uchar; sizeof(enum)
INF_SIZEOF_ALGN = 185 # uchar; default alignment
INF_SIZEOF_SHORT= 186
INF_SIZEOF_LONG = 187
INF_SIZEOF_LLONG= 188
INF_SIZEOF_LDBL = 189 # uchar; sizeof(long double)
INF_ABIBITS= 192 # uint32; ABI features
INF_CC_CM = 58 # uchar; memory model & calling convention
INF_CC_SIZE_I = 59 # uchar; sizeof(int)
INF_CC_SIZE_B = 60 # uchar; sizeof(bool)
INF_CC_SIZE_E = 61 # uchar; sizeof(enum)
INF_CC_DEFALIGN = 62 # uchar; default alignment
INF_CC_SIZE_S = 63
INF_CC_SIZE_L = 64
INF_CC_SIZE_LL = 65
INF_CC_SIZE_LDBL = 66 # uchar; sizeof(long double)
INF_COMPILER = INF_CC_ID
INF_MODEL = INF_CC_CM
INF_SIZEOF_INT = INF_CC_SIZE_I
INF_SIZEOF_BOOL = INF_CC_SIZE_B
INF_SIZEOF_ENUM = INF_CC_SIZE_E
INF_SIZEOF_ALGN = INF_CC_DEFALIGN
INF_SIZEOF_SHORT= INF_CC_SIZE_S
INF_SIZEOF_LONG = INF_CC_SIZE_L
INF_SIZEOF_LLONG= INF_CC_SIZE_LL
INF_SIZEOF_LDBL = INF_CC_SIZE_LDBL
INF_ABIBITS= 67 # uint32; ABI features
ABI_8ALIGN4 = 0x00000001 # 4 byte alignment for 8byte scalars (__int64/double) inside structures?
ABI_PACK_STKARGS = 0x00000002 # do not align stack arguments to stack slots
ABI_BIGARG_ALIGN = 0x00000004 # use natural type alignment for argument if the alignment exceeds native word size (e.g. __int64 argument should be 8byte aligned on some 32bit platforms)
@@ -2084,149 +2100,37 @@ ABI_STACK_LDBL = 0x00000008 # long double areuments are passed on stack
ABI_STACK_VARARGS= 0x00000010 # varargs are always passed on stack (even when there are free registers)
ABI_HARD_FLOAT = 0x00000020 # use the floating-point register set
ABI_SET_BY_USER = 0x00000040 # compiler/abi were set by user flag
INF_APPCALL_OPTIONS= 196 # uint32; appcall options
ABI_GCC_LAYOUT = 0x00000080 # use gcc layout for udts (used for mingw)
ABI_MAP_STKARGS = 0x00000100 # register arguments are mapped to stack area (and consume stack slots)
INF_APPCALL_OPTIONS= 68 # uint32; appcall options
# Redefine these offsets for 64-bit version
if __EA64__:
INF_VERSION = 4
INF_PROCNAME = 6
INF_GENFLAGS = 22
INF_LFLAGS = 24
INF_CHANGE_COUNTER = 28
INF_FILETYPE = 32
INF_OSTYPE = 34
INF_APPTYPE = 36
INF_ASMTYPE = 38
INF_SPECSEGS = 39
INF_AF = 40
INF_AF2 = 44
INF_BASEADDR = 48
INF_START_SS = 56
INF_START_CS = 64
INF_START_IP = 72
INF_START_EA = 80
INF_START_SP = 88
INF_MAIN = 96
INF_MIN_EA = 104
INF_MAX_EA = 112
INF_OMIN_EA = 120
INF_OMAX_EA = 128
INF_LOW_OFF = 136
INF_HIGH_OFF = 144
INF_MAXREF = 152
INF_START_PRIVRANGE = 160
INF_END_PRIVRANGE = 168
INF_NETDELTA = 176
INF_XREFNUM = 184
INF_TYPE_XREFS = 185
INF_REFCMTS = 186
INF_XREFS = 187
INF_MAX_AUTONAME_LEN = 188
INF_NAMETYPE = 190
INF_SHORT_DN = 192
INF_LONG_DN = 196
INF_DEMNAMES = 200
INF_LISTNAMES = 201
INF_INDENT = 202
INF_COMMENT = 203
INF_MARGIN = 204
INF_LENXREF = 206
INF_OUTFLAGS = 208
INF_CMTFLAG = 212
INF_BORDER = 213
INF_BINPREF = 214
INF_PREFFLAG = 216
INF_STRLIT_FLAGS = 217
INF_STRLIT_BREAK = 218
INF_STRLIT_ZEROES = 219
INF_STRTYPE = 220
INF_STRLIT_PREF = 224
INF_STRLIT_SERNUM = 240
INF_DATATYPES = 248
INF_COMPILER = 256
INF_MODEL = 257
INF_SIZEOF_INT = 258
INF_SIZEOF_BOOL = 259
INF_SIZEOF_ENUM = 260
INF_SIZEOF_ALGN = 261
INF_SIZEOF_SHORT = 262
INF_SIZEOF_LONG = 263
INF_SIZEOF_LLONG = 264
INF_SIZEOF_LDBL = 265
INF_ABIBITS = 268
INF_APPCALL_OPTIONS = 272
_signed_inf_attrs = [
INF_NETDELTA,
INF_NAMETYPE,
INF_BIN_PREFIX_SIZE,
INF_STRLIT_ZEROES,
INF_STRTYPE,
]
_INFMAP = {
INF_VERSION : (False, 'version'), # short; Version of database
INF_PROCNAME : (False, 'procname'), # char[8]; Name of current processor
INF_LFLAGS : (False, 'lflags'), # char; IDP-dependent flags
INF_DEMNAMES : (False, 'demnames'), # char; display demangled names as:
INF_FILETYPE : (False, 'filetype'), # short; type of input file (see ida.hpp)
INF_OSTYPE : (False, 'ostype'), # short; FLIRT: OS type the program is for
INF_APPTYPE : (False, 'apptype'), # short; FLIRT: Application type
INF_START_SP : (False, 'start_sp'), # long; SP register value at the start of
INF_AF : (False, 'af'), # uint32; Analysis flags
INF_AF2 : (False, 'af2'), # uint32; Analysis flags 2
INF_START_IP : (False, 'start_ip'), # long; IP register value at the start of
INF_START_EA : (False, 'start_ea'), # long; Linear address of program entry point
INF_MIN_EA : (False, 'min_ea'), # long; The lowest address used
INF_MAX_EA : (False, 'max_ea'), # long; The highest address used
INF_OMIN_EA : (False, 'omin_ea'),
INF_OMAX_EA : (False, 'omax_ea'),
INF_LOW_OFF : (False, 'lowoff'), # long; low limit of voids
INF_HIGH_OFF : (False, 'highoff'), # long; high limit of voids
INF_MAXREF : (False, 'maxref'), # long; max xref depth
INF_STRLIT_BREAK: (False, 'strlit_break'), # char; string literal line break symbol
INF_INDENT : (False, 'indent'), # char; Indention for instructions
INF_COMMENT : (False, 'comment'), # char; Indention for comments
INF_XREFNUM : (False, 'xrefnum'), # char; Number of references to generate
INF_TYPE_XREFS : (False, 'type_xrefnum'), # char; Number of references to generate in the struct & enum windows
INF_SPECSEGS : (False, 'specsegs'),
INF_BORDER : (False, 's_limiter'), # char; Generate borders?
INF_GENFLAGS : (False, 's_genflags'), # ushort; General flags:
INF_ASMTYPE : (False, 'asmtype'), # char; target assembler number (0..n)
INF_BASEADDR : (False, 'baseaddr'), # long; base paragraph of the program
INF_XREFS : (False, 's_xrefflag'), # char; xrefs representation:
INF_BINPREF : (False, 'bin_prefix_size'),
# short; # of instruction bytes to show
INF_CMTFLAG : (False, 's_cmtflg'), # char; comments:
INF_NAMETYPE : (False, 'nametype'), # char; dummy names represenation type
INF_PREFFLAG : (False, 's_prefflag'), # char; line prefix type:
INF_STRLIT_FLAGS: (False, 'strlit_flags'), # uchar; string literal flags
INF_LISTNAMES : (False, 'listnames'), # uchar; What names should be included in the list?
INF_STRLIT_PREF : (False, 'strlit_pref'), # char[16];ASCII names prefix
INF_STRLIT_SERNUM : (False, 'strlit_sernum'), # ulong; serial number
INF_STRLIT_ZEROES : (False, 'strlit_zeroes'), # char; leading zeroes
INF_START_SS : (False, 'start_ss'), # long; value of SS at the start
INF_START_CS : (False, 'start_cs'), # long; value of CS at the start
INF_MAIN : (False, 'main'), # long; address of main()
INF_SHORT_DN : (False, 'short_demnames'), # long; short form of demangled names
INF_LONG_DN : (False, 'long_demnames'), # long; long form of demangled names
INF_DATATYPES : (False, 'datatypes'), # long; data types allowed in data carousel
INF_STRTYPE : (False, 'strtype'), # long; current ascii string type
INF_MAX_AUTONAME_LEN : (False, 'max_autoname_len'), # ushort; max name length (without zero byte)
INF_MARGIN : (False, 'margin'), # ushort; max length of data lines
INF_LENXREF : (False, 'lenxref'), # ushort; max length of line with xrefs
INF_OUTFLAGS : (False, 'outflags'), # uchar; output flags
INF_COMPILER : (False, 'cc'), # uchar; compiler
#INF_MODEL = 184 # uchar; memory model & calling convention
#INF_SIZEOF_INT = 185 # uchar; sizeof(int)
#INF_SIZEOF_BOOL = 186 # uchar; sizeof(bool)
#INF_SIZEOF_ENUM = 187 # uchar; sizeof(enum)
#INF_SIZEOF_ALGN = 188 # uchar; default alignment
#INF_SIZEOF_SHORT = 189
#INF_SIZEOF_LONG = 190
#INF_SIZEOF_LLONG = 191
INF_CHANGE_COUNTER : (False, 'database_change_count'),
INF_APPCALL_OPTIONS : (False, 'appcall_options'),
INF_ABIBITS : (False, 'abibits'), # uint32; ABI features
INF_REFCMTS : (False, 'refcmtnum'),
#INF_NETDELTA : (False, 'netdelta'),
#INF_START_PRIVRANGE : (False, 'privrange.start_ea'),
#INF_END_PRIVRANGE : (False, 'privrange.end_ea')
}
def get_inf_attr(attr):
"""
"""
if attr == INF_PROCNAME:
return eval_idc("get_processor_name()")
v = eval_idc("get_inf_attr(%d)" % attr)
if v < 0 and not attr in _signed_inf_attrs:
if abs(v) < (1 << 32):
v = (1 << 32) + v
else:
v = (1 << 64) + v
return v
def set_inf_attr(attr, value):
if attr == INF_PROCNAME:
raise NotImplementedError("Please use ida_idp.set_processor_type() to change processor")
# We really want to go through IDC's equivalent, because it might
# have side-effects (i.e., send a notification, etc...)
return eval_idc("set_inf_attr(%d, %d)" % (attr, value))
set_processor_type = ida_idp.set_processor_type
@@ -2456,7 +2360,7 @@ ADDSEG_FILLGAP = ida_segment.ADDSEG_FILLGAP # If there is a gap between the new
# 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.
# It cannot hold more than ~1000 gaps.
ADDSEG_SPARSE = ida_segment.ADDSEG_SPARSE # Use sparse storage method for the new segment
def AddSeg(startea, endea, base, use32, align, comb):
@@ -5206,6 +5110,29 @@ def apply_type(ea, py_type, flags = TINFO_DEFINITE):
pt = py_type
return ida_typeinf.apply_type(None, pt[0], pt[1], ea, flags)
PT_SIL = ida_typeinf.PT_SIL # silent, no messages
PT_NDC = ida_typeinf.PT_NDC # don't decorate names
PT_TYP = ida_typeinf.PT_TYP # return declared type information
PT_VAR = ida_typeinf.PT_VAR # return declared object information
PT_PACKMASK = ida_typeinf.PT_PACKMASK # mask for pack alignment values
PT_HIGH = ida_typeinf.PT_HIGH # assume high level prototypes (with hidden args, etc)
PT_LOWER = ida_typeinf.PT_LOWER # lower the function prototypes
PT_REPLACE = ida_typeinf.PT_REPLACE # replace the old type (used in idc)
PT_RAWARGS = ida_typeinf.PT_RAWARGS # leave argument names unchanged (do not remove underscores)
PT_SILENT = PT_SIL # alias
PT_PAKDEF = 0x0000 # default pack value
PT_PAK1 = 0x0010 # #pragma pack(1)
PT_PAK2 = 0x0020 # #pragma pack(2)
PT_PAK4 = 0x0030 # #pragma pack(4)
PT_PAK8 = 0x0040 # #pragma pack(8)
PT_PAK16 = 0x0050 # #pragma pack(16)
# idc.py-specific
PT_FILE = 0x00010000 # input if a file name (otherwise contains type declarations)
def SetType(ea, newtype):
"""
Set type of function/variable
@@ -5219,7 +5146,7 @@ def SetType(ea, newtype):
@return: 1-ok, 0-failed.
"""
if newtype is not '':
pt = parse_decl(newtype, 1) # silent
pt = parse_decl(newtype, PT_SIL)
if pt is None:
# parsing failed
return None
@@ -5252,19 +5179,6 @@ def parse_decls(inputtype, flags = 0):
return ida_typeinf.idc_parse_types(inputtype, flags)
PT_FILE = 0x0001 # input if a file name (otherwise contains type declarations)
PT_SILENT = 0x0002 # silent mode
PT_PAKDEF = 0x0000 # default pack value
PT_PAK1 = 0x0010 # #pragma pack(1)
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 print_decls(ordinals, flags):
"""
Print types in a format suitable for use in a header file
@@ -5756,10 +5670,7 @@ def get_reg_value(name):
@return: register value (integer or floating point)
"""
rv = ida_idd.regval_t()
res = ida_dbg.get_reg_val(name, rv)
assert res, "get_reg_val() failed, bogus register name ('%s') perhaps?" % name
return rv.ival
return ida_dbg.get_reg_val(name)
def set_reg_value(value, name):
@@ -5773,19 +5684,7 @@ def set_reg_value(value, name):
It is not necessary to use this function to set register values.
A register name in the left side of an assignment will do too.
"""
rv = ida_idd.regval_t()
if type(value) == bytes:
value = int(value, 16)
elif type(value) != int and type(value) != int:
print("set_reg_value: value must be integer!")
return BADADDR
if value < 0:
#ival_set cannot handle negative numbers
value &= 0xFFFFFFFF
rv.ival = value
return ida_dbg.set_reg_val(name, rv)
return ida_dbg.set_reg_val(name, value)
def get_bpt_qty():
+200
View File
@@ -0,0 +1,200 @@
import ida_pro
import ida_funcs
import ida_lumina
import ida_typeinf
import ida_bytes
import idautils
dquot_escaped_str = ida_pro.str2user
def escaped_bytestr(bts):
return "".join(map(lambda b: "\\x%02X" % ord(b), bts))
class func_md_t:
def __init__(self, pfn, retrieve=True):
if type(pfn) in [int, long]:
pfn = ida_funcs.get_func(pfn)
self.pfn_ea = pfn.start_ea
self.func_info = ida_lumina.func_info_t()
if retrieve:
funcsize, self.sig = ida_lumina.calc_func_metadata(self.func_info, pfn)
def pfn(self):
return ida_funcs.get_func(self.pfn_ea)
class idb_md_t:
def __init__(self):
# take a snapshot right away
self.functions = []
for ea in idautils.Functions():
self.functions.append(func_md_t(ea))
class differ_t:
def __init__(self, flags=0):
self.flags = flags
self.lines = []
self.pfn_ea = None
def put(self, line):
self.lines.append(line)
def on_function_diff_start(self, pfn_ea):
pass
def on_score_changed(self, pfn, was, now):
pass
def on_func_name_changed(self, pfn, was, now):
pass
def on_func_proto_changed(self, pfn, was, now):
pass
def on_func_cmt_changed(self, pfn, was, now, rep):
pass
def on_cmt_changed(self, ea, was, now, rep):
pass
def on_extra_cmt_changed(self, ea, was, now, is_prev):
pass
def on_user_stkpnt_changed(self, ea, was, now):
pass
def on_frame_mem_changed(self, offset, was, now):
pass
def on_insn_ops_repr_changed(self, ea, was, now):
pass
def diff_function(self, left, right):
assert(left.pfn_ea == right.pfn_ea)
self.pfn_ea = left.pfn_ea
self.on_function_diff_start(left.pfn_ea)
class trampoline_t(ida_lumina.func_md_diff_handler_t):
def __init__(self, pfn, differ):
ida_lumina.func_md_diff_handler_t.__init__(self)
self.pfn = pfn
self.differ = differ
def _toea(self, fchunk_nr, fchunk_off):
site = ida_lumina.insn_site_t()
site.fchunk_nr = fchunk_nr
site.fchunk_off = fchunk_off
return site.toea(self.pfn)
def on_score_changed(self, l, r):
self.differ.on_score_changed(self.pfn, l, r)
def on_name_changed(self, l, r):
self.differ.on_func_name_changed(self.pfn, l, r)
def on_proto_changed(self, l, r):
ltif, rtif = ida_typeinf.tinfo_t(), ida_typeinf.tinfo_t()
self.differ.on_func_proto_changed(
self.pfn,
ltif if ltif.deserialize(None, l.type, l.fields) else None,
rtif if rtif.deserialize(None, r.type, r.fields) else None)
def on_function_comment_changed(self, l, r, rep):
self.differ.on_func_cmt_changed(self.pfn, l, r, rep)
def on_comment_changed(self, fchunk_nr, fchunk_off, l, r, rep):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_cmt_changed(ea, l, r, rep)
def on_extra_comment_changed(self, fchunk_nr, fchunk_off, l, r, is_prev):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_extra_cmt_changed(ea, l, r, is_prev)
def on_user_stkpnt_changed(self, fchunk_nr, fchunk_off, l, r):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_user_stkpnt_changed(ea, l, r)
def on_frame_member_changed(self, offset, l, r):
self.differ.on_frame_mem_changed(offset, l, r)
def on_insn_ops_repr_changed(self, fchunk_nr, fchunk_off, l, r):
ea = self._toea(fchunk_nr, fchunk_off)
self.differ.on_insn_ops_repr_changed(ea, l, r)
trampoline = trampoline_t(left.pfn(), self)
ida_lumina.diff_metadata(
trampoline,
left.func_info,
right.func_info,
self.flags)
class diff2script_t(differ_t):
def on_function_diff_start(self, pfn_ea):
self.put("pfn = ida_funcs.get_func(0x%x)" % pfn_ea)
def on_func_name_changed(self, pfn, was, now):
raise Exception("unimp!")
def on_func_proto_changed(self, pfn, was, now):
raise Exception("unimp!")
def on_func_cmt_changed(self, pfn, was, now, rep):
self.put("""ida_funcs.set_func_cmt(pfn, "%s", %s)""" % (
dquot_escaped_str(now or ''),
rep))
def on_cmt_changed(self, ea, was, now, rep):
self.put("""ida_bytes.set_cmt(0x%x, "%s", %s)""" % (
ea,
dquot_escaped_str(now or ''),
rep))
def on_extra_cmt_changed(self, ea, was, now, is_prev):
raise Exception("unimp!")
def on_user_stkpnt_changed(self, ea, was, now):
if now is not None:
self.put("""ida_frame.add_user_stkpnt(0x%x, %s)""" % (ea, hex(now)))
else:
self.put("""ida_frame.del_stkpnt(pfn, 0x%x)""" % (ea,))
def on_frame_mem_changed(self, offset, was, now):
put = self.put
put("""ida_struct.del_struc_member(frame, 0x%x)""" % offset)
if now:
put("""opinfo = None""")
put("""tif = ida_typeinf.tinfo_t()""")
if now.type.type:
put("""if tif.deserialize(None, "%s", "%s"):""" % (
escaped_bytestr(now.type.type),
escaped_bytestr(now.type.fields)))
put(""" ok, size, flags, opinfo, alsize = ida_typeinf.get_idainfo_by_type(tif)""")
elif ida_bytes.is_off0(now.flags):
put("""opinfo = ida_nalt.opinfo_t()""")
put("""opinfo.ri.target = 0x%x""" % now.opinfo.ri.target)
put("""opinfo.ri.base = 0x%x""" % now.opinfo.ri.base)
put("""opinfo.ri.tdelta = 0x%x""" % now.opinfo.ri.tdelta)
put("""opinfo.ri.flags = 0x%x""" % now.opinfo.ri.flags)
put("""ida_struct.add_struc_member(frame, "%s", 0x%x, 0x%x, opinfo, %d)""" % (
dquot_escaped_str(now.name),
offset,
now.info.flags,
now.nbytes))
put("""mptr = ida_struct.get_member(frame, 0x%x)""" % offset)
put("""if not tif.empty():""")
put(""" ida_struct.set_member_tinfo(frame, mptr, 0, tif, ida_struct.SET_MEMTI_USERTI)""")
put(""" ida_nalt.set_userti(mptr.id)""")
if now.cmt:
put("""ida_struct.set_member_cmt(mptr, "%s", False)""" % dquot_escaped_str(now.cmt))
if now.rptcmt:
put("""ida_struct.set_member_cmt(mptr, "%s", True)""" % dquot_escaped_str(now.rptcmt))
def on_insn_ops_repr_changed(self, ea, was, now):
raise Exception("Unimp")
+123 -347
View File
@@ -187,6 +187,31 @@ Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list)
return pyvar_walk_list(py_list, lambda_t::cvt, out);
}
//-------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PyListToEa64Vec(ea64vec_t *out, PyObject *py_list)
{
out->clear();
struct ida_local lambda_t
{
static int idaapi cvt(const ref_t &py_item, Py_ssize_t /*i*/, void *ud)
{
ea64vec_t &ea64vec = *(ea64vec_t *) ud;
ea64_t v = 0;
{
if ( PyInt_Check(py_item.o) )
v = PyInt_AsUnsignedLongMask(py_item.o);
else if ( PyLong_Check(py_item.o) )
v = uint64(PyLong_AsUnsignedLongLong(py_item.o));
else
return CIP_FAILED;
}
ea64vec.push_back(v);
return CIP_OK;
}
};
return pyvar_walk_list(py_list, lambda_t::cvt, out);
}
//---------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list)
{
@@ -369,12 +394,24 @@ static const ext_idcfunc_t opaque_dtor_desc =
//-------------------------------------------------------------------------
// Converts a Python variable into an IDC variable
// This function returns on one CIP_XXXX
int ida_export pyvar_to_idcvar(
static int pyvar_to_idcvar1(
const ref_t &py_var,
idc_value_t *idc_var,
int *gvar_sn)
int *gvar_sn,
qvector<const PyObject *> &_visited);
static int pyvar_to_idcvar2(
const ref_t &py_var,
idc_value_t *idc_var,
int *gvar_sn,
qvector<const PyObject *> &visited)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !visited.add_unique(py_var.o) )
{
qstring buf;
buf.sprnt("<PyObject-%p-snipped-to-prevent-infinite-recursion>", py_var.o);
idc_var->_set_string(buf.c_str());
return CIP_OK;
}
// None / NULL
if ( py_var == NULL || py_var.o == Py_None )
@@ -391,6 +428,12 @@ int ida_export pyvar_to_idcvar(
{
idc_var->_set_string(PyString_AsString(py_var.o), PyString_Size(py_var.o));
}
// Unicode
else if ( PyUnicode_Check(py_var.o) )
{
newref_t utf8(PyUnicode_AsEncodedString(py_var.o, ENC_UTF8, "strict"));
return pyvar_to_idcvar1(utf8, idc_var, gvar_sn, visited);
}
// Boolean
else if ( PyBool_Check(py_var.o) )
{
@@ -432,7 +475,7 @@ int ida_export pyvar_to_idcvar(
// Convert the item into an IDC variable
idc_value_t v;
ok = pyvar_to_idcvar(py_item, &v, gvar_sn) >= CIP_OK;
ok = pyvar_to_idcvar1(py_item, &v, gvar_sn, visited) >= CIP_OK;
if ( ok )
{
// Form the attribute name
@@ -475,7 +518,7 @@ int ida_export pyvar_to_idcvar(
// Convert the attribute into an IDC value
idc_value_t v;
ok = pyvar_to_idcvar(val, &v, gvar_sn) >= CIP_OK;
ok = pyvar_to_idcvar1(val, &v, gvar_sn, visited) >= CIP_OK;
if ( ok )
{
// Store the attribute
@@ -534,7 +577,7 @@ int ida_export pyvar_to_idcvar(
qsnprintf(buf, sizeof(buf), S_PY_IDC_GLOBAL_VAR_FMT, *gvar_sn);
idc_value_t *gvar = add_idc_gvar(buf);
// Convert the python value into the IDC global variable
bool ok = pyvar_to_idcvar(attr, gvar, gvar_sn) >= CIP_OK;
bool ok = pyvar_to_idcvar1(attr, gvar, gvar_sn, visited) >= CIP_OK;
if ( ok )
{
(*gvar_sn)++;
@@ -555,41 +598,40 @@ int ida_export pyvar_to_idcvar(
//
default:
// A normal object?
newref_t py_dir(PyObject_Dir(py_var.o));
Py_ssize_t size = PyList_Size(py_dir.o);
if ( py_dir == NULL || !PyList_Check(py_dir.o) || size == 0 )
return CIP_FAILED;
// Create the IDC object
idcv_object(idc_var);
for ( Py_ssize_t i=0; i < size; i++ )
{
borref_t item(PyList_GetItem(py_dir.o, i));
const char *field_name = PyString_AsString(item.o);
if ( field_name == NULL )
continue;
size_t len = strlen(field_name);
// Skip private attributes
if ( (len > 2 )
&& (strncmp(field_name, "__", 2) == 0 )
&& (strncmp(field_name+len-2, "__", 2) == 0) )
{
continue;
}
idc_value_t v;
// Get the non-private attribute from the object
newref_t attr(PyObject_GetAttrString(py_var.o, field_name));
if ( attr == NULL
// Convert the attribute into an IDC value
|| pyvar_to_idcvar(attr, &v, gvar_sn) < CIP_OK )
{
newref_t py_dir(PyObject_Dir(py_var.o));
Py_ssize_t size = PyList_Size(py_dir.o);
if ( py_dir == NULL || !PyList_Check(py_dir.o) || size == 0 )
return CIP_FAILED;
}
// Create the IDC object
idcv_object(idc_var);
for ( Py_ssize_t i=0; i < size; i++ )
{
borref_t item(PyList_GetItem(py_dir.o, i));
const char *field_name = PyString_AsString(item.o);
if ( field_name == NULL )
continue;
// Store the attribute
set_idcv_attr(idc_var, field_name, v);
size_t len = strlen(field_name);
// Skip private attributes
if ( (len > 2 )
&& (strncmp(field_name, "__", 2) == 0 )
&& (strncmp(field_name+len-2, "__", 2) == 0) )
{
continue;
}
idc_value_t v;
newref_t attr(PyObject_GetAttrString(py_var.o, field_name));
if ( attr == NULL )
return CIP_FAILED;
else if ( pyvar_to_idcvar1(attr, &v, gvar_sn, visited) < CIP_OK )
return CIP_FAILED;
// Store the attribute
set_idcv_attr(idc_var, field_name, v);
}
}
break;
}
@@ -597,6 +639,32 @@ int ida_export pyvar_to_idcvar(
return CIP_OK;
}
//-------------------------------------------------------------------------
// Converts a Python variable into an IDC variable
// This function returns on one CIP_XXXX
static int pyvar_to_idcvar1(
const ref_t &py_var,
idc_value_t *idc_var,
int *gvar_sn,
qvector<const PyObject *> &_visited)
{
qvector<const PyObject *> visited = _visited;
return pyvar_to_idcvar2(py_var, idc_var, gvar_sn, visited);
}
//-------------------------------------------------------------------------
// Converts a Python variable into an IDC variable
// This function returns on one CIP_XXXX
int ida_export pyvar_to_idcvar(
const ref_t &py_var,
idc_value_t *idc_var,
int *gvar_sn)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qvector<const PyObject *> visited;
return pyvar_to_idcvar1(py_var, idc_var, gvar_sn, visited);
}
//-------------------------------------------------------------------------
inline PyObject *cvt_to_pylong(int32 v)
{
@@ -1112,21 +1180,14 @@ ref_t ida_export PyW_TryImportModule(const char *name)
// If the number does not fit then VT_INT64 will be used
bool ida_export PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) )
uint64 num;
bool is_64;
if ( !PyW_GetNumber(py_var, &num, &is_64) )
return false;
PY_LONG_LONG pyll = PyLong_AsLongLong(py_var);
if ( PyErr_Occurred() )
return false;
bool as_i64 = pyll >= 0
? pyll > (PY_LONG_LONG) SVAL_MAX //-V547 'pyll > (__int64) SVAL_MAX' is always false
: pyll < (PY_LONG_LONG) SVAL_MIN; //-V547 is always false
if ( as_i64 ) //-V547 'as_i64' is always false
idc_var->set_int64(int64(pyll));
if ( !is_64 || int64(num) >= SVAL_MIN && int64(num) <= SVAL_MAX ) //-V560 is always true
idc_var->set_long(sval_t(num));
else
idc_var->set_long(sval_t(pyll));
idc_var->set_int64(int64(num));
return true;
}
@@ -1153,11 +1214,13 @@ bool ida_export PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64)
break;
}
constexpr bool is_long_64 = sizeof(long) > 4;
// Can we convert to C long?
long l = PyInt_AsLong(py_var);
if ( !PyErr_Occurred() )
{
SETNUM(uint64(l), false);
SETNUM(uint64(l), is_long_64);
break;
}
@@ -1168,7 +1231,7 @@ bool ida_export PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64)
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if ( !PyErr_Occurred() ) //-V547 '!PyErr_Occurred()' is always false
{
SETNUM(uint64(ul), false);
SETNUM(uint64(ul), is_long_64);
break;
}
PyErr_Clear();
@@ -1324,19 +1387,6 @@ bool ida_export PyW_GetError(qstring *out, bool clear_err)
return true;
}
//-------------------------------------------------------------------------
static 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;
qstrncpy(buf, s.c_str(), bufsz);
return true;
}
//-------------------------------------------------------------------------
// A loud version of PyGetError() which gets the error and displays it
// This method is used to display errors that occurred in a callback
@@ -1363,279 +1413,6 @@ void *ida_export pyobj_get_clink(PyObject *pyobj)
return t;
}
//------------------------------------------------------------------------
ssize_t idaapi pywraps_notify_when_t::idp_callback(void *ud, int event_id, va_list va)
{
pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud;
switch ( event_id )
{
case processor_t::ev_newfile:
case processor_t::ev_oldfile:
{
// This hook gets called from the kernel. Ensure we hold the GIL.
// Note that PYW_GIL_GET appears in each case of the switch, which is to
// ensure that the GIL is retrieved ONLY when we need it. If PYW_GIL_GET
// appears outside the switch, it will be executed each time this callback
// is called, which results in a huge slowdown (at least on mac).
PYW_GIL_GET;
int old = event_id == processor_t::ev_oldfile ? 1 : 0;
char *dbname = va_arg(va, char *);
_this->notify(NW_OPENIDB_SLOT, old);
}
break;
}
// event not processed, let other plugins or the processor module handle it
return 0;
}
//------------------------------------------------------------------------
ssize_t idaapi pywraps_notify_when_t::idb_callback(void *ud, int event_id, va_list va)
{
pywraps_notify_when_t *_this = (pywraps_notify_when_t *)ud;
switch ( event_id )
{
case idb_event::closebase:
{
PYW_GIL_GET;
_this->notify(NW_CLOSEIDB_SLOT);
}
break;
}
// event not processed, let other plugins or the processor module handle it
return 0;
}
//------------------------------------------------------------------------
bool pywraps_notify_when_t::unnotify_when(int when, PyObject *py_callable)
{
int cnt = 0;
for ( int slot=0; slot < NW_EVENTSCNT; slot++ )
{
// convert index to flag and see
if ( ((1 << slot) & when) != 0 )
{
unregister_callback(slot, py_callable);
++cnt;
}
}
return cnt > 0;
}
//------------------------------------------------------------------------
void pywraps_notify_when_t::register_callback(int slot, PyObject *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;
// Insert the element
tbl.push_back(callable_ref);
}
//------------------------------------------------------------------------
void pywraps_notify_when_t::unregister_callback(int slot, PyObject *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;
// Delete the element
tbl.erase(it);
}
//------------------------------------------------------------------------
bool pywraps_notify_when_t::init()
{
return hook_to_notification_point(HT_IDP, idp_callback, this);
return hook_to_notification_point(HT_IDB, idb_callback, this);
}
//------------------------------------------------------------------------
bool pywraps_notify_when_t::deinit()
{
// Uninstall all objects
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->o);
}
// ...and remove the notification
bool ok = unhook_from_notification_point(HT_IDP, idp_callback, this);
return unhook_from_notification_point(HT_IDB, idb_callback, this) && ok;
}
//------------------------------------------------------------------------
bool pywraps_notify_when_t::notify_when(int when, PyObject *py_callable)
{
// While in notify() do not allow insertion or deletion to happen on the spot
// Instead we will queue them so that notify() will carry the action when it finishes
// dispatching the notification handlers
if ( in_notify )
{
notify_when_args_t &args = delayed_notify_when_list.push_back();
args.when = when;
args.py_callable = py_callable;
return true;
}
// Uninstalling the notification?
if ( (when & NW_REMOVE) != 0 )
return unnotify_when(when & ~NW_REMOVE, py_callable);
int cnt = 0;
for ( int slot=0; slot < NW_EVENTSCNT; slot++ )
{
// is this flag set?
if ( ((1 << slot) & when) != 0 )
{
register_callback(slot, py_callable);
++cnt;
}
}
return cnt > 0;
}
//------------------------------------------------------------------------
bool pywraps_notify_when_t::notify(int slot, ...)
{
va_list va;
va_start(va, slot);
bool ok = notify_va(slot, va);
va_end(va);
return ok;
}
//------------------------------------------------------------------------
bool pywraps_notify_when_t::notify_va(int slot, va_list va)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// Sanity bounds check!
if ( slot < 0 || slot >= NW_EVENTSCNT )
return false;
bool ok = true;
in_notify = true;
int old = slot == NW_OPENIDB_SLOT ? va_arg(va, int) : 0;
for ( ref_vec_t::iterator it = table[slot].begin(), it_end = table[slot].end();
it != it_end;
++it )
{
// Form the notification code
newref_t py_code(PyInt_FromLong(1 << slot));
ref_t py_result;
switch ( slot )
{
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;
}
if ( PyW_GetError(&err) || py_result == NULL )
{
PyErr_Clear();
warning("notify_when(): Error occurred while notifying object.\n%s", err.c_str());
ok = false;
}
}
in_notify = false;
// Process any delayed notify_when() calls that
if ( !delayed_notify_when_list.empty() )
{
notify_when_args_vec_t::iterator it, it_end;
for ( it = delayed_notify_when_list.begin(), it_end=delayed_notify_when_list.end();
it != it_end;
++it )
{
notify_when(it->when, it->py_callable);
}
delayed_notify_when_list.qclear();
}
return ok;
}
//-------------------------------------------------------------------------
static pywraps_notify_when_t *g_nw = NULL;
//-------------------------------------------------------------------------
bool ida_export add_notify_when(int when, PyObject *py_callable)
{
return g_nw != NULL && g_nw->notify_when(when, py_callable);
}
//------------------------------------------------------------------------
// Initializes the notify_when mechanism
// (Normally called by IDAPython plugin.init())
static bool pywraps_nw_init()
{
if ( g_nw != NULL )
return true;
g_nw = new pywraps_notify_when_t();
if ( g_nw->init() )
return true;
// Things went bad, undo!
delete g_nw;
g_nw = NULL;
return false;
}
//------------------------------------------------------------------------
static 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);
va_end(va);
return ok;
}
//------------------------------------------------------------------------
// Deinitializes the notify_when mechanism
static 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;
return true;
}
//-------------------------------------------------------------------------
// lookup_info_t
//-------------------------------------------------------------------------
@@ -2141,7 +1918,7 @@ ssize_t ida_export get_callable_arg_count(ref_t callable)
if ( py_fun != NULL )
{
newref_t py_tuple(PyObject_CallFunctionObjArgs(py_fun.o, callable.o, NULL));
if ( PyTuple_Check(py_tuple.o) )
if ( py_tuple != NULL && PyTuple_Check(py_tuple.o) )
{
borref_t py_args(PyTuple_GetItem(py_tuple.o, 0));
if ( py_args != NULL && PySequence_Check(py_args.o) )
@@ -2164,34 +1941,33 @@ void register_module_lifecycle_callbacks(
//-------------------------------------------------------------------------
// hooks
//-------------------------------------------------------------------------
#ifdef TESTABLE_BUILD
struct hook_data_t
{
hook_type_t type;
hook_cb_t *cb;
void *ud;
bool is_hooks_base;
};
DECLARE_TYPE_AS_MOVABLE(hook_data_t);
typedef qvector<hook_data_t> hook_data_vec_t;
static hook_data_vec_t hook_data_vec;
#endif // TESTABLE_BUILD
//-------------------------------------------------------------------------
bool ida_export idapython_hook_to_notification_point(
hook_type_t hook_type,
hook_cb_t *cb,
void *user_data)
void *user_data,
bool is_hooks_base)
{
bool ok = hook_to_notification_point(hook_type, cb, user_data);
#ifdef TESTABLE_BUILD
if ( ok )
{
hook_data_t &hd = hook_data_vec.push_back();
hd.type = hook_type;
hd.cb = cb;
hd.ud = user_data;
hd.is_hooks_base = is_hooks_base;
}
#endif // TESTABLE_BUILD
return ok;
}
@@ -2202,7 +1978,6 @@ bool ida_export idapython_unhook_from_notification_point(
void *user_data)
{
bool ok = unhook_from_notification_point(hook_type, cb, user_data);
#ifdef TESTABLE_BUILD
if ( ok )
{
bool found = false;
@@ -2216,9 +1991,10 @@ bool ida_export idapython_unhook_from_notification_point(
break;
}
}
#ifdef TESTABLE_BUILD
QASSERT(30510, found);
}
#endif // TESTABLE_BUILD
}
return ok;
}
+175 -60
View File
@@ -132,19 +132,6 @@ static const char S_PY_IDA_IDAAPI_MODNAME[] = S_IDA_IDAAPI_MODNAME;
#define PY_ICID_BYREF 1
#define PY_ICID_OPAQUE 2
//------------------------------------------------------------------------
// Constants used with the notify_when()
#define NW_OPENIDB 0x0001
#define NW_OPENIDB_SLOT 0
#define NW_CLOSEIDB 0x0002
#define NW_CLOSEIDB_SLOT 1
#define NW_INITIDA 0x0004
#define NW_INITIDA_SLOT 2
#define NW_TERMIDA 0x0008
#define NW_TERMIDA_SLOT 3
#define NW_REMOVE 0x0010 // Uninstall flag
#define NW_EVENTSCNT 4 // Count of notify_when codes
//------------------------------------------------------------------------
// Constants used by the pyvar_to_idcvar and idcvar_to_pyvar functions
#define CIP_FAILED -1 // Conversion error
@@ -209,11 +196,6 @@ struct exc_report_t
// Returns the linked object (void *) from a PyObject
idaman void * ida_export pyobj_get_clink(PyObject *pyobj);
//------------------------------------------------------------------------
// All the exported functions from PyWraps are forward declared here
inline insn_t *insn_t_get_clink(PyObject *self) { return (insn_t *)pyobj_get_clink(self); }
inline op_t *op_t_get_clink(PyObject *self) { return (op_t *)pyobj_get_clink(self); }
inline switch_info_t *switch_info_t_get_clink(PyObject *self) { return (switch_info_t *)pyobj_get_clink(self); }
//-------------------------------------------------------------------------
// The base for a reference. Will automatically increase the reference
@@ -340,13 +322,21 @@ 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 )
size_t _n = size();
out->resize(_n);
for ( size_t i = 0; i < _n; ++i )
out->at(i) = at(i).o;
}
};
#ifdef _MSC_VER
// warning C4190: 'PyW_TryImportModule' has C-linkage specified, but returns UDT 'ref_t' which is incompatible with C
#pragma warning(disable : 4190)
#elif defined(__MAC__)
GCC_DIAG_OFF(return-type-c-linkage);
#endif
// Tries to import a module and swallows the exception if it fails and returns NULL
// Return value: New reference.
idaman ref_t ida_export PyW_TryImportModule(const char *name);
@@ -416,7 +406,7 @@ idaman int ida_export idcvar_to_pyvar(
idaman int ida_export pyvar_to_idcvar(
const ref_t &py_var,
idc_value_t *idc_var,
int *gvar_sn = NULL);
int *gvar_sn=NULL);
//-------------------------------------------------------------------------
// Walks a Python list or Sequence and calls the callback
@@ -437,6 +427,16 @@ idaman Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_li
idaman Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list);
idaman Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list);
#ifndef LUMINA_HPP // I'd rather put the def of ea64_t and ea64vec_t into pro.h...
#ifdef __EA64__
typedef ea_t ea64_t;
#else
typedef uint64 ea64_t;
#endif
typedef qvector<ea64_t> ea64vec_t;
#endif // LUMINA_HPP
idaman Py_ssize_t ida_export PyW_PyListToEa64Vec(ea64vec_t *out, PyObject *py_list);
//-------------------------------------------------------------------------
idaman bool ida_export PyWStringOrNone_Check(PyObject *tp);
@@ -450,41 +450,6 @@ idaman void ida_export PyW_register_compiled_form(PyObject *py_form);
//-------------------------------------------------------------------------
idaman void ida_export PyW_unregister_compiled_form(PyObject *py_form);
//---------------------------------------------------------------------------
// notify_when()
class pywraps_notify_when_t
{
ref_vec_t table[NW_EVENTSCNT];
qstring err;
bool in_notify;
struct notify_when_args_t
{
int when;
PyObject *py_callable;
};
typedef qvector<notify_when_args_t> notify_when_args_vec_t;
notify_when_args_vec_t delayed_notify_when_list;
static ssize_t idaapi idp_callback(void *ud, int event_id, va_list va);
static ssize_t idaapi idb_callback(void *ud, int event_id, va_list va);
bool unnotify_when(int when, PyObject *py_callable);
void register_callback(int slot, PyObject *py_callable);
void unregister_callback(int slot, PyObject *py_callable);
public:
bool init();
bool deinit();
bool notify_when(int when, PyObject *py_callable);
bool notify(int slot, ...);
bool notify_va(int slot, va_list va);
pywraps_notify_when_t() : in_notify(false) {}
};
idaman bool ida_export add_notify_when(int when, PyObject *py_callable);
// void hexrays_clear_python_cfuncptr_t_references(void);
// void free_compiled_form_instances(void);
// #define PYGDBG_ENABLED
#ifdef PYGDBG_ENABLED
#define PYGLOG(...) msg(__VA_ARGS__)
@@ -824,11 +789,22 @@ struct uninterruptible_op_t
~uninterruptible_op_t() { set_interruptible_state(true); }
};
// //-------------------------------------------------------------------------
//-------------------------------------------------------------------------
struct new_execution_t;
idaman void ida_export setup_new_execution(new_execution_t *instance, bool setup);
struct new_execution_t
{
bool created;
new_execution_t() { setup_new_execution(this, true); }
~new_execution_t() { setup_new_execution(this, false); }
};
//-------------------------------------------------------------------------
idaman bool ida_export idapython_hook_to_notification_point(
hook_type_t hook_type,
hook_cb_t *cb,
void *user_data);
void *user_data,
bool is_hooks_base);
idaman bool ida_export idapython_unhook_from_notification_point(
hook_type_t hook_type,
hook_cb_t *cb,
@@ -836,6 +812,137 @@ idaman bool ida_export idapython_unhook_from_notification_point(
#define hook_to_notification_point USE_IDAPYTHON_HOOK_TO_NOTIFICATION_POINT
#define unhook_from_notification_point USE_IDAPYTHON_UNHOOK_FROM_NOTIFICATION_POINT
//-------------------------------------------------------------------------
#define HBF_CALL_WITH_NEW_EXEC 0x00000001
#define HBF_VOLATILE_METHOD_SET 0x00000002
struct hooks_base_t
{
const char *class_name;
qstring identifier;
hook_cb_t *cb;
hook_type_t type;
uint32 flags;
typedef std::map<int,uchar> has_nondef_map_t;
has_nondef_map_t has_nondef;
bool hook() { return cb != NULL ? idapython_hook_to_notification_point(type, cb, this, true) : false; }
bool unhook() { return cb != NULL ? idapython_unhook_from_notification_point(type, cb, this) : false; }
bool call_requires_new_execution() const { return (flags & HBF_CALL_WITH_NEW_EXEC) != 0; }
bool has_fixed_method_set() const { return (flags & HBF_VOLATILE_METHOD_SET) == 0; }
hooks_base_t(
const char *_class_name,
hook_cb_t *_cb,
hook_type_t _type,
uint32 _flags=0)
: class_name(_class_name),
cb(_cb),
type(_type),
flags(_flags) {}
virtual ~hooks_base_t() { unhook(); }
struct ida_local event_code_to_method_name_t
{
int code;
const char *method_name;
};
protected:
void init_director_hooks(
PyObject *self,
const event_code_to_method_name_t *mappings,
size_t count)
{
// identifier
{
ref_t py_id = newref_t(PyObject_GetAttrString(self, "id"));
if ( py_id == NULL || !PyString_Check(py_id.o) )
py_id = newref_t(PyObject_Repr(self));
if ( py_id != NULL && PyString_Check(py_id.o) )
identifier = PyString_AsString(py_id.o);
}
// method set
QASSERT(30588, has_fixed_method_set());
qstring buf(class_name);
QASSERT(30589, !buf.empty());
char *p = qstrchr(buf.begin(), '.');
QASSERT(30590, p != NULL);
*p++ = '\0';
newref_t py_mod(PyImport_ImportModule(buf.c_str()));
#ifdef TESTABLE_BUILD
QASSERT(30591, py_mod != NULL);
#endif
if ( py_mod != NULL )
{
newref_t py_def_class(PyObject_GetAttrString(py_mod.o, p));
newref_t py_this_class(PyObject_GetAttrString(self, "__class__"));
#ifdef TESTABLE_BUILD
QASSERT(30592, py_def_class != NULL && py_this_class != NULL);
#endif
if ( py_def_class != NULL && py_this_class != NULL )
{
for ( size_t i = 0; i < count; ++i )
{
const event_code_to_method_name_t &cur = mappings[i];
uchar _has_nondef = 0;
newref_t py_def_meth(PyObject_GetAttrString(py_def_class.o, cur.method_name));
newref_t py_this_meth(PyObject_GetAttrString(py_this_class.o, cur.method_name));
#ifdef TESTABLE_BUILD
QASSERT(30593, py_def_meth != NULL && py_this_meth != NULL);
#endif
if ( py_def_meth != NULL && py_this_meth != NULL )
{
#ifdef BC695
if ( PyObject_HasAttrString(py_def_meth.o, "bc695_trampoline") > 0 )
_has_nondef = 2;
else
#endif
_has_nondef = PyObject_Compare(py_this_meth.o, py_def_meth.o) != 0 ? 1 : 0;
}
has_nondef[cur.code] = _has_nondef;
}
}
}
}
qstring dump_state(
const event_code_to_method_name_t *mappings,
size_t mappings_size) const
{
qstring buf;
#ifdef TESTABLE_BUILD
buf.sprnt("%s(this=%p) \"%s\" {type=%d, cb=%p, flags=%x}",
class_name, this, identifier.c_str(), int(type), cb, flags);
if ( has_fixed_method_set() )
{
for ( size_t i = 0; i < mappings_size; ++i )
{
const hooks_base_t::event_code_to_method_name_t &m = mappings[i];
has_nondef_map_t::const_iterator it = has_nondef.find(m.code);
if ( it != has_nondef.end() && it->second > 0 )
buf.cat_sprnt("\n\treimplements \"%s\"%s",
m.method_name,
it->second > 1 ? " (as 6.95 bw-compat)" : "");
}
}
else
{
buf.append(" is fully dynamic, and won't use 'has_nondef' lookup");
QASSERT(30594, has_nondef.empty());
}
if ( buf.last() != '\n' )
buf.append('\n');
#else
qnotused(mappings);
qnotused(mappings_size);
#endif
return buf;
}
};
//-------------------------------------------------------------------------
idaman bool ida_export idapython_convert_cli_completions(
qstrvec_t *out_completions,
@@ -843,12 +950,20 @@ idaman bool ida_export idapython_convert_cli_completions(
int *out_match_end,
ref_t py_res);
//-------------------------------------------------------------------------
idaman void ida_export dump_hooks_state(
qstrvec_t *out,
const hooks_base_t &h,
const hooks_base_t::event_code_to_method_name_t *mappings,
size_t mappings_size);
//-------------------------------------------------------------------------
struct module_callbacks_t
{
module_callbacks_t() { memset(this, 0, sizeof(*this)); }
void (*closebase) (void);
void (*init) (void);
void (*term) (void);
void (*closebase) (void);
};
DECLARE_TYPE_AS_MOVABLE(module_callbacks_t);
idaman void register_module_lifecycle_callbacks(
+1
View File
@@ -44,6 +44,7 @@ static int idaapi py_visit_patched_bytes_cb(
}
//-------------------------------------------------------------------------
static void ida_bytes_init(void) {}
static void ida_bytes_term(void) {}
//-------------------------------------------------------------------------
+5 -5
View File
@@ -99,7 +99,7 @@ def unregister_data_types_and_formats(formats):
# in a data_type_t subclass
# """
#
# def may_create_at(ea, nbytes):
# def may_create_at(self, ea, nbytes):
# """May create data?
# No such callback means: always succeed (i.e., no restriction where
# such a data type can be created.)
@@ -109,7 +109,7 @@ def unregister_data_types_and_formats(formats):
# """
# return True
#
# def calc_item_size(ea, maxsize):
# def calc_item_size(self, ea, maxsize):
# """This callback is used to determine size of the (possible)
# item at `ea`.
# No such callback means that datatype is of fixed size `value_size`.
@@ -127,7 +127,7 @@ def unregister_data_types_and_formats(formats):
# in a data_format_t subclass
# """
#
# def printf(value, current_ea, operand_num, dtid):
# def printf(self, value, current_ea, operand_num, dtid):
# """Convert `value` to colored string using custom format.
# @param value: value to print (of type 'str', sequence of bytes)
# @param current_ea: current address (BADADDR if unknown)
@@ -137,7 +137,7 @@ def unregister_data_types_and_formats(formats):
# """
# return None
#
# def scan(input, current_ea, operand_num):
# def scan(self, input, current_ea, operand_num):
# """Convert uncolored string (user input) to the value.
# This callback is called from the debugger when an user enters a
# new value for a register with a custom data representation (e.g.,
@@ -151,7 +151,7 @@ def unregister_data_types_and_formats(formats):
# """
# return (False, "Not implemented")
#
# def analyze(current_ea, operand_num):
# def analyze(self, current_ea, operand_num):
# """Analyze custom data format occurrence.
# This callback is called in 2 cases:
# - after emulating an instruction (after a call of
+372 -30
View File
@@ -2,6 +2,270 @@
#define __PYDBG__
//<code(py_dbg)>
// hookgenDBG:methodsinfo_def
//-------------------------------------------------------------------------
struct _cvt_status_t
{
PyObject *def_err_class;
const char *def_err_string;
qstring err_string;
PyObject *err_class;
bool ok;
_cvt_status_t(PyObject *_def_err_class, const char *_def_err_string)
: def_err_class(_def_err_class),
def_err_string(_def_err_string),
err_class(NULL),
ok(true) {}
~_cvt_status_t()
{
if ( !ok )
{
if ( err_class == NULL )
{
err_class = def_err_class;
err_string = def_err_string;
}
PyErr_SetString(err_class, err_string.c_str());
}
}
qstring &failed(PyObject *_err_class)
{
QASSERT(30587, ok == false);
err_class = _err_class;
return err_string;
}
};
//-------------------------------------------------------------------------
static bool _to_reg_val(regval_t **out, regval_t *buf, const char *name, PyObject *o)
{
if ( o == Py_None )
return false;
int cvt = SWIG_ConvertPtr(o, (void **) out, SWIGTYPE_p_regval_t, 0);
if ( SWIG_IsOK(cvt) && *out != NULL )
return true;
register_info_t ri;
if ( !get_dbg_reg_info(name, &ri) )
{
// we couldn't find the register information. This might
// mean that we are accessing another, sub register (e.g.,
// "eax" while the real register name is "rax".) Let's
// assume the dtype is DWORD then
ri.dtype = dt_dword;
}
struct ida_local cvt_t
{
static bool convert_int(regval_t *lout, PyObject *in, op_dtype_t dt)
{
uint64 u64 = 0;
_cvt_status_t status(PyExc_TypeError, "Expected integer value");
size_t nbits = 0;
switch ( dt )
{
case dt_byte: nbits = 8; break;
case dt_word: nbits = 16; break;
default:
case dt_dword: nbits = 32; break;
case dt_qword: nbits = 64; break;
}
status.ok = PyW_GetNumber(in, &u64);
if ( status.ok )
{
if ( nbits < 64 )
{
status.ok = u64 < (1ULL << nbits);
if ( !status.ok )
status.failed(PyExc_ValueError).sprnt("Integer value too large to fit in %" FMT_Z " bits", nbits);
}
}
if ( status.ok )
lout->set_int(u64);
return status.ok;
}
static bool convert_float(regval_t *lout, PyObject *in, op_dtype_t)
{
eNE ene;
_cvt_status_t status(PyExc_TypeError, "Expected float value");
double dbl = PyFloat_AsDouble(in);
status.ok = PyErr_Occurred() == NULL;
if ( status.ok )
status.ok = ieee_realcvt(&dbl, ene, 003 /*load double*/) == 0;
if ( !status.ok )
status.failed(PyExc_ValueError).sprnt("Float conversion failed");
if ( status.ok )
lout->set_float(ene);
return status.ok;
}
static bool convert_bytes(regval_t *lout, PyObject *in, op_dtype_t dt)
{
bytevec_t bytes;
_cvt_status_t status(PyExc_TypeError, "Unexpected value");
size_t nbytes = 0;
switch ( dt )
{
case dt_byte16: nbytes = 16; break;
case dt_byte32: nbytes = 32; break;
case dt_byte64: nbytes = 64; break;
default:
break;
}
status.ok = nbytes > 0;
Py_ssize_t got;
if ( status.ok )
{
status.ok = false;
if ( PyString_Check(in) )
{
char *buf;
status.ok = PyString_AsStringAndSize(in, &buf, &got) >= 0 && got <= nbytes;
if ( status.ok )
bytes.append((const uchar *) buf, got);
else
status.failed(PyExc_ValueError).sprnt(
"List of bytes is too long; was expecting at most %d bytes",
int(nbytes));
}
else if ( PyInt_Check(in) )
{
uint64 u64 = 0;
status.ok = PyW_GetNumber(in, &u64);
if ( status.ok )
{
got = sizeof(u64);
bytes.resize(got, 0);
memcpy(bytes.begin(), &u64, got);
}
}
else if ( PyLong_CheckExact(in) )
{
// (possibly very long) int or long value. Apparently it's rather
// safe to use _PyLong_AsByteArray (it's even present in 3.x)
// https://stackoverflow.com/questions/18290507/python-extension-construct-and-inspect-large-integers-efficiently
// /* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long
// v to a base-256 integer, stored in array bytes. Normally return 0,
// return -1 on error.
// If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at
// bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and
// the LSB at bytes[n-1].
// If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes
// are filled and there's nothing special about bit 0x80 of the MSB.
// If is_signed is 1/true, bytes is filled with the 2's-complement
// representation of v's value. Bit 0x80 of the MSB is the sign bit.
// Error returns (-1):
// + is_signed is 0 and v < 0. TypeError is set in this case, and bytes
// isn't altered.
// + n isn't big enough to hold the full mathematical value of v. For
// example, if is_signed is 0 and there are more digits in the v than
// fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of
// being large enough to hold a sign bit. OverflowError is set in this
// case, but bytes holds the least-significant n bytes of the true value.
// */
bytes.resize(nbytes, 0);
status.ok = _PyLong_AsByteArray(
(PyLongObject *) in,
bytes.begin(),
bytes.size(),
/*little_endian=*/ 1,
/*is_signed=*/ 1) >= 0;
if ( status.ok )
got = nbytes;
else
status.failed(PyExc_ValueError).sprnt(
"Integer value is too large to fit in %d bytes",
int(nbytes));
}
}
if ( status.ok )
{
bytes.growfill(nbytes - got, 0);
lout->set_bytes(bytes);
}
return status.ok;
}
};
bool ok = false;
regval_t &rv = *buf;
switch ( ri.dtype )
{
case dt_byte:
case dt_word:
case dt_dword:
case dt_qword:
default:
ok = cvt_t::convert_int(&rv, o, ri.dtype);
break;
case dt_float:
case dt_tbyte:
case dt_double:
case dt_ldbl:
ok = cvt_t::convert_float(&rv, o, ri.dtype);
break;
case dt_byte16:
case dt_byte32:
case dt_byte64:
ok = cvt_t::convert_bytes(&rv, o, ri.dtype);
break;
}
if ( ok )
*out = &rv;
return ok;
}
//-------------------------------------------------------------------------
static PyObject *_from_reg_val(
const char *name,
const regval_t &rv)
{
register_info_t ri;
if ( !get_dbg_reg_info(name, &ri) ) // see _to_reg_val()
ri.dtype = dt_dword;
PyObject *res = NULL;
_cvt_status_t status(PyExc_ValueError, "Conversion failed");
switch ( ri.dtype )
{
default:
if ( rv.ival <= uint64(PyInt_GetMax()) )
res = PyInt_FromLong(long(rv.ival));
else
res = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) rv.ival);
break;
case dt_float:
case dt_tbyte:
case dt_double:
case dt_ldbl:
{
double dbl;
status.ok = ieee_realcvt(&dbl, (uint16 *) rv.fval, 013 /*store double*/) == 0;
if ( status.ok )
res = PyFloat_FromDouble(dbl);
}
break;
case dt_byte16:
case dt_byte32:
case dt_byte64:
{
const bytevec_t &b = rv.bytes();
res = PyString_FromStringAndSize((const char *) b.begin(), b.size());
}
break;
}
return res;
}
//</code(py_dbg)>
//<inline(py_dbg)>
@@ -20,7 +284,9 @@ def get_manual_regions():
static PyObject *py_get_manual_regions()
{
meminfo_vec_t ranges;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
get_manual_regions(&ranges);
SWIG_PYTHON_THREAD_END_ALLOW;
return meminfo_vec_t_to_py(ranges);
}
@@ -53,6 +319,7 @@ def refresh_debugger_memory():
*/
static PyObject *refresh_debugger_memory()
{
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, 0);
@@ -62,20 +329,38 @@ static PyObject *refresh_debugger_memory()
// Invalidate the cache
is_mapped(0);
SWIG_PYTHON_THREAD_END_ALLOW;
PYW_GIL_CHECK_LOCKED_SCOPE();
Py_RETURN_NONE;
}
ssize_t idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
struct DBG_Hooks : public hooks_base_t
{
public:
virtual ~DBG_Hooks() { unhook(); }
// hookgenDBG:methodsinfo_decl
bool hook() { return idapython_hook_to_notification_point(HT_DBG, DBG_Callback, this); }
bool unhook() { return idapython_unhook_from_notification_point(HT_DBG, DBG_Callback, this); }
DBG_Hooks(uint32 _flags=0)
: hooks_base_t("ida_dbg.DBG_Hooks", DBG_Callback, HT_DBG, _flags) {}
bool hook() { return hooks_base_t::hook(); }
bool unhook() { return hooks_base_t::unhook(); }
#ifdef TESTABLE_BUILD
qstring dump_state() { return hooks_base_t::dump_state(mappings, mappings_size); }
#endif
// hookgenDBG:methods
ssize_t dispatch(int code, va_list va)
{
ssize_t ret = 0;
switch ( code )
{
// hookgenDBG:notifications
}
return ret;
}
private:
static ssize_t store_int(int rc, const debug_event_t *, int *warn)
{
*warn = rc;
@@ -87,35 +372,15 @@ public:
*warn = rc;
return 0;
}
// hookgenDBG:methods
};
ssize_t idaapi DBG_Callback(void *ud, int notification_code, va_list va)
//-------------------------------------------------------------------------
ssize_t idaapi DBG_Callback(void *ud, int 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;
ssize_t ret = 0;
try
{
switch ( notification_code )
{
// hookgenDBG:notifications
}
}
catch (Swig::DirectorException &e)
{
msg("Exception in DBG Hook function: %s\n", e.getMessage());
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
// hookgenDBG:safecall=DBG_Hooks
}
//------------------------------------------------------------------------
/*
#<pydoc>
@@ -204,5 +469,82 @@ def dbg_can_query():
#</pydoc>
*/
//-------------------------------------------------------------------------
static PyObject *py_set_reg_val(const char *regname, PyObject *o)
{
regval_t buf;
regval_t *ptr;
if ( !_to_reg_val(&ptr, &buf, regname, o) )
return NULL;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
bool ok = set_reg_val(regname, ptr);
SWIG_PYTHON_THREAD_END_ALLOW;
if ( !ok )
{
PyErr_SetString(PyExc_Exception, "Failed to set register value");
Py_RETURN_FALSE;
}
Py_RETURN_TRUE;
}
//-------------------------------------------------------------------------
static PyObject *py_set_reg_val(thid_t tid, int regidx, PyObject *o)
{
if ( dbg == NULL )
{
PyErr_SetString(PyExc_Exception, "No debugger loaded");
return NULL;
}
if ( regidx < 0 || regidx >= dbg->nregs )
{
qstring buf;
buf.sprnt("Bad register index: %d", regidx);
PyErr_SetString(PyExc_Exception, buf.c_str());
return NULL;
}
const register_info_t &ri = dbg->regs(regidx);
regval_t buf;
regval_t *ptr;
if ( !_to_reg_val(&ptr, &buf, ri.name, o) )
return NULL;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
bool ok = set_reg_val(tid, regidx, ptr);
SWIG_PYTHON_THREAD_END_ALLOW;
return PyInt_FromLong(ok);
}
//-------------------------------------------------------------------------
static PyObject *py_request_set_reg_val(const char *regname, PyObject *o)
{
regval_t buf;
regval_t *ptr;
if ( !_to_reg_val(&ptr, &buf, regname, o) )
return NULL;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
bool ok = request_set_reg_val(regname, ptr);
SWIG_PYTHON_THREAD_END_ALLOW;
if ( !ok )
{
PyErr_SetString(PyExc_Exception, "Failed to request set register value");
Py_RETURN_FALSE;
}
Py_RETURN_TRUE;
}
//-------------------------------------------------------------------------
static PyObject *py_get_reg_val(const char *regname)
{
regval_t buf;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
bool ok = get_reg_val(regname, &buf);
SWIG_PYTHON_THREAD_END_ALLOW;
if ( !ok )
{
PyErr_SetString(PyExc_Exception, "Failed to retrieve register value");
return NULL;
}
return _from_reg_val(regname, buf);
}
//</inline(py_dbg)>
#endif
+20 -18
View File
@@ -132,9 +132,6 @@ private:
// out: 0-ok, 1-ignore click
//graph_viewer_t *v = va_arg(va, graph_viewer_t *);
//selection_item_t *s = va_arg(va, selection_item_t *);
if ( item == NULL || !item->is_node )
return 1;
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t result(
PyObject_CallMethod(
@@ -197,7 +194,7 @@ private:
}
// a group is being created
int on_creating_group(mutable_graph_t *my_g, intvec_t *my_nodes)
int on_creating_group(mutable_graph_t * /*my_g*/, intvec_t *my_nodes)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_nodes(PyList_New(my_nodes->size()));
@@ -216,7 +213,7 @@ private:
}
// a group is being deleted
int on_deleting_group(mutable_graph_t * /*g*/, int old_group)
int on_deleting_group(mutable_graph_t * /*g*/, int /*old_group*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// TODO
@@ -224,7 +221,7 @@ private:
}
// a group is being collapsed/uncollapsed
int on_group_visibility(mutable_graph_t * /*g*/, int group, bool expand)
int on_group_visibility(mutable_graph_t * /*g*/, int /*group*/, bool /*expand*/)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
// TODO
@@ -236,7 +233,7 @@ private:
{
TWidget *view;
if ( pycim_lookup_info.find_by_py_view(&view, this) )
display_widget(view, WOPN_TAB);
display_widget(view, WOPN_DP_TAB);
}
void jump_to_node(int nid)
@@ -285,7 +282,7 @@ private:
this->self = borref_t(self);
graph_viewer_t *pview = create_graph_viewer(title, id, s_callback, this, 0);
this->self = ref_t();
display_widget(pview, WOPN_TAB);
display_widget(pview, WOPN_DP_TAB);
newref_t ret(PyObject_CallMethod(self, "hook", NULL));
if ( pview != NULL )
viewer_fit_window(pview);
@@ -579,17 +576,22 @@ ssize_t py_graph_t::gr_callback(int code, va_list va)
break;
//
case grcode_dblclicked:
if ( has_callback(GRCODE_HAVE_DBL_CLICKED) )
{
graph_viewer_t *view = va_arg(va, graph_viewer_t *);
selection_item_t *item = va_arg(va, selection_item_t *);
ret = on_dblclicked(view, item);
bool handled = has_callback(GRCODE_HAVE_DBL_CLICKED);
if ( handled )
{
graph_viewer_t *view = va_arg(va, graph_viewer_t *);
selection_item_t *item = va_arg(va, selection_item_t *);
handled = item != NULL && item->is_node;
if ( handled )
ret = on_dblclicked(view, item);
}
if ( !handled )
ret = 0; // We don't want to ignore the double click, but rather
// fallback to the default behavior (e.g., double-clicking
// on an edge will to jump to the node on the other side
// of that edge.)
}
else
ret = 0; // We don't want to ignore the double click, but rather
// fallback to the default behavior (e.g., double-clicking
// on an edge will to jump to the node on the other side
// of that edge.)
break;
//
case grcode_gotfocus:
@@ -614,7 +616,7 @@ ssize_t py_graph_t::gr_callback(int code, va_list va)
//
case grcode_user_hint:
{
mutable_graph_t *g = va_arg(va, mutable_graph_t *);
/*mutable_graph_t *g =*/ va_arg(va, mutable_graph_t *);
int node = va_arg(va, int);
int src = va_arg(va, int);
int dest = va_arg(va, int);
+97 -88
View File
@@ -43,23 +43,70 @@ static void *idaapi init_time_dummy_hexdsp(int code, ...)
case hx_remitem:
case hx_cexpr_t_cleanup:
case hx_cinsn_t_cleanup:
case hx_mop_t_erase:
case hx_mbl_array_t_term:
case hx_valrng_t_clear:
{
#ifdef _DEBUG
va_list va;
va_start(va, code);
citem_t *item = va_arg(va, citem_t *);
void *item = va_arg(va, void *);
// catch leaks
if ( code == hx_cexpr_t_cleanup )
if ( code == hx_remitem )
QASSERT(30529, ((cinsn_t *)item)->op == cot_empty || ((cinsn_t *)item)->op == cit_empty);
else if ( code == hx_cexpr_t_cleanup )
QASSERT(30497, ((cexpr_t *)item)->op == cot_empty && ((cexpr_t *)item)->n == NULL);
else if ( code == hx_cinsn_t_cleanup )
QASSERT(30498, ((cinsn_t *)item)->op == cit_empty && ((cinsn_t *)item)->cblock == NULL);
else // code == hx_remitem
QASSERT(30529, item->op == cot_empty || item->op == cit_empty);
else if ( code == hx_mop_t_erase )
QASSERT(30595, ((mop_t *)item)->t == mop_z && ((mop_t *)item)->nnn == NULL);
else if ( code == hx_mbl_array_t_term )
QASSERT(30596, ((mbl_array_t *)item)->blocks == NULL);
else if ( code == hx_valrng_t_clear )
QASSERT(30601, ((valrng_t *)item)->empty());
else
INTERR(30597);
va_end(va);
#endif
}
break;
case hx_remove_optinsn_handler:
{
#ifdef _DEBUG
static bool in_removal = false;
if ( !in_removal )
{
in_removal = true;
va_list va;
va_start(va, code);
optinsn_t *oi = va_arg(va, optinsn_t *);
QASSERT(30598, remove_optinsn_handler(oi) == false); // must have been removed already
in_removal = false;
}
#endif
}
break;
case hx_remove_optblock_handler:
{
#ifdef _DEBUG
static bool in_removal = false;
if ( !in_removal )
{
in_removal = true;
va_list va;
va_start(va, code);
optblock_t *ob = va_arg(va, optblock_t *);
QASSERT(30599, remove_optblock_handler(ob) == false); // must have been removed already
in_removal = false;
}
#endif
}
break;
default:
#ifdef _DEBUG
if ( under_debugger )
BPT;
#endif
warning("Hex-Rays Decompiler got called from Python without being loaded");
break;
}
@@ -84,45 +131,6 @@ void delete_qstring_printer_t(qstring_printer_t *qs)
delete qs;
}
//---------------------------------------------------------------------
static ref_t hexrays_python_call(ref_t fct, ref_t args)
{
PYW_GIL_GET;
newref_t resultobj(PyEval_CallObject(fct.o, args.o));
if ( PyErr_Occurred() )
{
PyErr_Print();
return borref_t(Py_None);
}
return resultobj;
}
//---------------------------------------------------------------------
static int hexrays_python_intcall(ref_t fct, ref_t args)
{
PYW_GIL_GET;
ref_t resultobj = hexrays_python_call(fct, args);
int result;
if ( SWIG_IsOK(SWIG_AsVal_int(resultobj.o, &result)) )
return result;
msg("IDAPython: Hex-rays python callback returned non-integer; value ignored.\n");
return 0;
}
//---------------------------------------------------------------------
static bool idaapi __python_custom_viewer_popup_item_callback(void *ud)
{
PYW_GIL_GET;
int ret;
borref_t fct((PyObject *)ud);
newref_t nil(NULL);
ret = hexrays_python_intcall(fct, nil);
return ret ? true : false;
}
//-------------------------------------------------------------------------
// Clearable objects
//-------------------------------------------------------------------------
@@ -134,9 +142,15 @@ enum hx_clearable_type_t
{
hxclr_unknown = 0,
hxclr_cfuncptr,
hxclr_cinsn,
hxclr_cexpr,
hxclr_cblock,
hxclr_cinsn_t,
hxclr_cexpr_t,
hxclr_cblock_t,
hxclr_mbl_array_t,
hxclr_mop_t,
hxclr_minsn_t,
hxclr_optinsn_t,
hxclr_optblock_t,
hxclr_valrng_t,
};
struct hx_clearable_t
{
@@ -159,15 +173,33 @@ void hexrays_unloading__clear_python_clearable_references(void)
case hxclr_cfuncptr:
((cfuncptr_t*) hxc.ptr)->reset();
break;
case hxclr_cinsn:
case hxclr_cinsn_t:
((cinsn_t *) hxc.ptr)->cleanup();
break;
case hxclr_cexpr:
case hxclr_cexpr_t:
((cexpr_t *) hxc.ptr)->cleanup();
break;
case hxclr_cblock:
case hxclr_cblock_t:
((cblock_t *) hxc.ptr)->clear();
break;
case hxclr_mbl_array_t:
((mbl_array_t *) hxc.ptr)->term();
break;
case hxclr_mop_t:
((mop_t *) hxc.ptr)->erase();
break;
case hxclr_minsn_t:
((minsn_t *) hxc.ptr)->_make_nop();
break;
case hxclr_optinsn_t:
remove_optinsn_handler((optinsn_t *) hxc.ptr);
break;
case hxclr_optblock_t:
remove_optblock_handler((optblock_t *) hxc.ptr);
break;
case hxclr_valrng_t:
((valrng_t *) hxc.ptr)->set_none();
break;
default: INTERR(30499);
}
}
@@ -178,6 +210,8 @@ void hexrays_register_python_clearable_instance(
void *ptr,
hx_clearable_type_t type)
{
if ( ptr == NULL )
return;
for ( size_t i = 0, n = python_clearables.size(); i < n; ++i )
if ( python_clearables[i].ptr == ptr )
return;
@@ -206,7 +240,6 @@ void hexrays_deregister_python_clearable_instance(void *ptr)
}
//-------------------------------------------------------------------------
#ifdef TESTABLE_BUILD
hx_clearable_type_t hexrays_is_registered_python_clearable_instance(
const void *ptr)
{
@@ -215,25 +248,9 @@ hx_clearable_type_t hexrays_is_registered_python_clearable_instance(
return python_clearables[i].type;
return hxclr_unknown;
}
#endif
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf)
{
try
{
cfuncptr_t cfunc = decompile(pfn, hf);
return cfunc;
}
catch(...)
{
error("Hex-Rays Python: decompiler threw an exception.\n");
}
return cfuncptr_t(0);
}
//-------------------------------------------------------------------------
static bool is_hexrays_plugin(const plugin_info_t *pinfo)
{
@@ -256,7 +273,7 @@ static void try_init()
}
//-------------------------------------------------------------------------
static void *idaapi exit_time_dummy_hexdsp(int code, ...)
static void *idaapi exit_time_dummy_hexdsp(int /*code*/, ...)
{
/* This callback exists to avoid crashes if the user calls any hexrays functions
after unloading the decompiler.
@@ -317,6 +334,9 @@ static ssize_t idaapi ida_hexrays_ui_notification(void *, int code, va_list va)
return 0;
}
//-------------------------------------------------------------------------
static void ida_hexrays_init(void) {}
//-------------------------------------------------------------------------
static void ida_hexrays_term(void)
{
@@ -343,24 +363,6 @@ bool py_init_hexrays_plugin(int flags=0)
return hexdsp_inited() || init_hexrays_plugin(flags);
}
cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf);
//-------------------------------------------------------------------------
bool py_decompile_many(const char *outfile, PyObject *funcaddrs, int flags)
{
eavec_t leas, *eas = NULL;
if ( funcaddrs != Py_None )
{
if ( !PySequence_Check(funcaddrs)
|| PyW_PyListToEaVec(&leas, funcaddrs) < 0 )
{
return false;
}
eas = &leas;
}
return decompile_many(outfile, eas, flags);
}
//-------------------------------------------------------------------------
// Some examples will want to use action_handler_t's whose update() method
// calls get_widget_vdui() to figure out whether the action should be enabled
@@ -375,12 +377,19 @@ vdui_t *py_get_widget_vdui(TWidget *f)
return hexdsp_inited() ? get_widget_vdui(f) : NULL;
}
inline boundaries_iterator_t py_boundaries_find(const boundaries_t *map, const cinsn_t *key)
//-------------------------------------------------------------------------
inline boundaries_iterator_t py_boundaries_find(
const boundaries_t *map,
const cinsn_t *key)
{
return boundaries_find(map, key);
}
inline boundaries_iterator_t py_boundaries_insert(boundaries_t *map, const cinsn_t *key, const rangeset_t &val)
//-------------------------------------------------------------------------
inline boundaries_iterator_t py_boundaries_insert(
boundaries_t *map,
const cinsn_t *key,
const rangeset_t &val)
{
return boundaries_insert(map, key, val);
}
@@ -390,5 +399,5 @@ void py_term_hexrays_plugin(void) {}
//</inline(py_hexrays)>
//<init(py_hexrays)>
idapython_hook_to_notification_point(HT_UI, ida_hexrays_ui_notification, NULL);
idapython_hook_to_notification_point(HT_UI, ida_hexrays_ui_notification, NULL, /*is_hooks_base=*/ false);
//</init(py_hexrays)>
+11 -5
View File
@@ -2,7 +2,12 @@
#<pycode(py_hexrays)>
import ida_funcs
hexrays_failure_t.__str__ = lambda self: str(self.str)
hexrays_failure_t.__str__ = lambda self: str("%x: %s" % (self.errea, self.desc()))
# ---------------------------------------------------------------------
# Renamings
is_allowed_on_small_struni = accepts_small_udts
is_small_struni = is_small_udt
# ---------------------------------------------------------------------
class DecompilationFailure(Exception):
@@ -17,7 +22,7 @@ class DecompilationFailure(Exception):
return
# ---------------------------------------------------------------------
def decompile(ea, hf=None):
def decompile(ea, hf=None, flags=0):
if isinstance(ea, (int, long)):
func = ida_funcs.get_func(ea)
if not func: return
@@ -29,7 +34,7 @@ def decompile(ea, hf=None):
if hf is None:
hf = hexrays_failure_t()
ptr = _decompile(func, hf)
ptr = _ida_hexrays.decompile_func(func, hf, flags)
if ptr.__deref__() is None:
raise DecompilationFailure(hf)
@@ -53,7 +58,8 @@ ida_idaapi._listify_types(
qvector_ccase_t,
hexwarns_t,
history_t,
lvar_saved_infos_t)
lvar_saved_infos_t,
ui_stroff_ops_t)
def citem_to_specific_type(self):
""" cast the citem_t object to its more specific type, either cexpr_t or cinsn_t. """
@@ -488,7 +494,7 @@ class __cbhooks_t(Hexrays_Hooks):
Hexrays_Hooks.__init__(self)
def maturity(self, *args): return self.callback(hxe_maturity, *args)
def interr(self, *args): return self.callback(hxe_interr, **args)
def interr(self, *args): return self.callback(hxe_interr, *args)
def print_func(self, *args): return self.callback(hxe_print_func, *args)
def func_printed(self, *args): return self.callback(hxe_func_printed, *args)
def open_pseudocode(self, *args): return self.callback(hxe_open_pseudocode, *args)
+47 -45
View File
@@ -1,27 +1,9 @@
//<code(py_hexrays_hooks)>
//---------------------------------------------------------------------------
ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t event, va_list va)
ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class Hexrays_Hooks *proxy = (class Hexrays_Hooks *)ud;
ssize_t ret = 0;
try
{
switch ( event )
{
// hookgenHEXRAYS:notifications
}
}
catch (Swig::DirectorException &e)
{
msg("Exception in Hexrays Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
// hookgenHEXRAYS:safecall=Hexrays_Hooks
}
//-------------------------------------------------------------------------
@@ -35,8 +17,9 @@ static void hexrays_unloading__unhook_hooks(void)
}
//-------------------------------------------------------------------------
Hexrays_Hooks::Hexrays_Hooks()
: hooked(false)
Hexrays_Hooks::Hexrays_Hooks(uint32 _flags)
: hooks_base_t("ida_hexrays.Hexrays_Hooks", NULL, hook_type_t(-1), _flags),
hooked(false)
{
hexrays_hooks_instances.push_back(this);
}
@@ -47,6 +30,9 @@ Hexrays_Hooks::~Hexrays_Hooks()
hexrays_hooks_instances.del(this);
unhook();
}
// hookgenHEXRAYS:methodsinfo_def
//</code(py_hexrays_hooks)>
//<inline(py_hexrays_hooks)>
@@ -56,9 +42,46 @@ Hexrays_Hooks::~Hexrays_Hooks()
ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t event, va_list va);
class control_graph_t;
class Hexrays_Hooks
// We'll inherit from hooks_base_t to benefit from some of its
// goodies, but the [un]hooking mechanism itself will be different.
struct Hexrays_Hooks : public hooks_base_t
{
friend ssize_t idaapi Hexrays_Callback(void *ud, hexrays_event_t event, va_list va);
// hookgenHEXRAYS:methodsinfo_decl
bool hooked;
Hexrays_Hooks(uint32 _flags=0);
virtual ~Hexrays_Hooks();
bool hook()
{
if ( !hooked )
hooked = install_hexrays_callback(Hexrays_Callback, this);
return hooked;
}
bool unhook()
{
if ( hooked )
hooked = !remove_hexrays_callback(Hexrays_Callback, this);
return !hooked;
}
#ifdef TESTABLE_BUILD
qstring dump_state() { return hooks_base_t::dump_state(mappings, mappings_size); }
#endif
// hookgenHEXRAYS:methods
ssize_t dispatch(hexrays_event_t code, va_list va)
{
ssize_t ret = 0;
switch ( code )
{
// hookgenHEXRAYS:notifications
}
return ret;
}
private:
static ssize_t handle_create_hint_output(PyObject *o, vdui_t *, qstring *out_hint, int *out_implines)
{
ssize_t rc = 0;
@@ -82,26 +105,5 @@ class Hexrays_Hooks
}
return rc;
}
bool hooked;
public:
Hexrays_Hooks();
virtual ~Hexrays_Hooks();
bool hook()
{
if ( !hooked )
hooked = install_hexrays_callback(Hexrays_Callback, this);
return hooked;
}
bool unhook()
{
if ( hooked )
hooked = !remove_hexrays_callback(Hexrays_Callback, this);
return !hooked;
}
// hookgenHEXRAYS:methods
};
//</inline(py_hexrays_hooks)>
+153
View File
@@ -1,3 +1,155 @@
#<pycode(py_ida)>
def __make_idainfo_bound(func, attr):
def __func(self, *args):
return func(*args)
setattr(idainfo, attr, __func)
_NO_SETTER = "<nosetter>"
def __make_idainfo_accessors(
attr,
getter_name=None,
setter_name=None):
if getter_name is None:
getter_name = attr
getter = globals()["idainfo_%s" % getter_name]
__make_idainfo_bound(getter, getter_name)
if setter_name != _NO_SETTER:
if setter_name is None:
setter_name = "set_%s" % attr
setter = globals()["idainfo_%s" % setter_name]
__make_idainfo_bound(setter, setter_name)
def __make_idainfo_getter(name):
return __make_idainfo_accessors(None, getter_name=name, setter_name=_NO_SETTER)
idainfo_big_arg_align = inf_big_arg_align
__make_idainfo_getter("big_arg_align")
idainfo_gen_null = inf_gen_null
idainfo_set_gen_null = inf_set_gen_null
__make_idainfo_accessors("gen_null")
idainfo_gen_lzero = inf_gen_lzero
idainfo_set_gen_lzero = inf_set_gen_lzero
__make_idainfo_accessors("gen_lzero")
idainfo_gen_tryblks = inf_gen_tryblks
idainfo_set_gen_tryblks = inf_set_gen_tryblks
__make_idainfo_accessors("gen_tryblks")
idainfo_get_demname_form = inf_get_demname_form
__make_idainfo_getter("get_demname_form")
idainfo_get_pack_mode = inf_get_pack_mode
idainfo_set_pack_mode = inf_set_pack_mode
__make_idainfo_accessors(None, "get_pack_mode", "set_pack_mode")
idainfo_is_32bit = inf_is_32bit
__make_idainfo_getter("is_32bit")
idainfo_is_64bit = inf_is_64bit
idainfo_set_64bit = inf_set_64bit
__make_idainfo_accessors(None, "is_64bit", "set_64bit")
idainfo_is_auto_enabled = inf_is_auto_enabled
idainfo_set_auto_enabled = inf_set_auto_enabled
__make_idainfo_accessors(None, "is_auto_enabled", "set_auto_enabled")
idainfo_is_be = inf_is_be
idainfo_set_be = inf_set_be
__make_idainfo_accessors(None, "is_be", "set_be")
idainfo_is_dll = inf_is_dll
__make_idainfo_getter("is_dll")
idainfo_is_flat_off32 = inf_is_flat_off32
__make_idainfo_getter("is_flat_off32")
idainfo_is_graph_view = inf_is_graph_view
idainfo_set_graph_view = inf_set_graph_view
__make_idainfo_accessors(None, "is_graph_view", "set_graph_view")
idainfo_is_hard_float = inf_is_hard_float
__make_idainfo_getter("is_hard_float")
idainfo_is_kernel_mode = inf_is_kernel_mode
__make_idainfo_getter("is_kernel_mode")
idainfo_is_mem_aligned4 = inf_is_mem_aligned4
__make_idainfo_getter("is_mem_aligned4")
idainfo_is_snapshot = inf_is_snapshot
__make_idainfo_getter("is_snapshot")
idainfo_is_wide_high_byte_first = inf_is_wide_high_byte_first
idainfo_set_wide_high_byte_first = inf_set_wide_high_byte_first
__make_idainfo_accessors(None, "is_wide_high_byte_first", "set_wide_high_byte_first")
idainfo_like_binary = inf_like_binary
__make_idainfo_getter("like_binary")
idainfo_line_pref_with_seg = inf_line_pref_with_seg
idainfo_set_line_pref_with_seg = inf_set_line_pref_with_seg
__make_idainfo_accessors("line_pref_with_seg")
idainfo_show_auto = inf_show_auto
idainfo_set_show_auto = inf_set_show_auto
__make_idainfo_accessors("show_auto")
idainfo_show_line_pref = inf_show_line_pref
idainfo_set_show_line_pref = inf_set_show_line_pref
__make_idainfo_accessors("show_line_pref")
idainfo_show_void = inf_show_void
idainfo_set_show_void = inf_set_show_void
__make_idainfo_accessors("show_void")
idainfo_loading_idc = inf_loading_idc
__make_idainfo_getter("loading_idc")
idainfo_map_stkargs = inf_map_stkargs
__make_idainfo_getter("map_stkargs")
idainfo_pack_stkargs = inf_pack_stkargs
__make_idainfo_getter("pack_stkargs")
idainfo_readonly_idb = inf_readonly_idb
__make_idainfo_getter("readonly_idb")
idainfo_set_store_user_info = lambda *args: not inf_set_store_user_info()
idainfo_stack_ldbl = inf_stack_ldbl
__make_idainfo_getter("stack_ldbl")
idainfo_stack_varargs = inf_stack_varargs
__make_idainfo_getter("stack_varargs")
idainfo_use_allasm = inf_use_allasm
__make_idainfo_getter("use_allasm")
idainfo_use_gcc_layout = inf_use_gcc_layout
__make_idainfo_getter("use_gcc_layout")
macros_enabled = inf_macros_enabled
should_create_stkvars = inf_should_create_stkvars
should_trace_sp = inf_should_trace_sp
show_all_comments = inf_show_all_comments
show_comments = lambda *args: not inf_hide_comments()
show_repeatables = inf_show_repeatables
__make_idainfo_accessors(None, "is_graph_view", "set_graph_view")
SW_RPTCMT = SCF_RPTCMT
SW_ALLCMT = SCF_ALLCMT
SW_NOCMT = SCF_NOCMT
SW_LINNUM = SCF_LINNUM
SW_TESTMODE = SCF_TESTMODE
SW_SHHID_ITEM = SCF_SHHID_ITEM
SW_SHHID_FUNC = SCF_SHHID_FUNC
SW_SHHID_SEGM = SCF_SHHID_SEGM
#</pycode(py_ida)>
#<pycode_BC695(py_ida)>
AF2_ANORET=AF_ANORET
@@ -42,6 +194,7 @@ def __wrap_hooks_callback(klass, new_name, old_name, do_call):
return rc
setattr(klass, bkp_name, getattr(klass, new_name))
setattr(__wrapper, "bc695_trampoline", True)
setattr(klass, new_name, __wrapper)
idainfo.ASCIIbreak = idainfo.strlit_break
@@ -115,11 +115,45 @@ void pycim_view_close(PyObject *self)
#undef CHK_THIS_OR_NULL
#undef CHK_THIS
#undef GET_THIS
//-------------------------------------------------------------------------
#define NOTIFY_DISPATCHER_INSTANCE "_notify_when_dispatcher"
#define NOTIFY_DISPATCHER_DISPATCH_METHOD "dispatch"
#define NW_INITIDA 4
#define NW_TERMIDA 8
//-------------------------------------------------------------------------
static void _ida_idaapi_notify_init_term(int what)
{
newref_t py_mod(PyImport_ImportModule("ida_idaapi"));
if ( py_mod != NULL )
{
newref_t py_obj(PyObject_GetAttrString(py_mod.o, NOTIFY_DISPATCHER_INSTANCE));
if ( py_obj != NULL && py_obj.o != Py_None )
PyObject_CallMethod(py_obj.o, NOTIFY_DISPATCHER_DISPATCH_METHOD, "i", what);
}
}
//-------------------------------------------------------------------------
static void ida_idaapi_init(void)
{
_ida_idaapi_notify_init_term(NW_INITIDA);
}
//-------------------------------------------------------------------------
static void ida_idaapi_term(void)
{
_ida_idaapi_notify_init_term(NW_TERMIDA);
}
//-------------------------------------------------------------------------
static void ida_idaapi_closebase(void) {}
//</code(py_idaapi)>
//<inline(py_idaapi)>
${BASE_HOOKS_FLAGS}
//------------------------------------------------------------------------
/*
@@ -204,6 +238,70 @@ def enable_extlang_python(enable):
idaman void ida_export enable_extlang_python(bool enable);
idaman void ida_export enable_python_cli(bool enable);
idaman PyObject *ida_export format_basestring(PyObject *_in)
{
// This is basically a reimplementation of str.__repr__, except that
// we don't want to turn non-ASCII bytes into a \xNN equivalent: IDA
// accepts UTF-8 everywhere internally (and this will end up in a
// 'msg' call eventually.)
PyObject *_pystr;
ref_t _tmp;
char *in_bytes;
Py_ssize_t in_len;
if ( PyUnicode_Check(_in) )
{
_tmp = newref_t(PyUnicode_AsUTF8String(_in));
if ( _tmp == NULL )
return _in;
_pystr = _tmp.o;
}
else
{
_pystr = _in;
}
if ( PyString_AsStringAndSize(_pystr, &in_bytes, &in_len) < 0 )
return _in;
char quote = '\'';
if ( memchr(in_bytes, '\'', in_len) != NULL
&& memchr(in_bytes, '"', in_len) == NULL )
{
quote = '"';
}
struct ida_local helper_t
{
static void put_escaped(qstring *out, char c)
{
out->append('\\');
out->append(c);
}
};
qstring buf;
buf.reserve(in_len + 10); // a few more bytes, let's assume a bit of escaping...
buf.append(quote);
for ( Py_ssize_t i = 0; i < in_len; ++i )
{
char c = in_bytes[i];
if ( c == quote || c == '\\' )
helper_t::put_escaped(&buf, c);
else if ( c == '\t' )
helper_t::put_escaped(&buf, 't');
else if ( c == '\n' )
helper_t::put_escaped(&buf, 'n');
else if ( c == '\r' )
helper_t::put_escaped(&buf, 'r');
else if ( uchar(c) < ' ' )
buf.cat_sprnt("\\x%02x", c);
else
buf.append(c);
}
buf.append(quote);
return PyString_FromStringAndSize(buf.c_str(), buf.length());
}
/*
#<pydoc>
def RunPythonStatement(stmt):
@@ -217,29 +315,6 @@ def RunPythonStatement(stmt):
#</pydoc>
*/
//------------------------------------------------------------------------
/*
#<pydoc>
def notify_when(when, callback):
"""
Register a callback that will be called when an event happens.
@param when: one of NW_XXXX constants
@param callback: This callback prototype varies depending on the 'when' parameter:
The general callback format:
def notify_when_callback(nw_code)
In the case of NW_OPENIDB:
def notify_when_callback(nw_code, is_old_database)
@return: Boolean
"""
pass
#</pydoc>
*/
static bool notify_when(int when, PyObject *py_callable)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCallable_Check(py_callable) && add_notify_when(when, py_callable);
}
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);
+84
View File
@@ -604,6 +604,7 @@ def _listify_types(*classes):
cls.at = cls.__getitem__ # '__getitem__' has bounds checkings
cls.__len__ = cls.size
cls.__iter__ = _bounded_getitem_iterator
cls.append = cls.push_back
# The general callback format of notify_when() is:
# def notify_when_callback(nw_code)
@@ -621,6 +622,26 @@ NW_REMOVE = 0x0010
"""Use this flag with other flags to uninstall a notifywhen callback"""
_notify_when_dispatcher = None
def notify_when(when, callback):
"""
Register a callback that will be called when an event happens.
@param when: one of NW_XXXX constants
@param callback: This callback prototype varies depending on the 'when' parameter:
The general callback format:
def notify_when_callback(nw_code)
In the case of NW_OPENIDB:
def notify_when_callback(nw_code, is_old_database)
@return: Boolean
"""
global _notify_when_dispatcher
import ida_idp
if _notify_when_dispatcher is None:
_notify_when_dispatcher = ida_idp._notify_when_dispatcher_t()
return _notify_when_dispatcher.notify_when(when, callback)
# Since version 5.5, PyQt5 doesn't simply print the PyQt exceptions by default
# anymore: https://github.com/baoboa/pyqt5/commit/1e1d8a3ba677ef3e47b916b8a5b9c281d0f8e4b5#diff-848704a82f6a6e3a13112145ce32ac69L63
# The default behavior now is that qFatal() is called, causing the application
@@ -634,6 +655,69 @@ def __install_excepthook():
__install_excepthook()
# ------------------------------------------------------------
class IDAPython_displayhook:
def __init__(self):
self.orig_displayhook = sys.displayhook
def format_seq(self, num_printer, storage, item, opn, cls):
storage.append(opn)
for idx, el in enumerate(item):
if idx > 0:
storage.append(', ')
self.format_item(num_printer, storage, el)
storage.append(cls)
def format_item(self, num_printer, storage, item):
if item is None or isinstance(item, bool):
storage.append(repr(item))
elif isinstance(item, basestring):
storage.append(_ida_idaapi.format_basestring(item))
elif isinstance(item, (int, long)):
storage.append(num_printer(item))
elif isinstance(item, list):
self.format_seq(num_printer, storage, item, '[', ']')
elif isinstance(item, tuple):
self.format_seq(num_printer, storage, item, '(', ')')
elif isinstance(item, set):
self.format_seq(num_printer, storage, item, 'set([', '])')
elif isinstance(item, (dict,)):
storage.append('{')
for idx, pair in enumerate(item.iteritems()):
if idx > 0:
storage.append(', ')
self.format_item(num_printer, storage, pair[0])
storage.append(": ")
self.format_item(num_printer, storage, pair[1])
storage.append('}')
else:
storage.append(str(item))
def displayhook(self, item):
if item is None or type(item) is bool:
self.orig_displayhook(item)
return
try:
storage = []
import ida_idp
num_printer = hex
dn = ida_idp.ph_get_flag() & ida_idp.PR_DEFNUM
if dn == ida_idp.PRN_OCT:
num_printer = oct
elif dn == ida_idp.PRN_DEC:
num_printer = str
elif dn == ida_idp.PRN_BIN:
num_printer = bin
self.format_item(num_printer, storage, item)
sys.stdout.write("%s\n" % "".join(storage))
except:
import traceback
traceback.print_exc()
self.orig_displayhook(item)
_IDAPython_displayhook = IDAPython_displayhook()
sys.displayhook = _IDAPython_displayhook.displayhook
# ----------------------------------- helpers for bw-compat w/ 6.95 API
class __BC695:
def __init__(self):
+68 -38
View File
@@ -11,6 +11,7 @@ import _ida_name
import _ida_bytes
import _ida_ida
import ida_idaapi
import ida_typeinf
dbg_can_query = _ida_dbg.dbg_can_query
@@ -79,14 +80,28 @@ class Appcall_callable__(object):
i = byref(5)
appcall.funcname(arg1, i, "hello", o)
"""
def __init__(self, ea, tp = None, fld = None):
def __init__(self, ea, tinfo_or_typestr = None, fields = None):
"""Initializes an appcall with a given function ea"""
self.__ea = ea
self.__type = tp
self.__fields = fld
self.__ea = ea
self.__tif = None
self.__type = None
self.__fields = None
self.__options = None # Appcall options
self.__timeout = None # Appcall timeout
if tinfo_or_typestr:
if type(tinfo_or_typestr) == types.StringType:
# a type string? assume (typestr, fields), try to deserialize
tif = ida_typeinf.tinfo_t()
if not tif.deserialize(None, tinfo_or_typestr, fields):
raise ValueError, "Could not deserialize type string"
else:
if not isinstance(tinfo_or_typestr, ida_typeinf.tinfo_t):
raise ValueError, "Invalid argument 'tinfo_or_typestr'"
tif = tinfo_or_typestr
self.__tif = tif
(self.__type, self.__fields, _) = tif.serialize()
def __get_timeout(self):
return self.__timeout
@@ -125,25 +140,16 @@ class Appcall_callable__(object):
Appcall__.set_appcall_options(self.options)
# Do the Appcall (use the wrapped version)
e_obj = None
try:
r = _ida_idd.appcall(
self.ea,
_ida_dbg.get_current_thread(),
self.type,
self.fields,
arg_list)
except Exception as e:
e_obj = e
# Restore appcall options
Appcall__.set_appcall_options(old_opt)
# Return or re-raise exception
if e_obj:
raise Exception(e_obj)
return r
return _ida_idd.appcall(
self.ea,
_ida_dbg.get_current_thread(),
self.type,
self.fields,
arg_list)
finally:
# Restore appcall options
Appcall__.set_appcall_options(old_opt)
def __get_ea(self):
return self.__ea
@@ -154,6 +160,12 @@ class Appcall_callable__(object):
ea = property(__get_ea, __set_ea)
"""Returns or sets the EA associated with this object"""
def __get_tif(self):
return self.__tif
tif = property(__get_tif)
"""Returns the tinfo_t object"""
def __get_size(self):
if self.__type == None:
return -1
@@ -291,11 +303,34 @@ class Appcall__(object):
return ea
@staticmethod
def proto(name_or_ea, prototype, flags = None):
def __typedecl_or_tinfo(typedecl_or_tinfo, flags = None):
"""
Function that accepts a tinfo_t object or type declaration as a string
If a type declaration is passed then ida_typeinf.parse_decl() is applied to prepare tinfo_t object
@return:
- Returns the tinfo_t object
- Raises an exception if the declaration cannot be parsed
"""
# a string? try to parse it
if type(typedecl_or_tinfo) == types.StringType:
if flags is None:
flags = ida_typeinf.PT_SIL|ida_typeinf.PT_NDC|ida_typeinf.PT_TYP
tif = ida_typeinf.tinfo_t()
if ida_typeinf.parse_decl(tif, None, typedecl_or_tinfo, flags) == None:
raise ValueError, "Could not parse type: " + typedecl_or_tinfo
else:
if not isinstance(typedecl_or_tinfo, ida_typeinf.tinfo_t):
raise ValueError, "Invalid argument 'typedecl_or_tinfo'"
tif = typedecl_or_tinfo
return tif
@staticmethod
def proto(name_or_ea, proto_or_tinfo, flags = None):
"""
Allows you to instantiate an appcall (callable object) with the desired prototype
@param name_or_ea: The name of the function (will be resolved with LocByName())
@param prototype:
@param proto_or_tinfo: function prototype as a string or type of the function as tinfo_t object
@return:
- On failure it raises an exception if the prototype could not be parsed
or the address is not resolvable
@@ -304,16 +339,12 @@ class Appcall__(object):
# resolve and raise exception on error
ea = Appcall__.__name_or_ea(name_or_ea)
# parse the type
if flags is None:
flags = 1 | 2 | 4 # PT_SIL | PT_NDC | PT_TYP
result = _ida_typeinf.idc_parse_decl(None, prototype, flags)
if result is None:
raise ValueError("Could not parse type: " + prototype)
# parse the type if it is given as (prototype, flags)
tif = Appcall__.__typedecl_or_tinfo(proto_or_tinfo, flags)
# Return the callable method with type info
return Appcall_callable__(ea, result[1], result[2])
return Appcall_callable__(ea, tif)
def __getattr__(self, name_or_ea):
"""Allows you to call functions as if they were member functions (by returning a callable object)"""
@@ -390,19 +421,18 @@ class Appcall__(object):
return Appcall_array__(type_name)
@staticmethod
def typedobj(typestr, ea=None):
def typedobj(typedecl_or_tinfo, ea=None):
"""
Parses a type string and returns an appcall object.
Returns an appcall object for a type (can be given as tinfo_t object or
as a string declaration)
One can then use retrieve() member method
@param ea: Optional parameter that later can be used to retrieve the type
@return: Appcall object or raises ValueError exception
"""
# parse the type
result = _ida_typeinf.idc_parse_decl(None, typestr, 1 | 2 | 4) # PT_SIL | PT_NDC | PT_TYP
if result is None:
raise ValueError("Could not parse type: " + typestr)
# parse the type if it is given as string
tif = Appcall__.__typedecl_or_tinfo(typedecl_or_tinfo)
# Return the callable method with type info
return Appcall_callable__(ea, result[1], result[2])
return Appcall_callable__(ea, tif)
@staticmethod
def set_appcall_options(opt):
+98 -43
View File
@@ -324,7 +324,6 @@ 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.regs_num);
for ( Py_ssize_t i=0; i < ph.regs_num; i++ )
@@ -597,9 +596,32 @@ struct proc_def;
struct libfunc_t;
ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va);
class IDP_Hooks
struct IDP_Hooks : public hooks_base_t
{
friend ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va);
// hookgenIDP:methodsinfo_decl
IDP_Hooks(uint32 _flags=0)
: hooks_base_t("ida_idp.IDP_Hooks", IDP_Callback, HT_IDP, _flags) {}
bool hook() { return hooks_base_t::hook(); }
bool unhook() { return hooks_base_t::unhook(); }
#ifdef TESTABLE_BUILD
qstring dump_state() { return hooks_base_t::dump_state(mappings, mappings_size); }
#endif
// hookgenIDP:methods
ssize_t dispatch(int code, va_list va)
{
ssize_t ret = 0;
switch ( code )
{
// hookgenIDP:notifications
}
return ret;
}
private:
static ssize_t bool_to_insn_t_size(bool in, const insn_t *insn) { return in ? insn->size : 0; }
static ssize_t bool_to_1or0(bool in) { return in ? 1 : 0; }
static ssize_t cm_t_to_ssize_t(cm_t cm) { return ssize_t(cm); }
@@ -615,7 +637,14 @@ class IDP_Hooks
{
return _handle_qstring_output(o, out) && !out->empty() ? 1 : 0;
}
static ssize_t handle_assemble_output(PyObject *o, uchar *bin, ea_t /*ea*/, ea_t /*cs*/, ea_t /*ip*/, bool /*use32*/, const char */*line*/)
static ssize_t handle_assemble_output(
PyObject *o,
uchar *bin,
ea_t /*ea*/,
ea_t /*cs*/,
ea_t /*ip*/,
bool /*use32*/,
const char * /*line*/)
{
ssize_t rc = 0;
if ( o != NULL && PyString_Check(o) )
@@ -649,7 +678,7 @@ class IDP_Hooks
newref_t py_bexec(PySequence_GetItem(o, 1));
newref_t py_fexec(PySequence_GetItem(o, 2));
uint64 nea = 0;
if ( PyW_GetNumber(py_ea.o, &nea, NULL)
if ( PyW_GetNumber(py_ea.o, &nea)
&& PyBool_Check(py_bexec.o)
&& PyBool_Check(py_fexec.o) )
{
@@ -683,9 +712,9 @@ class IDP_Hooks
PyObject *o,
int32 *out_res,
qstring *out,
const char *name,
uint32 disable_mask,
demreq_type_t demreq)
const char * /*name*/,
uint32 /*disable_mask*/,
demreq_type_t /*demreq*/)
{
ssize_t rc = 0;
if ( PySequence_Check(o) && PySequence_Size(o) == 3 )
@@ -714,8 +743,8 @@ class IDP_Hooks
static ssize_t handle_find_value_output(
PyObject *o,
uval_t *out,
const insn_t *pinsn,
int reg)
const insn_t * /*pinsn*/,
int /*reg*/)
{
uint64 num;
ssize_t rc = PyW_GetNumber(o, &num);
@@ -723,50 +752,76 @@ class IDP_Hooks
*out = num;
return rc;
}
public:
virtual ~IDP_Hooks()
static ssize_t handle_get_autocmt_output(
PyObject *o,
qstring *buf,
const insn_t * /*pinsn*/)
{
unhook();
ssize_t rc = 0;
if ( PyString_Check(o) )
{
char *s;
Py_ssize_t len = 0;
if ( PyString_AsStringAndSize(o, &s, &len) != -1 )
{
buf->qclear();
buf->append(s, len);
rc = 1;
}
}
return rc;
}
bool hook()
static ssize_t handle_get_operand_string_output(
PyObject *o,
qstring *buf,
const insn_t * /*pinsn*/,
int /*opnum*/)
{
return idapython_hook_to_notification_point(HT_IDP, IDP_Callback, this);
ssize_t rc = 0;
if ( PyString_Check(o) )
{
char *s;
Py_ssize_t len = 0;
if ( PyString_AsStringAndSize(o, &s, &len) != -1 )
{
buf->qclear();
buf->append(s, len);
rc = 1;
}
}
return rc;
}
bool unhook()
{
return idapython_unhook_from_notification_point(HT_IDP, IDP_Callback, this);
}
// hookgenIDP:methods
};
//-------------------------------------------------------------------------
static PyObject *_wrap_addr_in_pycobject(void *addr);
PyObject *get_idp_notifier_addr(PyObject *)
{
return _wrap_addr_in_pycobject((void *) IDP_Callback);
}
//-------------------------------------------------------------------------
PyObject *get_idp_notifier_ud_addr(IDP_Hooks *hooks)
{
return _wrap_addr_in_pycobject(hooks);
}
//</inline(py_idp)>
//-------------------------------------------------------------------------
//<code(py_idp)>
// hookgenIDP:methodsinfo_def
//-------------------------------------------------------------------------
ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va)
static PyObject *_wrap_addr_in_pycobject(void *addr)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
IDP_Hooks *proxy = (IDP_Hooks *)ud;
ssize_t ret = 0;
try
{
switch ( notification_code )
{
// hookgenIDP:notifications
}
}
catch (Swig::DirectorException &e)
{
msg("Exception in IDP Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
return PyCObject_FromVoidPtr(addr, NULL);
}
//-------------------------------------------------------------------------
ssize_t idaapi IDP_Callback(void *ud, int code, va_list va)
{
// hookgenIDP:safecall=IDP_Hooks
}
//-------------------------------------------------------------------------
+361 -3
View File
@@ -121,11 +121,24 @@ IDPOPT_BADTYPE = 2 # illegal type of value
IDPOPT_BADVALUE = 3 # illegal value (bad range, for example)
# ----------------------------------------------------------------------
import ida_pro
import ida_funcs
import ida_segment
import ida_ua
class processor_t(ida_idaapi.pyidc_opaque_object_t):
"""Base class for all processor module scripts"""
class processor_t(IDP_Hooks):
__idc_cvt_id__ = ida_idaapi.PY_ICID_OPAQUE
"""
Base class for all processor module scripts
A processor_t instance is both an ida_idp.IDP_Hooks, and
an ida_idp.IDB_Hooks at the same time: any method of
those two classes can be overridden in your processor_t
subclass.
"""
def __init__(self):
pass
IDP_Hooks.__init__(self, ida_idaapi.HBF_CALL_WITH_NEW_EXEC)
self.idb_hooks = _processor_t_Trampoline_IDB_Hooks(self)
def get_idpdesc(self):
"""
@@ -143,6 +156,351 @@ class processor_t(ida_idaapi.pyidc_opaque_object_t):
"""This function returns insn.auxpref value"""
return insn.auxpref
def _get_idp_notifier_addr(self):
return _ida_idp.get_idp_notifier_addr(self)
def _get_idp_notifier_ud_addr(self):
return _ida_idp.get_idp_notifier_ud_addr(self)
def _get_idb_notifier_addr(self):
return _ida_idp.get_idb_notifier_addr(self)
def _get_idb_notifier_ud_addr(self):
return _ida_idp.get_idb_notifier_ud_addr(self.idb_hooks)
def _make_forced_value_wrapper(self, val, meth=None):
def f(*args):
if meth:
meth(*args)
return val
return f
def _make_int_returning_wrapper(self, meth, intval=0):
def f(*args):
val = meth(*args)
if val is None:
val = intval
return val
return f
def _get_notify(self, what, unimp_val=0, imp_forced_val=None, add_prefix=True, mandatory_impl=None):
"""
This helper is used to implement backward-compatibility
of pre IDA 7.3 processor_t interfaces.
"""
if add_prefix:
what = "notify_%s" % what
meth = getattr(self, what, None)
if meth is None:
if mandatory_impl:
raise Exception("processor_t.%s() must be implemented" % mandatory_impl)
meth = self._make_forced_value_wrapper(unimp_val)
else:
if imp_forced_val is not None:
meth = self._make_forced_value_wrapper(imp_forced_val, meth)
else:
meth = self._make_int_returning_wrapper(meth)
return meth
# The default implementations below are what guarantees that
# pre IDA 7.3 processor_t subclasses, will continue working
def ev_newprc(self, *args):
return self._get_notify("newprc")(*args)
def ev_newfile(self, *args):
return self._get_notify("newfile")(*args)
def ev_oldfile(self, *args):
return self._get_notify("oldfile")(*args)
def ev_newbinary(self, *args):
return self._get_notify("newbinary")(*args)
def ev_endbinary(self, *args):
return self._get_notify("endbinary")(*args)
def ev_set_idp_options(self, keyword, value_type, value):
res = self._get_notify("set_idp_options", unimp_val=None)(keyword, value_type, value)
if res is None:
return 0
return 1 if res == IDPOPT_OK else -1
def ev_set_proc_options(self, *args):
return self._get_notify("set_proc_options")(*args)
def ev_ana_insn(self, *args):
rc = self._get_notify("ana", mandatory_impl="ev_ana_insn")(*args)
return rc > 0
def ev_emu_insn(self, *args):
rc = self._get_notify("emu", mandatory_impl="ev_emu_insn")(*args)
return rc > 0
def ev_out_header(self, *args):
return self._get_notify("out_header", imp_forced_val=1)(*args)
def ev_out_footer(self, *args):
return self._get_notify("out_footer", imp_forced_val=1)(*args)
def ev_out_segstart(self, ctx, s):
return self._get_notify("out_segstart", imp_forced_val=1)(ctx, s.start_ea)
def ev_out_segend(self, ctx, s):
return self._get_notify("out_segend", imp_forced_val=1)(ctx, s.end_ea)
def ev_out_assumes(self, *args):
return self._get_notify("out_assumes", imp_forced_val=1)(*args)
def ev_out_insn(self, *args):
return self._get_notify("out_insn", mandatory_impl="ev_out_insn", imp_forced_val=True)(*args)
def ev_out_mnem(self, *args):
return self._get_notify("out_mnem", add_prefix=False, imp_forced_val=1)(*args)
def ev_out_operand(self, *args):
rc = self._get_notify("out_operand", mandatory_impl="ev_out_operand", imp_forced_val=1)(*args)
return rc > 0
def ev_out_data(self, *args):
return self._get_notify("out_data", imp_forced_val=1)(*args)
def ev_out_label(self, *args):
return self._get_notify("out_label")(*args)
def ev_out_special_item(self, *args):
return self._get_notify("out_special_item")(*args)
def ev_gen_regvar_def(self, ctx, v):
return self._get_notify("gen_regvar_def")(ctx, v.canon, v.user, v.cmt)
def ev_gen_src_file_lnnum(self, *args):
return self._get_notify("gen_src_file_lnnum")(*args)
def ev_creating_segm(self, s):
sname = ida_segment.get_visible_segm_name(s)
sclass = ida_segment.get_segm_class(s)
return self._get_notify("creating_segm")(s.start_ea, sname, sclass)
def ev_moving_segm(self, s, to_ea, flags):
sname = ida_segment.get_visible_segm_name(s)
sclass = ida_segment.get_segm_class(s)
return self._get_notify("moving_segm")(s.start_ea, sname, sclass, to_ea, flags)
def ev_coagulate(self, *args):
return self._get_notify("coagulate")(*args)
def ev_undefine(self, *args):
return self._get_notify("undefine")(*args)
def ev_treat_hindering_item(self, *args):
return self._get_notify("treat_hindering_item")(*args)
def ev_rename(self, *args):
return self._get_notify("rename")(*args)
def ev_is_far_jump(self, *args):
rc = self._get_notify("is_far_jump", unimp_val=False)(*args)
return 1 if rc else -1
def ev_is_sane_insn(self, *args):
return self._get_notify("is_sane_insn")(*args)
def ev_is_call_insn(self, *args):
return self._get_notify("is_call_insn")(*args)
def ev_is_ret_insn(self, *args):
return self._get_notify("is_ret_insn")(*args)
def ev_may_be_func(self, *args):
return self._get_notify("may_be_func")(*args)
def ev_is_basic_block_end(self, *args):
return self._get_notify("is_basic_block_end")(*args)
def ev_is_indirect_jump(self, *args):
return self._get_notify("is_indirect_jump")(*args)
def ev_is_insn_table_jump(self, *args):
return self._get_notify("is_insn_table_jump")(*args)
def ev_is_switch(self, *args):
rc = self._get_notify("is_switch")(*args)
return 1 if rc else 0
def ev_create_switch_xrefs(self, *args):
return self._get_notify("create_switch_xrefs", imp_forced_val=1)(*args)
def ev_is_align_insn(self, *args):
return self._get_notify("is_align_insn")(*args)
def ev_is_alloca_probe(self, *args):
return self._get_notify("is_alloca_probe")(*args)
def ev_is_sp_based(self, mode, insn, op):
rc = self._get_notify("is_sp_based", unimp_val=None)(insn, op)
if type(rc) == int:
ida_pro.int_pointer.frompointer(mode).assign(rc)
return 1
return 0
def ev_can_have_type(self, *args):
rc = self._get_notify("can_have_type")(*args)
if rc is True:
return 1
elif rc is False:
return -1
else:
return 0
def ev_cmp_operands(self, *args):
rc = self._get_notify("cmp_operands")(*args)
if rc is True:
return 1
elif rc is False:
return -1
else:
return 0
def ev_get_operand_string(self, buf, insn, opnum):
rc = self._get_notify("get_operand_string")(insn, opnum)
if rc:
return 1
return 0
def ev_str2reg(self, *args):
rc = self._get_notify("notify_str2reg", unimp_val=-1)(*args)
return 0 if rc < 0 else rc + 1
def ev_get_autocmt(self, *args):
return self._get_notify("get_autocmt")(*args)
def ev_func_bounds(self, _possible_return_code, pfn, max_func_end_ea):
possible_return_code = ida_pro.int_pointer.frompointer(_possible_return_code)
rc = self._get_notify("func_bounds", unimp_val=None)(
possible_return_code.value(),
pfn.start_ea,
max_func_end_ea)
if type(rc) == int:
possible_return_code.assign(rc)
return 0
def ev_verify_sp(self, pfn):
return self._get_notify("verify_sp")(pfn.start_ea)
def ev_verify_noreturn(self, pfn):
return self._get_notify("verify_noreturn")(pfn.start_ea)
def ev_create_func_frame(self, pfn):
rc = self._get_notify("create_func_frame", imp_forced_val=1)(pfn.start_ea)
if rc is True:
return 1
elif rc is False:
return -1
else:
return rc
def ev_get_frame_retsize(self, frsize, pfn):
rc = self._get_notify("get_frame_retsize", unimp_val=None)(pfn.start_ea)
if type(rc) == int:
ida_pro.int_pointer.frompointer(frsize).assign(rc)
return 1
return 0
def ev_coagulate_dref(self, from_ea, to_ea, may_define, _code_ea):
code_ea = ida_pro.ea_pointer.frompointer(_code_ea)
rc = self._get_notify("coagulate_dref")(from_ea, to_ea, may_define, code_ea.value())
if rc == -1:
return -1
if rc != 0:
code_ea.assign(rc)
return 0
def ev_may_show_sreg(self, *args):
return self._get_notify("may_show_sreg")(*args)
def ev_auto_queue_empty(self, *args):
return self._get_notify("auto_queue_empty")(*args)
def ev_validate_flirt_func(self, *args):
return self._get_notify("validate_flirt_func")(*args)
def ev_assemble(self, *args):
return self._get_notify("assemble")(*args)
def ev_gen_map_file(self, nlines, fp):
import ida_fpro
qfile = ida_fpro.qfile_t_from_fp(fp)
rc = self._get_notify("gen_map_file")(qfile)
if rc > 0:
ida_pro.int_pointer.frompointer(nlines).assign(rc)
return 1
else:
return 0
def ev_calc_step_over(self, target, ip):
rc = self._get_notify("calc_step_over", unimp_val=None)(ip)
if rc is not None and rc != ida_idaapi.BADADDR:
ida_pro.ea_pointer.frompointer(target).assign(rc)
return 1
return 0
# IDB hooks handling
def closebase(self, *args):
self._get_notify("closebase")(*args)
def savebase(self, *args):
self._get_notify("savebase")(*args)
def auto_empty(self, *args):
self._get_notify("auto_empty")(*args)
def auto_empty_finally(self, *args):
self._get_notify("auto_empty_finally")(*args)
def determined_main(self, *args):
self._get_notify("determined_main")(*args)
def idasgn_loaded(self, *args):
self._get_notify("load_idasgn")(*args)
def kernel_config_loaded(self, *args):
self._get_notify("kernel_config_loaded")(*args)
def compiler_changed(self, *args):
self._get_notify("set_compiler")(*args)
def segm_moved(self, from_ea, to_ea, size, changed_netmap):
s = ida_segment.getseg(to_ea)
sname = ida_segment.get_visible_segm_name(s)
sclass = ida_segment.get_segm_class(s)
self._get_notify("move_segm")(from_ea, to_ea, sname, sclass, changed_netmap)
def func_added(self, pfn):
self._get_notify("add_func")(pfn.start_ea)
def set_func_start(self, *args):
self._get_notify("set_func_start")(*args)
def set_func_end(self, *args):
self._get_notify("set_func_end")(*args)
def deleting_func(self, pfn):
self._get_notify("del_func")(pfn.start_ea)
def sgr_changed(self, *args):
self._get_notify("setsgr")(*args)
def make_code(self, *args):
self._get_notify("make_code")(*args)
def make_data(self, *args):
self._get_notify("make_data")(*args)
def renamed(self, *args):
self._get_notify("renamed")(*args)
# ----------------------------------------------------------------------
class __ph(object):
+37 -31
View File
@@ -5,47 +5,53 @@
// IDB hooks
//---------------------------------------------------------------------------
ssize_t idaapi IDB_Callback(void *ud, int notification_code, va_list va);
class IDB_Hooks
struct IDB_Hooks : public hooks_base_t
{
public:
virtual ~IDB_Hooks() { unhook(); }
// hookgenIDB:methodsinfo_decl
bool hook()
{
return idapython_hook_to_notification_point(HT_IDB, IDB_Callback, this);
}
bool unhook()
{
return idapython_unhook_from_notification_point(HT_IDB, IDB_Callback, this);
}
IDB_Hooks(uint32 _flags=0)
: hooks_base_t("ida_idp.IDB_Hooks", IDB_Callback, HT_IDB, _flags) {}
bool hook() { return hooks_base_t::hook(); }
bool unhook() { return hooks_base_t::unhook(); }
#ifdef TESTABLE_BUILD
qstring dump_state() { return hooks_base_t::dump_state(mappings, mappings_size); }
#endif
// hookgenIDB:methods
ssize_t dispatch(int code, va_list va)
{
switch ( code )
{
// hookgenIDB:notifications
}
return 0;
}
};
//-------------------------------------------------------------------------
PyObject *get_idb_notifier_addr(PyObject *)
{
return _wrap_addr_in_pycobject((void *) IDB_Callback);
}
//-------------------------------------------------------------------------
PyObject *get_idb_notifier_ud_addr(IDB_Hooks *hooks)
{
return _wrap_addr_in_pycobject(hooks);
}
//</inline(py_idp_idbhooks)>
//<code(py_idp_idbhooks)>
// hookgenIDB:methodsinfo_def
//---------------------------------------------------------------------------
ssize_t idaapi IDB_Callback(void *ud, int notification_code, va_list va)
ssize_t idaapi IDB_Callback(void *ud, int 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;
ssize_t ret = 0;
try
{
switch ( notification_code )
{
// hookgenIDB:notifications
}
}
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;
// hookgenIDB:safecall=IDB_Hooks
}
//</code(py_idp_idbhooks)>
+27
View File
@@ -0,0 +1,27 @@
#<pycode(py_idp_idbhooks)>
class _processor_t_Trampoline_IDB_Hooks(IDB_Hooks):
def __init__(self, proc):
IDB_Hooks.__init__(self, ida_idaapi.HBF_CALL_WITH_NEW_EXEC | ida_idaapi.HBF_VOLATILE_METHOD_SET)
import weakref
self.proc = weakref.ref(proc)
for key in dir(self):
if not key.startswith("_") and not key in ["proc"]:
thing = getattr(self, key)
if hasattr(thing, "__call__"):
setattr(self, key, self.__make_parent_caller(key))
def __dummy(self, *args):
return 0
def __make_parent_caller(self, key):
# we can't get the method at this point, as it'll be bound
# to the processor_t instance, which means it'll increase
# the reference counting
def call_parent(*args):
return getattr(self.proc(), key, self.__dummy)(*args)
return call_parent
#</pycode(py_idp_idbhooks)>
+63
View File
@@ -0,0 +1,63 @@
#<pycode(py_idp_notify_when)>
import weakref
class _notify_when_dispatcher_t:
class _callback_t:
def __init__(self, fun):
self.fun = fun
self.slots = 0
class _IDP_Hooks(IDP_Hooks):
def __init__(self, dispatcher):
IDP_Hooks.__init__(self)
self.dispatcher = weakref.ref(dispatcher)
def ev_newfile(self, name):
return self.dispatcher().dispatch(ida_idaapi.NW_OPENIDB, 0)
def ev_oldfile(self, name):
return self.dispatcher().dispatch(ida_idaapi.NW_OPENIDB, 1)
class _IDB_Hooks(IDB_Hooks):
def __init__(self, dispatcher):
IDB_Hooks.__init__(self)
self.dispatcher = weakref.ref(dispatcher)
def closebase(self):
return self.dispatcher().dispatch(ida_idaapi.NW_CLOSEIDB)
def __init__(self):
self.idp_hooks = self._IDP_Hooks(self)
self.idp_hooks.hook()
self.idb_hooks = self._IDB_Hooks(self)
self.idb_hooks.hook()
self.callbacks = []
def _find(self, fun):
for idx, cb in enumerate(self.callbacks):
if cb.fun == fun:
return idx, cb
return None, None
def dispatch(self, slot, *args):
for cb in self.callbacks[:]: # make a copy, since dispatch() could cause some callbacks to disappear
if (cb.slots & slot) != 0:
cb.fun(slot, *args)
return 0
def notify_when(self, when, fun):
_, cb = self._find(fun)
if cb is None:
cb = self._callback_t(fun)
self.callbacks.append(cb)
if (when & ida_idaapi.NW_REMOVE) != 0:
cb.slots &= ~(when & ~ida_idaapi.NW_REMOVE)
else:
cb.slots |= when
if cb.slots == 0:
idx, cb = self._find(cb.fun)
del self.callbacks[idx]
return True
#</pycode(py_idp_notify_when)>
+103 -46
View File
@@ -684,7 +684,7 @@ static bool py_execute_ui_requests(PyObject *py_list)
static int idaapi s_py_list_walk_cb(
const ref_t &py_item,
Py_ssize_t index,
Py_ssize_t /*index*/,
void *ud)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
@@ -812,6 +812,38 @@ public:
}
Py_RETURN_NONE;
}
static bool fill_jobj_from_dict(jobj_t *out, PyObject *dict)
{
if ( PyDict_Check(dict) )
{
newref_t json_module(PyImport_ImportModule("json"));
if ( json_module != NULL )
{
borref_t json_globals(PyModule_GetDict(json_module.o));
if ( json_globals != NULL )
{
borref_t json_dumps(PyDict_GetItemString(json_globals.o, "dumps"));
if ( json_dumps != NULL )
{
newref_t str(PyObject_CallFunction(json_dumps.o, "O", dict));
Py_ssize_t len;
char *s;
if ( PyString_AsStringAndSize(str.o, &s, &len) != -1 )
{
jvalue_t tmp;
if ( parse_json_string(&tmp, s) == eOk )
{
out->swap(tmp.obj());
return true;
}
}
}
}
}
}
return false;
}
};
//---------------------------------------------------------------------------
@@ -931,24 +963,32 @@ class UI_Hooks(object):
#</pydoc>
*/
class UI_Hooks
struct UI_Hooks : public hooks_base_t
{
public:
virtual ~UI_Hooks()
// hookgenUI:methodsinfo_decl
UI_Hooks(uint32 _flags=0)
: hooks_base_t("ida_kernwin.UI_Hooks", UI_Callback, HT_UI, _flags) {}
bool hook() { return hooks_base_t::hook(); }
bool unhook() { return hooks_base_t::unhook(); }
#ifdef TESTABLE_BUILD
qstring dump_state() { return hooks_base_t::dump_state(mappings, mappings_size); }
#endif
// hookgenUI:methods
ssize_t dispatch(int code, va_list va)
{
unhook();
}
bool hook()
{
return idapython_hook_to_notification_point(HT_UI, UI_Callback, this);
}
bool unhook()
{
return idapython_unhook_from_notification_point(HT_UI, UI_Callback, this);
ssize_t ret = 0;
switch ( code )
{
// hookgenUI:notifications
}
return ret;
}
private:
static ssize_t handle_get_ea_hint_output(PyObject *o, qstring *buf, ea_t)
{
ssize_t rc = 0;
@@ -1018,7 +1058,10 @@ public:
return ssize_t(widget);
}
// hookgenUI:methods
static ssize_t handle_widget_cfg_output(PyObject *o, const TWidget *, jobj_t *cfg)
{
return jobj_wrapper_t::fill_jobj_from_dict(cfg, o);
}
};
//-------------------------------------------------------------------------
@@ -1128,7 +1171,6 @@ void py_gen_disasm_text(disasm_text_t &text, ea_t ea1, ea_t ea2, bool truncate_l
}
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def set_nav_colorizer(callback):
@@ -1162,12 +1204,12 @@ def set_nav_colorizer(callback):
pass
#</pydoc>
*/
nav_colorizer_t *py_set_nav_colorizer(PyObject *new_py_colorizer)
PyObject *py_set_nav_colorizer(PyObject *new_py_colorizer)
{
static ref_t py_colorizer;
struct ida_local lambda_t
{
static uint32 idaapi call_py_colorizer(ea_t ea, asize_t nbytes)
static uint32 idaapi call_py_colorizer(ea_t ea, asize_t nbytes, void *)
{
PYW_GIL_GET;
@@ -1198,8 +1240,17 @@ nav_colorizer_t *py_set_nav_colorizer(PyObject *new_py_colorizer)
// (e.g., updating the legend.)
bool first_install = py_colorizer == NULL;
py_colorizer = borref_t(new_py_colorizer);
nav_colorizer_t *prev = set_nav_colorizer(lambda_t::call_py_colorizer);
return first_install ? prev : NULL;
nav_colorizer_t *was_fun = NULL;
void *was_ud = NULL;
set_nav_colorizer(&was_fun, &was_ud, lambda_t::call_py_colorizer, NULL);
if ( !first_install )
Py_RETURN_NONE;
PyObject *was_fun_ptr = PyCObject_FromVoidPtr((void *) was_fun, NULL);
PyObject *was_ud_ptr = PyCObject_FromVoidPtr(was_ud, NULL);
PyObject *dict = PyDict_New();
PyDict_SetItemString(dict, "fun", was_fun_ptr);
PyDict_SetItemString(dict, "ud", was_ud_ptr);
return dict;
}
//-------------------------------------------------------------------------
@@ -1209,19 +1260,26 @@ def call_nav_colorizer(colorizer, ea, nbytes):
"""
To be used with the IDA-provided colorizer, that is
returned as result of the first call to set_nav_colorizer().
This is a trivial trampoline, so that SWIG can generate a
wrapper that will do the types checking.
"""
pass
#</pydoc>
*/
uint32 py_call_nav_colorizer(
nav_colorizer_t *col,
PyObject *dict,
ea_t ea,
asize_t nbytes)
{
return col(ea, nbytes);
if ( !PyDict_Check(dict) )
return 0;
borref_t py_fun(PyDict_GetItemString(dict, "fun"));
borref_t py_ud(PyDict_GetItemString(dict, "ud"));
if ( py_fun == NULL || !PyCObject_Check(py_fun.o) || !PyCObject_Check(py_ud.o) )
return 0;
nav_colorizer_t *fun = (nav_colorizer_t *) PyCObject_AsVoidPtr(py_fun.o);
void *ud = PyCObject_AsVoidPtr(py_ud.o);
if ( fun == NULL )
return 0;
return fun(ea, nbytes, ud);
}
PyObject *py_msg_get_lines(int count=-1)
@@ -1273,32 +1331,31 @@ static TWidget *TWidget__from_ptrval__(size_t ptrval)
return (TWidget *) ptrval;
}
//-------------------------------------------------------------------------
static PyObject *py_add_spaces(const char *s, size_t len)
{
qstring qbuf(s);
const size_t slen = tag_strlen(qbuf.c_str());
const size_t delta = qbuf.length() - slen;
if ( len > slen )
qbuf.resize(len + delta);
// we use the actual 'size' because we know that
// 'add_spaces()' will add a terminating zero anyway
add_spaces(qbuf.begin(), qbuf.size(), len);
return PyString_FromString(qbuf.c_str());
}
//</inline(py_kernwin)>
//---------------------------------------------------------------------------
//<code(py_kernwin)>
// hookgenUI:methodsinfo_def
//---------------------------------------------------------------------------
ssize_t idaapi UI_Callback(void *ud, int notification_code, va_list va)
ssize_t idaapi UI_Callback(void *ud, int 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;
ssize_t ret = 0;
try
{
switch ( notification_code )
{
// hookgenUI:notifications
}
}
catch (Swig::DirectorException &e)
{
msg("Exception in UI Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
// hookgenUI:safecall=UI_Hooks
}
//------------------------------------------------------------------------
+2 -2
View File
@@ -157,9 +157,9 @@ asktext=ask_text
askyn_c=ask_yn
choose2_activate=choose_activate
choose2_close=choose_close
choose2_create=choose_create
#choose2_create=choose_create
choose2_find=choose_find
choose2_get_embedded=_choose_get_embedded_chobj_pointer
#choose2_get_embedded=_choose_get_embedded_chobj_pointer
choose2_get_embedded_selection=lambda *args: None
choose2_refresh=choose_refresh
clearBreak=clr_cancelled
+3 -9
View File
@@ -48,18 +48,14 @@ static bool textctrl_info_t_set_flags(PyObject *self, unsigned int flags)
}
//-------------------------------------------------------------------------
static unsigned int textctrl_info_t_get_flags(
PyObject *self,
unsigned int flags)
static unsigned int textctrl_info_t_get_flags(PyObject *self)
{
textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self);
return ti == NULL ? 0 : ti->flags;
}
//-------------------------------------------------------------------------
static bool textctrl_info_t_set_tabsize(
PyObject *self,
unsigned int tabsize)
static bool textctrl_info_t_set_tabsize(PyObject *self, unsigned int tabsize)
{
textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self);
if ( ti == NULL )
@@ -69,9 +65,7 @@ static bool textctrl_info_t_set_tabsize(
}
//-------------------------------------------------------------------------
static unsigned int textctrl_info_t_get_tabsize(
PyObject *self,
unsigned int tabsize)
static unsigned int textctrl_info_t_get_tabsize(PyObject *self)
{
textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self);
return ti == NULL ? 0 : ti->tabsize;
+13 -5
View File
@@ -680,8 +680,11 @@ class Form(object):
if chooser is None or not isinstance(chooser, Choose):
raise ValueError("Invalid chooser passed.")
# Create an embedded chooser structure from the Choose instance
if chooser.Embedded() != 0:
# Create an embedded chooser structure from the Choose instance,
# and retrieve the pointer to the chooser_base_t.
emb = chooser.Embedded(create_chobj=True)
# if chooser.Embedded() != 0:
if emb is None:
raise ValueError("Failed to create embedded chooser instance.")
# Construct input control
@@ -689,9 +692,8 @@ class Form(object):
self.selobj = ida_pro.sizevec_t()
# Get a pointer to the chooser_info_t and the selection vector
# (These two parameters are the needed arguments for the ask_form())
emb = _ida_kernwin._choose_get_embedded_chobj_pointer(chooser)
# Get a pointer to the selection vector
# emb = _ida_kernwin._choose_get_embedded_chobj_pointer(chooser)
sel = self.selobj.this.__long__()
# Get a pointer to a c_void_p constructed from an address
@@ -1045,6 +1047,7 @@ class Form(object):
return form, i1, i2, ctrlname
control_count = 0
last_input_field_index = 0
# First pass: assign input_field_index values to controls
p = 0
@@ -1061,11 +1064,16 @@ class Form(object):
if ctrl is None:
raise ValueError("No matching control '%s'" % ctrlname)
if isinstance(ctrl, Form.FormChangeCb) and control_count > 0:
raise SyntaxError("Control '%s' should be the first control in the form" % ctrlname)
# If this control is an input, assign its index
if ctrl.is_input_field():
ctrl.input_field_index = last_input_field_index
last_input_field_index += 1
control_count += 1
p = 0
while True:
File diff suppressed because it is too large Load Diff
+41 -35
View File
@@ -8,10 +8,10 @@ class Choose(object):
Please refer to kernwin.hpp for more information.
"""
CH_MODAL = 0x01
CH_MODAL = _ida_kernwin.CH_MODAL
"""Modal chooser"""
CH_MULTI = 0x04
CH_MULTI = _ida_kernwin.CH_MULTI
"""
Allow multi selection.
Refer the description of the OnInsertLine(), OnDeleteLine(),
@@ -19,65 +19,67 @@ class Choose(object):
see a difference between single and multi selection callbacks.
"""
CH_NOBTNS = 0x10
CH_NOBTNS = _ida_kernwin.CH_NOBTNS
CH_ATTRS = 0x20
CH_ATTRS = _ida_kernwin.CH_ATTRS
CH_NOIDB = 0x40
CH_NOIDB = _ida_kernwin.CH_NOIDB
"""use the chooser even without an open database, same as x0=-2"""
CH_FORCE_DEFAULT = 0x80
CH_FORCE_DEFAULT = _ida_kernwin.CH_FORCE_DEFAULT
"""
If a non-modal chooser was already open, change selection to the given
default one
"""
CH_CAN_INS = 0x000100
CH_CAN_INS = _ida_kernwin.CH_CAN_INS
"""allow to insert new items"""
CH_CAN_DEL = 0x000200
CH_CAN_DEL = _ida_kernwin.CH_CAN_DEL
"""allow to delete existing item(s)"""
CH_CAN_EDIT = 0x000400
CH_CAN_EDIT = _ida_kernwin.CH_CAN_EDIT
"""allow to edit existing item(s)"""
CH_CAN_REFRESH = 0x000800
CH_CAN_REFRESH = _ida_kernwin.CH_CAN_REFRESH
"""allow to refresh chooser"""
CH_QFLT = 0x1000
CH_QFLT = _ida_kernwin.CH_QFLT
"""open with quick filter enabled and focused"""
CH_QFTYP_SHIFT = 13
CH_QFTYP_DEFAULT = 0 << CH_QFTYP_SHIFT
CH_QFTYP_NORMAL = 1 << CH_QFTYP_SHIFT
CH_QFTYP_WHOLE_WORDS = 2 << CH_QFTYP_SHIFT
CH_QFTYP_REGEX = 3 << CH_QFTYP_SHIFT
CH_QFTYP_FUZZY = 4 << CH_QFTYP_SHIFT
CH_QFTYP_MASK = 0x7 << CH_QFTYP_SHIFT
CH_QFTYP_SHIFT = _ida_kernwin.CH_QFTYP_SHIFT
CH_QFTYP_DEFAULT = _ida_kernwin.CH_QFTYP_DEFAULT
CH_QFTYP_NORMAL = _ida_kernwin.CH_QFTYP_NORMAL
CH_QFTYP_WHOLE_WORDS = _ida_kernwin.CH_QFTYP_WHOLE_WORDS
CH_QFTYP_REGEX = _ida_kernwin.CH_QFTYP_REGEX
CH_QFTYP_FUZZY = _ida_kernwin.CH_QFTYP_FUZZY
CH_QFTYP_MASK = _ida_kernwin.CH_QFTYP_MASK
CH_NO_STATUS_BAR = 0x00010000
CH_NO_STATUS_BAR = _ida_kernwin.CH_NO_STATUS_BAR
"""don't show a status bar"""
CH_RESTORE = 0x00020000
CH_RESTORE = _ida_kernwin.CH_RESTORE
"""restore floating position if present (equivalent of WOPN_RESTORE) (GUI version only)"""
CH_BUILTIN_SHIFT = 19
CH_BUILTIN_MASK = 0x1F << CH_BUILTIN_SHIFT
CH_BUILTIN_SHIFT = _ida_kernwin.CH_BUILTIN_SHIFT
CH_BUILTIN_MASK = _ida_kernwin.CH_BUILTIN_MASK
# column flags (are specified in the widths array)
CHCOL_PLAIN = 0x00000000
CHCOL_PATH = 0x00010000
CHCOL_HEX = 0x00020000
CHCOL_DEC = 0x00030000
CHCOL_FORMAT = 0x00070000
CHCOL_PLAIN = _ida_kernwin.CHCOL_PLAIN
CHCOL_PATH = _ida_kernwin.CHCOL_PATH
CHCOL_HEX = _ida_kernwin.CHCOL_HEX
CHCOL_DEC = _ida_kernwin.CHCOL_DEC
CHCOL_EA = _ida_kernwin.CHCOL_EA
CHCOL_FNAME = _ida_kernwin.CHCOL_FNAME
CHCOL_FORMAT = _ida_kernwin.CHCOL_FORMAT
# special values of the chooser index
NO_SELECTION = -1
"""there is no selected item"""
EMPTY_CHOOSER = -4
EMPTY_CHOOSER = -2
"""the chooser is initialized"""
ALREADY_EXISTS = -5
ALREADY_EXISTS = -3
"""the non-modal chooser with the same data is already open"""
NO_ATTR = -6
NO_ATTR = -4
"""some mandatory attribute is missing"""
# return value of ins(), del(), edit(), enter(), refresh() callbacks
@@ -155,14 +157,17 @@ class Choose(object):
self.ui_hooks_trampoline = None # set on Show
def Embedded(self):
def Embedded(self, create_chobj=False):
"""
Creates an embedded chooser (as opposed to Show())
@return: Returns 0 on success or NO_ATTR
"""
if not self.embedded:
return Choose.NO_ATTR
return _ida_kernwin.choose_create(self)
if create_chobj:
return _ida_kernwin.choose_create_embedded_chobj(self)
else:
return _ida_kernwin.choose_choose(self)
def GetEmbSelection(self):
@@ -195,7 +200,7 @@ class Choose(object):
# Disable the timeout
old = _ida_idaapi.set_script_timeout(0)
n = _ida_kernwin.choose_create(self)
n = _ida_kernwin.choose_choose(self)
_ida_idaapi.set_script_timeout(old)
# Delete the modal chooser instance
@@ -204,7 +209,7 @@ class Choose(object):
return n
else:
self.flags &= ~Choose.CH_MODAL
return _ida_kernwin.choose_create(self)
return _ida_kernwin.choose_choose(self)
def Activate(self):
@@ -219,7 +224,8 @@ class Choose(object):
def Close(self):
"""Closes the chooser"""
_ida_kernwin.choose_close(self)
if not self.embedded:
_ida_kernwin.choose_close(self)
def GetWidget(self):
"""
-2
View File
@@ -121,7 +121,6 @@ private:
if ( ok )
{
Py_ssize_t sz = PyTuple_Size(result.o);
PyObject *item;
#define GET_TUPLE_ENTRY(col, PyThingy, AsThingy, out) \
do \
@@ -227,7 +226,6 @@ public:
// Create a new instance
py_cli = new py_cli_t();
PyObject *attr;
// Start populating the 'cli' member
py_cli->cli.size = sizeof(cli_t);
+203 -352
View File
@@ -2,41 +2,21 @@
#define __PYWRAPS_CUSTVIEWER__
//<code(py_kernwin_custview)>
//---------------------------------------------------------------------------
// Base class for all custviewer place_t providers
class custviewer_data_t
class cvdata_simpleline_t
{
public:
virtual void *get_ud() = 0;
virtual place_t *get_min() = 0;
virtual place_t *get_max() = 0;
};
//---------------------------------------------------------------------------
class cvdata_simpleline_t: public custviewer_data_t
{
private:
strvec_t lines;
simpleline_place_t pl_min, pl_max;
public:
void *get_ud() { return &lines; }
place_t *get_min() { return &pl_min; }
place_t *get_max() { return &pl_max; }
strvec_t &get_lines() { return lines; }
void *get_ud()
void clear()
{
return &lines;
}
place_t *get_min()
{
return &pl_min;
}
place_t *get_max()
{
return &pl_max;
}
strvec_t &get_lines()
{
return lines;
lines.clear();
set_minmax();
}
void set_minmax(size_t start=0, size_t end=size_t(-1))
@@ -97,20 +77,11 @@ public:
return true;
}
const size_t to_lineno(place_t *pl) const
size_t to_lineno(place_t *pl) const
{
return ((simpleline_place_t *)pl)->n;
}
bool curline(place_t *pl, size_t *n)
{
if ( pl == NULL )
return false;
*n = to_lineno(pl);
return true;
}
simpleline_t *get_line(size_t nline)
{
return nline >= lines.size() ? NULL : &lines[nline];
@@ -121,7 +92,7 @@ public:
return pl == NULL ? NULL : get_line(((simpleline_place_t *)pl)->n);
}
const size_t count() const
size_t count() const
{
return lines.size();
}
@@ -137,15 +108,19 @@ public:
// FIXME: This should inherit py_view_base.hpp's py_customidamemo_t,
// just like py_graph.hpp's py_graph_t does.
// There should be a way to "merge" the two mechanisms; they are similar.
class customviewer_t
class py_simplecustview_t
{
protected:
qstring _title;
TWidget *_cv;
custviewer_data_t *_data;
int _features;
qstring title;
TWidget *widget;
custom_viewer_handlers_t handlers;
cvdata_simpleline_t data;
PyObject *py_self;
PyObject *py_this;
PyObject *py_last_link;
int features;
enum
{
HAVE_HINT = 0x0001,
@@ -155,17 +130,6 @@ protected:
HAVE_CLICK = 0x0010,
HAVE_CLOSE = 0x0020
};
private:
struct cvw_popupctx_t
{
size_t menu_id;
customviewer_t *cv;
cvw_popupctx_t(): menu_id(0), cv(NULL) {}
cvw_popupctx_t(size_t mid, customviewer_t *v): menu_id(mid), cv(v) {}
};
typedef std::map<unsigned int, cvw_popupctx_t> cvw_popupmap_t;
static size_t _global_popup_id;
qstring _curline;
static bool idaapi s_cv_keydown(
TWidget * /*cv*/,
@@ -174,7 +138,7 @@ private:
void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
return _this->on_keydown(vk_key, shift);
}
@@ -182,7 +146,7 @@ private:
static bool idaapi s_cv_click(TWidget * /*cv*/, int shift, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
return _this->on_click(shift);
}
@@ -190,7 +154,7 @@ private:
static bool idaapi s_cv_dblclick(TWidget * /*cv*/, int shift, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
return _this->on_dblclick(shift);
}
@@ -198,7 +162,7 @@ private:
static void idaapi s_cv_curpos(TWidget * /*cv*/, void *ud)
{
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
_this->on_curpos_changed();
}
@@ -207,262 +171,41 @@ private:
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
customviewer_t *_this = (customviewer_t *)ud;
py_simplecustview_t *_this = (py_simplecustview_t *)ud;
switch ( code )
{
case ui_get_custom_viewer_hint:
{
if ( (_this->features & HAVE_HINT) == 0 )
return 0;
qstring &hint = *va_arg(va, qstring *);
TWidget *viewer = va_arg(va, TWidget *);
place_t *place = va_arg(va, place_t *);
int *important_lines = va_arg(va, int *);
if ( (_this->_features & HAVE_HINT) == 0
|| place == NULL
|| _this->_cv != viewer )
{
if ( _this->widget != viewer )
return 0;
}
place_t *place = va_arg(va, place_t *);
if ( place == NULL )
return 0;
int *important_lines = va_arg(va, int *);
return _this->on_hint(place, important_lines, hint) ? 1 : 0;
}
case ui_widget_invisible:
{
TWidget *widget = va_arg(va, TWidget *);
if ( _this->_cv != widget )
if ( _this->widget != widget )
break;
}
// fallthrough...
case ui_term:
idapython_unhook_from_notification_point(HT_UI, s_ui_cb, _this);
_this->on_close();
_this->on_post_close();
_this->init_vars();
break;
}
return 0;
}
void on_post_close()
{
init_vars();
}
public:
inline TWidget *get_widget() { return _cv; }
//
// All the overridable callbacks
//
// OnClick
virtual bool on_click(int /*shift*/) { return false; }
// OnDblClick
virtual bool on_dblclick(int /*shift*/) { return false; }
// OnCurorPositionChanged
virtual void on_curpos_changed() {}
// OnHostFormClose
virtual void on_close() {}
// OnKeyDown
virtual bool on_keydown(int /*vk_key*/, int /*shift*/) { return false; }
// OnHint
virtual bool on_hint(place_t * /*place*/, int * /*important_lines*/, qstring &/*hint*/) { return false; }
// OnPopupMenuClick
virtual bool on_popup_menu(size_t menu_id) { return false; }
void init_vars()
{
_data = NULL;
_features = 0;
_curline.clear();
_cv = NULL;
}
customviewer_t()
{
init_vars();
}
~customviewer_t()
{
}
//--------------------------------------------------------------------------
void close()
{
if ( _cv != NULL )
close_widget(_cv, WCLS_SAVE | WCLS_CLOSE_LATER);
}
//--------------------------------------------------------------------------
bool set_range(
const place_t *minplace = NULL,
const place_t *maxplace = NULL)
{
if ( _cv == NULL )
return false;
set_custom_viewer_range(
_cv,
minplace == NULL ? _data->get_min() : minplace,
maxplace == NULL ? _data->get_max() : maxplace);
return true;
}
place_t *get_place(
bool mouse = false,
int *x = 0,
int *y = 0)
{
return _cv == NULL ? NULL : get_custom_viewer_place(_cv, mouse, x, y);
}
//--------------------------------------------------------------------------
bool refresh()
{
if ( _cv == NULL )
return false;
refresh_custom_viewer(_cv);
return true;
}
//--------------------------------------------------------------------------
bool refresh_current()
{
return refresh();
}
//--------------------------------------------------------------------------
bool get_current_word(bool mouse, qstring &word)
{
// query the cursor position
int x, y;
if ( get_place(mouse, &x, &y) == NULL )
return false;
// query the line at the cursor
const char *line = get_current_line(mouse, true);
if ( line == NULL )
return false;
if ( x >= (int)strlen(line) )
return false;
// find the beginning of the word
const char *ptr = line + x;
while ( ptr > line && !qisspace(ptr[-1]) )
ptr--;
// find the end of the word
const char *begin = ptr;
ptr = line + x;
while ( !qisspace(*ptr) && *ptr != '\0' )
ptr++;
word.qclear();
word.append(begin, ptr-begin);
return true;
}
//--------------------------------------------------------------------------
const char *get_current_line(bool mouse, bool notags)
{
const char *r = get_custom_viewer_curline(_cv, mouse);
if ( r == NULL || !notags )
return r;
_curline = r;
tag_remove(&_curline);
return _curline.c_str();
}
//--------------------------------------------------------------------------
bool is_focused()
{
return get_current_viewer() == _cv;
}
//--------------------------------------------------------------------------
bool jumpto(place_t *place, int x, int y)
{
return ::jumpto(_cv, place, x, y);
}
bool create(const char *title, int features, custviewer_data_t *data)
{
// Already created? (in the instance)
if ( _cv != NULL )
return true;
// Already created? (in IDA windows list)
TWidget *found = find_widget(title);
if ( found != NULL )
return false;
_title = title;
_data = data;
_features = features;
//
// Prepare handlers
//
if ( (features & HAVE_KEYDOWN) != 0 )
handlers.keyboard = s_cv_keydown;
if ( (features & HAVE_CLICK) != 0 )
handlers.click = s_cv_click;
if ( (features & HAVE_DBLCLICK) != 0 )
handlers.dblclick = s_cv_dblclick;
if ( (features & HAVE_CURPOS) != 0 )
handlers.curpos = s_cv_curpos;
// Create the viewer
_cv = create_custom_viewer(
title,
_data->get_min(),
_data->get_max(),
_data->get_min(),
(const renderer_info_t *) NULL,
_data->get_ud(),
&handlers,
this);
// Hook to UI notifications (for TWidget close event)
idapython_hook_to_notification_point(HT_UI, s_ui_cb, this);
return true;
}
//--------------------------------------------------------------------------
bool show()
{
// Closed already?
if ( _cv == NULL )
return false;
display_widget(_cv, WOPN_TAB|WOPN_RESTORE);
return true;
}
};
size_t customviewer_t::_global_popup_id = 0;
//---------------------------------------------------------------------------
class py_simplecustview_t: public customviewer_t
{
private:
cvdata_simpleline_t data;
PyObject *py_self, *py_this, *py_last_link;
int features;
//-------------------------------------------------------------------------
static bool get_color(uint32 *out, ref_t obj)
{
@@ -511,7 +254,7 @@ private:
//
// Callbacks
//
virtual bool on_click(int shift)
bool on_click(int shift)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CLICK, "i", shift));
@@ -521,7 +264,7 @@ private:
//--------------------------------------------------------------------------
// OnDblClick
virtual bool on_dblclick(int shift)
bool on_dblclick(int shift)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_DBL_CLICK, "i", shift));
@@ -531,7 +274,7 @@ private:
//--------------------------------------------------------------------------
// OnCurorPositionChanged
virtual void on_curpos_changed()
void on_curpos_changed()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(PyObject_CallMethod(py_self, (char *)S_ON_CURSOR_POS_CHANGED, NULL));
@@ -539,8 +282,7 @@ private:
}
//--------------------------------------------------------------------------
// OnHostFormClose
virtual void on_close()
void on_close()
{
if ( py_self != NULL )
{
@@ -559,8 +301,7 @@ private:
}
//--------------------------------------------------------------------------
// OnKeyDown
virtual bool on_keydown(int vk_key, int shift)
bool on_keydown(int vk_key, int shift)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
@@ -576,8 +317,7 @@ private:
}
//--------------------------------------------------------------------------
// OnHint
virtual bool on_hint(place_t *place, int *important_lines, qstring &hint)
bool on_hint(place_t *place, int *important_lines, qstring &hint)
{
size_t ln = data.to_lineno(place);
PYW_GIL_CHECK_LOCKED_SCOPE();
@@ -600,8 +340,7 @@ private:
}
//--------------------------------------------------------------------------
// OnPopupMenuClick
virtual bool on_popup_menu(size_t menu_id)
bool on_popup_menu(size_t menu_id)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t py_result(
@@ -625,12 +364,147 @@ public:
py_simplecustview_t()
{
py_this = py_self = py_last_link = NULL;
init_vars();
}
~py_simplecustview_t()
~py_simplecustview_t() {}
TWidget *get_widget() { return widget; }
void init_vars()
{
data.clear();
features = 0;
widget = NULL;
}
void close()
{
if ( widget != NULL )
close_widget(widget, WCLS_SAVE | WCLS_CLOSE_LATER);
}
bool set_range(
const place_t *minplace = NULL,
const place_t *maxplace = NULL)
{
if ( widget == NULL )
return false;
set_custom_viewer_range(
widget,
minplace == NULL ? data.get_min() : minplace,
maxplace == NULL ? data.get_max() : maxplace);
return true;
}
place_t *get_place(
bool mouse = false,
int *x = 0,
int *y = 0)
{
return widget == NULL ? NULL : get_custom_viewer_place(widget, mouse, x, y);
}
bool refresh()
{
if ( widget == NULL )
return false;
refresh_custom_viewer(widget);
return true;
}
bool get_current_word(bool mouse, qstring &word)
{
// query the cursor position
int x, y;
if ( get_place(mouse, &x, &y) == NULL )
return false;
// query the line at the cursor
qstring qline;
get_current_line(&qline, mouse, true);
const char *line = qline.begin();
if ( line == NULL )
return false;
if ( x >= (int)qstrlen(line) )
return false;
// find the beginning of the word
const char *ptr = line + x;
while ( ptr > line && !qisspace(ptr[-1]) )
ptr--;
// find the end of the word
const char *begin = ptr;
ptr = line + x;
while ( !qisspace(*ptr) && *ptr != '\0' )
ptr++;
word.qclear();
word.append(begin, ptr-begin);
return true;
}
void get_current_line(qstring *out, bool mouse, bool notags)
{
*out = get_custom_viewer_curline(widget, mouse);
if ( notags )
tag_remove(out);
}
bool is_focused()
{
return get_current_viewer() == widget;
}
bool create(const char *_title, int _features)
{
// Already created? (in the instance)
if ( widget != NULL )
return true;
// Already created? (in IDA windows list)
TWidget *found = find_widget(_title);
if ( found != NULL )
return false;
title = _title;
features = _features;
//
// Prepare handlers
//
if ( (features & HAVE_KEYDOWN) != 0 )
handlers.keyboard = s_cv_keydown;
if ( (features & HAVE_CLICK) != 0 )
handlers.click = s_cv_click;
if ( (features & HAVE_DBLCLICK) != 0 )
handlers.dblclick = s_cv_dblclick;
if ( (features & HAVE_CURPOS) != 0 )
handlers.curpos = s_cv_curpos;
// Create the viewer
widget = create_custom_viewer(
title.c_str(),
data.get_min(),
data.get_max(),
data.get_min(),
(const renderer_info_t *) NULL,
data.get_ud(),
&handlers,
this);
// Hook to UI notifications (for TWidget close event)
idapython_hook_to_notification_point(HT_UI, s_ui_cb, this, /*is_hooks_base=*/ false);
return true;
}
//--------------------------------------------------------------------------
// Edits an existing line
bool edit_line(size_t nline, PyObject *py_sl)
{
@@ -667,7 +541,6 @@ public:
return true;
}
//--------------------------------------------------------------------------
bool del_line(size_t nline)
{
bool ok = data.del_line(nline);
@@ -676,7 +549,6 @@ public:
return ok;
}
//--------------------------------------------------------------------------
// Gets the position and returns a tuple (lineno, x, y)
PyObject *get_pos(bool mouse)
{
@@ -689,7 +561,6 @@ public:
return Py_BuildValue("(" PY_BV_SZ "ii)", bvsz_t(data.to_lineno(pl)), x, y);
}
//--------------------------------------------------------------------------
// Returns the line tuple
PyObject *get_line(size_t nline)
{
@@ -701,7 +572,7 @@ public:
}
// Returns the count of lines
const size_t count() const
size_t count() const
{
return data.count();
}
@@ -713,23 +584,21 @@ public:
refresh_range();
}
//--------------------------------------------------------------------------
bool jumpto(size_t ln, int x, int y)
{
simpleline_place_t l(ln);
return customviewer_t::jumpto(&l, x, y);
return ::jumpto(widget, &l, x, y);
}
//--------------------------------------------------------------------------
// Initializes and links the Python object to this class
bool init(PyObject *py_link, const char *title)
{
// Already created?
if ( _cv != NULL )
if ( widget != NULL )
return true;
// Probe callbacks
features = 0;
int collected_features = 0;
static struct
{
const char *cb_name;
@@ -746,12 +615,10 @@ public:
PYW_GIL_CHECK_LOCKED_SCOPE();
for ( size_t i=0; i < qnumber(cbtable); i++ )
{
if ( PyObject_HasAttrString(py_link, cbtable[i].cb_name) )
features |= cbtable[i].feature;
}
collected_features |= cbtable[i].feature;
if ( !create(title, features, &data) )
if ( !create(title, collected_features) )
return false;
// Hold a reference to this object
@@ -765,26 +632,30 @@ public:
return true;
}
//--------------------------------------------------------------------------
bool show()
{
if ( _cv == NULL && py_last_link != NULL )
if ( widget == NULL && py_last_link != NULL )
{
// Re-create the view (with same previous parameters)
if ( !init(py_last_link, _title.c_str()) )
if ( !init(py_last_link, title.c_str()) )
return false;
}
return customviewer_t::show();
// Closed already?
if ( widget == NULL )
return false;
display_widget(widget, WOPN_DP_TAB|WOPN_RESTORE);
return true;
}
//--------------------------------------------------------------------------
bool get_selection(size_t *x1, size_t *y1, size_t *x2, size_t *y2)
{
if ( _cv == NULL )
if ( widget == NULL )
return false;
twinpos_t p1, p2;
if ( !::read_selection(_cv, &p1, &p2) )
if ( !::read_selection(widget, &p1, &p2) )
return false;
if ( y1 != NULL )
@@ -820,7 +691,6 @@ public:
return py_this;
}
};
//</code(py_kernwin_custview)>
//---------------------------------------------------------------------------
@@ -849,29 +719,7 @@ PyObject *pyscv_init(PyObject *py_link, const char *title)
bool pyscv_refresh(PyObject *py_this)
{
DECL_THIS;
if ( _this == NULL )
return false;
return _this->refresh();
}
//--------------------------------------------------------------------------
bool pyscv_delete(PyObject *py_this)
{
DECL_THIS;
if ( _this == NULL )
return false;
_this->close();
delete _this;
return true;
}
//--------------------------------------------------------------------------
bool pyscv_refresh_current(PyObject *py_this)
{
DECL_THIS;
if ( _this == NULL )
return false;
return _this->refresh_current();
return _this != NULL && _this->refresh();
}
//--------------------------------------------------------------------------
@@ -879,10 +727,13 @@ 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 )
if ( _this == NULL )
Py_RETURN_NONE;
return PyString_FromString(line);
qstring line;
_this->get_current_line(&line, mouse, notags);
if ( line.empty() )
Py_RETURN_NONE;
return PyString_FromStringAndSize(line.c_str(), line.length());
}
//--------------------------------------------------------------------------
+1 -8
View File
@@ -24,13 +24,6 @@ class simplecustviewer_t(object):
self.__this = None
self.ui_hooks_trampoline = self.UI_Hooks_Trampoline(self)
def __del__(self):
"""Destructor. It also frees the associated C++ object"""
try:
_ida_kernwin.pyscv_delete(self.__this)
except:
pass
@staticmethod
def __make_sl_arg(line, fgcolor=None, bgcolor=None):
return line if (fgcolor is None and bgcolor is None) else (line, fgcolor, bgcolor)
@@ -75,7 +68,7 @@ class simplecustviewer_t(object):
def RefreshCurrent(self):
"""Refreshes the current line only"""
return _ida_kernwin.pyscv_refresh_current(self.__this)
return _ida_kernwin.pyscv_refresh(self.__this)
def Count(self):
"""Returns the number of lines in the view"""
+2 -2
View File
@@ -74,7 +74,7 @@ public:
if ( widget == NULL )
return false;
if ( !idapython_hook_to_notification_point(HT_UI, s_callback, this) )
if ( !idapython_hook_to_notification_point(HT_UI, s_callback, this, /*is_hooks_base=*/ false) )
{
widget = NULL;
return false;
@@ -133,7 +133,7 @@ static bool plgform_show(
PyObject *py_link,
PyObject *py_obj,
const char *caption,
int options = WOPN_TAB|WOPN_RESTORE)
int options = WOPN_DP_TAB|WOPN_RESTORE)
{
DECL_PLGFORM;
return plgform->show(py_obj, caption, options);
+28 -4
View File
@@ -9,13 +9,12 @@ class PluginForm(object):
"""
WOPN_MDI = 0x01 # no-op
WOPN_TAB = 0x02
"""attached by default to a tab"""
WOPN_TAB = 0x02 # no-op
WOPN_RESTORE = 0x04
"""
if the widget is the only widget in a floating area when
it is closed, remember that area's geometry. The next
time that widget is created as floating (i.e., no WOPN_TAB)
time that widget is created as floating (i.e., WOPN_DP_FLOATING)
its geometry will be restored (e.g., "Execute script"
"""
WOPN_ONTOP = 0x08 # no-op
@@ -23,6 +22,31 @@ class PluginForm(object):
WOPN_CENTERED = 0x20 # no-op
WOPN_PERSIST = 0x40
"""form will persist until explicitly closed with Close()"""
WOPN_DP_LEFT = 0x00010000
""" Dock widget to the left of dest_ctrl"""
WOPN_DP_TOP = 0x00020000
""" Dock widget above dest_ctrl"""
WOPN_DP_RIGHT = 0x00040000
""" Dock widget to the right of dest_ctrl"""
WOPN_DP_BOTTOM = 0x00080000
""" Dock widget below dest_ctrl"""
WOPN_DP_INSIDE = 0x00100000
""" Create a new tab bar with both widget and dest_ctrl"""
WOPN_DP_TAB = 0x00400000
"""
Place widget into a tab next to dest_ctrl,
if dest_ctrl is in a tab bar
(otherwise the same as #WOPN_DP_INSIDE)
"""
WOPN_DP_BEFORE = 0x00200000
"""
place widget before dst_form in the tab bar instead of after
used with #WOPN_DP_INSIDE and #WOPN_DP_TAB
"""
WOPN_DP_FLOATING=0x00800000
""" Make widget floating"""
WOPN_DP_INSIDE_BEFORE = WOPN_DP_INSIDE | WOPN_DP_BEFORE
WOPN_DP_TAB_BEFORE = WOPN_DP_TAB | WOPN_DP_BEFORE
WOPN_CREATE_ONLY = {}
@@ -44,7 +68,7 @@ class PluginForm(object):
if options == self.WOPN_CREATE_ONLY:
options = -1
else:
options |= PluginForm.WOPN_TAB|PluginForm.WOPN_RESTORE
options |= PluginForm.WOPN_DP_TAB|PluginForm.WOPN_RESTORE
return _ida_kernwin.plgform_show(self.__clink__, self, caption, options)
+25 -31
View File
@@ -5,47 +5,41 @@
// View hooks
//---------------------------------------------------------------------------
ssize_t idaapi View_Callback(void *ud, int notification_code, va_list va);
class View_Hooks
struct View_Hooks : public hooks_base_t
{
public:
virtual ~View_Hooks() { unhook(); }
// hookgenVIEW:methodsinfo_decl
bool hook()
{
return idapython_hook_to_notification_point(HT_VIEW, View_Callback, this);
}
bool unhook()
{
return idapython_unhook_from_notification_point(HT_VIEW, View_Callback, this);
}
View_Hooks(uint32 _flags=0)
: hooks_base_t("ida_kernwin.View_Hooks", View_Callback, HT_VIEW, _flags) {}
bool hook() { return hooks_base_t::hook(); }
bool unhook() { return hooks_base_t::unhook(); }
#ifdef TESTABLE_BUILD
qstring dump_state() { return hooks_base_t::dump_state(mappings, mappings_size); }
#endif
// hookgenVIEW:methods
ssize_t dispatch(int code, va_list va)
{
switch ( code )
{
// hookgenVIEW:notifications
}
return 0;
}
};
//</inline(py_kernwin_viewhooks)>
//<code(py_kernwin_viewhooks)>
// hookgenVIEW:methodsinfo_def
//---------------------------------------------------------------------------
ssize_t idaapi View_Callback(void *ud, int notification_code, va_list va)
ssize_t idaapi View_Callback(void *ud, int code, va_list va)
{
// This hook gets called from the kernel. Ensure we hold the GIL.
PYW_GIL_GET;
class View_Hooks *proxy = (class View_Hooks *)ud;
ssize_t ret = 0;
try
{
switch ( notification_code )
{
// hookgenVIEW:notifications
}
}
catch (Swig::DirectorException &e)
{
msg("Exception in View Hook function: %s\n", e.getMessage());
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( PyErr_Occurred() )
PyErr_Print();
}
return 0;
// hookgenVIEW:safecall=View_Hooks
}
//</code(py_kernwin_viewhooks)>
+14
View File
@@ -100,6 +100,20 @@ static bool py_load_and_run_plugin(const char *name, size_t arg)
return rc;
}
//-------------------------------------------------------------------------
static PyObject *py_extract_module_from_archive(const char *fname, bool is_remote=false)
{
char *temp_file_ptr = NULL;
char fname_buf[QMAXPATH];
qstrncpy(fname_buf, fname, sizeof(fname_buf));
bool ok = extract_module_from_archive(
fname_buf,
sizeof(fname_buf),
&temp_file_ptr,
is_remote);
return Py_BuildValue("(ss)", ok ? fname_buf : NULL, ok ? temp_file_ptr : NULL);
}
//</inline(py_loader)>
#endif
+35
View File
@@ -0,0 +1,35 @@
//<inline(py_lumina)>
//-------------------------------------------------------------------------
bool py_extract_type_from_metadata(tinfo_t *out, const qstring &in)
{
md_type_parts_t tp;
if ( !in.empty() )
{
const uchar *ptr = (uchar *) in.begin();
const uchar *end = ptr + in.length();
extract_type_from_metadata(&tp, ptr, end);
out->deserialize(NULL, &tp.type, &tp.fields);
}
return tp.userti;
}
//-------------------------------------------------------------------------
PyObject *py_split_metadata(const metadata_t &md)
{
PyObject *py_dict = PyDict_New();
metadata_iterator_t p(md);
while ( p.next() )
{
newref_t py_key(PyInt_FromLong(p.key));
newref_t py_value(PyString_FromStringAndSize((const char *) p.data, p.size));
// PyDict_SetItem doesn't "steal" references; hence the 'newref_t's above.
PyDict_SetItem(py_dict, py_key.o, py_value.o);
}
return py_dict;
}
//</inline(py_lumina)>
+15 -5
View File
@@ -5,7 +5,7 @@
//------------------------------------------------------------------------
//<inline(py_name)>
//------------------------------------------------------------------------
PyObject *get_debug_names(ea_t ea1, ea_t ea2)
PyObject *get_debug_names(ea_t ea1, ea_t ea2, bool return_list=false)
{
// Get debug names
ea_name_vec_t names;
@@ -16,11 +16,21 @@ PyObject *get_debug_names(ea_t ea1, ea_t ea2)
PyObject *dict = Py_BuildValue("{}");
if ( dict != NULL )
{
for ( ea_name_vec_t::iterator it=names.begin(); it != names.end(); ++it )
ea_t last_ea = BADADDR;
PyObject *list = NULL;
for ( ea_name_vec_t::iterator it = names.begin(); it != names.end(); ++it )
{
PyDict_SetItem(dict,
Py_BuildValue(PY_BV_EA, bvea_t(it->ea)),
PyString_FromString(it->name.c_str()));
PyObject *name_obj = PyString_FromString(it->name.c_str());
if ( it->ea != last_ea )
{
if ( return_list )
list = PyList_New(0);
PyObject *ea_obj = Py_BuildValue(PY_BV_EA, bvea_t(it->ea));
PyDict_SetItem(dict, ea_obj, return_list ? list : name_obj);
last_ea = it->ea;
}
if ( return_list )
PyList_Append(list, name_obj);
}
}
return dict;
+1
View File
@@ -10,6 +10,7 @@ if ida_idaapi.__EA64__:
else:
svalvec_t = intvec_t
uvalvec_t = uintvec_t
eavec_t = uvalvec_t
ida_idaapi._listify_types(
intvec_t,
-1
View File
@@ -32,7 +32,6 @@ PyObject *py_reg_read_string(const char *name, const char *subkey = NULL, const
{
PYW_GIL_CHECK_LOCKED_SCOPE();
qstring utf8;
bool ok;
Py_BEGIN_ALLOW_THREADS;
if ( !reg_read_string(&utf8, name, subkey) && def != NULL )
utf8 = def;
+1 -2
View File
@@ -47,9 +47,8 @@ void set_defsr(segment_t *s, int reg, sel_t value)
int py_rebase_program(PyObject *delta, int flags)
{
int rc = MOVE_SEGM_PARAM;
bool is_64 = false;
uint64 num_delta;
if ( PyW_GetNumber(delta, &num_delta, &is_64) )
if ( PyW_GetNumber(delta, &num_delta) )
rc = rebase_program(adiff_t(num_delta), flags);
else
PyErr_SetString(PyExc_TypeError, "Expected a delta in bytes");
+7 -3
View File
@@ -398,7 +398,7 @@ PyObject *py_pack_object_to_bv(
&bytes,
NULL,
pio_flags);
if ( err == eOk && !bytes.relocate(base_ea, inf.is_be()) )
if ( err == eOk && !bytes.relocate(base_ea, inf_is_be()) )
err = -1;
Py_END_ALLOW_THREADS;
if ( err == eOk )
@@ -409,14 +409,18 @@ PyObject *py_pack_object_to_bv(
//-------------------------------------------------------------------------
/* Parse types from a string or file. See ParseTypes() in idc.py */
#define PT_FILE 0x00010000
int idc_parse_types(const char *input, int flags)
{
int hti = ((flags >> 4) & 7) << HTI_PAK_SHIFT;
if ( (flags & 1) != 0 )
if ( (flags & PT_FILE) != 0 )
{
hti |= HTI_FIL;
flags &= ~PT_FILE;
}
return parse_decls(NULL, input, (flags & 2) == 0 ? msg : NULL, hti);
return parse_decls(NULL, input, (flags & PT_SIL) == 0 ? msg : NULL, hti);
}
//-------------------------------------------------------------------------
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-2
View File
@@ -2,8 +2,6 @@
#include <bytes.hpp>
%}
%import "range.i"
// Unexported and kernel-only declarations
%ignore testf_t;
%ignore next_that;
+19 -9
View File
@@ -3,8 +3,6 @@
#include <loader.hpp>
%}
%import "idd.i"
%ignore dbg;
%ignore register_srcinfo_provider;
%ignore unregister_srcinfo_provider;
@@ -35,6 +33,12 @@
%ignore set_int_dbg_options;
%ignore set_dbg_default_options;
%ignore set_reg_val;
%rename (set_reg_val) py_set_reg_val;
%ignore request_set_reg_val;
%rename (request_set_reg_val) py_request_set_reg_val;
%rename (get_reg_val) py_get_reg_val;
/* %ignore invalidate_dbg_state; */
/* %ignore is_request_running; */
@@ -80,13 +84,7 @@ bool request_run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD);
// network traffic.
%include "dbg.hpp"
%nothread;
%ignore DBG_Callback;
%ignore DBG_Hooks::store_int;
%{
//<code(py_dbg)>
//</code(py_dbg)>
%}
%define_Hooks_class(DBG);
//-------------------------------------------------------------------------
// bpt_t
@@ -147,11 +145,23 @@ void bpt_t_elang_set(bpt_t *bpt, PyObject *val)
%}
}
%{
static bool _to_reg_val(regval_t **out, regval_t *buf, const char *name, PyObject *o);
static PyObject *_from_reg_val(
const char *name,
const regval_t &rv);
%}
%inline %{
//<inline(py_dbg)>
//</inline(py_dbg)>
%}
%{
//<code(py_dbg)>
//</code(py_dbg)>
%}
%pythoncode %{
#<pycode(py_dbg)>
#</pycode(py_dbg)>
+1
View File
@@ -33,6 +33,7 @@
%ignore qlfile;
%ignore make_linput;
%ignore unmake_linput;
%ignore linput_buffer_t;
%ignore eread;
%ignore ewrite;
+2
View File
@@ -53,6 +53,8 @@
%ignore idc_value_t::_set_int64;
%ignore idc_value_t::_set_pvoid;
%ignore idc_value_t::_set_string;
%ignore idc_value_t::idc_value_t(const qstring &);
%ignore idc_value_t::set_string(const qstring &);
%ignore eval_expr;
%rename (eval_expr) py_eval_expr;
-2
View File
@@ -2,8 +2,6 @@
#include <frame.hpp>
%}
%import "range.i"
%ignore add_frame_spec_member;
%ignore del_stkvars;
%ignore calc_frame_offset;
-2
View File
@@ -1,6 +1,4 @@
%import "range.i"
%{
#include <frame.hpp>
%}
-2
View File
@@ -2,8 +2,6 @@
#include <gdl.hpp>
%}
%import "range.i"
%ignore cancellable_graph_t;
%ignore gdl_graph_t;
+3 -2
View File
@@ -58,8 +58,8 @@
%extend graph_visitor_t {
public:
virtual int idaapi visit_node(int /*n*/, rect_t & /*r*/) { return 0; }
virtual int idaapi visit_edge(edge_t /*e*/, edge_info_t * /*ei*/) { return 0; }
virtual int idaapi visit_node(int /*n*/, rect_t & /*r*/) { qnotused(self); return 0; }
virtual int idaapi visit_edge(edge_t /*e*/, edge_info_t * /*ei*/) { qnotused(self); return 0; }
}
%extend mutable_graph_t {
@@ -70,6 +70,7 @@ public:
}
}
%template(screen_graph_selection_base_t) qvector<selection_item_t>;
%template(node_layout_t) qvector<rect_t>;
%template(pointvec_t) qvector<point_t>;
+343 -204
View File
@@ -2,7 +2,12 @@
#include <hexrays.hpp>
%}
%import "typeinf.i"
%{
SWIGINTERN void __raise_vdf(const vd_failure_t &e)
{
PyErr_SetString(PyExc_RuntimeError, e.desc().c_str());
}
%}
// KLUDGE: I have no idea how to force SWiG to declare a type for a module,
// unless that type is indeed used. That's why this wrapper exists..
@@ -41,14 +46,35 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m);
%include <windows.i>
#endif
//---------------------------------------------------------------------
// some defines to calm SWIG down.
#define DEFINE_MEMORY_ALLOCATION_FUNCS()
//#define DECLARE_UNCOPYABLE(f)
#define AS_PRINTF(format_idx, varg_idx)
%define %define_hexrays_lifecycle_object(TypeName)
%feature("ref") TypeName
{
hexrays_register_python_clearable_instance($this, hxclr_##TypeName);
}
%feature("unref") TypeName
{
hexrays_deregister_python_clearable_instance($this);
delete $this;
}
%extend TypeName {
void _register() { hexrays_register_python_clearable_instance($self, hxclr_##TypeName); }
void _deregister() { hexrays_deregister_python_clearable_instance($self); }
}
%enddef
%typemap(directorin) (const char *format, ...)
{
// %typemap(directorin) (const char *format, ...)
// AFAICT we should only ever be called from C++, so we can assume
// 'format' is followed with actual parameters, should it require them.
qstring $input_buf;
va_list $input_va;
va_start($input_va, format);
$input_buf.vsprnt(format, $input_va);
va_end($input_va);
$input = SWIG_Python_str_FromChar($input_buf.c_str());
}
%ignore vd_printer_t::vprint;
%ignore vd_printer_t::tmpbuf;
%ignore string_printer_t::vprint;
%ignore vdui_t::vdui_t;
%ignore cblock_t::find;
@@ -94,119 +120,130 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m);
%ignore term_hexrays_plugin;
%rename (term_hexrays_plugin) py_term_hexrays_plugin;
%rename (debug_hexrays_ctree) py_debug_hexrays_ctree;
%ignore vd_interr_t::vd_interr_t(ea_t, const qstring &);
// ignore microcode related stuff for now
%ignore bitset_t;
%ignore mlist_t;
%ignore rlist_t;
%ignore mbl_array_t;
%ignore mbl_graph_t;
%ignore mblock_t;
%ignore minsn_t;
%ignore mop_t;
%ignore mcode_t;
%ignore mop_addr_t;
%ignore mop_pair_t;
%ignore mcases_t;
%ignore mcallarg_t;
%ignore mcallinfo_t;
%ignore mnumber_t;
%ignore lvar_ref_t;
%ignore stkvar_ref_t;
%ignore scif_t;
%ignore op_parent_info_t;
%ignore scif_visitor_t;
%ignore mop_visitor_t;
%ignore mlist_mop_visitor_t;
%ignore minsn_visitor_t;
%ignore srcop_visitor_t;
%ignore chain_t;
%ignore block_chains_t;
%ignore block_chains_iterator_t;
%ignore block_chains_begin;
%ignore block_chains_clear;
%ignore block_chains_end;
%ignore block_chains_erase;
%ignore block_chains_find;
%ignore block_chains_free;
%ignore block_chains_get;
%ignore block_chains_insert;
%ignore block_chains_new;
%ignore block_chains_next;
%ignore block_chains_prev;
%ignore block_chains_size;
%ignore graph_chains_t;
%ignore chain_visitor_t;
%ignore gctype_t;
%ignore simple_graph_t;
%ignore get_signed_mcode;
%ignore get_unsigned_mcode;
%ignore mcode_modifies_d;
%ignore is_may_access;
%ignore is_mcode_addsub;
%ignore is_mcode_call;
%ignore is_mcode_commutative;
%ignore is_mcode_convertible_to_jmp;
%ignore is_mcode_convertible_to_set;
%ignore is_mcode_fpu;
%ignore is_mcode_j1;
%ignore is_mcode_jcond;
%ignore is_mcode_propagatable;
%ignore is_mcode_rotate;
%ignore is_mcode_set;
%ignore is_mcode_set1;
%ignore is_mcode_shift;
%ignore is_mcode_xdsu;
%ignore is_signed_mcode;
%ignore is_unsigned_mcode;
%ignore is_kreg;
%ignore get_first_stack_reg;
%ignore jcnd2set;
%ignore must_mcode_close_block;
%ignore negate_mcode_relation;
%ignore set2jcnd;
%ignore swap_mcode_relation;
%ignore get_mreg_name;
%ignore gen_microcode;
%ignore install_optinsn_handler;
%ignore remove_optinsn_handler;
%ignore install_optblock_handler;
%ignore remove_optblock_handler;
%ignore optinsn_t;
%ignore optblock_t;
%ignore getf_reginsn;
%ignore getb_reginsn;
%ignore reg2mreg;
%ignore mreg2reg;
%ignore chain_keeper_t;
%ignore bitset_t::print;
%ignore bitset_t::extract;
%ignore bitset_t::fill_gaps;
%template(array_of_bitsets) qvector<bitset_t>;
%ignore ivl_t::print;
%ignore ivl_t::allmem;
%ignore mlist_t::has_allmem;
%ignore mbl_array_t::mbl_array_t;
%ignore mbl_array_t::reserved;
%ignore mbl_array_t::vdump_mba;
%ignore mbl_array_t::idaloc2vd(const argloc_t &, int, sval_t);
%ignore mbl_array_t::idaloc2vd(const mbl_array_t *, const argloc_t &, int);
%ignore mbl_array_t::range_contains;
%ignore mbl_array_t::get_stkvar;
%ignore simple_graph_t::simple_graph_t;
%ignore simple_graph_t::~simple_graph_t;
%ignore mbl_graph_t::mbl_graph_t;
%ignore mbl_graph_t::~mbl_graph_t;
%define_hexrays_lifecycle_object(minsn_t);
%ignore minsn_t::find_ins_op(const mop_t **, mcode_t) const;
%ignore minsn_t::find_num_op(const mop_t **) const;
%ignore minsn_t::set_combined;
%define_hexrays_lifecycle_object(mop_t);
%ignore mop_t::_make_strlit(qstring *);
%template(mopvec_t) qvector<mop_t>;
%template(mcallargs_t) qvector<mcallarg_t>;
%uncomparable_elements_qvector(block_chains_t, block_chains_vec_t);
%ignore mblock_t::mblock_t;
%ignore mblock_t::find_first_use(mlist_t *, const minsn_t *, const minsn_t *, maymust_t) const;
%ignore mblock_t::find_redefinition(const mlist_t &, const minsn_t *, const minsn_t *, maymust_t) const;
%ignore mblock_t::reserved;
%ignore mblock_t::vdump_block;
// Note: we cannot use %delobject here, as that would disown
// the block itself, not the instruction.
%feature("pythonappend") mblock_t::insert_into_block %{
mn = args[0]
mn._maybe_disown_and_deregister()
%}
// Note: we could be using %newobject here, but for the sake of
// symmetry with 'insert_into_block', let's go with "pythonappend".
%feature("pythonprepend") mblock_t::remove_from_block %{
mn = args[0]
%}
%feature("pythonappend") mblock_t::remove_from_block %{
if mn:
mn._own_and_register()
%}
%feature("nodirector") mblock_t;
%extend mblock_t {
%pythoncode {
def preds(self):
"""
Iterates the list of predecessor blocks
"""
for ser in self.predset:
yield self.mba.get_mblock(ser)
def succs(self):
"""
Iterates the list of successor blocks
"""
for ser in self.succset:
yield self.mba.get_mblock(ser)
}
};
%ignore op_parent_info_t::really_alloc;
%ignore getf_reginsn(const minsn_t *);
%ignore getb_reginsn(const minsn_t *);
%ignore lvar_t::dstr;
%ignore lvar_locator_t::dstr;
%ignore fnumber_t::dstr;
%ignore dstr;
%ignore range_item_iterator_t;
%ignore mba_item_iterator_t;
%ignore range_chunk_iterator_t;
%ignore mba_range_iterator_t;
%ignore mba_ranges_t;
%ignore deserialize_mbl_array;
%ignore get_temp_regs;
%ignore ivl_t;
%ignore ivlset_t;
%ignore ivl_with_name_t;
%ignore vivl_t;
%ignore voff_t;
%ignore voff_set_t;
%ignore gco_info_t;
%ignore get_current_operand;
%ignore valrng_t;
%ignore mba_ranges_t::range_contains;
%newobject gen_microcode;
%define_hexrays_lifecycle_object(mbl_array_t);
%define_hexrays_lifecycle_object(valrng_t);
%apply ulonglong *OUTPUT { uvlr_t *v }; // valrng_t::cvt_to_single_value
%apply ulonglong *OUTPUT { uvlr_t *val }; // valrng_t::cvt_to_cmp
%apply int *OUTPUT { cmpop_t *cmp }; // valrng_t::cvt_to_cmp
%define %def_opt_handler(TypeName, Install, Remove)
%ignore Install;
%ignore Remove;
%extend TypeName {
void install()
{
hexrays_register_python_clearable_instance($self, hxclr_optinsn_t);
Install($self);
}
bool remove()
{
hexrays_deregister_python_clearable_instance($self);
return Remove($self);
}
~TypeName()
{
hexrays_deregister_python_clearable_instance($self);
Remove($self);
delete $self;
}
};
%enddef
%def_opt_handler(optinsn_t, install_optinsn_handler, remove_optinsn_handler);
%def_opt_handler(optblock_t, install_optblock_handler, remove_optblock_handler)
// "Warning 473: Returning a pointer or reference in a director method is not recommended."
// In this particular case, we are telling SWiG that the object is always a
// %newobject (thus: even for base classes), but it seems it's not enough to
// shut the warning up.
%warnfilter(473) codegen_t::emit_micro_mvm;
%newobject codegen_t::emit_micro_mvm;
%newobject codegen_t::emit;
%apply uchar { char ignore_micro };
%feature("nodirector") udc_filter_t::apply;
@@ -279,61 +316,24 @@ public:
};
//-------------------------------------------------------------------------
%typemap(check) citem_t *self
{
if ( $1 == INS_EPILOG )
SWIG_exception_fail(SWIG_ValueError, "invalid INS_EPILOG " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
}
%typemap(check) cinsn_t *self
{
if ( $1 == INS_EPILOG )
SWIG_exception_fail(SWIG_ValueError, "invalid INS_EPILOG " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
}
//-------------------------------------------------------------------------
// citem_t
//---------------------------------------------------------------------
%extend citem_t {
// define these two struct members that can be used for casting.
cinsn_t *cinsn const { return (cinsn_t *)self; }
cexpr_t *cexpr const { return (cexpr_t *)self; }
ctype_t _get_op() const { return self->op; }
void _set_op(ctype_t v) { self->op = v; }
PyObject *_obj_id() const { return PyLong_FromSize_t(size_t(self)); }
#ifdef TESTABLE_BUILD
qstring __dbg_get_meminfo() const
{
qstring s;
s.sprnt("%p (op=%s)", self, get_ctype_name(self->op));
return s;
}
%define %monitored_lifecycle_object_t(TypeName)
%extend TypeName {
int __dbg_get_registered_kind() const
{
return hexrays_is_registered_python_clearable_instance(self);
}
#endif
PyObject *_obj_id() const { return PyLong_FromSize_t(size_t(self)); }
%pythoncode {
obj_id = property(_obj_id)
op = property(
_get_op,
lambda self, v: self._ensure_no_op() and self._set_op(v))
def _ensure_cond(self, ok, cond_str):
if not ok:
raise Exception("Condition \"%s\" not verified" % cond_str)
return True
def _ensure_no_op(self):
if self.op not in [cot_empty, cit_empty]:
raise Exception("%s has op %s; cannot be modified" % (self, self.op))
return True
def _ensure_no_obj(self, o, attr, attr_is_acquired):
if attr_is_acquired and o is not None:
raise Exception("%s already owns attribute \"%s\" (%s); cannot be modified" % (self, attr, o))
@@ -364,29 +364,35 @@ public:
o._maybe_disown_and_deregister()
self._replace_by(o)
#ifdef TESTABLE_BUILD
def _meminfo(self):
cpp = self.__dbg_get_meminfo()
rkind = self.__dbg_get_registered_kind()
rkind_str = [
"(not owned)",
"cfuncptr",
"cinsn",
"cexpr",
"cblock"][rkind]
"cfuncptr_t",
"cinsn_t",
"cexpr_t",
"cblock_t",
"mbl_array_t",
"mop_t",
"minsn_t",
"optinsn_t",
"optblock_t",
"valrng_t"][rkind]
return "%s [thisown=%s, owned by IDAPython as=%s]" % (
cpp,
self.thisown,
rkind_str)
meminfo = property(_meminfo)
#endif
}
};
%enddef
//-------------------------------------------------------------------------
#define ___MEMBER_REF_BASE(Type, PName, Cond, Defval, Acquire, Setexpr) \
#define ___MEMBER_REF_BASE__ACCESSORS(Type, PName, Setexpr) \
Type _get_##PName() const { return self->##PName; } \
void _set_##PName(Type _v) { self->##PName = Setexpr; } \
void _set_##PName(Type _v) { self->##PName = Setexpr; }
#define ___MEMBER_REF_BASE__PROPERTY(PName, Cond, Defval, Acquire) \
%pythoncode { \
PName = property( \
lambda self: self._get_##PName() if Cond else Defval, \
@@ -397,6 +403,165 @@ public:
and self._set_##PName(v)) \
}
//-------------------------------------------------------------------------
#define ___MEMBER_REF_BASE(Type, PName, Cond, Defval, Acquire, Setexpr) \
___MEMBER_REF_BASE__ACCESSORS(Type, PName, Setexpr) \
___MEMBER_REF_BASE__PROPERTY(PName, Cond, Defval, Acquire)
//-------------------------------------------------------------------------
#define ___SCALAR_MEMBER_REF_BASE__PROPERTY(PName, Cond, Defval) \
%pythoncode { \
PName = property( \
lambda self: self._get_##PName() if Cond else Defval, \
lambda self, v: \
self._ensure_cond(Cond, #Cond) \
and self._set_##PName(v)) \
}
//-------------------------------------------------------------------------
// mop_t
//-------------------------------------------------------------------------
#define MOP_MEMBER_REF(Type, PName, Mopt) \
___MEMBER_REF_BASE(Type, PName, self.t == Mopt, None, True, _v)
#define MOP_SCALAR_MEMBER_REF(Type, PName, Mopt) \
___MEMBER_REF_BASE__ACCESSORS(Type, PName, _v) \
___SCALAR_MEMBER_REF_BASE__PROPERTY(PName, self.t == Mopt, None)
#define MOP_CSTRING_MEMBER_REF(PName, Mopt) \
const char *_get_##PName() const { return self->PName; } \
void _set_##PName(const char *_v) \
{ \
if ( $self->PName != NULL ) \
{ \
::qfree($self->PName); \
$self->PName = NULL; \
} \
$self->PName = ::qstrdup(_v); \
} \
___MEMBER_REF_BASE__PROPERTY(PName, self.t == Mopt, None, False)
%extend mop_t {
MOP_SCALAR_MEMBER_REF(mreg_t, r, mop_r);
MOP_MEMBER_REF(mnumber_t*, nnn, mop_n);
MOP_CSTRING_MEMBER_REF(cstr, mop_str);
MOP_MEMBER_REF(minsn_t*, d, mop_d)
MOP_MEMBER_REF(stkvar_ref_t*, s, mop_S);
MOP_SCALAR_MEMBER_REF(ea_t, g, mop_v);
MOP_SCALAR_MEMBER_REF(int, b, mop_b);
MOP_MEMBER_REF(mcallinfo_t*, f, mop_f);
MOP_MEMBER_REF(lvar_ref_t*, l, mop_l);
MOP_MEMBER_REF(mop_addr_t*, a, mop_a);
MOP_CSTRING_MEMBER_REF(helper, mop_h);
MOP_MEMBER_REF(mcases_t*, c, mop_c);
MOP_MEMBER_REF(fnumber_t*, fpc, mop_fn);
MOP_MEMBER_REF(mop_pair_t*, pair, mop_p);
MOP_MEMBER_REF(scif_t*, scif, mop_sc);
mopt_t _get_t() const { return self->t; }
void _set_t(mopt_t v) { self->t = v; }
%pythoncode {
def _ensure_no_t(self):
if self.t not in [mop_z]:
raise Exception("%s has type %s; cannot be modified" % (self, self.t))
return True
t = property(
_get_t,
lambda self, v: self._ensure_no_t() and self._set_t(v))
}
qstring __dbg_get_meminfo() const
{
qstring s;
s.sprnt("%p (t=%d)", self, self->t);
return s;
}
}
#undef MOP_MEMBER_REF
%monitored_lifecycle_object_t(mop_t);
//-------------------------------------------------------------------------
// minsn_t
//-------------------------------------------------------------------------
%extend minsn_t {
qstring __dbg_get_meminfo() const
{
qstring s;
s.sprnt("%p (opcode=%d)", self, self->opcode);
return s;
}
}
%monitored_lifecycle_object_t(minsn_t);
//-------------------------------------------------------------------------
// bitset_t
//-------------------------------------------------------------------------
%extend bitset_t {
int itv(const_iterator it) { qnotused(self); return *it; }
%pythoncode {
__len__ = count
def __iter__(self):
it = self.begin()
for i in xrange(self.count()):
yield self.itv(it)
self.inc(it)
}
};
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
%typemap(check) citem_t *self
{
if ( $1 == INS_EPILOG )
SWIG_exception_fail(SWIG_ValueError, "invalid INS_EPILOG " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
}
%typemap(check) cinsn_t *self
{
if ( $1 == INS_EPILOG )
SWIG_exception_fail(SWIG_ValueError, "invalid INS_EPILOG " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
}
//-------------------------------------------------------------------------
// citem_t
//---------------------------------------------------------------------
%extend citem_t {
// define these two struct members that can be used for casting.
cinsn_t *cinsn const;
cexpr_t *cexpr const;
ctype_t _get_op() const { return self->op; }
void _set_op(ctype_t v) { self->op = v; }
%pythoncode {
def _ensure_no_op(self):
if self.op not in [cot_empty, cit_empty]:
raise Exception("%s has op %s; cannot be modified" % (self, self.op))
return True
op = property(
_get_op,
lambda self, v: self._ensure_no_op() and self._set_op(v))
}
qstring __dbg_get_meminfo() const
{
qstring s;
s.sprnt("%p (op=%s)", self, get_ctype_name(self->op));
return s;
}
};
%monitored_lifecycle_object_t(citem_t);
%{
cinsn_t *citem_t_cinsn_get(citem_t *item) { return (cinsn_t *) item; }
cexpr_t *citem_t_cexpr_get(citem_t *item) { return (cexpr_t *) item; }
%}
//---------------------------------------------------------------------
// cinsn_t
@@ -404,21 +569,8 @@ public:
#define CINSN_MEMBER_REF(Name) \
___MEMBER_REF_BASE(c##Name##_t*, c##Name, self.op == cit_##Name, None, True, _v)
%feature("ref") cinsn_t
{
hexrays_register_python_clearable_instance($this, hxclr_cinsn);
if ( $this->op == cit_empty )
$this->cblock = NULL; // force clean instance
}
%feature("unref") cinsn_t
{
hexrays_deregister_python_clearable_instance($this);
delete $this;
}
%define_hexrays_lifecycle_object(cinsn_t);
%extend cinsn_t {
void _deregister() { hexrays_deregister_python_clearable_instance($self); }
void _register() { hexrays_register_python_clearable_instance($self, hxclr_cinsn); }
CINSN_MEMBER_REF(block);
CINSN_MEMBER_REF(expr);
CINSN_MEMBER_REF(if);
@@ -448,19 +600,8 @@ public:
#define CEXPR_MEMBER_REF_STR(Type, PName, Cond, Defval) \
___MEMBER_REF_BASE(Type, PName, Cond, Defval, False, ::qstrdup(_v))
%feature("ref") cexpr_t
{
hexrays_register_python_clearable_instance($this, hxclr_cexpr);
}
%feature("unref") cexpr_t
{
hexrays_deregister_python_clearable_instance($this);
delete $this;
}
%define_hexrays_lifecycle_object(cexpr_t);
%extend cexpr_t {
void _deregister() { hexrays_deregister_python_clearable_instance($self); }
void _register() { hexrays_register_python_clearable_instance($self, hxclr_cexpr); }
CEXPR_MEMBER_REF(cnumber_t*, n, self.op == cot_num, None, True);
CEXPR_MEMBER_REF(fnumber_t*, fpc, self.op == cot_fnum, None, True);
var_ref_t* get_v() { if ( self->op == cot_var ) { return &self->v; } else { return NULL; } }
@@ -530,9 +671,13 @@ public:
CTREE_CONDITIONAL_ITEM_MEMBER_REF(cinsn_t*, i, VDI_EXPR);
CTREE_CONDITIONAL_ITEM_MEMBER_REF(lvar_t*, l, VDI_LVAR);
CTREE_CONDITIONAL_ITEM_MEMBER_REF(cfunc_t*, f, VDI_FUNC);
treeloc_t* loc const { if ( self->citype == VDI_TAIL ) { return &self->loc; } else { return NULL; } }
treeloc_t *loc const;
};
%{
treeloc_t *ctree_item_t_loc_get(ctree_item_t *item) { return item->citype == VDI_TAIL ? &item->loc : NULL; }
%}
#undef CTREE_CONDITIONAL_ITEM_MEMBER_REF
#undef CTREE_ITEM_MEMBER_REF
@@ -656,12 +801,13 @@ class qlist_cinsn_t_iterator {};
%template(qvector_carg_t) qvector<carg_t>;
%template(qvector_ccase_t) qvector<ccase_t>;
%template(lvar_saved_infos_t) qvector<lvar_saved_info_t>;
%template(ui_stroff_ops_t) qvector<ui_stroff_op_t>;
%extend cblock_t {
cblock_t(void)
{
cblock_t *cb = new cblock_t();
hexrays_register_python_clearable_instance(cb, hxclr_cblock);
hexrays_register_python_clearable_instance(cb, hxclr_cblock_t);
return cb;
}
@@ -704,13 +850,7 @@ void qswap(cinsn_t &a, cinsn_t &b);
%ignore install_hexrays_callback;
%ignore remove_hexrays_callback;
%ignore decompile_many;
%rename (decompile_many) py_decompile_many;
%ignore decompile;
%ignore decompile_func;
%ignore decompile_snippet;
%rename (decompile) decompile_func;
%ignore get_widget_vdui;
%rename (get_widget_vdui) py_get_widget_vdui;
@@ -739,8 +879,6 @@ void qswap(cinsn_t &a, cinsn_t &b);
#error Ensure cfuncptr_t wrapping is compatible with this version of SWIG
#endif
%ignore decompile;
//---------------------------------------------------------------------
%define %python_callback_in(CB)
%typemap(check) CB {
@@ -792,7 +930,8 @@ void qswap(cinsn_t &a, cinsn_t &b);
//</inline(py_hexrays)>
%}
%ignore Hexrays_Callback;
%define_Hooks_class(Hexrays);
%ignore Hexrays_Hooks::hooked;
%inline %{
//<inline(py_hexrays_hooks)>
@@ -804,15 +943,15 @@ void qswap(cinsn_t &a, cinsn_t &b);
//</code(py_hexrays_hooks)>
%}
%include "hexrays.hpp"
%import "hexrays_templates.hpp";
%template(uval_ivl_t) ivl_tpl<uval_t>;
%template(uval_ivl_ivlset_t) ivlset_tpl<ivl_t, uval_t>;
%template(array_of_ivlsets) qvector<ivlset_t>;
%include "hexrays_notemplates.hpp"
%exception; // Delete & restore handlers
%exception_set_default_handlers();
// These are microcode-related. Let's not expose them right now.
/* %template(ivl_t) ivl_tpl<uval_t>; */
/* %template(ivlset_t) ivlset_tpl<ivl_t, uval_t>; */
/* %template(array_of_ivlsets) qvector<ivlset_t>; */
%pythoncode %{
#<pycode(py_hexrays)>
#</pycode(py_hexrays)>
+16
View File
@@ -11,6 +11,9 @@
%ignore idainfo::idainfo;
%ignore idainfo::~idainfo;
%ignore inf_get_procname();
%ignore inf_get_strlit_pref();
%ignore hook_cb_t;
%ignore hook_type_t;
%ignore hook_to_notification_point;
@@ -20,10 +23,18 @@
%ignore register_post_event_visitor;
%ignore unregister_post_event_visitor;
%ignore getinf;
%ignore getinf_buf;
%ignore getinf_flag;
%ignore setinf;
%ignore setinf_buf;
%ignore setinf_flag;
%extend idainfo
{
qstring get_abiname()
{
qnotused($self);
qstring buf;
get_abi_name(&buf);
return buf;
@@ -62,3 +73,8 @@
%include "ida.hpp"
%clear(char *buf);
%pythoncode %{
#<pycode(py_ida)>
#</pycode(py_ida)>
%}
+8 -3
View File
@@ -5,8 +5,6 @@
#include <err.h>
%}
%import "range.i"
%ignore free_debug_event;
%ignore copy_debug_event;
%ignore debugger_t;
@@ -14,12 +12,19 @@
%ignore lowcnd_vec_t;
%ignore update_bpt_info_t;
%ignore update_bpt_vec_t;
%ignore register_info_t;
%ignore appcall;
%ignore idd_opinfo_t;
%ignore gdecode_t;
%ignore memory_buffer_t;
%ignore debug_event_t::exit_code();
%ignore append_regval;
%ignore extract_regvals;
%ignore unpack_regvals;
%apply unsigned char { op_dtype_t dtype };
%ignore regval_t::_set_int;
%ignore regval_t::_set_float;
%ignore regval_t::_set_bytes;
%ignore regval_t::_set_unavailable;
%uncomparable_elements_qvector(exception_info_t, excvec_t);
%uncomparable_elements_qvector(process_info_t, procinfo_vec_t);
+28 -2
View File
@@ -5,7 +5,10 @@
#include <auto.hpp>
#include <fixup.hpp>
#include <tryblks.hpp>
struct undo_records_t;
%}
// Ignore the following symbols
%ignore rginfo;
%ignore insn_t::get_canon_mnem;
@@ -29,6 +32,9 @@
%ignore cfgopt_t__apply;
%ignore parse_config_value;
%define_Hooks_class(IDP);
%ignore _wrap_addr_in_pycobject;
%ignore s_preline;
%ignore ca_operation_t;
%ignore _chkarg_cmd;
@@ -40,7 +46,7 @@
%ignore instruc_t;
%ignore processor_t;
%ignore ph;
%ignore IDP_Callback;
%ignore IDP_Hooks::dispatch;
%ignore _py_getreg;
// @arnaud
@@ -121,7 +127,7 @@
#include <enum.hpp>
%}
%ignore IDB_Callback;
%define_Hooks_class(IDB);
%inline %{
//<inline(py_idp_idbhooks)>
@@ -132,3 +138,23 @@
//<code(py_idp_idbhooks)>
//</code(py_idp_idbhooks)>
%}
%pythoncode %{
#<pycode(py_idp_idbhooks)>
#</pycode(py_idp_idbhooks)>
%}
//-------------------------------------------------------------------------
// notify_when()
//-------------------------------------------------------------------------
%{
//<code(py_idp_notify_when)>
//</code(py_idp_notify_when)>
%}
%pythoncode %{
#<pycode(py_idp_notify_when)>
#</pycode(py_idp_notify_when)>
%}
+18 -11
View File
@@ -3,6 +3,10 @@
#include <parsejson.hpp>
%}
%apply qstring *result { qstring *label };
%apply qstring *result { qstring *shortcut };
%apply qstring *result { qstring *tooltip };
%{
#ifdef __NT__
idaman __declspec(dllimport) plugin_t PLUGIN;
@@ -18,6 +22,8 @@ extern plugin_t PLUGIN;
$result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
}
%ignore sync_source_t::sync_source_t();
// Ignore the va_list functions
%ignore vask_form;
%ignore ask_form;
@@ -43,6 +49,8 @@ extern plugin_t PLUGIN;
%thread ask_buttons;
%thread ask_file;
%ignore simpleline_t::simpleline_t(const qstring &);
%calls_execute_sync(clr_cancelled);
%calls_execute_sync(set_cancelled);
%calls_execute_sync(user_cancelled);
@@ -61,7 +69,9 @@ extern plugin_t PLUGIN;
%rename (msg) py_msg;
%ignore vinfo;
%ignore UI_Callback;
%define_Hooks_class(UI);
%ignore vnomem;
%ignore vmsg;
%ignore show_wait_box_v;
@@ -98,6 +108,9 @@ extern plugin_t PLUGIN;
%ignore get_registered_actions;
%rename (get_registered_actions) py_get_registered_actions;
%ignore add_spaces;
%rename (add_spaces) py_add_spaces;
%include "typemaps.i"
%rename (ask_text) py_ask_text;
@@ -130,12 +143,9 @@ extern plugin_t PLUGIN;
%ignore gen_disasm_text;
%rename (gen_disasm_text) py_gen_disasm_text;
%ignore UI_Hooks::handle_hint_output;
%ignore UI_Hooks::handle_get_ea_hint_output;
%ignore UI_Hooks::wrap_widget_cfg;
%ignore UI_Hooks::handle_create_desktop_widget_output;
%ignore jobj_wrapper_t::jobj_wrapper_t;
%ignore jobj_wrapper_t::~jobj_wrapper_t;
%ignore jobj_wrapper_t::fill_jobj_from_dict;
// We will %ignore those ATM, since they cannot be trivially
// wrapped: bytevec_t is not exposed.
@@ -231,10 +241,6 @@ void refresh_choosers(void)
%ignore textctrl_info_t;
SWIG_DECLARE_PY_CLINKED_OBJECT(textctrl_info_t)
%{
static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown);
%}
%{
//<decls(py_kernwin)>
//</decls(py_kernwin)>
@@ -311,6 +317,7 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown);
#endif
%pythoncode {
cur_extracted_ea = cur_value
#ifdef BC695
form = property(_get_form)
form_type = property(_get_form_type)
@@ -332,7 +339,7 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown);
int deflnnum = 0;
color_t pfx_color = 0;
bgcolor_t bgcolor = DEFCOLOR;
int generated = $self->generate(&lines, &deflnnum, &pfx_color, &bgcolor, ud, maxsize);
/*int generated = */ $self->generate(&lines, &deflnnum, &pfx_color, &bgcolor, ud, maxsize);
PyObject *tuple = PyTuple_New(4);
PyTuple_SetItem(tuple, 0, qstrvec2pylist(lines));
PyTuple_SetItem(tuple, 1, PyLong_FromLong(deflnnum));
@@ -438,7 +445,7 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown);
//-------------------------------------------------------------------------
// CustomIDAMemo
//-------------------------------------------------------------------------
%ignore View_Callback;
%define_Hooks_class(View);
%inline %{
//<inline(py_kernwin_viewhooks)>
+3
View File
@@ -80,6 +80,9 @@
%ignore load_and_run_plugin;
%rename (load_and_run_plugin) py_load_and_run_plugin;
%ignore extract_module_from_archive;
%rename (extract_module_from_archive) py_extract_module_from_archive;
%extend qvector< snapshot_t *> {
snapshot_t *at(size_t n) { return self->at(n); }
};
+195
View File
@@ -0,0 +1,195 @@
%{
#include <lumina.hpp>
%}
%feature("nodirector") lumina_client_t;
%ignore lumina_client_t::lumina_client_t;
%ignore metadata_t;
%ignore metadata_creator_t;
%ignore md5_t;
%ignore lumina_host;
%ignore lumina_port;
%ignore lumina_tls;
%ignore lumina_min_func_size;
%ignore lumina_rpc_packet_t_descs;
%ignore lumina_client_t::send_helo;
%ignore pattern_id_t::swap;
%ignore func_info_base_t::swap;
%ignore func_info_t::swap;
%ignore func_info_and_frequency_t::swap;
%ignore func_info_pattern_and_frequency_t::swap;
%ignore input_file_t::swap;
%ignore mdkey2str;
%ignore str2mdkey;
%ignore serialize;
%ignore deserialize;
%ignore new_lumina_client;
%ignore close_server_connection;
%ignore get_mdkey_preferred_format;
%ignore extract_type_from_metadata;
%rename (extract_type_from_metadata) py_extract_type_from_metadata;
%rename (split_metadata) py_split_metadata;
%ignore swap_md5;
%ignore print_md5;
%ignore parse_md5;
%ignore auto_apply_lumina;
%ignore eavec_to_ea64vec;
%ignore ea64vec_to_eavec;
%feature("nodirector") simple_diff_handler_t;
%ignore simple_diff_handler_t::simple_diff_handler_t;
%feature("nodirector") simple_idb_diff_handler_t;
%ignore simple_idb_diff_handler_t::simple_idb_diff_handler_t;
%ignore serialized_tinfo::empty;
%define %rpc_packet_data_t(TYPE, ENUMERATOR)
%feature("nodirector") TYPE;
%extend TYPE {
TYPE() { return (TYPE *) new_packet(ENUMERATOR); }
};
%ignore TYPE::TYPE;
%enddef
%rpc_packet_data_t(pkt_rpc_ok_t, PKT_RPC_OK);
%rpc_packet_data_t(pkt_rpc_fail_t, PKT_RPC_FAIL);
%rpc_packet_data_t(pkt_rpc_notify_t, PKT_RPC_NOTIFY);
%rpc_packet_data_t(pkt_helo_t, PKT_HELO);
%rpc_packet_data_t(pkt_pull_md_t, PKT_PULL_MD);
%rpc_packet_data_t(pkt_pull_md_result_t, PKT_PULL_MD_RESULT);
%rpc_packet_data_t(pkt_push_md_t, PKT_PUSH_MD);
%rpc_packet_data_t(pkt_push_md_result_t, PKT_PUSH_MD_RESULT);
%rpc_packet_data_t(pkt_get_pop_t, PKT_GET_POP);
%rpc_packet_data_t(pkt_get_pop_result_t, PKT_GET_POP_RESULT);
%rpc_packet_data_t(pkt_dump_md_t, PKT_DUMP_MD);
%rpc_packet_data_t(pkt_dump_md_result_t, PKT_DUMP_MD_RESULT);
%rpc_packet_data_t(pkt_clean_db_t, PKT_CLEAN_DB);
%rpc_packet_data_t(pkt_debugctl_t, PKT_DEBUGCTL);
%template(lumina_op_res_vec_t) qvector<lumina_op_res_t>;
//-------------------------------------------------------------------------
// metadata_t
//-------------------------------------------------------------------------
%bytes_container(metadata_t *, metadata_t, begin, size,);
%bytes_container(metadata_t &, metadata_t, begin, size,);
%typemap(argout) (qstring *errbuf) {
if ( !$1->empty() )
{
if ( $result != NULL )
delete $result;
SWIG_exception_fail(SWIG_RuntimeError, $1->c_str());
}
}
%uncomparable_elements_qvector(func_info_t, func_info_vec_t);
%uncomparable_elements_qvector(func_info_and_frequency_t, func_info_and_frequency_vec_t);
%uncomparable_elements_qvector(func_info_and_pattern_t, func_info_and_pattern_vec_t);
%uncomparable_elements_qvector(func_info_pattern_and_frequency_t, func_info_pattern_and_frequency_vec_t);
%uncomparable_elements_qvector(insn_cmt_t, insn_cmts_t);
%uncomparable_elements_qvector(user_stkpnt_t, user_stkpnts_t);
%uncomparable_elements_qvector(frame_mem_t, frame_mems_t);
%uncomparable_elements_qvector(extra_cmt_t, extra_cmts_t);
%uncomparable_elements_qvector(skipped_func_t, skipped_funcs_t);
%uncomparable_elements_qvector(insn_ops_repr_t, insn_ops_reprs_t);
//-------------------------------------------------------------------------
// metadata_t blob
//-------------------------------------------------------------------------
%typemap(in) (const uchar *ptr, const uchar *end) // for _wrap_extract_..._from_metadata
{
if ( !PyString_Check($input) )
SWIG_exception_fail(SWIG_TypeError, "Expected string in method '$symname', argument $argnum of type 'str'");
char *buf = NULL;
Py_ssize_t length = 0;
int success = PyString_AsStringAndSize($input, &buf, &length);
if ( success >= 0 )
{
$1 = (uchar *) buf;
$2 = $1 + length;
QASSERT(30575, $2 >= $1);
}
}
%apply metadata_t *result { metadata_t *out_md };
%typemap(argout) (metadata_t *out_md)
{
// bytes_container typemap(argout) (metadata_t *out_md)
PyObject *py_md = PyString_FromStringAndSize((const char *) $1->begin(), $1->size());
$result = SWIG_Python_AppendOutput($result, py_md);
}
//-------------------------------------------------------------------------
// md5_t
//-------------------------------------------------------------------------
%typemap(in) md5_t *md5 // for _wrap_input_file_t_md5_set
{
// typemap(in) md5_t *
char *buf = NULL;
Py_ssize_t length = 0;
/*int success =*/ PyString_AsStringAndSize($input, &buf, &length);
$1 = new md5_t;
memmove($1->hash, buf, qmin(sizeof($1->hash), length));
}
%typemap(freearg) md5_t *md5 // for _wrap_input_file_t_md5_set
{
// typemap(freearg) md5_t *
delete $1;
}
%typemap(out) md5_t *
{ // typemap(out) md5_t *
$result = PyString_FromStringAndSize((const char *) $1->hash, sizeof($1->hash));
}
// suppress the output parameter as an input.
%typemap(in,numinputs=0) md5_t *out (md5_t tmp) %{
// typemap(in,numinputs=0) md5_t *out
$1 = &tmp;
%}
%typemap(argout) (md5_t *out)
{
// typemap(argout) (md5_t *out)
PyObject *py_hash = PyString_FromStringAndSize((const char *) $1->hash, sizeof($1->hash));
$result = SWIG_Python_AppendOutput($result, py_hash);
}
%apply md5_t *out { md5_t *out_hash };
%apply longlong *INPUT { const int64 * };
%typemap(directorin) const int64 *
{ // %typemap(directorin) const int64 *
if ( $1 != NULL )
{
$input = PyLong_FromLongLong(longlong(*($1)));
}
else
{
Py_INCREF(Py_None);
$input = Py_None;
}
}
// We can't put that in header.i.in ATM, because it would
// inappropriately apply to the qstrvec_t/clink thing.
%typemap(out) qstrvec_t *
{ // %typemap(out) qstrvec_t *
resultobj = qstrvec2pylist(*($1));
}
%numbers_list_to_values_vec(ea64vec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PyListToEa64Vec);
%include "lumina.hpp"
%inline %{
//<inline(py_lumina)>
//</inline(py_lumina)>
%}
+5
View File
@@ -0,0 +1,5 @@
* DONE gen_microcode() creates a new mbl_array_t; user must delete it
* DONE mop_t::cstr must be dup'd when set
* DONE mop_t ownership might not be transferred when setting to a parent (and thus neither is mcallarg_t)
* TODO how about all visitors? scif_visitor_t, mop_visitor_t, ...
* TODO
+4 -2
View File
@@ -11,10 +11,12 @@
%ignore location_t::location_t(bool);
%ignore lochist_t::is_hexrays68_compat;
%ignore lochist_entry_t::set_place(const place_t &);
%ignore lochist_entry_t::serialize;
%ignore lochist_entry_t::deserialize;
%ignore graph_location_info_t::serialize(bytevec_t *) const;
%ignore graph_location_info_t::deserialize(const uchar **, const uchar *);
%ignore graph_location_info_t::deserialize(memory_deserializer_t &);
%ignore renderer_info_pos_t::serialize(bytevec_t *) const;
%ignore renderer_info_pos_t::deserialize(const uchar **, const uchar *);
%ignore renderer_info_pos_t::deserialize(memory_deserializer_t &);
%template(segm_move_info_vec_t) qvector<segm_move_info_t>;
+1 -2
View File
@@ -2,8 +2,7 @@
%cstring_bounded_output(char *dstname, MAXSTR);
%cstring_bounded_output(char *buf, MAXSTR);
%apply unsigned long *OUTPUT { uval_t *value }; // get_name_value
%apply unsigned long *INPUT { ea_t *ea_ptr }; // get_debug_name
%typemap(check) uval_t *value { *($1) = BADADDR; } // get_name_value
// FIXME: These should be fixed
%ignore get_struct_operand;
+2
View File
@@ -71,6 +71,7 @@
%ignore netnode_setblob;
%ignore netnode_delblob;
%ignore netnode_inited;
%ignore netnode_is_available;
%ignore netnode_copy;
%ignore netnode_altshift;
%ignore netnode_charshift;
@@ -89,6 +90,7 @@
%ignore netnode::upgrade;
%ignore netnode::compress;
%ignore netnode::inited;
%ignore netnode::is_available;
%ignore netnode::init;
%ignore netnode::can_write;
%ignore netnode::flush;
+29 -23
View File
@@ -10,6 +10,7 @@
%ignore qustrlen;
%ignore get_utf8_char;
%ignore put_utf8_char;
%ignore is_cp_graphical;
%ignore prev_utf8_char;
%ignore idb_utf8;
%ignore scr_utf8;
@@ -17,6 +18,9 @@
%ignore change_codepage;
%ignore utf16_utf8;
%ignore utf8_utf16;
%ignore is_lead_surrogate;
%ignore is_tail_surrogate;
%ignore utf16_surrogates_to_cp;
%ignore acp_utf8;
%ignore utf8_wchar16;
%ignore utf8_wchar32;
@@ -32,18 +36,22 @@
%ignore bitcount;
%ignore round_up_power2;
%ignore round_down_power2;
%ignore unpack_memory;
//<typemaps(pro)>
//</typemaps(pro)>
%include "pro.h"
// we must include those manually here
%import "ida.hpp"
%import "xref.hpp"
%import "typeinf.hpp"
%import "enum.hpp"
%import "netnode.hpp"
#ifdef IDA_MODULE_PRO
// we must include those manually here
%import "ida.hpp"
%import "xref.hpp"
%import "typeinf.hpp"
%import "enum.hpp"
%import "netnode.hpp"
#endif
//
void qvector<int>::grow(const int &x=0);
@@ -62,13 +70,9 @@ void qvector<unsigned long long>::grow(const unsigned long long &x=0);
%template(ulonglongvec_t) qvector<unsigned long long>;
%template(boolvec_t) qvector<bool>;
%pythoncode %{
%}
%uncomparable_elements_qvector(simpleline_t, strvec_t);
%template(sizevec_t) qvector<size_t>;
typedef uvalvec_t eavec_t;// vector of addresses
%template(sizevec_t) qvector<size_t>;
typedef uvalvec_t eavec_t; // vector of addresses
SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)
@@ -77,17 +81,19 @@ SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)
//</inline(py_pro)>
%}
%include "carrays.i"
%include "cpointer.i"
%array_class(uchar, uchar_array);
%array_class(tid_t, tid_array);
%array_class(ea_t, ea_array);
%array_class(sel_t, sel_array);
%array_class(uval_t, uval_array);
%pointer_class(int, int_pointer);
%pointer_class(ea_t, ea_pointer);
%pointer_class(sval_t, sval_pointer);
%pointer_class(sel_t, sel_pointer);
#ifdef IDA_MODULE_PRO
%include "carrays.i"
%include "cpointer.i"
%array_class(uchar, uchar_array);
%array_class(tid_t, tid_array);
%array_class(ea_t, ea_array);
%array_class(sel_t, sel_array);
%array_class(uval_t, uval_array);
%pointer_class(int, int_pointer);
%pointer_class(ea_t, ea_pointer);
%pointer_class(sval_t, sval_pointer);
%pointer_class(sel_t, sel_pointer);
#endif
%pythoncode %{
#<pycode(py_pro)>
+2
View File
@@ -36,6 +36,8 @@
%rename (reg_subkey_values) py_reg_subkey_values;
%ignore reg_subkey_children;
%apply qstrvec_t *out { qstrvec_t *list };
%{
//<code(py_registry)>
//</code(py_registry)>
-2
View File
@@ -1,7 +1,5 @@
// Ignore functions with callbacks
%import "range.i"
%ignore enumerate_selectors;
%ignore enumerate_segments_with_selector;
-2
View File
@@ -2,8 +2,6 @@
#include <segregs.hpp>
%}
%import "range.i"
// Ignore kernel-only symbols
%ignore delete_v660_segreg_t;
%ignore v660_segreg_t;
-2
View File
@@ -2,8 +2,6 @@
#include <tryblks.hpp>
%}
%import "range.i"
%ignore tryblk_t::reserve;
%ignore tryblk_t::cpp() const;
%ignore tryblk_t::seh() const;
+29 -30
View File
@@ -3,8 +3,6 @@
#include <struct.hpp>
%}
%import "idp.i"
// Most of these could be wrapped if needed
%ignore get_cc;
%ignore get_cc_type_size;
@@ -130,6 +128,7 @@
%ignore tinfo_t::serialize(qtype *, qtype *, qtype *, int) const;
%ignore name_requires_qualifier;
%ignore tinfo_visitor_t::level;
%ignore tinfo_t::deserialize(const til_t *, const qtype *, const qtype *, const qtype *);
%ignore custloc_desc_t;
%ignore install_custom_argloc;
@@ -149,6 +148,7 @@
}
}
//-------------------------------------------------------------------------
%extend tinfo_t {
PyObject *serialize(
@@ -166,38 +166,29 @@
return $self->deserialize(til, &type, &fields, cmts == NULL ? NULL : &cmts);
}
// The typemap in typeconv.i will take care of registering newly-constructed
// tinfo_t instances. However, there's no such thing as a destructor typemap.
// Therefore, we need to do the grunt work of de-registering ourselves.
// Note: The 'void' here is important: Without it, SWIG considers it to
// be a different destructor (which, of course, makes a ton of sense.)
~tinfo_t(void)
tinfo_t copy() const
{
til_deregister_python_tinfo_t_instance($self);
delete $self;
return *$self;
}
qstring __str__() const {
qstring __str__() const
{
qstring qs;
$self->print(&qs);
return qs;
}
}
%ignore tinfo_t::~tinfo_t(void);
//---------------------------------------------------------------------
// NOTE: This will ***NOT*** work for tinfo_t objects. Those must
// be created and owned (or not) according to the kind of access.
// To implement that, we use typemaps (see typeconv.i).
%define %simple_tinfo_t_container_lifecycle(Type, CtorSig, ParamsList)
%define %tinfo_t_or_simple_tinfo_t_container_lifecycle(Type)
// Instead of re-defining all constructors, add the registering
// to a specialized 'ret' typemap
%typemap(ret) Type* Type::Type
{
// %typemap(ret) Type* Type::Type
til_register_python_##Type##_instance($1);
}
%extend Type {
Type CtorSig
{
Type *inst = new Type ParamsList;
til_register_python_##Type##_instance(inst);
return inst;
}
~Type(void)
{
til_deregister_python_##Type##_instance($self);
@@ -205,14 +196,22 @@
}
}
%enddef
%simple_tinfo_t_container_lifecycle(ptr_type_data_t, (tinfo_t c=tinfo_t(), uchar bps=0, tinfo_t p=tinfo_t(), int32 d=0), (c, bps, p, d));
%simple_tinfo_t_container_lifecycle(array_type_data_t, (size_t b=0, size_t n=0), (b, n));
%simple_tinfo_t_container_lifecycle(func_type_data_t, (), ());
%simple_tinfo_t_container_lifecycle(udt_type_data_t, (), ());
%template(funcargvec_t) qvector<funcarg_t>;
%template(udtmembervec_t) qvector<udt_member_t>;
%template(reginfovec_t) qvector<reg_info_t>;
%tinfo_t_or_simple_tinfo_t_container_lifecycle(tinfo_t);
%tinfo_t_or_simple_tinfo_t_container_lifecycle(ptr_type_data_t);
%tinfo_t_or_simple_tinfo_t_container_lifecycle(array_type_data_t);
%tinfo_t_or_simple_tinfo_t_container_lifecycle(func_type_data_t);
%tinfo_t_or_simple_tinfo_t_container_lifecycle(udt_type_data_t);
%ignore tinfo_t::~tinfo_t(void);
%template(funcargvec_t) qvector<funcarg_t>;
%template(udtmembervec_t) qvector<udt_member_t>;
%template(reginfovec_t) qvector<reg_info_t>;
%template(enum_member_vec_t) qvector<enum_member_t>;
%template(argpartvec_t) qvector<argpart_t>;
%uncomparable_elements_qvector(valstr_t, valstrvec_t);
%uncomparable_elements_qvector(regobj_t, regobjvec_t);
%uncomparable_elements_qvector(type_attr_t, type_attrs_t);
%extend tinfo_t {
+1
View File
@@ -30,6 +30,7 @@
%ignore outctx_base_t::gen_vprintf;
%ignore outctx_base_t::get_xrefgen_state;
%ignore outctx_base_t::get_cmtgen_state;
%ignore outctx_base_t::get_binop_state;
%ignore outctx_base_t::regname_idx;
%ignore outctx_base_t::suspop;
+55 -33
View File
@@ -48,44 +48,44 @@ def check_cpp(opts):
#
"_wrap_qstrvec_t_assign" : {
"mustcall" : "qstrvec_t_assign"
},
},
"_wrap_qstrvec_t_addressof" : {
"mustcall" : "qstrvec_t_addressof"
},
},
"_wrap_qstrvec_t_set" : {
"mustcall" : "qstrvec_t_set"
},
},
"_wrap_qstrvec_t_from_list" : {
"mustcall" : "qstrvec_t_from_list"
},
},
"_wrap_qstrvec_t_size" : {
"mustcall" : "qstrvec_t_size"
},
},
"_wrap_qstrvec_t_get" : {
"mustcall" : "qstrvec_t_get"
},
},
"_wrap_qstrvec_t_add" : {
"mustcall" : "qstrvec_t_add"
},
},
"_wrap_qstrvec_t_clear" : {
"mustcall" : "qstrvec_t_clear"
},
},
"_wrap_qstrvec_t_insert" : {
"mustcall" : "qstrvec_t_insert"
},
},
"_wrap_qstrvec_t_remove" : {
"mustcall" : "qstrvec_t_remove"
},
},
#
# Misc.
#
"_wrap_tinfo_t_deserialize__SWIG_2" : {
"mustcall" : "tinfo_t_deserialize__SWIG_2",
},
"_wrap_tinfo_t_deserialize__SWIG_1" : {
"mustcall" : "tinfo_t_deserialize__SWIG_1",
},
"_wrap_get_bpt_group" : {
"mustcall" : "PyString_FromStringAndSize",
},
"mustcall" : "_maybe_sized_cstring_result",
},
"_wrap_get_ip_val" : {
"string" : "resultobj = PyLong_FromUnsigned",
},
@@ -95,6 +95,15 @@ def check_cpp(opts):
"SwigDirector_UI_Hooks::populating_widget_popup" : {
"string" : "get_callable_arg_count",
},
"_wrap_idc_get_local_type" : {
"mustcall" : "__chkreqidb"
},
"_wrap_append_argloc" : {
"mustcall" : "__chkreqidb"
},
"_wrap_is_type_ptr" : {
"nostring" : "__chkreqidb",
},
# "_wrap_get_array_parameters" : {
# "string" : "resultobj = PyLong_FromLongLong(result)",
@@ -125,14 +134,14 @@ def check_cpp(opts):
# },
"_wrap_guess_tinfo" : {
"mustcall" : "PyW_GetNumber",
},
},
"_wrap_IDP_Hooks_ev_adjust_refinfo" : {
"string" : "fixup_data_t",
},
},
# char[ANY] out typemap
"_wrap_idainfo_tag_get" : {
"nostring" : " --size;",
},
},
"_wrap_warning__varargs__" : {
"nullptrcheck" : 1, # 1st arg
@@ -174,28 +183,28 @@ def check_cpp(opts):
functions_coherence_hexrays = {
"_wrap_cfuncptr_t___str__" : {
"mustcall" : ["cfunc_t___str__", "PyString_FromStringAndSize"],
},
},
"_wrap_cfunc_t___str__" : {
"mustcall" : ["cfunc_t___str__", "PyString_FromStringAndSize"],
},
},
"_wrap_hexrays_failure_t_desc" : {
"mustcall" : "PyString_FromStringAndSize",
},
},
"_wrap_vd_failure_t_desc" : {
"mustcall" : "PyString_FromStringAndSize",
},
},
"_wrap_create_field_name" : {
"mustcall" : "PyString_FromStringAndSize",
},
},
"delete_qrefcnt_t_Sl_cfunc_t_Sg_" : {
"mustcall" : "hexrays_deregister_python_clearable_instance",
},
"_wrap__decompile" : {
},
"_wrap_decompile" : {
"mustcall" : "hexrays_register_python_clearable_instance",
},
},
"_wrap_vdui_t_cfunc_get" : {
"mustcall" : "hexrays_register_python_clearable_instance",
},
},
"delete_cexpr_t" : {
"mustcall" : "hexrays_deregister_python_clearable_instance",
},
@@ -229,26 +238,30 @@ def check_cpp(opts):
"_wrap_boundaries_find" : {
"nostring" : "SWIGTYPE_p_p_cinsn_t",
},
"mbl_array_t_serialize" : {
"string" : "bytes_container typemap(argout) (bytevec_t &vout)",
"mustcall" : "PyString_FromStringAndSize",
},
#
# qvector<simpleline_t>
#
"_wrap_strvec_t___len__" : {
"mustcall" : "qvector_Sl_simpleline_t_Sg____len__",
},
},
"_wrap_strvec_t___setitem__" : {
"mustcall" : "qvector_Sl_simpleline_t_Sg____setitem__",
},
},
"_wrap_strvec_t___getitem__" : {
"mustcall" : "qvector_Sl_simpleline_t_Sg____getitem__",
},
},
#
# vdui_t::cfunc
#
"_wrap_vdui_t_cfunc_get" : {
"string" : "SWIGTYPE_p_qrefcnt_tT_cfunc_t_t", # proper typemap must be used
},
}
},
}
functions_coherence = functions_coherence_base.copy()
if opts.with_hexrays:
@@ -385,6 +398,12 @@ def check_cpp(opts):
"func_pat_t_relbits_set",
"new_func_md_t",
"new_func_pat_t",
"DBG_Hooks_dump_state",
"Hexrays_Hooks_dump_state",
"IDB_Hooks_dump_state",
"IDP_Hooks_dump_state",
"UI_Hooks_dump_state",
"View_Hooks_dump_state",
]
to_report = sorted(filter(
lambda fn: fn not in ignorable_functions,
@@ -426,7 +445,7 @@ def check_python(opts):
"insn_t" : { "mustinherit" : "object" },
"op_t" : { "mustinherit" : "object" },
"plugin_t" : { "mustinherit" : "pyidc_opaque_object_t" },
"processor_t" : { "mustinherit" : "ida_idaapi.pyidc_opaque_object_t" },
"processor_t" : { "mustinherit" : "IDP_Hooks" },
"py_clinked_object_t" : { "mustinherit" : "pyidc_opaque_object_t" },
"segm_move_infos_t" : { "mustinherit" : "segm_move_info_vec_t" },
"simpleline_place_t" : { "mustinherit" : "place_t" },
@@ -463,7 +482,10 @@ def check_python(opts):
"qstring_printer_t" : { "mustinherit" : "vc_printer_t" },
"vc_printer_t" : { "mustinherit" : "vd_printer_t" },
"vd_interr_t" : { "mustinherit" : "vd_failure_t" },
# "casm_t" : { "mustinherit" : "eavec_t" },
# "vivl_t" : { "mustinherit" : "ivl_t" },
"ivl_t" : { "mustinherit" : "uval_ivl_t" },
"ivlset_t" : { "mustinherit" : "uval_ivl_ivlset_t" },
}
types_coherence = types_coherence_base.copy()
+3 -2
View File
@@ -184,12 +184,13 @@ def deploy(module, template, output, pywraps, iface_deps, lifecycle_aware, verbo
%%init %%{
{
module_callbacks_t module_lfc;
module_lfc.closebase = ida_%s_closebase;
module_lfc.init = ida_%s_init;
module_lfc.term = ida_%s_term;
module_lfc.closebase = ida_%s_closebase;
register_module_lifecycle_callbacks(module_lfc);
}
%%}
""" % (module, module))
""" % (module, module, module))
deploy(
args.module,
+249 -139
View File
@@ -1,8 +1,12 @@
#ifndef __HEADER_I__
#define __HEADER_I__
%{
#ifndef USE_DANGEROUS_FUNCTIONS
#define USE_DANGEROUS_FUNCTIONS 1
#endif
#include <pro.h>
#undef DEPRECATED
#define DEPRECATED
%}
// Auto-inserted header
@@ -18,8 +22,6 @@
%feature("nodirector") qstring_printer_t;
%feature("nodirector") simpleline_place_t;
%feature("nodirector") structplace_t;
%feature("nodirector") vc_printer_t;
%feature("nodirector") vd_printer_t;
%feature("nodirector") qflow_chart_t;
%feature("nodirector") lowertype_helper_t;
%feature("nodirector") ida_lowertype_helper_t;
@@ -119,6 +121,7 @@
%ignore clear_bit;
%ignore set_all_bits;
%ignore clear_all_bits;
%ignore interval::last;
%ignore interval::overlap;
%ignore interval::includes;
%ignore interval::contains;
@@ -158,11 +161,6 @@
// Do not move this. We need to override the define from pro.h
#define CASSERT(type)
// If the module is 'pro', don't import pro.h, or the %include
// at the beginning of pro.i won't have any effect. Same for all
// modules.
${ALL_IMPORTS}
%pythoncode {
import ida_idaapi
}
@@ -199,13 +197,13 @@ if _BC695:
// instead of that:
// resultobj = SWIG_From_unsigned_SS_int(static_cast< unsigned int >(*result));
inline const T& __getitem__(size_t i) const {
if (i >= $self->size() || i < 0)
if ( i >= $self->size() )
throw std::out_of_range("out of bounds access");
return $self->at(i);
}
inline void __setitem__(size_t i, const T& v) {
if (i >= $self->size() || i < 0)
if ( i >= $self->size() )
throw std::out_of_range("out of bounds access");
$self->at(i) = v;
}
@@ -221,56 +219,13 @@ if _BC695:
}
}
%{
static void __raise_ba(const std::bad_alloc &ba)
{
PyErr_SetString(PyExc_MemoryError, "Out of memory (bad_alloc)");
}
static void __raise_u()
{
PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
}
static void __raise_e(const std::exception &e)
{
const char *what = e.what();
if ( what == NULL || what[0] == '\0' )
{
__raise_u();
}
else
{
PyErr_SetString(PyExc_RuntimeError, what);
}
}
static void __raise_ie(const interr_exc_t &ie)
{
qstring emsg;
emsg.sprnt(INTERR_EXC_FMT, ie.code);
PyErr_SetString(PyExc_RuntimeError, emsg.begin());
}
static void __raise_de(const Swig::DirectorException &e)
{
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
}
static void __raise_oor(const std::out_of_range &e)
{
PyErr_SetString(PyExc_IndexError, e.what());
}
static bool __chkthr()
{
bool ok = is_main_thread();
if ( !ok )
PyErr_SetString(PyExc_RuntimeError, "Function can be called from the main thread only");
return ok;
}
%}
#if IDAPYTHON_MODULE_hexrays
%define %ida_hexrays_wrapper_exception_catch()
catch ( const vd_failure_t &e ) { __raise_vdf(e); SWIG_fail; }
%enddef
#else
%define %ida_hexrays_wrapper_exception_catch()%enddef
#endif
%define %exception_set_default_handlers()
%exception {
@@ -280,7 +235,7 @@ static bool __chkthr()
}
catch ( const std::bad_alloc &ba ) { __raise_ba(ba); SWIG_fail; }
catch ( const std::out_of_range &e ) { __raise_oor(e); SWIG_fail; }
catch ( const interr_exc_t &e ) { __raise_ie(e); SWIG_fail; }
catch ( const interr_exc_t &e ) { __raise_ie(e); SWIG_fail; }%ida_hexrays_wrapper_exception_catch()
catch ( const std::exception &e ) { __raise_e(e); SWIG_fail; }
catch ( const Swig::DirectorException &e ) { __raise_de(e); SWIG_fail; }
catch ( ... ) { __raise_u(); SWIG_fail; }
@@ -432,48 +387,73 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
$2 = int(temp.size());
}
%{
SWIGINTERN PyObject *_maybe_cstring_result(
PyObject *resultobj,
const char *cstr,
int result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
return PyString_FromString(cstr);
}
SWIGINTERN PyObject *_maybe_sized_cstring_result(
PyObject *resultobj,
const char *cstr,
size_t cstrsz,
int result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
return PyString_FromStringAndSize(cstr, cstrsz);
}
SWIGINTERN PyObject *_maybe_binary_result(
PyObject *resultobj,
void *buf,
ssize_t result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
return PyString_FromStringAndSize((const char *) buf, result);
}
%}
//---------------------------------------------------------------------
%define %cstring_output_maxstr_none(TYPEMAP, SIZE)
%typemap (default) SIZE {
$1 = MAXSTR;
%define %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG)
%typemap(default) (BUFFER_ARG, SIZE_ARG) {
// %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG) %typemap(default) (BUFFER_ARG, SIZE_ARG)
$2 = MAXSTR;
}
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
%typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG) {
// %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG) %typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG)
$1 = ($1_ltype) qalloc(MAXSTR+1);
}
%typemap(argout) (TYPEMAP,SIZE) {
Py_XDECREF(resultobj);
if (result > 0)
{
resultobj = PyString_FromString($1);
}
else
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
%typemap(argout) (BUFFER_ARG, SIZE_ARG) {
// %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG) %typemap(argout) (BUFFER_ARG, SIZE_ARG)
resultobj = _maybe_cstring_result(resultobj, $1, int(result));
qfree($1);
}
%enddef
//---------------------------------------------------------------------
%define %binary_output_or_none(TYPEMAP, SIZE)
%typemap (default) SIZE {
$1 = MAXSPECSIZE;
%define %binary_output_or_none(BUFFER_ARG, SIZE_ARG)
%typemap(default) (BUFFER_ARG, SIZE_ARG) {
// %binary_output_or_none(BUFFER_ARG, SIZE_ARG) %typemap(default) (BUFFER_ARG, SIZE_ARG)
$2 = MAXSPECSIZE;
}
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
%typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG) {
// %binary_output_or_none(BUFFER_ARG, SIZE_ARG) %typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG)
$1 = (char *) qalloc(MAXSPECSIZE+1);
}
%typemap(argout) (TYPEMAP,SIZE) {
Py_XDECREF(resultobj);
if (result > 0)
{
resultobj = PyString_FromStringAndSize((char *)$1, result);
}
else
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
%typemap(argout) (BUFFER_ARG, SIZE_ARG) {
// %binary_output_or_none(BUFFER_ARG, SIZE_ARG) %typemap(argout) (BUFFER_ARG, SIZE_ARG)
resultobj = _maybe_binary_result(resultobj, $1, ssize_t(result));
qfree((void *)$1);
}
%enddef
@@ -617,6 +597,10 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
// IN/OUT qstring/bytevec_t
//---------------------------------------------------------------------
%define %bytes_container(REFTYPE, CONTAINER_TYPE, START_ACCESSOR, SIZE_ACCESSOR, INSTANCE_CAST)
%typemap(typecheck) REFTYPE
{ // bytes_container REFTYPE typemap(typecheck)
$1 = PyString_Check($input) ? 1 : 0;
}
%typemap(in) REFTYPE
{ // bytes_container REFTYPE, CONTAINER_TYPE typemap(in)
if ( PyString_Check($input) )
@@ -657,25 +641,31 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
// bytes_container typemap(in,numinputs=0) CONTAINER_TYPE *result (CONTAINER_TYPE temp)
$1 = &temp;
}
%typemap(in,numinputs=0) CONTAINER_TYPE &result (CONTAINER_TYPE temp)
{
// bytes_container typemap(in,numinputs=0) CONTAINER_TYPE &result (CONTAINER_TYPE temp)
$1 = &temp;
}
%typemap(argout) CONTAINER_TYPE *result
{
// bytes_container typemap(argout) CONTAINER_TYPE *result
Py_XDECREF(resultobj);
if (result > 0)
{
resultobj = PyString_FromStringAndSize((const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
else
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
resultobj = _maybe_sized_cstring_result(resultobj, $1->START_ACCESSOR(), $1->SIZE_ACCESSOR(), int(result));
}
%typemap(argout) CONTAINER_TYPE &result
{
// bytes_container typemap(argout) CONTAINER_TYPE &result
resultobj = _maybe_sized_cstring_result(resultobj, $1->START_ACCESSOR(), $1->SIZE_ACCESSOR(), int(result));
}
%typemap(freearg) CONTAINER_TYPE* result
{
// bytes_container typemap(freearg) CONTAINER_TYPE *result
// Nothing. We certainly don't want 'temp' to be deleted.
}
%typemap(freearg) CONTAINER_TYPE& result
{
// bytes_container typemap(freearg) CONTAINER_TYPE &result
// Nothing. We certainly don't want 'temp' to be deleted.
}
// We determine that the following parameter: "CONTAINER_TYPE *vout" has the
// following characteristics:
// - the C function being called returns void
@@ -684,6 +674,7 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
//
// Re-use the 'CONTAINER_TYPE *result' typemaps, ...
%apply CONTAINER_TYPE *result { CONTAINER_TYPE *vout };
%apply CONTAINER_TYPE &result { CONTAINER_TYPE &vout };
// ...but override the argout one, so that it doesn't rely on a 'result'
%typemap(argout) (CONTAINER_TYPE *vout)
{
@@ -691,6 +682,28 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
Py_XDECREF(resultobj);
resultobj = PyString_FromStringAndSize((const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
%typemap(argout) (CONTAINER_TYPE &vout)
{
// bytes_container typemap(argout) (CONTAINER_TYPE &vout)
Py_XDECREF(resultobj);
resultobj = PyString_FromStringAndSize((const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
%typemap(directorin) CONTAINER_TYPE *
{ // bytes_container typemap(directorin) CONTAINER_TYPE *
if ( $1 != NULL )
{
$input = PyString_FromStringAndSize($1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
else
{
Py_INCREF(Py_None);
$input = Py_None;
}
}
%typemap(directorin) REFTYPE
{ // bytes_container typemap(directorin) REFTYPE
$input = PyString_FromStringAndSize($1.START_ACCESSOR(), $1.SIZE_ACCESSOR());
}
%enddef
%bytes_container(qstring *, qstring, c_str, length,);
@@ -733,26 +746,27 @@ typedef long long longlong;
#endif
#ifdef __EA64__
%apply longlong *INOUT { sval_t *value };
%apply longlong *INOUT { sval_t *value };
%apply longlong *INOUT { adiff_t *disp };
%apply ulonglong *INOUT { ea_t *addr };
%apply ulonglong *INOUT { sel_t *sel };
%apply ulonglong *INOUT { ea_t *addr };
%apply ulonglong *INPUT { ea_t *ea_ptr }; // get_debug_name
%apply ulonglong *INOUT { sel_t *sel };
%apply ulonglong *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_range_selection()
%apply ulonglong *OUTPUT { ea_t *from, ea_t *to, asize_t *size }; // get_mapping()
%apply ulonglong *OUTPUT { uval_t *value }; // get_name_value
#else
%apply int *INOUT { sval_t *value };
%apply int *INOUT { adiff_t *disp };
%apply unsigned int *INOUT { ea_t *addr };
%apply unsigned int *INOUT { sel_t *sel };
%apply unsigned int *INOUT { ea_t *addr };
%apply unsigned int *INPUT { ea_t *ea_ptr }; // get_debug_name
%apply unsigned int *INOUT { sel_t *sel };
%apply unsigned int *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_range_selection()
%apply unsigned int *OUTPUT { ea_t *from, ea_t *to, asize_t *size }; // get_mapping()
%apply unsigned int *OUTPUT { uval_t *value }; // get_name_value
#endif
%apply long long { qoff64_t };
%apply qstring *result { qstring *label };
%apply qstring *result { qstring *shortcut };
%apply qstring *result { qstring *tooltip };
%apply qstring *result { qstring *out };
%apply qstring *result { qstring *buf };
%apply qstring *result { qstring *errbuf };
@@ -785,16 +799,16 @@ struct wrapped_array_t {
%mutable;
%extend wrapped_array_t {
inline size_t __len__() const { return N; }
inline size_t __len__() const { qnotused($self); return N; }
inline const Type& __getitem__(size_t i) const throw(std::out_of_range) {
if (i >= N || i < 0)
if ( i >= N )
throw std::out_of_range("out of bounds access");
return $self->data[i];
}
inline void __setitem__(size_t i, const Type& v) throw(std::out_of_range) {
if (i >= N || i < 0)
if ( i >= N )
throw std::out_of_range("out of bounds access");
$self->data[i] = v;
}
@@ -822,13 +836,13 @@ struct dynamic_wrapped_array_t {
inline size_t __len__() const { return $self->count; }
inline const Type& __getitem__(size_t i) const throw(std::out_of_range) {
if (i >= $self->count || i < 0)
if ( i >= $self->count )
throw std::out_of_range("out of bounds access");
return $self->data[i];
}
inline void __setitem__(size_t i, const Type& v) throw(std::out_of_range) {
if (i >= $self->count || i < 0)
if ( i >= $self->count )
throw std::out_of_range("out of bounds access");
$self->data[i] = v;
}
@@ -849,27 +863,6 @@ struct dynamic_wrapped_array_t {
$result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0);
}
// KLUDGE: We'll let the compiler (or at worse the runtime)
// decide of the flags to use, depending on the method we are currently
// wrapping: at new-time, a SWIG_POINTER_NEW is required.
%typemap(out) tinfo_t* {}
%typemap(ret) tinfo_t*
{
// ret tinfo_t*
tinfo_t *ni = new tinfo_t(*($1));
til_register_python_tinfo_t_instance(ni);
if ( strcmp("new_tinfo_t", "$symname") == 0 )
{
$result = SWIG_NewPointerObj(SWIG_as_voidptr(ni), $1_descriptor, SWIG_POINTER_NEW | 0);
delete $1;
}
else
{
$result = SWIG_NewPointerObj(SWIG_as_voidptr(ni), $1_descriptor, SWIG_POINTER_OWN | 0);
}
}
%typemap(check) tinfo_t*
{
if ( $1 == NULL )
@@ -883,12 +876,12 @@ struct dynamic_wrapped_array_t {
%cstring_output_maxstr_none(char *buf, size_t bufsize);
%cstring_output_maxstr_none(char *buf, int bufsize);
%binary_output_or_none(void *buf, size_t bufsize);
%binary_output_with_size(void *buf, size_t *bufsize);
// Accept single Python string for const void * + size input arguments
// For example: put_many_bytes() and patch_many_bytes()
%apply (char *STRING, int LENGTH) { (const void *buf, size_t size) };
%apply (char *STRING, int LENGTH) { (const void *buf, size_t bufsize) };
%apply (char *STRING, int LENGTH) { (const void *buf, size_t len) };
%apply (char *STRING, int LENGTH) { (const void *value, size_t length) };
%apply (char *STRING, int LENGTH) { (const void *dataptr,size_t len) };
@@ -906,7 +899,7 @@ struct dynamic_wrapped_array_t {
%{
static PyObject *qstrvec2pylist(const qstrvec_t &vec)
SWIGINTERN PyObject *qstrvec2pylist(const qstrvec_t &vec)
{
size_t n = vec.size();
PyObject *py_list = PyList_New(n);
@@ -942,14 +935,14 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec)
%define %uint_result_as_output(TYPE, CONVFUNC)
%typemap(in,numinputs=0) TYPE *result (TYPE temp)
{
// %typemap(in,numinputs=0) TYPE *result
// %uint_result_as_output(TYPE, CONVFUNC) %typemap(in,numinputs=0) TYPE *result
$1 = &temp;
}
%typemap(argout) TYPE *result
{
// %typemap(argout) TYPE *result
// %uint_result_as_output(TYPE, CONVFUNC) %typemap(argout) TYPE *result
Py_XDECREF(resultobj);
if (result > 0)
if ( int(result) > 0 )
{
resultobj = CONVFUNC(*(TYPE *) $1);
}
@@ -1083,7 +1076,11 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec)
%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, *);
%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, &);
%enddef
#ifdef __EA64__
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PyListToEaVec);
#else
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_int_t, PyW_PyListToEaVec);
#endif
//-------------------------------------------------------------------------
// Make sure the GIL is released, in case 'NAME' is calling execute_sync
@@ -1092,10 +1089,123 @@ static PyObject *qstrvec2pylist(const qstrvec_t &vec)
%thread NAME;
%enddef
#ifdef TESTABLE_BUILD
# define HOOKS_DUMP_STATE() %ignore NAME##_Hooks::dump_state;
#else
# define HOOKS_DUMP_STATE()
#endif
%define %define_Hooks_class(NAME)
%ignore NAME##_Callback;
%ignore NAME##_Hooks::dispatch;
%ignore NAME##_Hooks::mappings;
%ignore NAME##_Hooks::mappings_size;
HOOKS_DUMP_STATE();
%enddef
%{
#include <expr.hpp>
#include <ieee.h>
#include "../../../pywraps.hpp"
%}
%{
#ifdef __EA64__
# define ea_t_SWIGTYPE_name SWIGTYPE_p_unsigned_long_long
#else
# define ea_t_SWIGTYPE_name SWIGTYPE_p_unsigned_int
#endif
SWIGINTERN void __raise_ba(const std::bad_alloc &SWIGUNUSEDPARM(ba))
{
PyErr_SetString(PyExc_MemoryError, "Out of memory (bad_alloc)");
}
SWIGINTERN void __raise_u()
{
PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
}
SWIGINTERN void __raise_e(const std::exception &e)
{
const char *what = e.what();
if ( what == NULL || what[0] == '\0' )
{
__raise_u();
}
else
{
PyErr_SetString(PyExc_RuntimeError, what);
}
}
SWIGINTERN void __raise_ie(const interr_exc_t &ie)
{
qstring emsg;
emsg.sprnt(INTERR_EXC_FMT, ie.code);
PyErr_SetString(PyExc_RuntimeError, emsg.begin());
}
SWIGINTERN void __raise_de(const Swig::DirectorException &e)
{
bool handled = false;
if ( PyErr_Occurred() != NULL )
{
// Add the new bits of info to the error
PyObject *exception, *v, *tb;
PyErr_Fetch(&exception, &v, &tb);
if ( exception != NULL )
{
PyErr_NormalizeException(&exception, &v, &tb);
if ( exception != NULL )
{
// FIXME: We retrieve the message, but not the context (i.e., the
// stack trace.) Ideally we should perhaps swoop in our own
// 'sys.stderr', call PyErr_Print(), retrieve the result, and
// append that to the new exception message.
newref_t as_str(PyObject_Str(v));
if ( as_str != NULL )
{
qstring buf(e.getMessage());
buf.append(" : ");
buf.append(PyString_AsString(as_str.o));
PyErr_SetString(PyExc_RuntimeError, buf.c_str());
handled = true;
}
}
}
}
if ( !handled )
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
}
SWIGINTERN void __raise_oor(const std::out_of_range &e)
{
PyErr_SetString(PyExc_IndexError, e.what());
}
SWIGINTERN bool __chkthr()
{
bool ok = is_main_thread();
if ( !ok )
PyErr_SetString(PyExc_RuntimeError, "Function can be called from the main thread only");
return ok;
}
SWIGINTERN bool __chkreqidb()
{
bool ok = netnode::inited();
if ( !ok )
PyErr_SetString(PyExc_RuntimeError, "Function requires a database");
return ok;
}
%}
// If the module is 'pro', don't import pro.h, or the %include
// at the beginning of pro.i won't have any effect. Same for all
// modules.
${ALL_IMPORTS}
#endif // __HEADER_I__
// END: auto-inserted header
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More