mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
IDAPython for IDA 7.3
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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))
|
||||
|
||||
@@ -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.')
|
||||
|
||||
@@ -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.')
|
||||
@@ -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.')
|
||||
|
||||
@@ -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.')
|
||||
|
||||
@@ -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,5 +1,6 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import ida_idaapi
|
||||
import ida_pro
|
||||
import ida_hexrays
|
||||
import ida_kernwin
|
||||
|
||||
@@ -9,6 +9,7 @@ from __future__ import print_function
|
||||
|
||||
import idautils
|
||||
import idc
|
||||
import ida_idaapi
|
||||
import ida_hexrays
|
||||
import ida_lines
|
||||
|
||||
|
||||
+2
-4
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -3,6 +3,7 @@ Various hooks for Hexrays Decompiler
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import ida_idaapi
|
||||
import ida_typeinf
|
||||
import ida_hexrays
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -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
@@ -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
@@ -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
@@ -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():
|
||||
|
||||
@@ -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
@@ -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
@@ -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(
|
||||
|
||||
@@ -44,6 +44,7 @@ static int idaapi py_visit_patched_bytes_cb(
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static void ida_bytes_init(void) {}
|
||||
static void ida_bytes_term(void) {}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)>
|
||||
|
||||
@@ -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);
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)>
|
||||
|
||||
@@ -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)>
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
+464
-623
File diff suppressed because it is too large
Load Diff
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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)>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,8 +2,6 @@
|
||||
#include <bytes.hpp>
|
||||
%}
|
||||
|
||||
%import "range.i"
|
||||
|
||||
// Unexported and kernel-only declarations
|
||||
%ignore testf_t;
|
||||
%ignore next_that;
|
||||
|
||||
+19
-9
@@ -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)>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
%ignore qlfile;
|
||||
%ignore make_linput;
|
||||
%ignore unmake_linput;
|
||||
%ignore linput_buffer_t;
|
||||
|
||||
%ignore eread;
|
||||
%ignore ewrite;
|
||||
|
||||
@@ -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,8 +2,6 @@
|
||||
#include <frame.hpp>
|
||||
%}
|
||||
|
||||
%import "range.i"
|
||||
|
||||
%ignore add_frame_spec_member;
|
||||
%ignore del_stkvars;
|
||||
%ignore calc_frame_offset;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
|
||||
%import "range.i"
|
||||
|
||||
%{
|
||||
#include <frame.hpp>
|
||||
%}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include <gdl.hpp>
|
||||
%}
|
||||
|
||||
%import "range.i"
|
||||
|
||||
%ignore cancellable_graph_t;
|
||||
%ignore gdl_graph_t;
|
||||
|
||||
|
||||
+3
-2
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)>
|
||||
|
||||
@@ -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
@@ -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)>
|
||||
%}
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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)>
|
||||
|
||||
@@ -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)>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// Ignore functions with callbacks
|
||||
|
||||
%import "range.i"
|
||||
|
||||
%ignore enumerate_selectors;
|
||||
%ignore enumerate_segments_with_selector;
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include <segregs.hpp>
|
||||
%}
|
||||
|
||||
%import "range.i"
|
||||
|
||||
// Ignore kernel-only symbols
|
||||
%ignore delete_v660_segreg_t;
|
||||
%ignore v660_segreg_t;
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user