diff --git a/Scripts/AsmViewer.py b/Scripts/AsmViewer.py
index 7b78cfe..3b7e951 100644
--- a/Scripts/AsmViewer.py
+++ b/Scripts/AsmViewer.py
@@ -3,11 +3,14 @@
# The sample will allow you to open an assembly file and display it in color
# (c) Hex-Rays
#
-import idaapi
-import idautils
-import idc
+
import os
+import ida_idaapi
+import ida_kernwin
+import ida_lines
+import idautils
+
# ----------------------------------------------------------------------
class asm_colorizer_t(object):
def is_id(self, ch):
@@ -79,11 +82,38 @@ class asm_colorizer_t(object):
x += 1
self.add_line(s)
+
+class base_asmview_ah_t(ida_kernwin.action_handler_t):
+ def __init__(self, obj):
+ ida_kernwin.action_handler_t.__init__(self)
+ self.obj = obj
+
+ def update(self, ctx):
+ if self.obj.view and self.obj.view.GetWidget() == ctx.widget:
+ return ida_kernwin.AST_ENABLE_FOR_WIDGET
+ else:
+ return ida_kernwin.AST_DISABLE_FOR_WIDGET
+
+
+class refresh_ah_t(base_asmview_ah_t):
+ def activate(self, ctx):
+ self.obj.view.reload_file()
+ print("Reloaded")
+
+
+class close_ah_t(base_asmview_ah_t):
+ def activate(self, ctx):
+ self.obj.view.Close()
+ print("Closed")
+
+
# -----------------------------------------------------------------------
-class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
+class asmview_t(ida_kernwin.simplecustviewer_t, asm_colorizer_t):
def Create(self, fn):
# Create the customview
- if not idaapi.simplecustviewer_t.Create(self, "Viewing file - %s" % os.path.basename(fn)):
+ if not ida_kernwin.simplecustviewer_t.Create(
+ self,
+ "Viewing file - %s" % os.path.basename(fn)):
return False
self.instruction_list = idautils.GetInstructionList()
@@ -95,9 +125,6 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
if not self.reload_file():
return False
- self.id_refresh = self.AddPopupMenu("Refresh")
- self.id_close = self.AddPopupMenu("Close")
-
return True
def reload_file(self):
@@ -123,38 +150,25 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
self.AddLine(s)
def as_comment(self, s):
- return idaapi.COLSTR(s, idaapi.SCOLOR_RPTCMT)
+ return ida_lines.COLSTR(s, ida_lines.SCOLOR_RPTCMT)
def as_id(self, s):
t = s.lower()
if t in self.register_list:
- return idaapi.COLSTR(s, idaapi.SCOLOR_REG)
+ return ida_lines.COLSTR(s, ida_lines.SCOLOR_REG)
elif t in self.instruction_list:
- return idaapi.COLSTR(s, idaapi.SCOLOR_INSN)
+ return ida_lines.COLSTR(s, ida_lines.SCOLOR_INSN)
else:
return s
def as_string(self, s):
- return idaapi.COLSTR(s, idaapi.SCOLOR_STRING)
+ return ida_lines.COLSTR(s, ida_lines.SCOLOR_STRING)
def as_num(self, s):
- return idaapi.COLSTR(s, idaapi.SCOLOR_NUMBER)
+ return ida_lines.COLSTR(s, ida_lines.SCOLOR_NUMBER)
def as_directive(self, s):
- return idaapi.COLSTR(s, idaapi.SCOLOR_KEYWORD)
-
- def OnPopupMenu(self, menu_id):
- """
- A context (or popup) menu item was executed.
- @param menu_id: ID previously registered with AddPopupMenu()
- @return: Boolean
- """
- if self.id_refresh == menu_id:
- return self.reload_file()
- elif self.id_close == menu_id:
- self.Close()
- return True
- return False
+ return ida_lines.COLSTR(s, ida_lines.SCOLOR_KEYWORD)
def OnKeydown(self, vkey, shift):
"""
@@ -170,8 +184,8 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
lineno = self.GetLineNo()
if lineno is not None:
line, fg, bg = self.GetLine(lineno)
- if line and line[0] != idaapi.SCOLOR_INV:
- s = idaapi.SCOLOR_INV + line + idaapi.SCOLOR_INV
+ if line and line[0] != ida_lines.SCOLOR_INV:
+ s = ida_lines.SCOLOR_INV + line + ida_lines.SCOLOR_INV
self.EditLine(lineno, s, fg, bg)
self.Refresh()
elif vkey == ord('C'):
@@ -186,8 +200,11 @@ class asmview_t(idaapi.simplecustviewer_t, asm_colorizer_t):
return True
# -----------------------------------------------------------------------
-class asmviewplg(idaapi.plugin_t):
- flags = idaapi.PLUGIN_KEEP
+ACTNAME_REFRESH = "asmview_t::refresh"
+ACTNAME_CLOSE = "asmview_t::close"
+
+class asmviewplg(ida_idaapi.plugin_t):
+ flags = ida_idaapi.PLUGIN_KEEP
comment = "ASM viewer"
help = "This is help"
wanted_name = "ASM file viewer"
@@ -196,17 +213,30 @@ class asmviewplg(idaapi.plugin_t):
self.view = None
def init(self):
- return idaapi.PLUGIN_KEEP
+ # Register actions
+ ida_kernwin.register_action(
+ ida_kernwin.action_desc_t(
+ ACTNAME_REFRESH, "Refresh", refresh_ah_t(self)))
+ ida_kernwin.register_action(
+ ida_kernwin.action_desc_t(
+ ACTNAME_CLOSE, "Close", close_ah_t(self)))
+ return ida_idaapi.PLUGIN_KEEP
+
def run(self, arg):
if self.view:
self.Close()
- fn = idaapi.ask_file(0, "*.asm", "Select ASM file to view")
+ fn = ida_kernwin.ask_file(0, "*.asm", "Select ASM file to view")
if not fn:
return
self.view = asmview_t()
if not self.view.Create(fn):
return
self.view.Show()
+ widget = self.view.GetWidget()
+
+ # Attach actions to this widget's popup menu
+ ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_REFRESH)
+ ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_CLOSE)
def term(self):
if self.view:
diff --git a/Scripts/CallStackWalk.py b/Scripts/CallStackWalk.py
index cb63383..1a5f3cd 100644
--- a/Scripts/CallStackWalk.py
+++ b/Scripts/CallStackWalk.py
@@ -4,17 +4,19 @@ 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-2009 Hex-Rays
+Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
-
-
-v1.0 - initial version
-v1.0.1 - added stack segment bitness detection, thus works with 64bit processes too
"""
-import idaapi
-import idc
+import ida_ua
+import ida_bytes
+import ida_kernwin
+import ida_funcs
+import ida_name
+import ida_ida
+import ida_idp
+import ida_segment
+import ida_dbg
import idautils
-from ida_kernwin import Choose
# -----------------------------------------------------------------------
# class to take a copy of a segment_t
@@ -24,6 +26,7 @@ class Seg():
self.end_ea = s.end_ea
self.perm = s.perm
self.bitness = s.bitness
+
def __cmp__(self, other):
return cmp(self.start_ea, other.start_ea)
@@ -51,18 +54,18 @@ def IsPrevInsnCall(ea):
is a CALL instruction
"""
global CallPattern
- if ea == idaapi.BADADDR or ea < 10:
+ if ea == ida_idaapi.BADADDR or ea < 10:
return None
for delta, opcodes in CallPattern:
# assume caller's ea
caller = ea + delta
# get the bytes
- bytes = [x for x in GetDataList(caller, len(opcodes), 1)]
+ bytes = [x for x in idautils.GetDataList(caller, len(opcodes), 1)]
# do we have a match? is it a call instruction?
if bytes == opcodes:
- tmp = idaapi.insn_t()
- if idaapi.decode_insn(tmp, caller) and idaapi.is_call_insn(tmp):
+ insn = ida_ua.insn_t()
+ if ida_ua.decode_insn(insn, caller) and ida_idp.is_call_insn(insn):
return caller
return None
@@ -79,32 +82,35 @@ def CallStackWalk(nn):
def __init__(self, caller, sp):
self.caller = caller
self.sp = sp
- f = idaapi.get_func(caller)
- self.displ = ""
+ f = ida_funcs.get_func(caller)
+ self.displ = "%08x: " % caller
if f:
- self.displ += idc.get_func_name(caller)
+ self.displ += ida_funcs.get_func_name(caller)
t = caller - f.start_ea
if t > 0: self.displ += "+" + hex(t)
else:
self.displ += hex(caller)
self.displ += " [" + hex(sp) + "]"
+ def __str__(self):
+ return self.displ
+
# get stack pointer
- sp = cpu.Esp
- seg = idaapi.getseg(sp)
+ sp = idautils.cpu.Esp
+ seg = ida_segment.getseg(sp)
if not seg:
return (False, "Could not locate stack segment!")
stack_seg = Seg(seg)
word_size = 2 ** (seg.bitness + 1)
callers = []
- sp = cpu.Esp - word_size
+ sp = idautils.cpu.Esp - word_size
while sp < stack_seg.end_ea:
sp += word_size
ptr = idautils.GetDataList(sp, 1, word_size).next()
- seg = idaapi.getseg(ptr)
+ seg = ida_segment.getseg(ptr)
# only accept executable segments
- if (not seg) or ((seg.perm & idaapi.SEGPERM_EXEC) == 0):
+ if (not seg) or ((seg.perm & ida_segment.SEGPERM_EXEC) == 0):
continue
# try to find caller
caller = IsPrevInsnCall(ptr)
@@ -118,16 +124,16 @@ def CallStackWalk(nn):
if ret:
ea = ret[0]
# function exists?
- f = idaapi.get_func(ea)
+ f = ida_funcs.get_func(ea)
if not f:
# create function
- idc.add_func(ea, idaapi.BADADDR)
+ ida_funcs.add_func(ea)
# get the flags
- f = idc.get_flags(caller)
+ f = ida_bytes.get_flags(caller)
# no code there?
- if not is_code(f):
- create_insn(caller)
+ if not ida_bytes.is_code(f):
+ ida_ua.create_insn(caller)
callers.append(Result(caller, sp))
#
@@ -135,52 +141,46 @@ def CallStackWalk(nn):
# -----------------------------------------------------------------------
# Chooser class
-class CallStackWalkChoose(Choose):
+class CallStackWalkChoose(ida_kernwin.Choose):
def __init__(self, title, items):
- Choose.__init__(self, title, [ ["Caller", 16], ["Display", 250] ])
+ ida_kernwin.Choose.__init__(
+ self,
+ title,
+ [["Location", 30]])
self.items = items
-
- def OnGetLine(self, n):
- o = self.items[n]
- line = []
- line.append("%X" % o.caller)
- line.append("%s" % o.displ)
- return line
+ self.modal = True
def OnGetSize(self):
return len(self.items)
+ def OnGetLine(self, n):
+ return [str(self.items[n])]
+
def OnSelectLine(self, n):
- o = self.items[n]
- jumpto(o.caller)
- return (Choose.NOTHING_CHANGED, )
+ ida_kernwin.jumpto(self.items[n].caller)
# -----------------------------------------------------------------------
def main():
- if not idaapi.is_debugger_on():
- idc.warning("Please run the process first!")
+ if not ida_dbg.is_debugger_on():
+ ida_kernwin.warning("Please run the process first!")
return
- if idaapi.get_process_state() != -1:
- idc.warning("Please suspend the debugger first!")
+ if ida_dbg.get_process_state() != -1:
+ ida_kernwin.warning("Please suspend the debugger first!")
return
- # only avail from IdaPython r232
- if hasattr(idaapi, "NearestName"):
- # get all debug names
- dn = idaapi.get_debug_names(idaapi.cvar.inf.min_ea, idaapi.cvar.inf.max_ea)
- # initiate a nearest name search (using debug names)
- nn = idaapi.NearestName(dn)
- else:
- nn = None
+ # get all debug namesp
+ dn = ida_name.get_debug_names(ida_ida.cvar.inf.min_ea, ida_ida.cvar.inf.max_ea)
+ # initiate a nearest name search (using debug names)
+ nn = ida_name.NearestName(dn)
ret, callstack = CallStackWalk(nn)
if ret:
- title = "Call stack walker (thread %X)" % (get_current_thread())
- idaapi.close_chooser(title)
+ title = "Call stack walker (thread %X)" % (ida_dbg.get_current_thread())
+ ida_kernwin.close_chooser(title)
c = CallStackWalkChoose(title, callstack)
- c.Show()
+ c.Show(True)
else:
- idc.warning("Failed to walk the stack:" + callstack)
+ ida_kernwin.warning("Failed to walk the stack:" + callstack)
# -----------------------------------------------------------------------
main()
diff --git a/Scripts/DbgCmd.py b/Scripts/DbgCmd.py
index d19e564..e3e8e2d 100644
--- a/Scripts/DbgCmd.py
+++ b/Scripts/DbgCmd.py
@@ -2,37 +2,70 @@
# Debugger command prompt with CustomViewers
# (c) Hex-Rays
#
-import idaapi
-import idc
-from idaapi import simplecustviewer_t
+import ida_idaapi
+import ida_kernwin
+import ida_lines
+import ida_expr
+import ida_dbg
-def SendDbgCommand(cmd):
- """Sends a command to the debugger and returns the output string.
- An exception will be raised if the debugger is not running or the current debugger does not export
- the 'send_dbg_command' IDC command.
- """
- s = idc.eval('send_dbg_command("%s");' % cmd)
- if s.startswith("IDC_FAILURE"):
- raise Exception, "Debugger command is available only when the debugger is active!"
- return s
+# The viewer instance
+dbgcmd = None
# -----------------------------------------------------------------------
-class dbgcmd_t(simplecustviewer_t):
+class base_dbgcmd_ah_t(ida_kernwin.action_handler_t):
+ def __init__(self):
+ ida_kernwin.action_handler_t.__init__(self)
+
+ def update(self, ctx):
+ if dbgcmd and ctx.widget == dbgcmd.GetWidget():
+ return ida_kernwin.AST_ENABLE_FOR_WIDGET
+ else:
+ return ida_kernwin.AST_DISABLE_FOR_WIDGET
+
+# -----------------------------------------------------------------------
+class clear_dbgcmd_ah_t(base_dbgcmd_ah_t):
+ def activate(self, ctx):
+ dbgcmd.ResetOutput()
+
+# -----------------------------------------------------------------------
+class newcmd_dbgcmd_ah_t(base_dbgcmd_ah_t):
+ def activate(self, ctx):
+ dbgcmd.IssueCommand()
+
+# -----------------------------------------------------------------------
+class close_dbgcmd_ah_t(base_dbgcmd_ah_t):
+ def activate(self, ctx):
+ dbgcmd.Close()
+
+# -----------------------------------------------------------------------
+# Register actions (if needed)
+ACTNAME_CLEAR = "dbgcmd:clear"
+ACTNAME_NEWCMD = "dbgcmd:newcmd"
+ACTNAME_CLOSE = "dbgcmd:close"
+ida_kernwin.register_action(
+ ida_kernwin.action_desc_t(
+ ACTNAME_CLEAR, "Clear", clear_dbgcmd_ah_t(), "x"))
+ida_kernwin.register_action(
+ ida_kernwin.action_desc_t(
+ ACTNAME_NEWCMD, "New command", newcmd_dbgcmd_ah_t(), "Insert"))
+ida_kernwin.register_action(
+ ida_kernwin.action_desc_t(
+ ACTNAME_CLOSE, "Close", close_dbgcmd_ah_t(), "Escape"))
+
+# -----------------------------------------------------------------------
+class dbgcmd_t(ida_kernwin.simplecustviewer_t):
def Create(self):
# Form the title
title = "Debugger command window"
# Create the customview
- if not simplecustviewer_t.Create(self, title):
+ if not ida_kernwin.simplecustviewer_t.Create(self, title):
return False
self.last_cmd = ""
- self.menu_clear = self.AddPopupMenu("Clear")
- self.menu_cmd = self.AddPopupMenu("New command")
-
self.ResetOutput()
return True
def IssueCommand(self):
- s = idaapi.ask_str(self.last_cmd, 0, "Please enter a debugger command")
+ s = ida_kernwin.ask_str(self.last_cmd, 0, "Please enter a debugger command")
if not s:
return
@@ -40,43 +73,24 @@ class dbgcmd_t(simplecustviewer_t):
self.last_cmd = s
# Add it using a different color
- self.AddLine("debugger>" + idaapi.COLSTR(s, idaapi.SCOLOR_VOIDOP))
+ self.AddLine("debugger>" + ida_lines.COLSTR(s, ida_lines.SCOLOR_VOIDOP))
- try:
- r = SendDbgCommand(s).split("\n")
- for s in r:
- self.AddLine(idaapi.COLSTR(s, idaapi.SCOLOR_LIBNAME))
- except:
- self.AddLine(idaapi.COLSTR("Debugger is not active or does not export send_dbg_command()", idaapi.SCOLOR_ERROR))
+ ok, out = ida_dbg.send_dbg_command(s)
+ if ok:
+ for line in out.split("\n"):
+ self.AddLine(ida_lines.COLSTR(line, ida_lines.SCOLOR_LIBNAME))
+ else:
+ self.AddLine(
+ ida_lines.COLSTR(
+ "Debugger is not active or does not export ida_dbg.send_dbg_command() (%s)" % out,
+ ida_lines.SCOLOR_ERROR))
self.Refresh()
def ResetOutput(self):
self.ClearLines()
- self.AddLine(idaapi.COLSTR("Please press INS to enter command; X to clear output", idaapi.SCOLOR_AUTOCMT))
+ self.AddLine(ida_lines.COLSTR("Please press INS to enter command; X to clear output", ida_lines.SCOLOR_AUTOCMT))
self.Refresh()
- def OnKeydown(self, vkey, shift):
- # ESCAPE?
- if vkey == 27:
- self.Close()
- # VK_INSERT
- elif vkey == 45:
- self.IssueCommand()
- elif vkey == ord('X'):
- self.ResetOutput()
- else:
- return False
- return True
-
- def OnPopupMenu(self, menu_id):
- if menu_id == self.menu_clear:
- self.ResetOutput()
- elif menu_id == self.menu_cmd:
- self.IssueCommand()
- else:
- # Unhandled
- return False
- return True
# -----------------------------------------------------------------------
def show_win():
@@ -85,17 +99,16 @@ def show_win():
print "Failed to create debugger command line!"
return None
x.Show()
+
+ # Attach actions to this widget's popup menu
+ widget = x.GetWidget()
+ ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_CLEAR)
+ ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_NEWCMD)
+ ida_kernwin.attach_action_to_popup(widget, None, ACTNAME_CLOSE)
return x
-try:
- # created already?
- dbgcmd
+if dbgcmd is not None:
dbgcmd.Close()
- del dbgcmd
-except:
- pass
+ dbgcmd = None
dbgcmd = show_win()
-if not dbgcmd:
- del dbgcmd
-
diff --git a/Scripts/DrvsDispatch.py b/Scripts/DrvsDispatch.py
index ae7c298..defbb74 100644
--- a/Scripts/DrvsDispatch.py
+++ b/Scripts/DrvsDispatch.py
@@ -2,30 +2,34 @@
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
-Copyright (c) 1990-2009 Hex-Rays
+Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
"""
import re
-import idc
-from ida_kernwin import Choose
+
+import ida_idaapi
+import ida_expr
+import ida_kernwin
+import ida_dbg
+
+# -----------------------------------------------------------------------
+def WinDbg_command(cmd):
+ ok, s = ida_dbg.send_dbg_command(cmd)
+ return s if ok else False
# -----------------------------------------------------------------------
def CmdDriverList():
- s = idc.eval('send_dbg_command("lm o");')
- if "IDC_FAILURE" in s: return False
- return s
+ return WinDbg_command("lm o")
# -----------------------------------------------------------------------
def CmdDrvObj(drvname, flag=2):
- return idc.eval('send_dbg_command("!drvobj %s %d");' % (drvname, flag))
+ return WinDbg_command("!drvobj %s %d" % (drvname, flag))
# -----------------------------------------------------------------------
def CmdReloadForce():
- s = idc.eval('send_dbg_command(".reload /f");')
- if "IDC_FAILURE" in s: return False
- return True
+ return WinDbg_command(".reload /f")
# -----------------------------------------------------------------------
# class to hold dispatch entry information
@@ -33,82 +37,83 @@ class DispatchEntry:
def __init__(self, addr, name):
self.addr = addr
self.name = name
+ def __repr__(self):
+ return "%08X: %s" % (self.addr, self.name)
# -----------------------------------------------------------------------
def GetDriverDispatch():
- # return a list of arrays of the form: [addr, name]
- ret_list = []
-
- # build the RE for parsing output from the "lm o" command
- re_drv = re.compile('^[a-f0-9]+\s+[a-f0-9]+\s+(\S+)', re.I)
- # build the RE for parsing output from the "!drvobj DRV_NAME 2" command
- re_tbl = re.compile('^\[\d{2}\]\s+IRP_MJ_(\S+)\s+([0-9a-f]+)', re.I)
+ # return a list of arrays of the form: [addr, name]
+ ret_list = []
- # force reloading of module symbols
- if not CmdReloadForce():
- print "Could not communicate with WinDbg, make sure the debugger is running!"
- return None
+ # build the RE for parsing output from the "lm o" command
+ re_drv = re.compile('^[a-f0-9]+\s+[a-f0-9]+\s+(\S+)', re.I)
- # get driver list
- lm_out = CmdDriverList()
- if not lm_out:
- return "Failed to get driver list!"
+ # build the RE for parsing output from the "!drvobj DRV_NAME 2" command
+ re_tbl = re.compile('^\[\d{2}\]\s+IRP_MJ_(\S+)\s+([0-9a-f]+)', re.I)
- # for each line
- for line in lm_out.split("\n"):
- # parse
- r = re_drv.match(line)
- if not r: continue
+ # force reloading of module symbols
+ if not CmdReloadForce():
+ print "Could not communicate with WinDbg, make sure the debugger is running!"
+ return None
- # extract driver name
- drvname = r.group(1).strip()
-
- # execute "drvobj" command
- tbl_out = CmdDrvObj(drvname)
-
- if not tbl_out:
- print "Failed to get driver object for", drvname
- continue
+ # get driver list
+ lm_out = CmdDriverList()
+ if not lm_out:
+ return "Failed to get driver list!"
# for each line
- for line in tbl_out.split("\n"):
+ for line in lm_out.split("\n"):
# parse
- r = re_tbl.match(line)
+ r = re_drv.match(line)
if not r: continue
- disp_addr = int(r.group(2), 16) # convert hex string to number
- disp_name = "Dispatch" + r.group(1)
- ret_list.append(DispatchEntry(disp_addr, drvname + "_" + disp_name))
- return ret_list
+ # extract driver name
+ drvname = r.group(1).strip()
+
+ # execute "drvobj" command
+ tbl_out = CmdDrvObj(drvname)
+
+ if not tbl_out:
+ print "Failed to get driver object for", drvname
+ continue
+
+ # for each line
+ for line in tbl_out.split("\n"):
+ # parse
+ r = re_tbl.match(line)
+ if not r: continue
+ disp_addr = int(r.group(2), 16) # convert hex string to number
+ disp_name = "Dispatch" + r.group(1)
+ ret_list.append(DispatchEntry(disp_addr, drvname + "_" + disp_name))
+
+ return ret_list
# -----------------------------------------------------------------------
# Chooser class
-class DispatchChoose(Choose):
+class DispatchChoose(ida_kernwin.Choose):
def __init__(self, title, items):
- Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ])
+ ida_kernwin.Choose.__init__(
+ self,
+ title,
+ [["Address", 30]],
+ width=250)
self.items = items
- def OnGetLine(self, n):
- o = self.items[n]
- line = []
- line.append("%08X" % o.addr)
- line.append("%s" % o.name)
- return line
-
def OnGetSize(self):
return len(self.items)
+ def OnGetLine(self, n):
+ return [str(self.items[n])]
+
def OnSelectLine(self, n):
- o = self.items[n]
- Jump(o.addr)
- return (Choose.NOTHING_CHANGED, )
+ ida_kernwin.jumpto(self.items[n].addr)
# -----------------------------------------------------------------------
# main
r = GetDriverDispatch()
if r:
c = DispatchChoose("Dispatch table browser", r)
- c.Show()
+ c.Show(True)
else:
- print "Failed to retrieve dispatchers list!"
+ print "Failed to retrieve dispatchers list!"
diff --git a/Scripts/ExchainDump.py b/Scripts/ExchainDump.py
index 75c729d..bb29f28 100644
--- a/Scripts/ExchainDump.py
+++ b/Scripts/ExchainDump.py
@@ -7,56 +7,48 @@ ALL RIGHTS RESERVED.
"""
-import idc
import re
+
import ida_kernwin
-from ida_kernwin import Choose
# class to store parsed results
class exchain:
def __init__(self, m):
- self.name = m.group(1)
- self.addr = int(m.group(2), 16)
+ self.name = m.group(1)
+ self.addr = int(m.group(2), 16)
# Chooser class
-class MyChoose(Choose):
+class MyChoose(ida_kernwin.Choose):
def __init__(self, title, items):
- Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ])
+ ida_kernwin.Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ])
self.items = items
def OnGetLine(self, n):
o = self.items[n]
- line = []
- line.append("%08X" % o.addr)
- line.append("%s" % o.name)
- return line
+ return ["%08X" % o.addr, o.name]
def OnGetSize(self):
return len(self.items)
def OnSelectLine(self, n):
- o = self.items[n]
- Jump(o.addr)
- return (Choose.NOTHING_CHANGED, )
+ ida_kernwin.jumpto(self.items[n].addr)
+ return (ida_kernwin.Choose.NOTHING_CHANGED, )
-# main
def main():
- s = idc.eval('send_dbg_command("!exchain")')
- if "IDC_FAILURE" in s:
- return (False, "Cannot execute the command")
+ ok, s = ida_dbg.send_dbg_command("!exchain")
+ if not ok:
+ return (False, "Cannot execute the command (%s)" % s)
matches = re.finditer(r'[^:]+: ([^\(]+) \(([^\)]+)\)\n', s)
- L = []
- for x in matches:
- L.append(exchain(x))
- if not L:
+ entries = [exchain(x) for x in matches]
+ if not entries:
return (False, "Nothing to display: Could parse the result!")
- # Get a Choose instance
- chooser = MyChoose("Exchain choose", L)
- # Run the chooser
+ # Show a list of results, and let the user possibly jump to one of those
+ chooser = MyChoose("Exchain choose", entries)
chooser.Show()
return (True, "Success!")
+
ok, r = main()
if not ok:
print r
diff --git a/Scripts/FindInstructions.py b/Scripts/FindInstructions.py
index d85d67c..8c50017 100644
--- a/Scripts/FindInstructions.py
+++ b/Scripts/FindInstructions.py
@@ -1,5 +1,5 @@
"""
-FindInstructions.py: A script to help you find desired opcodes/instructions in a database
+A script to help you find desired opcodes/instructions in a database
The script accepts opcodes and assembly statements (which will be assembled) separated by semicolon
@@ -13,15 +13,22 @@ 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-2009 Hex-Rays
+Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
-
-v1.0 - initial version
"""
-import idaapi
+import re
+
+import ida_idaapi
+import ida_lines
+import ida_segment
+import ida_kernwin
+import ida_bytes
+import ida_ua
+import ida_ida
+import ida_search
+import ida_funcs
+
import idautils
-import idc
-from ida_kernwin import Choose
# -----------------------------------------------------------------------
def FindInstructions(instr, asm_where=None):
@@ -31,8 +38,9 @@ def FindInstructions(instr, asm_where=None):
"""
if not asm_where:
# get first segment
- asm_where = get_first_seg()
- if asm_where == idaapi.BADADDR:
+ seg = ida_segment.get_first_seg()
+ asm_where = seg.start_ea if seg else ida_idaapi.BADADDR
+ if asm_where == ida_idaapi.BADADDR:
return (False, "No segments defined")
# regular expression to distinguish between opcodes and instructions
@@ -49,7 +57,7 @@ def FindInstructions(instr, asm_where=None):
buf = ''.join([chr(int(x, 16)) for x in line.split()])
else:
# assemble the instruction
- ret, buf = Assemble(asm_where, line)
+ ret, buf = idautils.Assemble(asm_where, line)
if not ret:
return (False, "Failed to assemble:"+line)
# add the assembled buffer
@@ -66,63 +74,66 @@ def FindInstructions(instr, asm_where=None):
# find all binary strings
print "Searching for: [%s]" % bin_str
- ea = get_inf_attr(INF_MIN_EA)
+ ea = ida_ida.cvar.inf.min_ea
ret = []
while True:
- ea = find_binary(ea, SEARCH_DOWN, bin_str)
- if ea == idaapi.BADADDR:
+ ea = ida_search.find_binary(ea, ida_idaapi.BADADDR, bin_str, 16, ida_search.SEARCH_DOWN)
+ if ea == ida_idaapi.BADADDR:
break
ret.append(ea)
- msg(".")
+ ida_kernwin.msg(".")
ea += tlen
if not ret:
return (False, "Could not match [%s]" % bin_str)
- msg("\n")
+ ida_kernwin.msg("\n")
return (True, ret)
# -----------------------------------------------------------------------
# Chooser class
-class SearchResultChoose(Choose):
+class SearchResultChoose(ida_kernwin.Choose):
def __init__(self, title, items):
- Choose.__init__(self, title, [ ["Address", 16], ["Results", 250] ])
+ ida_kernwin.Choose.__init__(
+ self,
+ title,
+ [["Address", 30], ["Function (or segment)", 25], ["Instruction", 20]],
+ width=250)
self.items = items
- def OnGetLine(self, n):
- o = self.items[n]
- line = []
- line.append("%08X" % o.ea)
- line.append("%s" % o.display)
- return line
-
def OnGetSize(self):
return len(self.items)
+ def OnGetLine(self, n):
+ i = self.items[n]
+ ea = i.ea
+ return [
+ hex(i.ea),
+ i.funcname_or_segname,
+ i.text
+ ]
+
def OnSelectLine(self, n):
- o = self.items[n]
- Jump(o.ea)
- return (Choose.NOTHING_CHANGED, )
+ ida_kernwin.jumpto(self.items[n].ea)
# -----------------------------------------------------------------------
# class to represent the results
class SearchResult:
def __init__(self, ea):
self.ea = ea
- if not is_code(get_flags(ea)):
- create_insn(ea)
- t = idaapi.generate_disasm_line(ea)
+ self.funcname_or_segname = ""
+ self.text = ""
+ if not ida_bytes.is_code(ida_bytes.get_flags(ea)):
+ ida_ua.create_insn(ea)
+
+ # text
+ t = ida_lines.generate_disasm_line(ea)
if t:
- line = idaapi.tag_remove(t)
- else:
- line = ""
- func = get_func_name(ea)
- self.display = ""
- if func:
- self.display += func + ": "
- else:
- n = get_segm_name(ea)
- if n:
- self.display += n + ": "
- self.display += line
+ self.text = ida_lines.tag_remove(t)
+
+ # funcname_or_segname
+ n = ida_funcs.get_func_name(ea) \
+ or ida_segment.get_segm_name(ida_segment.getseg(ea))
+ if n:
+ self.funcname_or_segname = n
# -----------------------------------------------------------------------
def find(s=None, x=False, asm_where=None):
@@ -132,16 +143,16 @@ def find(s=None, x=False, asm_where=None):
if x:
results = []
for ea in ret:
- seg = idaapi.getseg(ea)
- if (not seg) or (seg.perm & idaapi.SEGPERM_EXEC) == 0:
+ seg = ida_segment.getseg(ea)
+ if (not seg) or (seg.perm & ida_segment.SEGPERM_EXEC) == 0:
continue
results.append(SearchResult(ea))
else:
results = [SearchResult(ea) for ea in ret]
title = "Search result for: [%s]" % s
- idaapi.close_chooser(title)
+ ida_kernwin.close_chooser(title)
c = SearchResultChoose(title, results)
- c.Show()
+ c.Show(True)
else:
print ret
diff --git a/Scripts/ImpRef.py b/Scripts/ImpRef.py
index 9d9471c..fe6827a 100644
--- a/Scripts/ImpRef.py
+++ b/Scripts/ImpRef.py
@@ -4,12 +4,14 @@
#
# (c) Hex-Rays
#
-
-import idaapi
-import idc
-import idautils
import re
+import ida_kernwin
+import ida_nalt
+import ida_funcs
+
+import idautils
+
# -----------------------------------------------------------------------
def find_imported_funcs(dllname):
def imp_cb(ea, name, ord):
@@ -19,12 +21,12 @@ def find_imported_funcs(dllname):
return True
imports = []
- nimps = idaapi.get_import_module_qty()
+ nimps = ida_nalt.get_import_module_qty()
for i in xrange(0, nimps):
- name = idaapi.get_import_module_name(i)
+ name = ida_nalt.get_import_module_name(i)
if re.match(dllname, name, re.IGNORECASE) is None:
continue
- idaapi.enum_import_names(i, imp_cb)
+ ida_nalt.enum_import_names(i, imp_cb)
return imports
@@ -38,9 +40,9 @@ def find_import_ref(dllname):
for xref in idautils.XrefsTo(ea):
# check if referrer is a thunk
ea = xref.frm
- f = idaapi.get_func(ea)
- if f and (f.flags & idaapi.FUNC_THUNK) != 0:
- imports.append([f.start_ea, idaapi.get_func_name(f.start_ea), 0])
+ f = ida_funcs.get_func(ea)
+ if f and (f.flags & ida_funcs.FUNC_THUNK) != 0:
+ imports.append([f.start_ea, ida_funcs.get_func_name(f.start_ea), 0])
#print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.start_ea)
continue
@@ -54,7 +56,7 @@ def find_import_ref(dllname):
# -----------------------------------------------------------------------
def main():
- dllname = idaapi.ask_str('kernel32', 0, "Enter module name")
+ dllname = ida_kernwin.ask_str('kernel32', 0, "Enter module name")
if not dllname:
print("Cancelled")
return
diff --git a/Scripts/PteDump.py b/Scripts/PteDump.py
index 705e7c0..37a168d 100644
--- a/Scripts/PteDump.py
+++ b/Scripts/PteDump.py
@@ -1,8 +1,9 @@
-import idaapi
-import idc
-from ida_kernwin import Choose
-def parse_pte(str):
+import ida_kernwin
+import ida_segment
+import ida_dbg
+
+def parse_pte(s):
try:
parse_pte.re
except:
@@ -10,15 +11,17 @@ def parse_pte(str):
parse_pte.items = ('pde', 'pte', 'pdec', 'ptec', 'pdepfn', 'pdepfns', 'ptepfn', 'ptepfns')
m = parse_pte.re.search(s)
+ if not m:
+ return None
r = {}
for i in range(0, len(parse_pte.items)):
r[parse_pte.items[i]] = m.group(i+1)
return r
-class MyChoose(Choose):
+class MyChoose(ida_kernwin.Choose):
def __init__(self, title, ea1, ea2):
- Choose.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ])
+ ida_kernwin.Choose.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ])
self.ea1 = ea1
self.ea2 = ea2
self.icon = 5
@@ -26,17 +29,14 @@ class MyChoose(Choose):
self.Refresh()
def OnGetLine(self, n):
- print("getline %d" % n)
return self.items[n]
def OnGetSize(self):
- n = len(self.items)
- self.Refresh()
- return n
+ return len(self.items)
def OnRefresh(self, n):
- print("refresh %d" % n)
- return None # call standard refresh
+ self.Refresh()
+ return (ida_kernwin.Choose.ALL_CHANGED, )
def Refresh(self):
items = []
@@ -44,11 +44,12 @@ class MyChoose(Choose):
ea1 = self.ea1
npages = (self.ea2 - ea1) / PG
for i in range(npages):
- r = idc.send_dbg_command("!pte %x" % ea1)
- if not r:
+ ok, r = ida_dbg.send_dbg_command("!pte %x" % ea1)
+ if not ok:
return False
r = parse_pte(r)
- items.append([hex(ea1), r['ptepfns']])
+ if r:
+ items.append([hex(ea1), r['ptepfns']])
ea1 += PG
self.items = items
@@ -66,16 +67,17 @@ def DumpPTE(ea1, ea2):
PG = 0x1000
npages = (ea2 - ea1) / PG
for i in range(npages):
- r = idc.send_dbg_command("!pte %x" % ea1)
- if not r:
+ ok, r = ida_dbg.send_dbg_command("!pte %x" % ea1)
+ if not ok:
return False
- print r
r = parse_pte(r)
- print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns']))
+ if r:
+ print("VA: %08X PTE: %s PDE: %s" % (ea1, r['ptepfns'], r['pdepfns']))
ea1 += PG
def DumpSegPTE(ea):
- DumpPTE(idc.get_segm_start(ea), idc.get_segm_end(ea))
+ s = ida_segment.getseg(ea)
+ DumpPTE(s.start_ea, s.end_ea)
DumpSegPTE(here())
diff --git a/Scripts/SEHGraph.py b/Scripts/SEHGraph.py
index 6ad3a0c..61d72f8 100644
--- a/Scripts/SEHGraph.py
+++ b/Scripts/SEHGraph.py
@@ -4,26 +4,24 @@ 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-2009 Hex-Rays
+Copyright (c) 1990-2017 Hex-Rays
ALL RIGHTS RESERVED.
-
-
-v1.0 - initial version
-
"""
-import idaapi
-import idautils
-import idc
+import ida_kernwin
+import ida_graph
+import ida_idd
+import ida_dbg
+import ida_funcs
-from idaapi import GraphViewer
+import idautils
# -----------------------------------------------------------------------
# Since Windbg debug module does not support get_thread_sreg_base()
# we will call the debugger engine "dg" command and parse its output
def WindbgGetRegBase(tid):
- s = idc.eval('send_dbg_command("dg %x")' % cpu.fs)
- if "IDC_FAILURE" in s:
+ ok, s = ida_dbg.send_dbg_command("dg %x" % idautils.cpu.fs)
+ if not ok:
return 0
m = re.compile("[0-9a-f]{4} ([0-9a-f]{8})")
t = m.match(s.split('\n')[-2])
@@ -33,8 +31,8 @@ def WindbgGetRegBase(tid):
# -----------------------------------------------------------------------
def GetFsBase(tid):
- idc.select_thread(tid)
- base = idaapi.dbg_get_thread_sreg_base(tid, cpu.fs)
+ ida_dbg.select_thread(tid)
+ base = ida_idd.dbg_get_thread_sreg_base(tid, idautils.cpu.fs)
if base != 0:
return base
return WindbgGetRegBase(tid)
@@ -43,7 +41,8 @@ def GetFsBase(tid):
# Walks the SEH chain and returns a list of handlers
def GetExceptionChain(tid):
fs_base = GetFsBase(tid)
- exc_rr = get_wide_dword(fs_base)
+ print("FS_BASE for %s: %s (cpu.fs=%s)" % (repr(tid), repr(fs_base), repr(idautils.cpu.fs)))
+ exc_rr = ida_bytes.get_wide_dword(fs_base)
result = []
while exc_rr != 0xffffffff:
prev = get_wide_dword(exc_rr)
@@ -53,9 +52,9 @@ def GetExceptionChain(tid):
return result
# -----------------------------------------------------------------------
-class SEHGraph(GraphViewer):
+class SEHGraph(ida_graph.GraphViewer):
def __init__(self, title, result):
- GraphViewer.__init__(self, title)
+ ida_graph.GraphViewer.__init__(self, title)
self.result = result
self.names = {} # ea -> name
@@ -74,13 +73,13 @@ class SEHGraph(GraphViewer):
# Add each handler
for handler in chain:
# Check if a function is created at the handler's address
- f = idaapi.get_func(handler)
+ f = ida_funcs.get_func(handler)
if not f:
# create function
- idc.add_func(handler, idaapi.BADADDR)
+ ida_funcs.add_func(handler)
# Node label is function name or address
- s = get_func_name(handler)
+ s = ida_funcs.get_func_name(handler)
if not s:
s = "%x" % handler
@@ -110,7 +109,7 @@ class SEHGraph(GraphViewer):
def OnDblClick(self, node_id):
is_thread, value, label = self[node_id]
if is_thread:
- idc.select_thread(value)
+ ida_dbg.select_thread(value)
self.Show()
s = "SEH chain for " + hex(value)
t = "-" * len(s)
@@ -121,18 +120,18 @@ class SEHGraph(GraphViewer):
print "%x: %s" % (handler, self.names[handler])
print t
else:
- idc.jumpto(value)
+ ida_kernwin.jumpto(value)
return True
# -----------------------------------------------------------------------
def main():
- if not idaapi.dbg_can_query():
+ if not ida_idd.dbg_can_query():
print "The debugger must be active and suspended before using this script!"
return
# Save current thread id
- tid = get_current_thread()
+ tid = ida_dbg.get_current_thread()
# Iterate through all function instructions and take only call instructions
result = {}
@@ -140,7 +139,7 @@ def main():
result[tid] = GetExceptionChain(tid)
# Restore previously selected thread
- idc.select_thread(tid)
+ ida_dbg.select_thread(tid)
# Build the graph
g = SEHGraph("SEH graph", result)
diff --git a/Scripts/VaDump.py b/Scripts/VaDump.py
index bcb3d33..82eed1a 100644
--- a/Scripts/VaDump.py
+++ b/Scripts/VaDump.py
@@ -7,11 +7,10 @@ ALL RIGHTS RESERVED.
"""
-import idc
-from ida_kernwin import Choose
-
import re
+import ida_kernwin
+
# class to store parsed results
class memva:
def __init__(self, m):
@@ -29,7 +28,7 @@ class memva:
self.typestr = ""
# Chooser class
-class MemChoose(Choose):
+class MemChoose(ida_kernwin.Choose):
def __init__(self, title, items):
headers = []
headers.append(["Base", 10])
@@ -37,7 +36,7 @@ class MemChoose(Choose):
headers.append(["State", 20])
headers.append(["Protect", 20])
headers.append(["Type", 20])
- Choose.__init__(self, title, headers)
+ ida_kernwin.Choose.__init__(self, title, headers)
self.items = items
def OnGetLine(self, n):
@@ -55,13 +54,13 @@ class MemChoose(Choose):
def OnSelectLine(self, n):
o = self.items[n]
- idc.jumpto(o.base)
- return (NOTHING_CHANGED, )
+ ida_kernwin.jumpto(o.base)
+ return (ida_kernwin.Choose.NOTHING_CHANGED, )
# main
def main():
- s = idc.eval('send_dbg_command("!vadump")')
- if "IDC_FAILURE" in s:
+ ok, s = ida_dbg.send_dbg_command("!vadump")
+ if not ok:
return (False, "Cannot execute the command")
matches = re.finditer(r'BaseAddress:\s*?(\w+?)\n' \
diff --git a/Scripts/msdnapihelp.py b/Scripts/msdnapihelp.py
index b920c6e..72881f9 100644
--- a/Scripts/msdnapihelp.py
+++ b/Scripts/msdnapihelp.py
@@ -5,30 +5,33 @@ This script fetches the API reference (from MSDN) of a given highlighted identif
and returns the results in a new web browser page.
This script depends on the feedparser package: http://code.google.com/p/feedparser/
-
-10/05/2010
-- initial version
-
-
"""
-import idaapi
+# -----------------------------------------------------------------------
+import ida_kernwin
+import ida_name
+import ida_idaapi
+
+try:
+ import feedparser
+except:
+ ida_kernwin.warning('Feedparser package not installed')
# -----------------------------------------------------------------------
-class msdnapihelp_plugin_t(idaapi.plugin_t):
- flags = idaapi.PLUGIN_UNL
+class msdnapihelp_plugin_t(ida_idaapi.plugin_t):
+ flags = ida_idaapi.PLUGIN_UNL
comment = "Online MSDN API Help"
help = "Help me"
wanted_name = "MSDN API Help"
wanted_hotkey = "F3"
def init(self):
- return idaapi.PLUGIN_OK
+ return ida_idaapi.PLUGIN_OK
@staticmethod
def sanitize_name(name):
- t = idaapi.FUNC_IMPORT_PREFIX
+ t = ida_name.FUNC_IMPORT_PREFIX
if name.startswith(t):
return name[len(t):]
return name
@@ -36,28 +39,25 @@ class msdnapihelp_plugin_t(idaapi.plugin_t):
def run(self, arg):
# Get the highlighted identifier
- v = idaapi.get_current_viewer()
- id = ida_kernwin.get_highlight(v)[0]
- if not id:
+ v = ida_kernwin.get_current_viewer()
+ ident, ok = ida_kernwin.get_highlight(v)
+ if not ok:
print "No identifier was highlighted"
return
- import webbrowser
-
- try:
- import feedparser
- except:
- idaapi.warning('Feedparser package not installed')
- return
-
- id = self.sanitize_name(id)
- print "Looking up '%s' in MSDN online" % id
- d = feedparser.parse("http://social.msdn.microsoft.com/Search/Feed.aspx?locale=en-us&format=RSS&Query=%s" % id)
+ ident = self.sanitize_name(ident)
+ print "Looking up '%s' in MSDN online" % ident
+ qurl = "https://social.msdn.microsoft.com/search/en-US/feed?query=%s&format=RSS&theme=feed%%2fen-us"
+ d = feedparser.parse(qurl % ident)
if len(d['entries']) > 0:
url = d['entries'][0].link
- webbrowser.open_new_tab(url)
+ if arg > 0:
+ print("URL: %s" % url)
+ else:
+ import webbrowser
+ webbrowser.open_new_tab(url)
else:
- print "API documentation not found for: %s" % id
+ print "API documentation not found for: %s" % ident
def term(self):
diff --git a/out_of_tree/parsed_notifications.zip b/out_of_tree/parsed_notifications.zip
index 2cec574..cdeb21a 100644
Binary files a/out_of_tree/parsed_notifications.zip and b/out_of_tree/parsed_notifications.zip differ
diff --git a/python/idc.py b/python/idc.py
index 6d3183f..24f5838 100644
--- a/python/idc.py
+++ b/python/idc.py
@@ -2611,6 +2611,7 @@ AF_FINAL = 0x80000000 # Final pass of analysis
INF_AF2 = 44 # uint32; Analysis flags 2
AF2_DOEH = 0x00000001 # Handle EH information
+AF2_DORTTI = 0x00000002 # Handle RTTI information
INF_BASEADDR = 48 # uval_t; base paragraph of the program
INF_START_SS = 52 # int32; value of SS at the start
@@ -8338,6 +8339,13 @@ if sys.modules["__main__"].IDAPYTHON_COMPAT_695_API:
def MakeStr(ea, endea):
return create_strlit(ea, endea)
+ def GetProcessorName():
+ return ida_ida.cvar.inf.procname
+
+ def SegStart(ea): return get_segm_start(ea)
+ def SegEnd(ea): return get_segm_end(ea)
+ def SetSegmentType(ea, type): return set_segm_type(ea, type)
+
# Convenience functions:
def here(): return get_screen_ea()
def is_mapped(ea): return (prev_addr(ea+1)==ea)
diff --git a/pywraps/py_dbg.py b/pywraps/py_dbg.py
index 87b22ef..04b8909 100644
--- a/pywraps/py_dbg.py
+++ b/pywraps/py_dbg.py
@@ -1,5 +1,7 @@
#
+import ida_idaapi
import ida_idd
+import ida_expr
def get_tev_reg_val(tev, reg):
rv = ida_idd.regval_t()
@@ -27,6 +29,32 @@ def get_tev_reg_mem_ea(tev, idx):
if get_insn_tev_reg_mem(tev, mis):
if idx >= 0 and idx < mis.size():
return mis[idx].ea
+
+def send_dbg_command(command):
+ """
+ Send a direct command to the debugger backend, and
+ retrieve the result as a string.
+
+ Note: any double-quotes in 'command' must be backslash-escaped.
+ Note: this only works with some debugger backends: Bochs, WinDbg, GDB.
+
+ Returns: (True, ) on success, or (False, ) on failure
+ """
+ rv = ida_expr.idc_value_t()
+ err = ida_expr.eval_idc_expr(rv, ida_idaapi.BADADDR, """send_dbg_command("%s");""" % command)
+ if err:
+ return False, "eval_idc_expr() failed: %s" % err
+ vtype = ord(rv.vtype)
+ if vtype == ida_expr.VT_STR:
+ s = rv.c_str()
+ if "IDC_FAILURE" in s:
+ return False, "eval_idc_expr() reported an error: %s" % s
+ return True, s
+ elif vtype == ida_expr.VT_LONG:
+ return True, str(rv.num)
+ else:
+ return False, "eval_idc_expr(): wrong return type: %d" % vtype
+
#
#
diff --git a/pywraps/py_idd.hpp b/pywraps/py_idd.hpp
index f426871..52c97f5 100644
--- a/pywraps/py_idd.hpp
+++ b/pywraps/py_idd.hpp
@@ -236,11 +236,15 @@ static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_va
{
PYW_GIL_CHECK_LOCKED_SCOPE();
- if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) )
+ if ( !dbg_can_query()
+ || (!PyInt_Check(py_tid) && !PyLong_Check(py_tid))
+ || (!PyInt_Check(py_sreg_value) && !PyLong_Check(py_sreg_value)) )
+ {
Py_RETURN_NONE;
+ }
ea_t answer;
- thid_t tid = PyInt_AsLong(py_tid);
- int sreg_value = PyInt_AsLong(py_sreg_value);
+ thid_t tid = PyLong_AsLong(py_tid);
+ int sreg_value = PyLong_AsLong(py_sreg_value);
if ( internal_get_sreg_base(&answer, tid, sreg_value) != 1 )
Py_RETURN_NONE;
diff --git a/pywraps/py_idd.py b/pywraps/py_idd.py
index 45ca764..3a008ad 100644
--- a/pywraps/py_idd.py
+++ b/pywraps/py_idd.py
@@ -224,11 +224,14 @@ class Appcall_callable__(object):
class Appcall_consts__(object):
"""Helper class used by Appcall.Consts attribute
It is used to retrieve constants via attribute access"""
- def __init__(self, default=0):
+ def __init__(self, default=None):
self.__default = default
def __getattr__(self, attr):
- return Appcall__.valueof(attr, self.__default)
+ v = Appcall__.valueof(attr, self.__default)
+ if v is None:
+ raise ValueError, "No constant with name " + attr
+ return v
# -----------------------------------------------------------------------
class Appcall__(object):
diff --git a/pywraps/py_kernwin.py b/pywraps/py_kernwin.py
index d426796..0a5b77b 100644
--- a/pywraps/py_kernwin.py
+++ b/pywraps/py_kernwin.py
@@ -91,7 +91,10 @@ chtype_segreg=chtype_srcp
close_tform=close_widget
find_tform=find_widget
get_current_tform=get_current_widget
-get_highlighted_identifier=get_highlight
+def get_highlighted_identifier():
+ thing = get_highlight(get_current_widget())
+ if thing and thing[1]:
+ return thing[0]
get_tform_title=get_widget_title
get_tform_type=get_widget_type
is_chooser_tform=is_chooser_widget
diff --git a/swig/diskio.i b/swig/diskio.i
index 070e564..fea5496 100644
--- a/swig/diskio.i
+++ b/swig/diskio.i
@@ -67,6 +67,21 @@
%ignore close_linput;
%rename (close_linput) py_close_linput;
+%apply qstrvec_t *out { qstrvec_t *dirs };
+
+%cstring_output_buf_and_size_returning_charptr(
+ 1,
+ char *buf,
+ size_t bufsize,
+ const char *filename,
+ const char *subdir); // getsysfile
+%cstring_output_buf_and_size_returning_charptr(
+ 3,
+ linput_t *li,
+ int64 fpos,
+ char *buf,
+ size_t bufsize); // qlgetz
+
%include "diskio.hpp"
%{
diff --git a/swig/expr.i b/swig/expr.i
index c5291fd..02d2caa 100644
--- a/swig/expr.i
+++ b/swig/expr.i
@@ -63,6 +63,12 @@
%ignore compile_idc_text;
%rename (compile_idc_text) py_compile_idc_text;
+%cstring_output_buf_and_size_returning_charptr(
+ 1,
+ char *buf,
+ size_t bufsize,
+ const char *file); // get_idc_filename
+
%nonnul_argument_prototype(
bool py_compile_idc_file(const char *nonnul_line, qstring *errbuf),
const char *nonnul_line);
diff --git a/swig/fixup.i b/swig/fixup.i
index 009569c..6395e59 100644
--- a/swig/fixup.i
+++ b/swig/fixup.i
@@ -7,4 +7,15 @@
%ignore register_custom_fixup;
%ignore unregister_custom_fixup;
+%cstring_output_qstring_returning_charptr(
+ 1,
+ qstring *buf,
+ ea_t source); // fixup_data_t::get_desc
+
+%cstring_output_qstring_returning_charptr(
+ 1,
+ qstring *buf,
+ ea_t source,
+ const fixup_data_t &fd); // get_fixup_desc
+
%include "fixup.hpp"
diff --git a/swig/idp.i b/swig/idp.i
index 6f95b45..ee69655 100644
--- a/swig/idp.i
+++ b/swig/idp.i
@@ -80,6 +80,20 @@
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *nonnul_line),
const char *nonnul_line);
+#ifndef SWIGIMPORTED // let's not modify the wrappers for modules %import'ing us (e.g., typeinf.i, hexrays.i)
+%cstring_output_buf_and_size_returning_charptr(
+ 1,
+ char *buf,
+ size_t bufsize); // get_idp_name
+#endif // SWIGIMPORTED
+
+%cstring_output_qstring_returning_charptr(
+ 1,
+ qstring *out,
+ const char *name,
+ uint32 disable_mask,
+ int demreq); // ev_demangle_name
+
%include "idp.hpp"
%include "config.hpp"
diff --git a/swig/kernwin.i b/swig/kernwin.i
index 22ffe02..669376d 100644
--- a/swig/kernwin.i
+++ b/swig/kernwin.i
@@ -131,6 +131,9 @@ extern plugin_t PLUGIN;
%ignore place_t__serialize;
%ignore place_t::deserialize;
%ignore place_t__deserialize;
+%ignore place_t::generate;
+%ignore place_t__generate;
+%rename (generate) py_generate;
%ignore register_place_class;
%ignore register_loc_converter;
@@ -297,6 +300,21 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown);
static enumplace_t *as_enumplace_t(place_t *p) { return (enumplace_t *) p; }
static structplace_t *as_structplace_t(place_t *p) { return (structplace_t *) p; }
static simpleline_place_t *as_simpleline_place_t(place_t *p) { return (simpleline_place_t *) p; }
+
+ PyObject *py_generate(void *ud, int maxsize)
+ {
+ qstrvec_t lines;
+ int deflnnum = 0;
+ color_t pfx_color = 0;
+ bgcolor_t bgcolor = DEFCOLOR;
+ 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));
+ PyTuple_SetItem(tuple, 2, PyLong_FromLong(uchar(pfx_color)));
+ PyTuple_SetItem(tuple, 3, PyLong_FromLong(bgcolor));
+ return tuple;
+ }
}
%extend twinpos_t {
diff --git a/swig/typeinf.i b/swig/typeinf.i
index 58dc76f..009fa6e 100644
--- a/swig/typeinf.i
+++ b/swig/typeinf.i
@@ -255,6 +255,12 @@
%ignore remove_tinfo_pointer;
%rename (remove_tinfo_pointer) py_remove_tinfo_pointer;
+%cstring_output_buf_and_size_returning_charptr(
+ 2,
+ ea_t ea,
+ char *buf,
+ size_t bufsize); // idc_guess_type, idc_get_type
+
%include "typeinf.hpp"
// Custom wrappers
diff --git a/tools/deploy/header.i.in b/tools/deploy/header.i.in
index 720cef4..165923a 100644
--- a/tools/deploy/header.i.in
+++ b/tools/deploy/header.i.in
@@ -468,6 +468,28 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
}
%enddef
+//-------------------------------------------------------------------------
+// and a helper for overriding the 'argout' of some of those functions,
+// that return the input char* as return code; those build on recent
+// versions of Xcode (>= 9.0), and need special care
+%define %cstring_output_buf_and_size_returning_charptr(BUFIDX, ...)
+%typemap(argout) (__VA_ARGS__) {
+ // cstring_output_buf_and_size_returning_charptr's argout
+ Py_XDECREF(resultobj);
+ if (result != NULL)
+ {
+ resultobj = PyString_FromString($BUFIDX);
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ resultobj = Py_None;
+ }
+ qfree($BUFIDX);
+}
+%enddef
+
+
//---------------------------------------------------------------------
// IN/OUT qstring
//---------------------------------------------------------------------
@@ -491,8 +513,43 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
// Nothing. We certainly don't want 'temp' to be deleted.
}
-//---------------------------------------------------------------------
-// md5/sha256 hash retrieval
+//-------------------------------------------------------------------------
+// see %cstring_output_buf_and_size_returning_charptr above
+%define %cstring_output_qstring_returning_charptr(BUFIDX, ...)
+%typemap(argout) (__VA_ARGS__) {
+ // cstring_output_qstring_returning_charptr's argout
+ Py_XDECREF(resultobj);
+ if (result != NULL)
+ {
+ resultobj = PyString_FromStringAndSize($BUFIDX->begin(), $BUFIDX->length());
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ resultobj = Py_None;
+ }
+}
+%enddef
+
+//-------------------------------------------------------------------------
+// OUT qstrvec_t
+//-------------------------------------------------------------------------
+%typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp) {
+ $1 = &temp;
+}
+%typemap(argout) qstrvec_t *out
+{
+ Py_XDECREF(resultobj);
+ resultobj = qstrvec2pylist(*($1));
+}
+%typemap(freearg) qstrvec_t* out
+{
+ // Nothing. We certainly don't want 'temp' to be deleted.
+}
+
+//-------------------------------------------------------------------------
+// md5/sha256 hash retrieval
+//-------------------------------------------------------------------------
%typemap(in, numinputs=0) uchar hash[ANY] (uchar temp[$1_dim0])
{
$1 = temp;
@@ -771,7 +828,7 @@ struct wrapped_array_t {
%{
-static PyObject *qstrvec2pylist(qstrvec_t &vec)
+static PyObject *qstrvec2pylist(const qstrvec_t &vec)
{
size_t n = vec.size();
PyObject *py_list = PyList_New(n);
diff --git a/tools/gen_idc_bc695.py b/tools/gen_idc_bc695.py
index 23c12a9..01afe72 100644
--- a/tools/gen_idc_bc695.py
+++ b/tools/gen_idc_bc695.py
@@ -64,6 +64,10 @@ forbidden = [
"SaveBase",
"eval",
"MakeStr",
+ "GetProcessorName",
+ "SegStart",
+ "SegEnd",
+ "SetSegmentType",
]
symbols_modules = {