diff --git a/CHANGES.txt b/CHANGES.txt deleted file mode 100644 index 90e355b..0000000 --- a/CHANGES.txt +++ /dev/null @@ -1,229 +0,0 @@ -Please see http://code.google.com/p/idapython/source/list for a detailed list of changes. - -Changes from version 1.5.6 to 1.5.7 ------------------------------------- -- Added '--with-hexrays' switch to the build script so it wrap Hex-Rays Decompiler API -- Experimental: integrated Hex-Rays Decompiler bindings that were contributed by EiNSTeiN: - https://github.com/EiNSTeiN-/hexrays-python -- Added one Hex-Rays decompiler sample: vds1.py -- Fixed small mismatch between SWIG define and CL defines (/DNO_OBSOLETE_FUNCS) -- Use print_type2() instead of the deprecated function print_type() - -Changes from version 1.5.5 to 1.5.6 ------------------------------------- -- IDA Pro 6.4 support - -Changes from version 1.5.4 to 1.5.5 ------------------------------------- -- IDA Pro 6.3 support -- The Functions() generator function now accepts function tail start parameter -- Added into idc.py: DbgRead/DbgWrite/SetTargetAssembler and stack pointer related functions -- Wrapped more type info related functions - -Changes from version 1.5.3 to 1.5.4 ------------------------------------- -- fix for Python autorun script vulnerability reported by Greg MacManus -- remove current directory from sys.path during initialization -- added PyWraps sources. This will facilitate deployment, development and - debugging of IDAPython additions -- bugfix: op_t.is_reg() was buggy -- bugfix: build.py was putting duplicate files into the .zip -- bugfix: added back wrapped version of get_ascii_contents() - -Changes from version 1.5.2 to 1.5.3 ------------------------------------- -- IDA Pro 6.2 support -- added set_idc_func_ex(): it is now possible to add new IDC functions using Python -- added visit_patched_bytes() (see ex_patch.py) -- added support for the multiline text input control in the Form class -- added support for the editable/readonly dropdown list control in the Form class -- added execute_sync() to register a function call into the UI message queue -- added execute_ui_requests() / check ex_uirequests.py -- added add_hotkey() / del_hotkey() to bind Python methods to hotkeys -- added register_timer()/unregister_timer(). Check ex_timer.py -- added the IDC (Arrays) netnode manipulation layer into idc.py -- added idautils.Structs() and StructMembers() generator functions -- removed the "Run Python Statement" menu item. IDA now has a unified dialog. - Use RunPlugin("python", 0) to invoke it manually. -- better error messages for script plugins, loaders and processor modules -- bugfix: Dbg_Hooks.dbg_run_to() was receiving wrong input -- bugfix: A few Enum related functions were not properly working in idc.py -- bugfix: GetIdaDirectory() and GetProcessName() were broken in idc.py -- bugfix: idaapi.get_item_head() / idc.ItemHead() were not working - -Changes from version 1.5.1 to 1.5.2 ------------------------------------- -- added ui_term/ui_save/ui_saved/ui_get_ea_hint UI notifications -- added ph_get_operand_info() to retrieve operand information while debugging -- added PteDump.py script -- bugfix: read/write_dbg_memory() and dbg_get_thread_sreg_base() were not working with all debugger modules -- bugfix: idaapi.netnode.getblob() was limited to MAXSPECSIZE -- bugfix: idc.GetString()/idaapi.get_ascii_contents()/idautils.Strings() were limited to MAXSTR string length -- bugfix: idaapi.del_menu_item() was failing to delete some menu items -- bugfix: dbg_bpt was called instead of dbg_trace for a DBG_Hooks class implementation (old bug from 0.9.x) -- bugfix: Form.GetControlValue() was not working with numeric controls -- bugfix: SetBptCnd() was broken -- bugfix: idaapi.get_func_cmt() was memory leaking - -Changes from version 1.5.0 to 1.5.1 ------------------------------------- -- Introduced the CLI '?' pseudo-command to retrieve doc strings -- Introduced the CLI '!' pseudo-command to shell execute a command -- bugfix: High 64 bit addresses were not parsed correctly in IDA64 -- Added IDP/assemble notification event -- bugfix: AskUsingForm() C function was not wrapped by SWIG -- NextHead()/PrevHead() have optional 2nd parameter now - -Changes from version 1.4.3 to 1.5.0 ------------------------------------- -- IDA Pro 6.1 support -- Added AskUsingForm() with embedded forms support (check ex_askusingform.py example and formchooser.py in the SDK) -- Added idautils.DecodePreviousInstruction() / DecodePrecedingInstruction() -- Added idc.BeginTypeUpdating() / EndTypeUpdating() for fast batch type update operations -- Added more IDP callbacks -- Added UI_Hooks with a few notification events -- Added idaapi.process_ui_action() / idc.ProcessUiAction() -- Added netnode.index() to get netnode number -- Better handling of ea_t values with bitwise negation -- Execute statement hotkey (Ctrl-F3), script timeout, and other options are now configurable with Python.cfg -- bugfix: idaapi.msg() / error() and warning() so they don't accept vararg -- bugfix: processor_t.id constants were incorrect -- bugfix: get_debug_names() was broken with IDA64 -- Various bugfixes -- Added Scripts folder containing various IDAPython scripts - -Changes from version 1.4.2 to 1.4.3 ------------------------------------- -- IDA Pro 6.0 support -- Python CLI now prints expression evaluation result (no need to use print()) -- Changed Alt-8 to Ctrl-F3 (because it conflicts with window switching key Alt+n) -- Added get_highlighted_identifier() -- Added PluginForm class to allow UI development with either PyQt4 or PySide -- Added idautils.Entries() to enum entrypoints - - -Changes from version 1.4.1 to 1.4.2 ------------------------------------- -- Added command completion -- Added necessary changes so it compiles with Python 2.7 -- Wrapped set_user_defined_prefix() - - -Changes from version 1.4.0 to 1.4.1 ------------------------------------- -- Added cli_t -- Added idaapi.ph to access current process fields -- Changed the copyright string to IDAPython Team -- Some platform dependant classes are present but useable only where applicable - - -Changes from version 1.3.0 to 1.4.0 ------------------------------------- -- IDA Pro 5.7 support -- idaapi.cvar.cmd is now accessible via idapi.cmd instead -- Python statement (Alt-8) is now 16kb long -- Dropped script box and File/Python file. IDA has this functionality now. -- Refactored the code -- It is possible to turn off script timeout -- All scripts are executed via 'IDAPython_ExecScript' (check idaapi.i) -- Added '--doc' switch to "build.py" script -- Documented all manually wrapped functions (check 'pywraps' module in the docs) -- Lots of cleanups and fixes - - -Changes from version 1.2.0 to 1.3.0 ------------------------------------- -- IDA Pro 5.6 support -- Added Appcall mechanism -- Added procregs to idautils.py (r254) -- Lots of cleanups and fixes - -Changes from version 1.1.0 to 1.2.0 ------------------------------------- -- 64-bit support (largely untested) -- IDA Pro 5.5 support -- Long running (or inifinitely looping) scripts can now be stopped -- Host of IDC updates and fixes -- netnode.hpp is now mostly wrapped -- idautils use generators instead of lists -- Functions() and GetFchunkAttr() now work properly -- Lots of cleanups and fixes - - -Changes from version 0.9.0 to 1.0.0 ------------------------------------ -- Upgraded IDA Pro base version to 5.1 -- Dropped Python 2.4 support -- Mac OS X support -- IDC compatibility layer is now complete and up to date for IDA 5.1 -- INCOMPATIBLE CHANGE: the idaapi module needs to be imported manually -- Support for IDB and debug notification hooks -- Support for GUI hotkeys (see examples/hotkey.py) -- Simple two-way calling mechanism between IDC and IDAPython -- Significantly better IDA API coverage -- Support for IDB and debug event hooks -- get_current_instruction() deprecated, use the idaapi.cvar.cmd variable -- Tons of IDC fixes -- Tons of other misc fixes - - -Changes from version 0.8.0 to 0.9.0 ------------------------------------ -- Upgraded base version to IDA Pro 5.0 -- Works with IDA Pro 5.1 -- Python 2.4 and 2.5 supported -- Close to complete IDC compatbility layer (in sync with 4.9) -- Significatnly improved IDA SDK API covergage (see STATUS.txt for details) -- IDA SDK patch size reduced to less than half -- Simplified installation (plugins.cfg modification not needed) -- Evaluation window content is saved over IDA restarts (in the database) -- Windows version is built with Microsoft Visual C++ Express Edition -- Build makefile replaced with a Python script -- Cleanups and small fixes - - -Changes from version 0.7.0 to 0.8.0 ------------------------------------ -- Added support for IDA Pro 4.9 -- Dropped support for IDA Pro 4.7 -- NOTE: Windows version is linked against Python 2.4. -- New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp -- idc.py synced up to IDA 4.8 -- Added 38 IDC functions -- Fixed asklong(), askseg() and askaddr() -- Automatically generated cross reference documentation (epydoc) -- User-specific init file support (see README,txt) -- Deprecated some functions that have direct Python equivalents (see idc.py) -- Fixed exception in ScriptBox when invoked empty. -- Lots of cleanups and small fixes - - -Changes from version 0.6.0 to 0.7.0 ------------------------------------ -- Batch execution support (use the option -OIDAPython:yourscript.py) -- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7) -- Added support for IDA Pro 4.8 (both Linux and Windows) -- Dropped support for IDA Pro 4.6 and 4.6SP1 versions -- Wrapped the list chooser (see examples/choose.py) -- A dozen or so IDC functions added -- Lots of char * API calls wrapped -- Added Python error handling in the plugin C layer -- Bunch of misc small cleanups and fixes -- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt - -- API CHANGE: {Next|Prev}Function() return BADADDR instead of -1 - - -Changes from version 0.5.0 to 0.6.0 ------------------------------------ -- Added support for IDA Pro 4.7 (both Linux and Windows) -- Dropped support for IDA Pro 4.6SP1 beta on Linux -- Lots of IDC wrapper additions and fixes: - - Added 30+ new wrappers to idc.py - - Most Find*, Ask* and Seg* are now wrapped - - Fixed broken NextAddr(), PrevAddr(), MakeFunction() and MakeName() -- Fixes to the makefile -- Cleanups for the idaapi wrapper -- Bunch of misc small cleanups and fixes -- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt - diff --git a/HOWTO.md b/HOWTO.md new file mode 100644 index 0000000..d89e1f8 --- /dev/null +++ b/HOWTO.md @@ -0,0 +1,30 @@ +# HOW-TO + +### How to add new module? + +We use the "zzz" placeholder for a module name in this "how-to". + +1. create file swig/zzz.i +``` +%{ +#include +%} +%include "zzz.hpp" +``` + +2. add zzz to the `MODULES_NAMES` var in makefile + +3. add a line to python/idc.py if you want to autoload this module +``` +import ida_zzz +``` + +4. build + +5. update the content of api_contents.txt + (from obj/.../api_contents.txt.new) + +6. rebuild + +7. update the content of pydoc_injections.txt + (from obj/.../pydoc_injections.txt) diff --git a/README.md b/README.md index abc1566..727e943 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ of Python code from IDC * Invoking IDC from Python -It is possible to use the idc.Eval() to evaluate IDC expressions from Python +It is possible to use the idc.eval() to evaluate IDC expressions from Python * Making Python the default language @@ -99,8 +99,8 @@ Python instead of IDC. In order to do that, please use the following IDC code: -RunPlugin("python", 3) +load_and_run_plugin("python", 3) To disable Python language and revert back to IDC: -RunPlugin("python", 4) +load_and_run_plugin("python", 4) diff --git a/STATUS.txt b/STATUS.txt index 2fbb834..aa4a35d 100644 --- a/STATUS.txt +++ b/STATUS.txt @@ -1,7 +1,7 @@ Status of the IDC layer ----------------------- -The IDC emulation layer is complete and at par with IDA 5.1, +The IDC emulation layer is complete and at par with IDA 5.1, although it would benefit from more testing. @@ -13,7 +13,7 @@ INCOMPLETE: some wrapping or SWIG ifdefs still left EXCLUDED: will not be wrapped allins.hpp - COMPLETE -area.hpp - COMPLETE (necessary SWIGdefs) +range.hpp - COMPLETE (necessary SWIGdefs) auto.hpp - COMPLETE bytes.hpp - COMPLETE (some minor unwrapped) compress.hpp - EXCLUDED @@ -37,7 +37,6 @@ idd.hpp - COMPLETE (necessary SWIGs) idp.hpp - COMPLETE ieee.h - EXCLUDED intel.hpp - EXCLUDED -ints.hpp - COMPLETE kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do) lex.hpp - EXCLUDED lines.hpp - INCOMPLETE (few FIXMEs) @@ -56,7 +55,7 @@ regex.h - EXCLUDED search.hpp - COMPLETE segment.hpp - COMPLETE sistack.hpp - EXCLUDED -srarea.hpp - INCOMPLETE (not wrapped at all) +segregs.hpp - INCOMPLETE (not wrapped at all) strlist.hpp - COMPLETE struct.hpp - COMPLETE typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do) diff --git a/Scripts/AsmViewer.py b/Scripts/AsmViewer.py index bcec428..7b78cfe 100644 --- a/Scripts/AsmViewer.py +++ b/Scripts/AsmViewer.py @@ -200,7 +200,7 @@ class asmviewplg(idaapi.plugin_t): def run(self, arg): if self.view: self.Close() - fn = idc.AskFile(0, "*.asm", "Select ASM file to view") + fn = idaapi.ask_file(0, "*.asm", "Select ASM file to view") if not fn: return self.view = asmview_t() @@ -213,4 +213,4 @@ class asmviewplg(idaapi.plugin_t): self.view.Close() def PLUGIN_ENTRY(): - return asmviewplg() \ No newline at end of file + return asmviewplg() diff --git a/Scripts/CallStackWalk.py b/Scripts/CallStackWalk.py index f1fef78..cb63383 100644 --- a/Scripts/CallStackWalk.py +++ b/Scripts/CallStackWalk.py @@ -14,17 +14,18 @@ v1.0.1 - added stack segment bitness detection, thus works with 64bit processes import idaapi import idc import idautils +from ida_kernwin import Choose # ----------------------------------------------------------------------- # class to take a copy of a segment_t class Seg(): def __init__(self, s): - self.startEA = s.startEA - self.endEA = s.endEA - self.perm = s.perm - self.bitness = s.bitness + self.start_ea = s.start_ea + self.end_ea = s.end_ea + self.perm = s.perm + self.bitness = s.bitness def __cmp__(self, other): - return cmp(self.startEA, other.startEA) + return cmp(self.start_ea, other.start_ea) # ----------------------------------------------------------------------- # each item described as: @@ -59,8 +60,10 @@ def IsPrevInsnCall(ea): # get the bytes bytes = [x for x in GetDataList(caller, len(opcodes), 1)] # do we have a match? is it a call instruction? - if bytes == opcodes and idaapi.is_call_insn(caller): - return caller + if bytes == opcodes: + tmp = idaapi.insn_t() + if idaapi.decode_insn(tmp, caller) and idaapi.is_call_insn(tmp): + return caller return None # ----------------------------------------------------------------------- @@ -77,18 +80,15 @@ def CallStackWalk(nn): self.caller = caller self.sp = sp f = idaapi.get_func(caller) - self.displ = "%08x: " % caller + self.displ = "" if f: - self.displ += idc.GetFunctionName(caller) - t = caller - f.startEA + self.displ += idc.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) @@ -99,7 +99,7 @@ def CallStackWalk(nn): word_size = 2 ** (seg.bitness + 1) callers = [] sp = cpu.Esp - word_size - while sp < stack_seg.endEA: + while sp < stack_seg.end_ea: sp += word_size ptr = idautils.GetDataList(sp, 1, word_size).next() seg = idaapi.getseg(ptr) @@ -121,13 +121,13 @@ def CallStackWalk(nn): f = idaapi.get_func(ea) if not f: # create function - idc.MakeFunction(ea, idaapi.BADADDR) + idc.add_func(ea, idaapi.BADADDR) # get the flags - f = idc.GetFlags(caller) + f = idc.get_flags(caller) # no code there? - if not isCode(f): - MakeCode(caller) + if not is_code(f): + create_insn(caller) callers.append(Result(caller, sp)) # @@ -136,27 +136,38 @@ def CallStackWalk(nn): # ----------------------------------------------------------------------- # Chooser class class CallStackWalkChoose(Choose): - def __init__(self, list, title): - Choose.__init__(self, list, title) - self.width = 250 + def __init__(self, title, items): + Choose.__init__(self, title, [ ["Caller", 16], ["Display", 250] ]) + self.items = items - def enter(self, n): - o = self.list[n-1] - idc.Jump(o.caller) + def OnGetLine(self, n): + o = self.items[n] + line = [] + line.append("%X" % o.caller) + line.append("%s" % o.displ) + return line + + def OnGetSize(self): + return len(self.items) + + def OnSelectLine(self, n): + o = self.items[n] + jumpto(o.caller) + return (Choose.NOTHING_CHANGED, ) # ----------------------------------------------------------------------- def main(): if not idaapi.is_debugger_on(): - idc.Warning("Please run the process first!") + idc.warning("Please run the process first!") return if idaapi.get_process_state() != -1: - idc.Warning("Please suspend the debugger first!") + idc.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.minEA, idaapi.cvar.inf.maxEA) + 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: @@ -164,12 +175,12 @@ def main(): ret, callstack = CallStackWalk(nn) if ret: - title = "Call stack walker (thread %X)" % (GetCurrentThreadId()) + title = "Call stack walker (thread %X)" % (get_current_thread()) idaapi.close_chooser(title) - c = CallStackWalkChoose(callstack, title) - c.choose() + c = CallStackWalkChoose(title, callstack) + c.Show() else: - idc.Warning("Failed to walk the stack:" + callstack) + idc.warning("Failed to walk the stack:" + callstack) # ----------------------------------------------------------------------- -main() \ No newline at end of file +main() diff --git a/Scripts/DbgCmd.py b/Scripts/DbgCmd.py index a15544b..d19e564 100644 --- a/Scripts/DbgCmd.py +++ b/Scripts/DbgCmd.py @@ -9,9 +9,9 @@ from idaapi import simplecustviewer_t 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 'SendDbgCommand' IDC command. + the 'send_dbg_command' IDC command. """ - s = Eval('SendDbgCommand("%s");' % cmd) + 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 @@ -32,7 +32,7 @@ class dbgcmd_t(simplecustviewer_t): return True def IssueCommand(self): - s = idaapi.askstr(0, self.last_cmd, "Please enter a debugger command") + s = idaapi.ask_str(self.last_cmd, 0, "Please enter a debugger command") if not s: return @@ -47,7 +47,7 @@ class dbgcmd_t(simplecustviewer_t): 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 SendDbgCommand()", idaapi.SCOLOR_ERROR)) + self.AddLine(idaapi.COLSTR("Debugger is not active or does not export send_dbg_command()", idaapi.SCOLOR_ERROR)) self.Refresh() def ResetOutput(self): diff --git a/Scripts/DrvsDispatch.py b/Scripts/DrvsDispatch.py index db984d3..ae7c298 100644 --- a/Scripts/DrvsDispatch.py +++ b/Scripts/DrvsDispatch.py @@ -8,21 +8,22 @@ ALL RIGHTS RESERVED. """ import re -from idaapi import Choose +import idc +from ida_kernwin import Choose # ----------------------------------------------------------------------- def CmdDriverList(): - s = Eval('WinDbgCommand("lm o");') + s = idc.eval('send_dbg_command("lm o");') if "IDC_FAILURE" in s: return False return s # ----------------------------------------------------------------------- def CmdDrvObj(drvname, flag=2): - return Eval('WinDbgCommand("!drvobj %s %d");' % (drvname, flag)) + return idc.eval('send_dbg_command("!drvobj %s %d");' % (drvname, flag)) # ----------------------------------------------------------------------- def CmdReloadForce(): - s = Eval('WinDbgCommand(".reload /f");') + s = idc.eval('send_dbg_command(".reload /f");') if "IDC_FAILURE" in s: return False return True @@ -32,12 +33,9 @@ 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 = [] @@ -54,7 +52,7 @@ def GetDriverDispatch(): # get driver list lm_out = CmdDriverList() - if not lm_out: + if not lm_out: return "Failed to get driver list!" # for each line @@ -69,7 +67,7 @@ def GetDriverDispatch(): # execute "drvobj" command tbl_out = CmdDrvObj(drvname) - if not tbl_out: + if not tbl_out: print "Failed to get driver object for", drvname continue @@ -87,19 +85,30 @@ def GetDriverDispatch(): # ----------------------------------------------------------------------- # Chooser class class DispatchChoose(Choose): - def __init__(self, list, title): - Choose.__init__(self, list, title) - self.width = 250 + def __init__(self, title, items): + Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ]) + self.items = items - def enter(self, n): - o = self.list[n-1] - idc.Jump(o.addr) + 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 OnSelectLine(self, n): + o = self.items[n] + Jump(o.addr) + return (Choose.NOTHING_CHANGED, ) # ----------------------------------------------------------------------- # main r = GetDriverDispatch() if r: - c = DispatchChoose(r, "Dispatch table browser") - c.choose() + c = DispatchChoose("Dispatch table browser", r) + c.Show() else: - print "Failed to retrieve dispatchers list!" \ No newline at end of file + print "Failed to retrieve dispatchers list!" diff --git a/Scripts/ExchainDump.py b/Scripts/ExchainDump.py index f8d93b9..75c729d 100644 --- a/Scripts/ExchainDump.py +++ b/Scripts/ExchainDump.py @@ -9,6 +9,8 @@ ALL RIGHTS RESERVED. import idc import re +import ida_kernwin +from ida_kernwin import Choose # class to store parsed results class exchain: @@ -16,22 +18,30 @@ class exchain: self.name = m.group(1) self.addr = int(m.group(2), 16) - def __str__(self): - return "%x: %s" % (self.addr, self.name) - # Chooser class class MyChoose(Choose): - def __init__(self, list, title): - Choose.__init__(self, list, title) - self.width = 250 + def __init__(self, title, items): + Choose.__init__(self, title, [ ["Address", 16], ["Name", 250] ]) + self.items = items - def enter(self, n): - o = self.list[n-1] - idc.Jump(o.addr) + 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 OnSelectLine(self, n): + o = self.items[n] + Jump(o.addr) + return (Choose.NOTHING_CHANGED, ) # main def main(): - s = idc.Eval('SendDbgCommand("!exchain")') + s = idc.eval('send_dbg_command("!exchain")') if "IDC_FAILURE" in s: return (False, "Cannot execute the command") @@ -43,9 +53,9 @@ def main(): return (False, "Nothing to display: Could parse the result!") # Get a Choose instance - chooser = MyChoose(L, "Exchain choose") + chooser = MyChoose("Exchain choose", L) # Run the chooser - chooser.choose() + chooser.Show() return (True, "Success!") ok, r = main() if not ok: diff --git a/Scripts/FindInstructions.py b/Scripts/FindInstructions.py index 5bfaac5..d85d67c 100644 --- a/Scripts/FindInstructions.py +++ b/Scripts/FindInstructions.py @@ -21,6 +21,7 @@ v1.0 - initial version import idaapi import idautils import idc +from ida_kernwin import Choose # ----------------------------------------------------------------------- def FindInstructions(instr, asm_where=None): @@ -30,7 +31,7 @@ def FindInstructions(instr, asm_where=None): """ if not asm_where: # get first segment - asm_where = FirstSeg() + asm_where = get_first_seg() if asm_where == idaapi.BADADDR: return (False, "No segments defined") @@ -56,7 +57,7 @@ def FindInstructions(instr, asm_where=None): # join the buffer into one string buf = ''.join(bufs) - + # take total assembled instructions length tlen = len(buf) @@ -65,55 +66,64 @@ def FindInstructions(instr, asm_where=None): # find all binary strings print "Searching for: [%s]" % bin_str - ea = MinEA() + ea = get_inf_attr(INF_MIN_EA) ret = [] while True: - ea = FindBinary(ea, SEARCH_DOWN, bin_str) + ea = find_binary(ea, SEARCH_DOWN, bin_str) if ea == idaapi.BADADDR: break ret.append(ea) - Message(".") + msg(".") ea += tlen if not ret: return (False, "Could not match [%s]" % bin_str) - Message("\n") + msg("\n") return (True, ret) # ----------------------------------------------------------------------- # Chooser class class SearchResultChoose(Choose): - def __init__(self, list, title): - Choose.__init__(self, list, title) - self.width = 250 + def __init__(self, title, items): + Choose.__init__(self, title, [ ["Address", 16], ["Results", 250] ]) + self.items = items - def enter(self, n): - o = self.list[n-1] + 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 OnSelectLine(self, n): + o = self.items[n] Jump(o.ea) + return (Choose.NOTHING_CHANGED, ) # ----------------------------------------------------------------------- # class to represent the results class SearchResult: def __init__(self, ea): self.ea = ea - if not isCode(GetFlags(ea)): - MakeCode(ea) + if not is_code(get_flags(ea)): + create_insn(ea) t = idaapi.generate_disasm_line(ea) if t: line = idaapi.tag_remove(t) else: line = "" - func = GetFunctionName(ea) - self.display = hex(ea) + ": " + func = get_func_name(ea) + self.display = "" if func: self.display += func + ": " else: - n = SegName(ea) - if n: self.display += n + ": " + n = get_segm_name(ea) + if n: + self.display += n + ": " self.display += line - def __str__(self): - return self.display - # ----------------------------------------------------------------------- def find(s=None, x=False, asm_where=None): b, ret = FindInstructions(s, asm_where) @@ -130,8 +140,8 @@ def find(s=None, x=False, asm_where=None): results = [SearchResult(ea) for ea in ret] title = "Search result for: [%s]" % s idaapi.close_chooser(title) - c = SearchResultChoose(results, title) - c.choose() + c = SearchResultChoose(title, results) + c.Show() else: print ret diff --git a/Scripts/ImpRef.py b/Scripts/ImpRef.py index 5dc8542..9d9471c 100644 --- a/Scripts/ImpRef.py +++ b/Scripts/ImpRef.py @@ -40,8 +40,8 @@ def find_import_ref(dllname): ea = xref.frm f = idaapi.get_func(ea) if f and (f.flags & idaapi.FUNC_THUNK) != 0: - imports.append([f.startEA, idaapi.get_func_name(f.startEA), 0]) - #print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.startEA) + imports.append([f.start_ea, idaapi.get_func_name(f.start_ea), 0]) + #print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.start_ea) continue # save results @@ -54,7 +54,7 @@ def find_import_ref(dllname): # ----------------------------------------------------------------------- def main(): - dllname = idc.AskStr('kernel32', "Enter module name") + dllname = idaapi.ask_str('kernel32', 0, "Enter module name") if not dllname: print("Cancelled") return @@ -66,4 +66,4 @@ def main(): print("\t%x" % ea) # ----------------------------------------------------------------------- -main() \ No newline at end of file +main() diff --git a/Scripts/PteDump.py b/Scripts/PteDump.py index 1bd20f3..705e7c0 100644 --- a/Scripts/PteDump.py +++ b/Scripts/PteDump.py @@ -1,6 +1,6 @@ import idaapi import idc -from idaapi import Choose2 +from ida_kernwin import Choose def parse_pte(str): try: @@ -15,17 +15,15 @@ def parse_pte(str): r[parse_pte.items[i]] = m.group(i+1) return r -class MyChoose2(Choose2): +class MyChoose(Choose): def __init__(self, title, ea1, ea2): - Choose2.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ]) + Choose.__init__(self, title, [ ["VA", 10], ["PTE attr", 30] ]) self.ea1 = ea1 self.ea2 = ea2 - self.n = 0 self.icon = 5 self.items = [] self.Refresh() - self.selcount = 0 def OnGetLine(self, n): print("getline %d" % n) @@ -38,7 +36,7 @@ class MyChoose2(Choose2): def OnRefresh(self, n): print("refresh %d" % n) - return n + return None # call standard refresh def Refresh(self): items = [] @@ -46,7 +44,7 @@ class MyChoose2(Choose2): ea1 = self.ea1 npages = (self.ea2 - ea1) / PG for i in range(npages): - r = idc.SendDbgCommand("!pte %x" % ea1) + r = idc.send_dbg_command("!pte %x" % ea1) if not r: return False r = parse_pte(r) @@ -59,7 +57,7 @@ class MyChoose2(Choose2): @staticmethod def Execute(ea1, ea2): - c = MyChoose2("PTE Viewer [%x..%x]" % (ea1, ea2), ea1, ea2) + c = MyChoose("PTE Viewer [%x..%x]" % (ea1, ea2), ea1, ea2) return (c, c.Show()) @@ -68,7 +66,7 @@ def DumpPTE(ea1, ea2): PG = 0x1000 npages = (ea2 - ea1) / PG for i in range(npages): - r = idc.SendDbgCommand("!pte %x" % ea1) + r = idc.send_dbg_command("!pte %x" % ea1) if not r: return False print r @@ -77,9 +75,9 @@ def DumpPTE(ea1, ea2): ea1 += PG def DumpSegPTE(ea): - DumpPTE(idc.SegStart(ea), idc.SegEnd(ea)) + DumpPTE(idc.get_segm_start(ea), idc.get_segm_end(ea)) DumpSegPTE(here()) -#MyChoose2.Execute(0xF718F000, 0xF718F000+0x1000) +#MyChoose.Execute(0xF718F000, 0xF718F000+0x1000) diff --git a/Scripts/SEHGraph.py b/Scripts/SEHGraph.py index 88ab71d..6ad3a0c 100644 --- a/Scripts/SEHGraph.py +++ b/Scripts/SEHGraph.py @@ -22,7 +22,7 @@ from idaapi import GraphViewer # 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('WinDbgCommand("dg %x")' % cpu.fs) + s = idc.eval('send_dbg_command("dg %x")' % cpu.fs) if "IDC_FAILURE" in s: return 0 m = re.compile("[0-9a-f]{4} ([0-9a-f]{8})") @@ -33,7 +33,7 @@ def WindbgGetRegBase(tid): # ----------------------------------------------------------------------- def GetFsBase(tid): - idc.SelectThread(tid) + idc.select_thread(tid) base = idaapi.dbg_get_thread_sreg_base(tid, cpu.fs) if base != 0: return base @@ -43,11 +43,11 @@ def GetFsBase(tid): # Walks the SEH chain and returns a list of handlers def GetExceptionChain(tid): fs_base = GetFsBase(tid) - exc_rr = Dword(fs_base) + exc_rr = get_wide_dword(fs_base) result = [] while exc_rr != 0xffffffff: - prev = Dword(exc_rr) - handler = Dword(exc_rr + 4) + prev = get_wide_dword(exc_rr) + handler = get_wide_dword(exc_rr + 4) exc_rr = prev result.append(handler) return result @@ -77,10 +77,10 @@ class SEHGraph(GraphViewer): f = idaapi.get_func(handler) if not f: # create function - idc.MakeFunction(handler, idaapi.BADADDR) + idc.add_func(handler, idaapi.BADADDR) # Node label is function name or address - s = GetFunctionName(handler) + s = get_func_name(handler) if not s: s = "%x" % handler @@ -110,7 +110,7 @@ class SEHGraph(GraphViewer): def OnDblClick(self, node_id): is_thread, value, label = self[node_id] if is_thread: - idc.SelectThread(value) + idc.select_thread(value) self.Show() s = "SEH chain for " + hex(value) t = "-" * len(s) @@ -121,7 +121,7 @@ class SEHGraph(GraphViewer): print "%x: %s" % (handler, self.names[handler]) print t else: - idc.Jump(value) + idc.jumpto(value) return True @@ -132,7 +132,7 @@ def main(): return # Save current thread id - tid = GetCurrentThreadId() + tid = get_current_thread() # Iterate through all function instructions and take only call instructions result = {} @@ -140,7 +140,7 @@ def main(): result[tid] = GetExceptionChain(tid) # Restore previously selected thread - idc.SelectThread(tid) + idc.select_thread(tid) # Build the graph g = SEHGraph("SEH graph", result) diff --git a/Scripts/VaDump.py b/Scripts/VaDump.py index cf606eb..bcb3d33 100644 --- a/Scripts/VaDump.py +++ b/Scripts/VaDump.py @@ -8,7 +8,7 @@ ALL RIGHTS RESERVED. """ import idc -from idaapi import Choose +from ida_kernwin import Choose import re @@ -27,25 +27,40 @@ class memva: else: self.type = 0 self.typestr = "" - def __str__(self): - return "(Base %08X; RegionSize: %08X; State: %08X/%10s; protect: %08X/%10s; type: %08X/%10s)" % ( - self.base, self.regionsize, self.state, - self.statestr, self.protect, - self.protectstr, self.type, self.typestr) # Chooser class class MemChoose(Choose): - def __init__(self, list, title): - Choose.__init__(self, list, title) - self.width = 250 + def __init__(self, title, items): + headers = [] + headers.append(["Base", 10]) + headers.append(["RegionSize", 10]) + headers.append(["State", 20]) + headers.append(["Protect", 20]) + headers.append(["Type", 20]) + Choose.__init__(self, title, headers) + self.items = items - def enter(self, n): - o = self.list[n-1] - idc.Jump(o.base) + def OnGetLine(self, n): + o = self.items[n] + line = [] + line.append("%08X" % o.base) + line.append("%08X" % o.regionsize) + line.append("%08X/%10s" % (o.state, o.statestr)) + line.append("%08X/%10s" % (o.protect, o.protectstr)) + line.append("%08X/%10s" % (o.type, o.typestr)) + return line + + def OnGetSize(self): + return len(self.items) + + def OnSelectLine(self, n): + o = self.items[n] + idc.jumpto(o.base) + return (NOTHING_CHANGED, ) # main def main(): - s = idc.Eval('SendDbgCommand("!vadump")') + s = idc.eval('send_dbg_command("!vadump")') if "IDC_FAILURE" in s: return (False, "Cannot execute the command") @@ -61,9 +76,9 @@ def main(): return (False, "Nothing to display: Could not parse the result!") # Get a Choose instance - chooser = MemChoose(L, "Memory choose") + chooser = MemChoose("Memory choose", L) # Run the chooser - chooser.choose() + chooser.Show() return (True, "Success!") r = main() if not r[0]: diff --git a/Scripts/VirusTotal.py b/Scripts/VirusTotal.py index ca2a86f..8069b3a 100644 --- a/Scripts/VirusTotal.py +++ b/Scripts/VirusTotal.py @@ -9,7 +9,8 @@ # import idaapi import idc -from idaapi import Choose2, plugin_t +from idaapi import plugin_t +from ida_kernwin import Choose import BboeVt as vt import webbrowser import urllib @@ -46,7 +47,7 @@ class VirusTotalConfig(object): def Default(self): - self.md5sum = GetInputMD5() + self.md5sum = retrieve_input_file_md5() self.infile = idaapi.dbg_get_input_path() if not self.infile: self.infile = "" @@ -118,15 +119,15 @@ def VtReport(apikey, filename=None, md5sum=None): # ----------------------------------------------------------------------- -class VirusTotalChooser(Choose2): +class VirusTotalChooser(Choose): """ Chooser class to display results from VT """ def __init__(self, title, items, icon, embedded=False): - Choose2.__init__(self, - title, - [ ["Antivirus", 20], ["Result", 40] ], - embedded=embedded) + Choose.__init__(self, + title, + [ ["Antivirus", 20], ["Result", 40] ], + embedded=embedded) self.items = items self.icon = icon @@ -139,10 +140,6 @@ class VirusTotalChooser(Choose2): self.items = [] if items is None else items - def OnClose(self): - pass - - def OnGetLine(self, n): return self.items[n] @@ -155,6 +152,7 @@ class VirusTotalChooser(Choose2): # Google search for the malware name and the antivirus name s = urllib.urlencode({"q" : " ".join(self.items[n])}) webbrowser.open_new_tab("http://www.google.com/search?%s" % s) + return (NOTHING_CHANGED, ) # -------------------------------------------------------------------------- @@ -224,7 +222,7 @@ Options: # Error? if not ok: - idc.Warning(r) + idc.warning(r) return 1 # Pass the result @@ -245,20 +243,20 @@ Options: if r is None: if as_file: # Propose to upload - if idc.AskYN(0, "HIDECANCEL\nNo previous results. Do you want to submit the file:\n\n'%s'\n\nto VirusTotal?" % input) == 0: + if idc.ask_yn(0, "HIDECANCEL\nNo previous results. Do you want to submit the file:\n\n'%s'\n\nto VirusTotal?" % input) == 0: return 1 try: r = vt.scan_file(input) except Exception as e: - idc.Warning("Exceptio during upload: %s" % str(e)) + idc.warning("Exceptio during upload: %s" % str(e)) else: if r is None: - idc.Warning("Failed to upload the file!") + idc.warning("Failed to upload the file!") else: - idc.Warning("File uploaded. Check again later to get the analysis report. Scan id: %s" % r) + idc.warning("File uploaded. Check again later to get the analysis report. Scan id: %s" % r) else: - idc.Warning("No results found for hash: %s" % input) + idc.warning("No results found for hash: %s" % input) return 1 diff --git a/Scripts/msdnapihelp.py b/Scripts/msdnapihelp.py index 8a90d60..b920c6e 100644 --- a/Scripts/msdnapihelp.py +++ b/Scripts/msdnapihelp.py @@ -36,7 +36,8 @@ class msdnapihelp_plugin_t(idaapi.plugin_t): def run(self, arg): # Get the highlighted identifier - id = idaapi.get_highlighted_identifier() + v = idaapi.get_current_viewer() + id = ida_kernwin.get_highlight(v)[0] if not id: print "No identifier was highlighted" return diff --git a/api_contents.txt b/api_contents.txt index e7f5b5a..092cece 100644 --- a/api_contents.txt +++ b/api_contents.txt @@ -1,7 +1,4 @@ {'functions': ['AssembleLine', - 'Compile', - 'CompileEx', - 'CompileLine', 'DBG_Hooks_dbg_bpt', 'DBG_Hooks_dbg_bpt_changed', 'DBG_Hooks_dbg_exception', @@ -23,33 +20,37 @@ 'DBG_Hooks_dbg_trace', 'DBG_Hooks_hook', 'DBG_Hooks_unhook', - 'ExtraFree', 'IDB_Hooks_allsegs_moved', - 'IDB_Hooks_area_cmt_changed', + 'IDB_Hooks_auto_empty', + 'IDB_Hooks_auto_empty_finally', 'IDB_Hooks_byte_patched', - 'IDB_Hooks_changed_stkpnts', - 'IDB_Hooks_changed_struc', - 'IDB_Hooks_changing_area_cmt', 'IDB_Hooks_changing_cmt', 'IDB_Hooks_changing_enum_bf', 'IDB_Hooks_changing_enum_cmt', 'IDB_Hooks_changing_op_ti', 'IDB_Hooks_changing_op_type', + 'IDB_Hooks_changing_range_cmt', 'IDB_Hooks_changing_segm_class', 'IDB_Hooks_changing_segm_end', 'IDB_Hooks_changing_segm_name', 'IDB_Hooks_changing_segm_start', - 'IDB_Hooks_changing_struc', + 'IDB_Hooks_changing_struc_align', 'IDB_Hooks_changing_struc_cmt', 'IDB_Hooks_changing_struc_member', 'IDB_Hooks_changing_ti', + 'IDB_Hooks_closebase', 'IDB_Hooks_cmt_changed', + 'IDB_Hooks_compiler_changed', 'IDB_Hooks_deleting_enum', - 'IDB_Hooks_deleting_enum_const', + 'IDB_Hooks_deleting_enum_member', + 'IDB_Hooks_deleting_func', + 'IDB_Hooks_deleting_func_tail', 'IDB_Hooks_deleting_segm', 'IDB_Hooks_deleting_struc', 'IDB_Hooks_deleting_struc_member', + 'IDB_Hooks_deleting_tryblks', 'IDB_Hooks_destroyed_items', + 'IDB_Hooks_determined_main', 'IDB_Hooks_enum_bf_changed', 'IDB_Hooks_enum_cmt_changed', 'IDB_Hooks_enum_created', @@ -58,26 +59,43 @@ 'IDB_Hooks_enum_member_deleted', 'IDB_Hooks_enum_renamed', 'IDB_Hooks_expanding_struc', + 'IDB_Hooks_extlang_changed', 'IDB_Hooks_extra_cmt_changed', + 'IDB_Hooks_flow_chart_created', + 'IDB_Hooks_frame_deleted', + 'IDB_Hooks_func_added', 'IDB_Hooks_func_noret_changed', 'IDB_Hooks_func_tail_appended', - 'IDB_Hooks_func_tail_removed', + 'IDB_Hooks_func_tail_deleted', + 'IDB_Hooks_func_updated', 'IDB_Hooks_hook', + 'IDB_Hooks_idasgn_loaded', + 'IDB_Hooks_kernel_config_loaded', + 'IDB_Hooks_loader_finished', 'IDB_Hooks_local_types_changed', + 'IDB_Hooks_make_code', + 'IDB_Hooks_make_data', 'IDB_Hooks_op_ti_changed', 'IDB_Hooks_op_type_changed', - 'IDB_Hooks_removing_func_tail', + 'IDB_Hooks_range_cmt_changed', + 'IDB_Hooks_renamed', 'IDB_Hooks_renaming_enum', 'IDB_Hooks_renaming_struc', 'IDB_Hooks_renaming_struc_member', + 'IDB_Hooks_savebase', 'IDB_Hooks_segm_added', - 'IDB_Hooks_segm_attrs_changed', + 'IDB_Hooks_segm_attrs_updated', 'IDB_Hooks_segm_class_changed', 'IDB_Hooks_segm_deleted', 'IDB_Hooks_segm_end_changed', 'IDB_Hooks_segm_moved', 'IDB_Hooks_segm_name_changed', 'IDB_Hooks_segm_start_changed', + 'IDB_Hooks_set_func_end', + 'IDB_Hooks_set_func_start', + 'IDB_Hooks_sgr_changed', + 'IDB_Hooks_stkpnts_changed', + 'IDB_Hooks_struc_align_changed', 'IDB_Hooks_struc_cmt_changed', 'IDB_Hooks_struc_created', 'IDB_Hooks_struc_deleted', @@ -90,147 +108,136 @@ 'IDB_Hooks_tail_owner_changed', 'IDB_Hooks_thunk_func_created', 'IDB_Hooks_ti_changed', + 'IDB_Hooks_tryblks_updated', 'IDB_Hooks_unhook', - 'IDP_Hooks_add_cref', - 'IDP_Hooks_add_dref', - 'IDP_Hooks_add_func', - 'IDP_Hooks_adjust_libfunc_ea', - 'IDP_Hooks_adjust_refinfo', - 'IDP_Hooks_assemble', - 'IDP_Hooks_auto_empty', - 'IDP_Hooks_auto_empty_finally', - 'IDP_Hooks_auto_queue_empty', - 'IDP_Hooks_based_ptr', - 'IDP_Hooks_calc_arglocs3', - 'IDP_Hooks_calc_cdecl_purged_bytes2', - 'IDP_Hooks_calc_next_eas', - 'IDP_Hooks_calc_purged_bytes3', - 'IDP_Hooks_calc_retloc3', - 'IDP_Hooks_calc_step_over', - 'IDP_Hooks_calc_switch_cases', - 'IDP_Hooks_calc_varglocs3', - 'IDP_Hooks_clean_tbit', - 'IDP_Hooks_closebase', - 'IDP_Hooks_coagulate', - 'IDP_Hooks_coagulate_dref', - 'IDP_Hooks_create_flat_group', - 'IDP_Hooks_create_switch_xrefs', - 'IDP_Hooks_custom_ana', - 'IDP_Hooks_custom_emu', - 'IDP_Hooks_custom_mnem', - 'IDP_Hooks_custom_out', - 'IDP_Hooks_custom_outop', - 'IDP_Hooks_custom_refinfo', - 'IDP_Hooks_decorate_name3', - 'IDP_Hooks_del_cref', - 'IDP_Hooks_del_dref', - 'IDP_Hooks_del_func', - 'IDP_Hooks_delay_slot_insn', - 'IDP_Hooks_determined_main', - 'IDP_Hooks_endbinary', - 'IDP_Hooks_equal_reglocs', - 'IDP_Hooks_extlang_changed', - 'IDP_Hooks_func_bounds', - 'IDP_Hooks_gen_asm_or_lst', - 'IDP_Hooks_gen_regvar_def', - 'IDP_Hooks_get_autocmt', - 'IDP_Hooks_get_bg_color', - 'IDP_Hooks_get_dbr_opnum', - 'IDP_Hooks_get_default_enum_size', - 'IDP_Hooks_get_fastcall_regs3', - 'IDP_Hooks_get_func_cvtarg_map', - 'IDP_Hooks_get_jump_target', - 'IDP_Hooks_get_macro_insn_head', - 'IDP_Hooks_get_operand_string', - 'IDP_Hooks_get_reg_info2', - 'IDP_Hooks_get_reg_name', - 'IDP_Hooks_get_simd_types', - 'IDP_Hooks_get_stkarg_offset2', - 'IDP_Hooks_get_stkvar_scale_factor', - 'IDP_Hooks_get_thiscall_regs3', - 'IDP_Hooks_get_varcall_regs3', - 'IDP_Hooks_get_vxd_name', + 'IDB_Hooks_updating_tryblks', + 'IDB_Hooks_upgraded', + 'IDP_Hooks_ev_add_cref', + 'IDP_Hooks_ev_add_dref', + 'IDP_Hooks_ev_adjust_argloc', + 'IDP_Hooks_ev_adjust_libfunc_ea', + 'IDP_Hooks_ev_adjust_refinfo', + 'IDP_Hooks_ev_ana_insn', + 'IDP_Hooks_ev_arg_addrs_ready', + 'IDP_Hooks_ev_assemble', + 'IDP_Hooks_ev_auto_queue_empty', + 'IDP_Hooks_ev_calc_arglocs', + 'IDP_Hooks_ev_calc_cdecl_purged_bytes', + 'IDP_Hooks_ev_calc_next_eas', + 'IDP_Hooks_ev_calc_purged_bytes', + 'IDP_Hooks_ev_calc_retloc', + 'IDP_Hooks_ev_calc_step_over', + 'IDP_Hooks_ev_calc_switch_cases', + 'IDP_Hooks_ev_calc_varglocs', + 'IDP_Hooks_ev_can_have_type', + 'IDP_Hooks_ev_clean_tbit', + 'IDP_Hooks_ev_cmp_operands', + 'IDP_Hooks_ev_coagulate', + 'IDP_Hooks_ev_coagulate_dref', + 'IDP_Hooks_ev_create_flat_group', + 'IDP_Hooks_ev_create_func_frame', + 'IDP_Hooks_ev_create_switch_xrefs', + 'IDP_Hooks_ev_creating_segm', + 'IDP_Hooks_ev_decorate_name', + 'IDP_Hooks_ev_del_cref', + 'IDP_Hooks_ev_del_dref', + 'IDP_Hooks_ev_delay_slot_insn', + 'IDP_Hooks_ev_demangle_name', + 'IDP_Hooks_ev_emu_insn', + 'IDP_Hooks_ev_endbinary', + 'IDP_Hooks_ev_equal_reglocs', + 'IDP_Hooks_ev_extract_address', + 'IDP_Hooks_ev_func_bounds', + 'IDP_Hooks_ev_gen_asm_or_lst', + 'IDP_Hooks_ev_gen_map_file', + 'IDP_Hooks_ev_gen_regvar_def', + 'IDP_Hooks_ev_gen_src_file_lnnum', + 'IDP_Hooks_ev_gen_stkvar_def', + 'IDP_Hooks_ev_get_abi_info', + 'IDP_Hooks_ev_get_autocmt', + 'IDP_Hooks_ev_get_bg_color', + 'IDP_Hooks_ev_get_cc_regs', + 'IDP_Hooks_ev_get_dbr_opnum', + 'IDP_Hooks_ev_get_default_enum_size', + 'IDP_Hooks_ev_get_frame_retsize', + 'IDP_Hooks_ev_get_macro_insn_head', + 'IDP_Hooks_ev_get_operand_string', + 'IDP_Hooks_ev_get_reg_info', + 'IDP_Hooks_ev_get_reg_name', + 'IDP_Hooks_ev_get_simd_types', + 'IDP_Hooks_ev_get_stkarg_offset', + 'IDP_Hooks_ev_get_stkvar_scale_factor', + 'IDP_Hooks_ev_getreg', + 'IDP_Hooks_ev_init', + 'IDP_Hooks_ev_insn_reads_tbit', + 'IDP_Hooks_ev_is_align_insn', + 'IDP_Hooks_ev_is_alloca_probe', + 'IDP_Hooks_ev_is_basic_block_end', + 'IDP_Hooks_ev_is_call_insn', + 'IDP_Hooks_ev_is_cond_insn', + 'IDP_Hooks_ev_is_far_jump', + 'IDP_Hooks_ev_is_indirect_jump', + 'IDP_Hooks_ev_is_insn_table_jump', + 'IDP_Hooks_ev_is_jump_func', + 'IDP_Hooks_ev_is_ret_insn', + 'IDP_Hooks_ev_is_sane_insn', + 'IDP_Hooks_ev_is_sp_based', + 'IDP_Hooks_ev_is_switch', + 'IDP_Hooks_ev_loader', + 'IDP_Hooks_ev_lower_func_type', + 'IDP_Hooks_ev_max_ptr_size', + 'IDP_Hooks_ev_may_be_func', + 'IDP_Hooks_ev_may_show_sreg', + 'IDP_Hooks_ev_moving_segm', + 'IDP_Hooks_ev_newasm', + 'IDP_Hooks_ev_newbinary', + 'IDP_Hooks_ev_newfile', + 'IDP_Hooks_ev_newprc', + 'IDP_Hooks_ev_next_exec_insn', + 'IDP_Hooks_ev_oldfile', + 'IDP_Hooks_ev_out_assumes', + 'IDP_Hooks_ev_out_data', + 'IDP_Hooks_ev_out_footer', + 'IDP_Hooks_ev_out_header', + 'IDP_Hooks_ev_out_insn', + 'IDP_Hooks_ev_out_label', + 'IDP_Hooks_ev_out_mnem', + 'IDP_Hooks_ev_out_operand', + 'IDP_Hooks_ev_out_segend', + 'IDP_Hooks_ev_out_segstart', + 'IDP_Hooks_ev_out_special_item', + 'IDP_Hooks_ev_realcvt', + 'IDP_Hooks_ev_rename', + 'IDP_Hooks_ev_set_idp_options', + 'IDP_Hooks_ev_set_proc_options', + 'IDP_Hooks_ev_setup_til', + 'IDP_Hooks_ev_shadow_args_size', + 'IDP_Hooks_ev_str2reg', + 'IDP_Hooks_ev_term', + 'IDP_Hooks_ev_treat_hindering_item', + 'IDP_Hooks_ev_undefine', + 'IDP_Hooks_ev_use_arg_types', + 'IDP_Hooks_ev_use_regarg_type', + 'IDP_Hooks_ev_use_stkarg_type', + 'IDP_Hooks_ev_validate_flirt_func', + 'IDP_Hooks_ev_verify_noreturn', + 'IDP_Hooks_ev_verify_sp', 'IDP_Hooks_hook', - 'IDP_Hooks_init', - 'IDP_Hooks_insn_reads_tbit', - 'IDP_Hooks_is_alloca_probe', - 'IDP_Hooks_is_basic_block_end', - 'IDP_Hooks_is_call_insn', - 'IDP_Hooks_is_indirect_jump', - 'IDP_Hooks_is_insn_table_jump', - 'IDP_Hooks_is_jump_func', - 'IDP_Hooks_is_ret_insn', - 'IDP_Hooks_is_sane_insn', - 'IDP_Hooks_kernel_config_loaded', - 'IDP_Hooks_load_idasgn', - 'IDP_Hooks_loader', - 'IDP_Hooks_loader_finished', - 'IDP_Hooks_make_code', - 'IDP_Hooks_make_data', - 'IDP_Hooks_max_ptr_size', - 'IDP_Hooks_may_be_func', - 'IDP_Hooks_may_show_sreg', - 'IDP_Hooks_might_change_sp', - 'IDP_Hooks_move_segm', - 'IDP_Hooks_moving_segm', - 'IDP_Hooks_newasm', - 'IDP_Hooks_newbinary', - 'IDP_Hooks_newfile', - 'IDP_Hooks_newprc', - 'IDP_Hooks_newseg', - 'IDP_Hooks_obsolete_makemicro', - 'IDP_Hooks_oldfile', - 'IDP_Hooks_out_3byte', - 'IDP_Hooks_out_src_file_lnnum', - 'IDP_Hooks_outlabel', - 'IDP_Hooks_preprocess_chart', - 'IDP_Hooks_register_custom_fixup', - 'IDP_Hooks_reglink', - 'IDP_Hooks_rename', - 'IDP_Hooks_renamed', - 'IDP_Hooks_savebase', - 'IDP_Hooks_set_compiler', - 'IDP_Hooks_set_func_end', - 'IDP_Hooks_set_func_start', - 'IDP_Hooks_set_proc_options', - 'IDP_Hooks_setsgr', - 'IDP_Hooks_setup_til', - 'IDP_Hooks_shadow_args_size', - 'IDP_Hooks_str2reg', - 'IDP_Hooks_term', - 'IDP_Hooks_til_for_file', - 'IDP_Hooks_treat_hindering_item', - 'IDP_Hooks_undefine', 'IDP_Hooks_unhook', - 'IDP_Hooks_use_arg_types3', - 'IDP_Hooks_use_regarg_type3', - 'IDP_Hooks_use_stkarg_type3', - 'IDP_Hooks_validate_flirt_func', - 'IDP_Hooks_verify_noreturn', - 'IDP_Hooks_verify_sp', - 'InstrIsSet', - 'MakeBorder', - 'MakeLine', - 'MakeNull', - 'MakeSolidBorder', - 'OutBadInstruction', - 'OutChar', - 'OutImmChar', - 'OutLine', - 'OutLong', - 'OutMnem', - 'OutValue', - 'QueueDel', - 'QueueGetMessage', - 'QueueGetType', - 'QueueIsPresent', - 'QueueMark', - 'QueueSet', - 'SetDefaultRegisterValue', - 'UI_Hooks_current_tform_changed', + 'TPointDouble___eq__', + 'TPointDouble___ne__', + 'TPointDouble_add', + 'TPointDouble_negate', + 'TPointDouble_sub', + 'TPointDouble_x_get', + 'TPointDouble_x_set', + 'TPointDouble_y_get', + 'TPointDouble_y_set', + 'UI_Hooks_current_widget_changed', 'UI_Hooks_database_inited', 'UI_Hooks_debugger_menu_change', - 'UI_Hooks_finish_populating_tform_popup', + 'UI_Hooks_finish_populating_widget_popup', + 'UI_Hooks_get_chooser_item_attrs', 'UI_Hooks_get_custom_viewer_hint', 'UI_Hooks_get_ea_hint', 'UI_Hooks_get_item_hint', @@ -239,9 +246,9 @@ 'UI_Hooks_idcstop', 'UI_Hooks_plugin_loaded', 'UI_Hooks_plugin_unloading', - 'UI_Hooks_populating_tform_popup', - 'UI_Hooks_postprocess', - 'UI_Hooks_preprocess', + 'UI_Hooks_populating_widget_popup', + 'UI_Hooks_postprocess_action', + 'UI_Hooks_preprocess_action', 'UI_Hooks_range', 'UI_Hooks_ready_to_run', 'UI_Hooks_resume', @@ -249,41 +256,46 @@ 'UI_Hooks_saving', 'UI_Hooks_suspend', 'UI_Hooks_term', - 'UI_Hooks_tform_invisible', - 'UI_Hooks_tform_visible', 'UI_Hooks_unhook', 'UI_Hooks_updated_actions', 'UI_Hooks_updating_actions', - 'VarAssign', - 'VarCopy', - 'VarDelAttr', - 'VarDeref', - 'VarFirstAttr', - 'VarGetAttr', - 'VarGetClassName', - 'VarGetSlice', - 'VarInt64', - 'VarLastAttr', - 'VarMove', - 'VarNextAttr', - 'VarObject', - 'VarPrevAttr', - 'VarPrint', - 'VarRef', - 'VarSetAttr', - 'VarSetSlice', - 'VarString2', - 'VarSwap', - '_askaddr', - '_askaddr__varargs__', - '_asklong', - '_asklong__varargs__', - '_askseg', - '_askseg__varargs__', + 'UI_Hooks_widget_closing', + 'UI_Hooks_widget_invisible', + 'UI_Hooks_widget_visible', + 'View_Hooks_hook', + 'View_Hooks_unhook', + 'View_Hooks_view_activated', + 'View_Hooks_view_click', + 'View_Hooks_view_close', + 'View_Hooks_view_created', + 'View_Hooks_view_curpos', + 'View_Hooks_view_dblclick', + 'View_Hooks_view_deactivated', + 'View_Hooks_view_keydown', + 'View_Hooks_view_loc_changed', + 'View_Hooks_view_mouse_moved', + 'View_Hooks_view_mouse_over', + 'View_Hooks_view_switched', + '_ask_addr', + '_ask_addr__varargs__', + '_ask_long', + '_ask_long__varargs__', + '_ask_seg', + '_ask_seg__varargs__', '_decompile', '_kludge_use_TPopupMenu', - 'a2funcoff', + '_ll_call_helper', + '_ll_call_helper__varargs__', + '_ll_create_helper', + '_ll_create_helper__varargs__', + '_ll_dereference', + '_ll_lnot', + '_ll_make_num', + '_ll_make_ref', + '_ll_new_block', 'accepts_udts', + 'action_ctx_base_t__get_form_type', + 'action_ctx_base_t__get_reg', 'action_ctx_base_t_action_get', 'action_ctx_base_t_action_set', 'action_ctx_base_t_chooser_selection_get', @@ -306,16 +318,22 @@ 'action_ctx_base_t_cur_strmem_set', 'action_ctx_base_t_cur_struc_get', 'action_ctx_base_t_cur_struc_set', - 'action_ctx_base_t_form_get', - 'action_ctx_base_t_form_set', - 'action_ctx_base_t_form_title_get', - 'action_ctx_base_t_form_title_set', - 'action_ctx_base_t_form_type_get', - 'action_ctx_base_t_form_type_set', + 'action_ctx_base_t_focus_get', + 'action_ctx_base_t_focus_set', 'action_ctx_base_t_has_flag', + 'action_ctx_base_t_reserved_get', + 'action_ctx_base_t_reserved_set', 'action_ctx_base_t_reset', + 'action_ctx_base_t_widget_get', + 'action_ctx_base_t_widget_set', + 'action_ctx_base_t_widget_title_get', + 'action_ctx_base_t_widget_title_set', + 'action_ctx_base_t_widget_type_get', + 'action_ctx_base_t_widget_type_set', 'action_desc_t_cb_get', 'action_desc_t_cb_set', + 'action_desc_t_flags_get', + 'action_desc_t_flags_set', 'action_desc_t_icon_get', 'action_desc_t_icon_set', 'action_desc_t_label_get', @@ -328,54 +346,47 @@ 'action_desc_t_shortcut_set', 'action_desc_t_tooltip_get', 'action_desc_t_tooltip_set', + 'activate_widget', 'add_auto_stkpnt', - 'add_auto_stkpnt2', 'add_bpt', 'add_bpt__SWIG_0', 'add_bpt__SWIG_1', 'add_byte', - 'add_chooser_command', - 'add_chooser_command__SWIG_0', - 'add_chooser_command__SWIG_1', - 'add_const', 'add_cref', - 'add_custom_viewer_popup_item', - 'add_custom_viewer_popup_item__SWIG_1', 'add_dref', + 'add_dword', 'add_encoding', 'add_entry', 'add_enum', 'add_enum_member', + 'add_extra_cmt', + 'add_extra_cmt__varargs__', + 'add_extra_line', + 'add_extra_line__varargs__', 'add_frame', 'add_func', 'add_func_ex', - 'add_hidden_area', + 'add_hidden_range', 'add_hotkey', 'add_idc_class', 'add_idc_gvar', 'add_idc_hotkey', - 'add_long', - 'add_long_cmt', - 'add_long_cmt__varargs__', - 'add_menu_item', - 'add_output_popup', + 'add_mapping', 'add_pgm_cmt', 'add_pgm_cmt__varargs__', 'add_qword', + 'add_refinfo_dref', 'add_regarg', - 'add_regarg2', 'add_regvar', 'add_segm', 'add_segm_ex', 'add_segment_translation', 'add_sourcefile', 'add_spaces', - 'add_stkvar2', - 'add_stkvar3', 'add_struc', 'add_struc_member', 'add_til', - 'add_til2', + 'add_tryblk', 'add_user_stkpnt', 'add_virt_module', 'add_word', @@ -398,134 +409,28 @@ 'addon_info_t_url_set', 'addon_info_t_version_get', 'addon_info_t_version_set', - 'alignflag', + 'align_flag', 'alloc_type_ordinal', 'alloc_type_ordinals', 'allocate_selector', 'aloc_visitor_t_visit_location', - 'analyze_area', 'analyzer_options', - 'ansi2idb', 'appcall', + 'append_abi_opts', 'append_argloc', 'append_cmt', - 'append_complex_n', - 'append_da', - 'append_de', - 'append_dt', 'append_func_tail', - 'append_name', - 'append_struct_fields2', + 'append_struct_fields', 'append_tinfo_covered', - 'append_varloc', 'apply_callee_tinfo', 'apply_cdecl', - 'apply_cdecl2', - 'apply_idasgn', 'apply_idasgn_to', 'apply_named_type', 'apply_once_tinfo_and_name', - 'apply_once_type_and_name', 'apply_startup_sig', 'apply_tinfo', - 'apply_tinfo2', 'apply_tinfo_to_stkarg', 'apply_type', - 'apply_type2', - 'apply_type_to_stkarg', - 'area_t___eq__', - 'area_t___gt__', - 'area_t___lt__', - 'area_t___ne__', - 'area_t__print', - 'area_t_clear', - 'area_t_compare', - 'area_t_contains', - 'area_t_contains__SWIG_0', - 'area_t_contains__SWIG_1', - 'area_t_empty', - 'area_t_endEA_get', - 'area_t_endEA_set', - 'area_t_extend', - 'area_t_intersect', - 'area_t_overlaps', - 'area_t_print', - 'area_t_size', - 'area_t_startEA_get', - 'area_t_startEA_set', - 'area_visitor2_t_visit_area', - 'areacb_t_create', - 'areacb_t_create_area', - 'areacb_t_del_area', - 'areacb_t_del_area_cmt', - 'areacb_t_first_area_ptr', - 'areacb_t_for_all_areas2', - 'areacb_t_get_area', - 'areacb_t_get_area_cmt', - 'areacb_t_get_area_num', - 'areacb_t_get_area_qty', - 'areacb_t_get_netnode', - 'areacb_t_get_next_area', - 'areacb_t_get_prev_area', - 'areacb_t_get_type', - 'areacb_t_getn_area', - 'areacb_t_kill', - 'areacb_t_last_area_ptr', - 'areacb_t_link', - 'areacb_t_make_hole', - 'areacb_t_may_end_at', - 'areacb_t_may_lock_area', - 'areacb_t_may_start_at', - 'areacb_t_next_area_ptr', - 'areacb_t_prepare_to_create', - 'areacb_t_prev_area_ptr', - 'areacb_t_resize_areas', - 'areacb_t_save', - 'areacb_t_set_area_cmt', - 'areacb_t_set_end', - 'areacb_t_set_start', - 'areacb_t_terminate', - 'areacb_t_update', - 'areacb_t_zero', - 'areaset_t___eq__', - 'areaset_t___ne__', - 'areaset_t__print', - 'areaset_t_add', - 'areaset_t_add__SWIG_0', - 'areaset_t_add__SWIG_1', - 'areaset_t_add__SWIG_2', - 'areaset_t_begin', - 'areaset_t_begin__SWIG_0', - 'areaset_t_begin__SWIG_1', - 'areaset_t_cached_area', - 'areaset_t_clear', - 'areaset_t_contains', - 'areaset_t_contains__SWIG_0', - 'areaset_t_contains__SWIG_1', - 'areaset_t_empty', - 'areaset_t_end', - 'areaset_t_end__SWIG_0', - 'areaset_t_end__SWIG_1', - 'areaset_t_find_area', - 'areaset_t_getarea', - 'areaset_t_has_common', - 'areaset_t_has_common__SWIG_0', - 'areaset_t_has_common__SWIG_1', - 'areaset_t_includes', - 'areaset_t_intersect', - 'areaset_t_is_equal', - 'areaset_t_is_subset_of', - 'areaset_t_lastarea', - 'areaset_t_nareas', - 'areaset_t_next_addr', - 'areaset_t_next_area', - 'areaset_t_prev_addr', - 'areaset_t_prev_area', - 'areaset_t_sub', - 'areaset_t_sub__SWIG_0', - 'areaset_t_sub__SWIG_1', - 'areaset_t_sub__SWIG_2', - 'areaset_t_swap', 'argloc_t___eq__', 'argloc_t___ge__', 'argloc_t___gt__', @@ -600,36 +505,18 @@ 'array_type_data_t_nelems_get', 'array_type_data_t_nelems_set', 'array_type_data_t_swap', - 'asciflag', 'asgop', 'asgop_revert', + 'ask_buttons', + 'ask_buttons__varargs__', + 'ask_file', + 'ask_file__varargs__', 'ask_for_feedback', 'ask_for_feedback__varargs__', - 'ask_selector', - 'askbuttons_c', - 'askbuttons_c__varargs__', - 'askfile2_c', - 'askfile2_c__varargs__', - 'askfile2_cv', - 'askfile_c', - 'askfile_c__varargs__', - 'askident', - 'askident__varargs__', - 'askqstr', - 'askqstr__varargs__', - 'askstr', - 'askstr__varargs__', - 'asktext', - 'askyn_c', - 'askyn_c__varargs__', - 'asm_t_XlatAsciiOutput_get', - 'asm_t_XlatAsciiOutput_set', - 'asm_t__UNUSED1_was_atomprefix_get', - 'asm_t__UNUSED1_was_atomprefix_set', - 'asm_t__UNUSED2_was_checkarg_operations_get', - 'asm_t__UNUSED2_was_checkarg_operations_set', - 'asm_t_a_3byte_get', - 'asm_t_a_3byte_set', + 'ask_str', + 'ask_text', + 'ask_yn', + 'ask_yn__varargs__', 'asm_t_a_align_get', 'asm_t_a_align_set', 'asm_t_a_ascii_get', @@ -698,8 +585,6 @@ 'asm_t_accsep_set', 'asm_t_ascsep_get', 'asm_t_ascsep_set', - 'asm_t_badworks_get', - 'asm_t_badworks_set', 'asm_t_cmnt2_get', 'asm_t_cmnt2_set', 'asm_t_cmnt_get', @@ -737,19 +622,13 @@ 'assemble', 'attach_action_to_menu', 'attach_action_to_popup', - 'attach_action_to_popup__SWIG_0', - 'attach_action_to_popup__SWIG_1', 'attach_action_to_toolbar', + 'attach_custom_data_format', 'attach_dynamic_action_to_popup', 'attach_process', - 'autoCancel', - 'autoGetName', - 'autoIsOk', - 'autoMark', - 'autoStep', - 'autoUnmark', - 'autoWait', + 'auto_apply_tail', 'auto_apply_type', + 'auto_cancel', 'auto_display_t_ea_get', 'auto_display_t_ea_set', 'auto_display_t_state_get', @@ -757,9 +636,14 @@ 'auto_display_t_type_get', 'auto_display_t_type_set', 'auto_get', + 'auto_is_ok', 'auto_make_code', 'auto_make_proc', + 'auto_mark', 'auto_mark_range', + 'auto_recreate_insn', + 'auto_unmark', + 'auto_wait', 'banner', 'base2file', 'beep', @@ -770,8 +654,8 @@ 'bgcolors_t_prolog_color_set', 'bgcolors_t_switch_color_get', 'bgcolors_t_switch_color_set', + 'bin_flag', 'bin_search', - 'binflag', 'bitfield_type_data_t___eq__', 'bitfield_type_data_t___ge__', 'bitfield_type_data_t___gt__', @@ -800,9 +684,6 @@ 'boolvec_t__del', 'boolvec_t_add_unique', 'boolvec_t_at', - 'boolvec_t_back', - 'boolvec_t_back__SWIG_0', - 'boolvec_t_back__SWIG_1', 'boolvec_t_begin', 'boolvec_t_begin__SWIG_0', 'boolvec_t_begin__SWIG_1', @@ -819,9 +700,6 @@ 'boolvec_t_find', 'boolvec_t_find__SWIG_0', 'boolvec_t_find__SWIG_1', - 'boolvec_t_front', - 'boolvec_t_front__SWIG_0', - 'boolvec_t_front__SWIG_1', 'boolvec_t_grow', 'boolvec_t_has', 'boolvec_t_inject', @@ -895,6 +773,7 @@ 'bpt_t_enabled', 'bpt_t_flags_get', 'bpt_t_flags_set', + 'bpt_t_get_cnd_elang_idx', 'bpt_t_get_size', 'bpt_t_is_absbpt', 'bpt_t_is_active', @@ -930,9 +809,6 @@ 'bpt_vec_t___len__', 'bpt_vec_t___setitem__', 'bpt_vec_t_at', - 'bpt_vec_t_back', - 'bpt_vec_t_back__SWIG_0', - 'bpt_vec_t_back__SWIG_1', 'bpt_vec_t_begin', 'bpt_vec_t_begin__SWIG_0', 'bpt_vec_t_begin__SWIG_1', @@ -946,9 +822,6 @@ 'bpt_vec_t_erase__SWIG_0', 'bpt_vec_t_erase__SWIG_1', 'bpt_vec_t_extract', - 'bpt_vec_t_front', - 'bpt_vec_t_front__SWIG_0', - 'bpt_vec_t_front__SWIG_1', 'bpt_vec_t_grow', 'bpt_vec_t_inject', 'bpt_vec_t_insert', @@ -965,46 +838,36 @@ 'bpt_vec_t_swap', 'bpt_vec_t_truncate', 'bring_debugger_to_front', - 'build_array_type', - 'build_func_type', - 'build_func_type2', - 'build_funcarg_info', 'build_snapshot_tree', 'build_stkvar_name', 'build_stkvar_xrefs', - 'byteflag', + 'build_strlist', + 'byte_flag', 'bytesize', - 'calc_argloc_info', + 'calc_basevalue', 'calc_bg_color', - 'calc_c_cpp_name4', + 'calc_c_cpp_name', + 'calc_dataseg', 'calc_def_align', 'calc_default_idaplace_flags', - 'calc_func_nargs', + 'calc_dist', + 'calc_fixup_size', 'calc_idasgn_state', - 'calc_idc_expr', 'calc_max_align', - 'calc_max_children_qty', 'calc_max_item_end', - 'calc_max_number_of_children', 'calc_min_align', 'calc_number_of_children', + 'calc_offset_base', 'calc_prefix_color', 'calc_probable_base_by_value', - 'calc_reference_basevalue', - 'calc_reference_target', + 'calc_reference_data', 'calc_stkvar_struc_offset', 'calc_switch_cases', 'calc_target', 'calc_thunk_func_target', 'calc_tinfo_gaps', 'calc_type_size', - 'calc_varloc_info', - 'calcexpr', - 'call_helper', - 'call_helper__varargs__', - 'call_idc_method', 'call_nav_colorizer', - 'call_script_method', 'call_stack_info_t___eq__', 'call_stack_info_t___ne__', 'call_stack_info_t_callea_get', @@ -1017,8 +880,6 @@ 'call_stack_info_t_funcok_set', 'call_stack_t_dirty_get', 'call_stack_t_dirty_set', - 'call_system', - 'callregs_init_regs', 'callregs_t_fpregs_get', 'callregs_t_fpregs_set', 'callregs_t_gpregs_get', @@ -1033,6 +894,7 @@ 'callregs_t_reset', 'callregs_t_set', 'can_be_off32', + 'can_decode', 'can_define_item', 'can_exc_continue', 'cancel_exec_request', @@ -1069,9 +931,6 @@ 'casevec_t__del', 'casevec_t_add_unique', 'casevec_t_at', - 'casevec_t_back', - 'casevec_t_back__SWIG_0', - 'casevec_t_back__SWIG_1', 'casevec_t_begin', 'casevec_t_begin__SWIG_0', 'casevec_t_begin__SWIG_1', @@ -1088,9 +947,6 @@ 'casevec_t_find', 'casevec_t_find__SWIG_0', 'casevec_t_find__SWIG_1', - 'casevec_t_front', - 'casevec_t_front__SWIG_0', - 'casevec_t_front__SWIG_1', 'casevec_t_grow', 'casevec_t_has', 'casevec_t_inject', @@ -1115,12 +971,57 @@ 'casm_t___ne__', 'casm_t_compare', 'casm_t_one_insn', + 'catch_t_obj_get', + 'catch_t_obj_set', + 'catch_t_type_id_get', + 'catch_t_type_id_set', + 'catchvec_t___eq__', + 'catchvec_t___getitem__', + 'catchvec_t___len__', + 'catchvec_t___ne__', + 'catchvec_t___setitem__', + 'catchvec_t__del', + 'catchvec_t_add_unique', + 'catchvec_t_at', + 'catchvec_t_begin', + 'catchvec_t_begin__SWIG_0', + 'catchvec_t_begin__SWIG_1', + 'catchvec_t_capacity', + 'catchvec_t_clear', + 'catchvec_t_empty', + 'catchvec_t_end', + 'catchvec_t_end__SWIG_0', + 'catchvec_t_end__SWIG_1', + 'catchvec_t_erase', + 'catchvec_t_erase__SWIG_0', + 'catchvec_t_erase__SWIG_1', + 'catchvec_t_extract', + 'catchvec_t_find', + 'catchvec_t_find__SWIG_0', + 'catchvec_t_find__SWIG_1', + 'catchvec_t_grow', + 'catchvec_t_has', + 'catchvec_t_inject', + 'catchvec_t_insert', + 'catchvec_t_pop_back', + 'catchvec_t_push_back', + 'catchvec_t_push_back__SWIG_0', + 'catchvec_t_push_back__SWIG_1', + 'catchvec_t_qclear', + 'catchvec_t_reserve', + 'catchvec_t_resize', + 'catchvec_t_resize__SWIG_0', + 'catchvec_t_resize__SWIG_1', + 'catchvec_t_size', + 'catchvec_t_swap', + 'catchvec_t_truncate', 'cblock_t___eq__', 'cblock_t___ge__', 'cblock_t___gt__', 'cblock_t___le__', 'cblock_t___lt__', 'cblock_t___ne__', + 'cblock_t__deregister', 'cblock_t_compare', 'ccase_t___eq__', 'ccase_t___ge__', @@ -1155,7 +1056,35 @@ 'cexpr_t___le__', 'cexpr_t___lt__', 'cexpr_t___ne__', - 'cexpr_t_a_get', + 'cexpr_t__deregister', + 'cexpr_t__get_a', + 'cexpr_t__get_fpc', + 'cexpr_t__get_helper', + 'cexpr_t__get_insn', + 'cexpr_t__get_m', + 'cexpr_t__get_n', + 'cexpr_t__get_obj_ea', + 'cexpr_t__get_ptrsize', + 'cexpr_t__get_refwidth', + 'cexpr_t__get_string', + 'cexpr_t__get_x', + 'cexpr_t__get_y', + 'cexpr_t__get_z', + 'cexpr_t__register', + 'cexpr_t__replace_by', + 'cexpr_t__set_a', + 'cexpr_t__set_fpc', + 'cexpr_t__set_helper', + 'cexpr_t__set_insn', + 'cexpr_t__set_m', + 'cexpr_t__set_n', + 'cexpr_t__set_obj_ea', + 'cexpr_t__set_ptrsize', + 'cexpr_t__set_refwidth', + 'cexpr_t__set_string', + 'cexpr_t__set_x', + 'cexpr_t__set_y', + 'cexpr_t__set_z', 'cexpr_t_assign', 'cexpr_t_calc_type', 'cexpr_t_cleanup', @@ -1175,16 +1104,14 @@ 'cexpr_t_find_op', 'cexpr_t_find_op__SWIG_0', 'cexpr_t_find_op__SWIG_1', - 'cexpr_t_fpc_get', 'cexpr_t_get_1num_op', 'cexpr_t_get_const_value', 'cexpr_t_get_high_nbit_bound', 'cexpr_t_get_low_nbit_bound', 'cexpr_t_get_ptr_or_array', 'cexpr_t_get_type_sign', + 'cexpr_t_get_v', 'cexpr_t_has_side_effects', - 'cexpr_t_helper_get', - 'cexpr_t_insn_get', 'cexpr_t_is_call_arg_of', 'cexpr_t_is_call_object_of', 'cexpr_t_is_child_of', @@ -1196,30 +1123,22 @@ 'cexpr_t_is_nice_expr', 'cexpr_t_is_non_zero_const', 'cexpr_t_is_odd_lvalue', + 'cexpr_t_is_type_signed', + 'cexpr_t_is_type_unsigned', 'cexpr_t_is_zero_const', - 'cexpr_t_m_get', 'cexpr_t_maybe_ptr', - 'cexpr_t_n_get', 'cexpr_t_numval', - 'cexpr_t_obj_ea_get', 'cexpr_t_print1', - 'cexpr_t_ptrsize_get', 'cexpr_t_put_number', - 'cexpr_t_refwidth_get', - 'cexpr_t_replace_by', 'cexpr_t_requires_lvalue', 'cexpr_t_set_cpadone', - 'cexpr_t_string_get', + 'cexpr_t_set_v', 'cexpr_t_swap', 'cexpr_t_theother', 'cexpr_t_theother__SWIG_0', 'cexpr_t_theother__SWIG_1', 'cexpr_t_type_get', 'cexpr_t_type_set', - 'cexpr_t_v_get', - 'cexpr_t_x_get', - 'cexpr_t_y_get', - 'cexpr_t_z_get', 'cfg_get_cc_header_path', 'cfg_get_cc_parm', 'cfg_get_cc_predefined_macros', @@ -1253,6 +1172,7 @@ 'cfunc_t_get_line_item', 'cfunc_t_get_lvars', 'cfunc_t_get_pseudocode', + 'cfunc_t_get_stkoff_delta', 'cfunc_t_get_user_cmt', 'cfunc_t_get_user_iflags', 'cfunc_t_get_user_union_selection', @@ -1312,6 +1232,7 @@ 'cfuncptr_t_get_line_item', 'cfuncptr_t_get_lvars', 'cfuncptr_t_get_pseudocode', + 'cfuncptr_t_get_stkoff_delta', 'cfuncptr_t_get_user_cmt', 'cfuncptr_t_get_user_iflags', 'cfuncptr_t_get_user_union_selection', @@ -1363,7 +1284,6 @@ 'cgoto_t_compare', 'cgoto_t_label_num_get', 'cgoto_t_label_num_set', - 'change_encoding_name', 'change_segment_status', 'change_storage_type', 'channel_redir_t_fd_get', @@ -1380,44 +1300,42 @@ 'channel_redir_t_length_set', 'channel_redir_t_start_get', 'channel_redir_t_start_set', - 'charflag', + 'char_flag', 'check_bpt', 'check_process_exit', - 'check_skip_type', 'check_type_trait', 'check_type_trait__SWIG_0', 'check_type_trait__SWIG_1', - 'choose2_activate', - 'choose2_add_command', - 'choose2_close', - 'choose2_create', - 'choose2_find', - 'choose2_get_embedded', - 'choose2_get_embedded_selection', - 'choose2_refresh', - 'choose_choose', - 'choose_enter', + 'choose_activate', + 'choose_close', + 'choose_create', 'choose_entry', 'choose_enum', 'choose_enum_by_value', + 'choose_find', 'choose_func', - 'choose_getl', + 'choose_get_embedded', + 'choose_get_embedded_selection', + 'choose_get_widget', 'choose_idasgn', 'choose_local_tinfo', - 'choose_local_type', 'choose_name', - 'choose_named_type2', + 'choose_named_type', + 'choose_refresh', 'choose_segm', - 'choose_segreg', - 'choose_sizer', 'choose_srcp', 'choose_stkvar_xref', 'choose_struc', 'choose_til', 'choose_trace_file', 'choose_xref', - 'chunksize', - 'chunkstart', + 'chooser_item_attrs_t_color_get', + 'chooser_item_attrs_t_color_set', + 'chooser_item_attrs_t_flags_get', + 'chooser_item_attrs_t_flags_set', + 'chooser_item_attrs_t_reset', + 'chunk_size', + 'chunk_start', 'cif_t___eq__', 'cif_t___ge__', 'cif_t___gt__', @@ -1437,15 +1355,31 @@ 'cinsn_t___le__', 'cinsn_t___lt__', 'cinsn_t___ne__', + 'cinsn_t__deregister', + 'cinsn_t__get_casm', + 'cinsn_t__get_cblock', + 'cinsn_t__get_cdo', + 'cinsn_t__get_cexpr', + 'cinsn_t__get_cfor', + 'cinsn_t__get_cgoto', + 'cinsn_t__get_cif', + 'cinsn_t__get_creturn', + 'cinsn_t__get_cswitch', + 'cinsn_t__get_cwhile', 'cinsn_t__print', + 'cinsn_t__register', + 'cinsn_t__replace_by', + 'cinsn_t__set_casm', + 'cinsn_t__set_cblock', + 'cinsn_t__set_cdo', + 'cinsn_t__set_cexpr', + 'cinsn_t__set_cfor', + 'cinsn_t__set_cgoto', + 'cinsn_t__set_cif', + 'cinsn_t__set_creturn', + 'cinsn_t__set_cswitch', + 'cinsn_t__set_cwhile', 'cinsn_t_assign', - 'cinsn_t_casm_get', - 'cinsn_t_cblock_get', - 'cinsn_t_cdo_get', - 'cinsn_t_cexpr_get', - 'cinsn_t_cfor_get', - 'cinsn_t_cgoto_get', - 'cinsn_t_cif_get', 'cinsn_t_cleanup', 'cinsn_t_collect_free_breaks', 'cinsn_t_collect_free_continues', @@ -1454,14 +1388,10 @@ 'cinsn_t_contains_free_continue', 'cinsn_t_contains_insn', 'cinsn_t_create_if', - 'cinsn_t_creturn_get', - 'cinsn_t_cswitch_get', - 'cinsn_t_cwhile_get', - 'cinsn_t_is_epilog', + 'cinsn_t_insn_is_epilog', 'cinsn_t_is_ordinary_flow', 'cinsn_t_new_insn', 'cinsn_t_print1', - 'cinsn_t_replace_by', 'cinsn_t_swap', 'cinsn_t_zero', 'cinsnptrvec_t___eq__', @@ -1472,9 +1402,6 @@ 'cinsnptrvec_t__del', 'cinsnptrvec_t_add_unique', 'cinsnptrvec_t_at', - 'cinsnptrvec_t_back', - 'cinsnptrvec_t_back__SWIG_0', - 'cinsnptrvec_t_back__SWIG_1', 'cinsnptrvec_t_begin', 'cinsnptrvec_t_begin__SWIG_0', 'cinsnptrvec_t_begin__SWIG_1', @@ -1491,9 +1418,6 @@ 'cinsnptrvec_t_find', 'cinsnptrvec_t_find__SWIG_0', 'cinsnptrvec_t_find__SWIG_1', - 'cinsnptrvec_t_front', - 'cinsnptrvec_t_front__SWIG_0', - 'cinsnptrvec_t_front__SWIG_1', 'cinsnptrvec_t_has', 'cinsnptrvec_t_inject', 'cinsnptrvec_t_insert', @@ -1524,6 +1448,9 @@ 'citem_locator_t_ea_set', 'citem_locator_t_op_get', 'citem_locator_t_op_set', + 'citem_t__get_op', + 'citem_t__obj_id', + 'citem_t__set_op', 'citem_t_cexpr_get', 'citem_t_cinsn_get', 'citem_t_contains_label', @@ -1537,17 +1464,14 @@ 'citem_t_is_expr', 'citem_t_label_num_get', 'citem_t_label_num_set', - 'citem_t_op_get', - 'citem_t_op_set', 'citem_t_print1', 'citem_t_swap', 'cleanup_appcall', 'cleanup_name', - 'cleanup_varloc', - 'clearBreak', 'clear_cached_cfuncs', - 'clear_func_struct', + 'clear_refresh_request', 'clear_requests_queue', + 'clear_strlist', 'clear_tinfo_t', 'clear_trace', 'cloop_t_assign', @@ -1557,14 +1481,16 @@ 'close_chooser', 'close_linput', 'close_pseudocode', - 'close_tform', + 'close_widget', 'clr__bnot0', 'clr__bnot1', 'clr__invsign0', 'clr__invsign1', 'clr_abits', 'clr_align_flow', + 'clr_cancelled', 'clr_colored_item', + 'clr_database_flag', 'clr_fixed_spd', 'clr_has_lname', 'clr_has_ti', @@ -1574,9 +1500,11 @@ 'clr_lzero', 'clr_lzero0', 'clr_lzero1', - 'clr_node_info2', + 'clr_node_info', 'clr_noret', 'clr_notcode', + 'clr_notproc', + 'clr_op_type', 'clr_retfp', 'clr_terse_struc', 'clr_tilcmt', @@ -1598,13 +1526,24 @@ 'cnumber_t_nf_get', 'cnumber_t_nf_set', 'cnumber_t_value', - 'codeSeg', - 'codeflag', + 'code_flag', + 'codegen_t_analyze_prolog', + 'codegen_t_gen_micro', + 'codegen_t_ignore_micro_get', + 'codegen_t_ignore_micro_set', + 'codegen_t_insn_get', + 'codegen_t_insn_set', + 'codegen_t_load_operand', + 'codegen_t_mb_get', + 'codegen_t_mb_set', + 'codegen_t_mba_get', + 'codegen_t_mba_set', 'compact_til', 'compare', 'compare', 'compare', - 'compare__SWIG_1', + 'compare__SWIG_10', + 'compare__SWIG_11', 'compare__SWIG_12', 'compare__SWIG_13', 'compare__SWIG_14', @@ -1613,7 +1552,6 @@ 'compare__SWIG_17', 'compare__SWIG_18', 'compare__SWIG_19', - 'compare__SWIG_2', 'compare__SWIG_20', 'compare__SWIG_21', 'compare__SWIG_22', @@ -1624,23 +1562,25 @@ 'compare__SWIG_27', 'compare__SWIG_28', 'compare__SWIG_29', - 'compare__SWIG_3', - 'compare__SWIG_3', 'compare__SWIG_30', - 'compare__SWIG_4', 'compare__SWIG_5', 'compare__SWIG_6', 'compare__SWIG_7', + 'compare__SWIG_7', + 'compare__SWIG_8', + 'compare__SWIG_9', 'compare_tinfo', 'compare_typsrc', - 'compile_script_file', - 'compile_script_func', + 'compile_idc_file', + 'compile_idc_snippet', + 'compile_idc_text', 'compiler_info_t_cm_get', 'compiler_info_t_cm_set', 'compiler_info_t_defalign_get', 'compiler_info_t_defalign_set', 'compiler_info_t_id_get', 'compiler_info_t_id_set', + 'compiler_info_t_set_64bit_pointer_size', 'compiler_info_t_size_b_get', 'compiler_info_t_size_b_set', 'compiler_info_t_size_e_get', @@ -1649,47 +1589,64 @@ 'compiler_info_t_size_i_set', 'compiler_info_t_size_l_get', 'compiler_info_t_size_l_set', + 'compiler_info_t_size_ldbl_get', + 'compiler_info_t_size_ldbl_set', 'compiler_info_t_size_ll_get', 'compiler_info_t_size_ll_set', 'compiler_info_t_size_s_get', 'compiler_info_t_size_s_set', 'const_aloc_visitor_t_visit_location', - 'const_visitor_t_visit_const', - 'const_vloc_visitor_t_visit_location', 'construct_macro', 'contains_fixups', 'continue_process', - 'convert_argloc_to_varloc', - 'convert_encoding', 'convert_pt_flags_to_hti', 'convert_to_user_call', - 'convert_varloc_to_argloc', - 'copy_srareas', + 'copy_idcv', + 'copy_sreg_ranges', 'copy_tinfo_t', - 'copy_varloc', + 'create_16bit_data', + 'create_32bit_data', + 'create_align', + 'create_byte', 'create_bytearray_linput', 'create_code_viewer', - 'create_custom_fixup', - 'create_ea_viewer', + 'create_custdata', + 'create_data', + 'create_disasm_graph', + 'create_disasm_graph__SWIG_0', + 'create_disasm_graph__SWIG_1', + 'create_double', + 'create_dword', + 'create_empty_widget', 'create_field_name', + 'create_float', 'create_generic_linput', - 'create_generic_linput64', - 'create_helper', - 'create_helper__varargs__', + 'create_graph_viewer', + 'create_idcv_ref', 'create_insn', 'create_memory_linput', 'create_menu', + 'create_mutable_graph', 'create_numbered_type_name', - 'create_numbered_type_reference', + 'create_outctx', + 'create_oword', + 'create_packed_real', + 'create_qword', 'create_source_viewer', + 'create_strlit', + 'create_struct', 'create_switch_table', 'create_switch_xrefs', - 'create_tform', + 'create_tbyte', 'create_tinfo', 'create_toolbar', 'create_typedef', 'create_typedef__SWIG_0', 'create_typedef__SWIG_1', + 'create_user_graph_place', + 'create_word', + 'create_yword', + 'create_zword', 'creturn_t___eq__', 'creturn_t___ge__', 'creturn_t___gt__', @@ -1731,18 +1688,18 @@ 'ctree_anchor_t_is_valid_anchor', 'ctree_anchor_t_value_get', 'ctree_anchor_t_value_set', + 'ctree_item_t__get_e', + 'ctree_item_t__get_f', + 'ctree_item_t__get_i', + 'ctree_item_t__get_it', + 'ctree_item_t__get_l', 'ctree_item_t_citype_get', 'ctree_item_t_citype_set', - 'ctree_item_t_e_get', - 'ctree_item_t_f_get', 'ctree_item_t_get_ea', 'ctree_item_t_get_label_num', 'ctree_item_t_get_lvar', 'ctree_item_t_get_memptr', - 'ctree_item_t_i_get', 'ctree_item_t_is_citem', - 'ctree_item_t_it_get', - 'ctree_item_t_l_get', 'ctree_item_t_loc_get', 'ctree_items_t___eq__', 'ctree_items_t___getitem__', @@ -1752,9 +1709,6 @@ 'ctree_items_t__del', 'ctree_items_t_add_unique', 'ctree_items_t_at', - 'ctree_items_t_back', - 'ctree_items_t_back__SWIG_0', - 'ctree_items_t_back__SWIG_1', 'ctree_items_t_begin', 'ctree_items_t_begin__SWIG_0', 'ctree_items_t_begin__SWIG_1', @@ -1771,9 +1725,6 @@ 'ctree_items_t_find', 'ctree_items_t_find__SWIG_0', 'ctree_items_t_find__SWIG_1', - 'ctree_items_t_front', - 'ctree_items_t_front__SWIG_0', - 'ctree_items_t_front__SWIG_1', 'ctree_items_t_has', 'ctree_items_t_inject', 'ctree_items_t_insert', @@ -1811,34 +1762,13 @@ 'ctree_visitor_t_set_restart', 'ctree_visitor_t_visit_expr', 'ctree_visitor_t_visit_insn', - 'curloc_copy_current_location', - 'curloc_ea_get', - 'curloc_ea_set', - 'curloc_flags_get', - 'curloc_flags_set', - 'curloc_get', - 'curloc_get_entry', - 'curloc_hide_if_necessary', - 'curloc_jump', - 'curloc_jump_push', - 'curloc_linkTo', - 'curloc_lnnum_get', - 'curloc_lnnum_set', - 'curloc_mark', - 'curloc_markdesc', - 'curloc_markedpos', - 'curloc_pop', - 'curloc_setx', - 'curloc_size', - 'curloc_target_get', - 'curloc_target_set', - 'curloc_unhide_if_necessary', - 'curloc_x_get', - 'curloc_x_set', - 'curloc_y_get', - 'curloc_y_set', - 'custflag', - 'custfmtflag', + 'cust_flag', + 'custfmt_flag', + 'custom_data_type_ids_fids_array___getitem__', + 'custom_data_type_ids_fids_array___len__', + 'custom_data_type_ids_fids_array___setitem__', + 'custom_data_type_ids_fids_array_data_get', + 'custom_data_type_ids_t___getFids', 'custom_data_type_ids_t_dtid_get', 'custom_data_type_ids_t_dtid_set', 'custom_data_type_ids_t_fids_get', @@ -1851,9 +1781,32 @@ 'cwhile_t___lt__', 'cwhile_t___ne__', 'cwhile_t_compare', - 'dataSeg', - 'dataSeg_op', - 'dataSeg_opreg', + 'data_format_t___get_id', + 'data_format_t_hotkey_get', + 'data_format_t_hotkey_set', + 'data_format_t_menu_name_get', + 'data_format_t_menu_name_set', + 'data_format_t_name_get', + 'data_format_t_name_set', + 'data_format_t_props_get', + 'data_format_t_props_set', + 'data_format_t_text_width_get', + 'data_format_t_text_width_set', + 'data_format_t_value_size_get', + 'data_format_t_value_size_set', + 'data_type_t___get_id', + 'data_type_t_asm_keyword_get', + 'data_type_t_asm_keyword_set', + 'data_type_t_hotkey_get', + 'data_type_t_hotkey_set', + 'data_type_t_menu_name_get', + 'data_type_t_menu_name_set', + 'data_type_t_name_get', + 'data_type_t_name_set', + 'data_type_t_props_get', + 'data_type_t_props_set', + 'data_type_t_value_size_get', + 'data_type_t_value_size_set', 'dbg_add_bpt_tev', 'dbg_add_call_tev', 'dbg_add_debug_event', @@ -1900,14 +1853,15 @@ 'debug_event_t_pid_set', 'debug_event_t_tid_get', 'debug_event_t_tid_set', - 'decflag', + 'dec_flag', 'decode_insn', 'decode_preceding_insn', 'decode_prev_insn', 'decompile_many', + 'deep_copy_idcv', 'default_compiler', 'define_exception', - 'delValue', + 'define_stkvar', 'del_absbase', 'del_aflags', 'del_alignment', @@ -1916,7 +1870,6 @@ 'del_bpt__SWIG_0', 'del_bpt__SWIG_1', 'del_bptgrp', - 'del_const', 'del_cref', 'del_custom_data_type_ids', 'del_debug_names', @@ -1928,47 +1881,50 @@ 'del_fixup', 'del_frame', 'del_func', - 'del_func_cmt', 'del_global_name', - 'del_hidden_area', + 'del_hidden_range', 'del_hotkey', 'del_idasgn', 'del_idc_hotkey', + 'del_idcv_attr', 'del_ind_purged', 'del_item_color', - 'del_jumptable_info', + 'del_items', 'del_local_name', + 'del_mapping', 'del_member_tinfo', - 'del_menu_item', 'del_named_type', - 'del_node_info2', + 'del_node_info', 'del_numbered_type', + 'del_op_tinfo', 'del_refinfo', 'del_regvar', 'del_segm', - 'del_segment_cmt', 'del_segment_translations', 'del_selector', 'del_source_linnum', 'del_sourcefile', - 'del_srarea', + 'del_sreg_range', 'del_stkpnt', + 'del_str_type', 'del_struc', 'del_struc_member', 'del_struc_members', - 'del_switch_info_ex', + 'del_switch_info', 'del_switch_parent', 'del_til', - 'del_tinfo2', - 'del_tinfo2__SWIG_0', - 'del_tinfo2__SWIG_1', + 'del_tinfo', 'del_tinfo_attr', + 'del_tryblks', + 'del_value', 'del_virt_module', 'delay_slot_insn', 'delete_DBG_Hooks', 'delete_IDB_Hooks', 'delete_IDP_Hooks', + 'delete_TPointDouble', 'delete_UI_Hooks', + 'delete_View_Hooks', 'delete___qmutex_t', 'delete___qsemaphore_t', 'delete___qthread_t', @@ -1979,11 +1935,6 @@ 'delete_action_update_ctx_t', 'delete_addon_info_t', 'delete_aloc_visitor_t', - 'delete_area_t', - 'delete_area_visitor2_t', - 'delete_areacb_t', - 'delete_areaset_t', - 'delete_areavec_t', 'delete_argloc_t', 'delete_argpart_t', 'delete_array_parameters_t', @@ -2006,6 +1957,8 @@ 'delete_cases_and_targets_t', 'delete_casevec_t', 'delete_casm_t', + 'delete_catch_t', + 'delete_catchvec_t', 'delete_cblock_t', 'delete_ccase_t', 'delete_ccases_t', @@ -2018,6 +1971,7 @@ 'delete_cfuncptr_t', 'delete_cgoto_t', 'delete_channel_redir_t', + 'delete_chooser_item_attrs_t', 'delete_cif_t', 'delete_cinsn_t', 'delete_cinsnptrvec_t', @@ -2026,10 +1980,9 @@ 'delete_citem_t', 'delete_cloop_t', 'delete_cnumber_t', + 'delete_codegen_t', 'delete_compiler_info_t', 'delete_const_aloc_visitor_t', - 'delete_const_visitor_t', - 'delete_const_vloc_visitor_t', 'delete_creturn_t', 'delete_cswitch_t', 'delete_ctext_position_t', @@ -2038,9 +1991,11 @@ 'delete_ctree_items_t', 'delete_ctree_parentee_t', 'delete_ctree_visitor_t', - 'delete_curloc', + 'delete_custom_data_type_ids_fids_array', 'delete_custom_data_type_ids_t', 'delete_cwhile_t', + 'delete_data_format_t', + 'delete_data_type_t', 'delete_debapp_attrs_t', 'delete_debug_event_t', 'delete_disasm_line_t', @@ -2052,6 +2007,10 @@ 'delete_ea_pointer', 'delete_eamap_iterator_t', 'delete_eamap_t', + 'delete_edge_info_t', + 'delete_edge_layout_point_t', + 'delete_edge_segment_t', + 'delete_edge_t', 'delete_enum_const_t', 'delete_enum_member_t', 'delete_enum_member_visitor_t', @@ -2062,55 +2021,53 @@ 'delete_excvec_t', 'delete_extra_cmts', 'delete_fixup_data_t', + 'delete_fixup_info_t', + 'delete_fnum_array', 'delete_fnumber_t', 'delete_func_item_iterator_t', 'delete_func_parent_iterator_t', 'delete_func_t', 'delete_func_tail_iterator_t', 'delete_func_type_data_t', - 'delete_func_type_info_t', - 'delete_funcarg_info_t', 'delete_funcarg_t', 'delete_funcargvec_t', - 'delete_generic_linput64_t', 'delete_generic_linput_t', - 'delete_get_strmem_t', + 'delete_graph_item_t', 'delete_graph_location_info_t', + 'delete_graph_node_visitor_t', + 'delete_graph_path_visitor_t', + 'delete_graph_visitor_t', + 'delete_group_crinfo_t', 'delete_hexrays_failure_t', 'delete_hexwarn_t', 'delete_hexwarns_t', - 'delete_hidden_area_t', + 'delete_hidden_range_t', 'delete_highlighter_cbs_t', 'delete_history_item_t', 'delete_history_t', - 'delete_ida_false_type', 'delete_ida_lowertype_helper_t', - 'delete_ida_true_type', - 'delete_idainfo', 'delete_idaplace_t', 'delete_idc_global_t', 'delete_idc_value_t', - 'delete_idd_opinfo_old_t', + 'delete_idc_values_t', 'delete_idp_desc_t', 'delete_idp_name_t', - 'delete_ids_array', + 'delete_imports', + 'delete_insn_t', 'delete_instant_dbgopts_t', 'delete_int64vec_t', 'delete_int_pointer', + 'delete_interval_t', 'delete_intvec_t', - 'delete_jumptable_info_t', 'delete_linput_buffer_t', 'delete_llabel_t', 'delete_loader_input_t', 'delete_loader_t', - 'delete_location_t', 'delete_locchange_md_t', 'delete_lochist_entry_t', 'delete_lochist_t', - 'delete_lock_area', 'delete_lock_func', 'delete_lock_segment', - 'delete_lock_segreg', 'delete_lowertype_helper_t', 'delete_lvar_locator_t', 'delete_lvar_mapping_iterator_t', @@ -2126,16 +2083,26 @@ 'delete_menu', 'delete_microcode_filter_t', 'delete_module_info_t', + 'delete_mutable_graph', + 'delete_mutable_graph_t', 'delete_netnode', 'delete_node_info_t', 'delete_node_iterator', + 'delete_node_ordering_t', 'delete_number_format_t', + 'delete_op_t', 'delete_operand_locator_t', + 'delete_operands_array', 'delete_operator_info_t', 'delete_opinfo_t', 'delete_place_t', 'delete_plugin_info_t', + 'delete_point_t', + 'delete_pointseq_t', + 'delete_predicate_t', + 'delete_printop_t', 'delete_process_info_t', + 'delete_procinfo_vec_t', 'delete_ptr_type_data_t', 'delete_qbasic_block_t', 'delete_qfile_t', @@ -2149,6 +2116,11 @@ 'delete_qvector_history_t', 'delete_qvector_lvar_t', 'delete_qvector_snapshotvec_t', + 'delete_range_t', + 'delete_rangeset_t', + 'delete_rangevec_base_t', + 'delete_rangevec_t', + 'delete_rect_t', 'delete_refinfo_t', 'delete_reg_info_t', 'delete_regarg_t', @@ -2157,25 +2129,31 @@ 'delete_regobjs_t', 'delete_regval_t', 'delete_regvar_t', + 'delete_renderer_info_pos_t', 'delete_renderer_info_t', 'delete_renderer_pos_info_t', + 'delete_row_info_t', 'delete_rrel_t', 'delete_scattered_aloc_t', - 'delete_scattered_vloc_t', + 'delete_scattered_segm_t', + 'delete_screen_graph_selection_t', 'delete_segm_move_info_t', 'delete_segm_move_info_vec_t', 'delete_segm_move_infos_t', 'delete_segment_t', - 'delete_segreg_area_t', - 'delete_segreg_t', + 'delete_seh_t', 'delete_sel_array', 'delete_sel_pointer', + 'delete_selection_item_t', 'delete_simd_info_t', 'delete_simpleline_place_t', 'delete_simpleline_t', + 'delete_sizevec_t', 'delete_snapshot_t', + 'delete_sreg_range_t', 'delete_strarray_t', 'delete_string_info_t', + 'delete_strpath_ids_array', 'delete_strpath_t', 'delete_struc_t', 'delete_struct_field_visitor_t', @@ -2184,7 +2162,6 @@ 'delete_strwinsetup_t', 'delete_sval_pointer', 'delete_tev_info_t', - 'delete_text_options_t', 'delete_text_sink_t', 'delete_tid_array', 'delete_til_symbol_t', @@ -2193,13 +2170,13 @@ 'delete_tinfo_visitor_t', 'delete_toolbar', 'delete_treeloc_t', + 'delete_try_handler_t', + 'delete_tryblk_t', + 'delete_tryblks_t', 'delete_twinpos_t', 'delete_type_attr_t', - 'delete_type_mapper_t', + 'delete_type_attrs_t', 'delete_type_mods_t', - 'delete_type_pair_t', - 'delete_type_pair_vec_t', - 'delete_type_visitor_t', 'delete_typedef_type_data_t', 'delete_uchar_array', 'delete_udc_filter_t', @@ -2212,6 +2189,7 @@ 'delete_unreferenced_stkvars', 'delete_user_cmts_iterator_t', 'delete_user_cmts_t', + 'delete_user_graph_place_t', 'delete_user_iflags_iterator_t', 'delete_user_iflags_t', 'delete_user_labels_iterator_t', @@ -2224,34 +2202,28 @@ 'delete_uval_array', 'delete_uvalvec_t', 'delete_valstr_t', - 'delete_valstrs_deprecated2_t', - 'delete_valstrs_deprecated_t', 'delete_valstrs_t', 'delete_var_ref_t', - 'delete_varloc_t', - 'delete_varpart_t', 'delete_vc_printer_t', 'delete_vd_failure_t', 'delete_vd_interr_t', 'delete_vd_printer_t', 'delete_vdloc_t', 'delete_vdui_t', - 'delete_vloc_visitor_t', + 'delete_view_mouse_event_location_t', + 'delete_view_mouse_event_t', 'delete_wrong_stkvar_ops', 'delete_xrefblk_t', 'delete_xreflist_entry_t', 'delete_xreflist_t', 'demangle_name', - 'demangle_name2', + 'deref_idcv', 'deref_ptr', - 'deref_ptr2', - 'dereference', - 'describe', - 'describe__varargs__', 'deserialize_tinfo', 'detach_action_from_menu', 'detach_action_from_popup', 'detach_action_from_toolbar', + 'detach_custom_data_format', 'detach_process', 'diff_trace_file', 'disable_flags', @@ -2270,9 +2242,6 @@ 'disasm_text_t___len__', 'disasm_text_t___setitem__', 'disasm_text_t_at', - 'disasm_text_t_back', - 'disasm_text_t_back__SWIG_0', - 'disasm_text_t_back__SWIG_1', 'disasm_text_t_begin', 'disasm_text_t_begin__SWIG_0', 'disasm_text_t_begin__SWIG_1', @@ -2286,9 +2255,6 @@ 'disasm_text_t_erase__SWIG_0', 'disasm_text_t_erase__SWIG_1', 'disasm_text_t_extract', - 'disasm_text_t_front', - 'disasm_text_t_front__SWIG_0', - 'disasm_text_t_front__SWIG_1', 'disasm_text_t_grow', 'disasm_text_t_inject', 'disasm_text_t_insert', @@ -2308,58 +2274,34 @@ 'disown_IDB_Hooks', 'disown_IDP_Hooks', 'disown_UI_Hooks', + 'disown_View_Hooks', 'disown_aloc_visitor_t', - 'disown_area_visitor2_t', 'disown_cfunc_parentee_t', + 'disown_codegen_t', 'disown_const_aloc_visitor_t', 'disown_ctree_parentee_t', 'disown_ctree_visitor_t', 'disown_enum_member_visitor_t', + 'disown_graph_node_visitor_t', + 'disown_graph_path_visitor_t', + 'disown_graph_visitor_t', 'disown_highlighter_cbs_t', 'disown_microcode_filter_t', + 'disown_mutable_graph_t', + 'disown_predicate_t', 'disown_struct_field_visitor_t', 'disown_text_sink_t', 'disown_tinfo_visitor_t', 'disown_udc_filter_t', 'disown_user_lvar_modifier_t', - 'display_complex_call_chart', 'display_copyright_warning', - 'display_flow_graph', 'display_gdl', - 'display_simple_call_chart', - 'do16bit', - 'do32bit', - 'do3byte', - 'doASCI', - 'doAlign', - 'doByte', - 'doCustomData', - 'doDouble', - 'doDwrd', - 'doFloat', - 'doImmd', - 'doOwrd', - 'doPackReal', - 'doQwrd', - 'doStruct', - 'doTbyt', - 'doVar', - 'doWord', - 'doYwrd', - 'doZwrd', - 'do_data_ex', - 'do_name_anyway', - 'do_unknown', - 'do_unknown_range', - 'dosysfile', - 'doubleflag', + 'display_widget', + 'double_flag', 'dstr_tinfo', - 'dto_copy_from_inf', - 'dto_copy_to_inf', - 'dto_init', 'dummy_ptrtype', 'dump_func_type_data', - 'dwrdflag', + 'dword_flag', 'e_breakpoint_t_hea_get', 'e_breakpoint_t_hea_set', 'e_breakpoint_t_kea_get', @@ -2372,6 +2314,7 @@ 'e_exception_t_ea_set', 'e_exception_t_info_get', 'e_exception_t_info_set', + 'ea2node', 'ea2str', 'ea_array___getitem__', 'ea_array___setitem__', @@ -2405,12 +2348,48 @@ 'eamap_size', 'eamap_t_at', 'eamap_t_size', - 'echsize', - 'echsize64', 'eclose', - 'ecreate', - 'ecreateT', + 'edge_info_t_color_get', + 'edge_info_t_color_set', + 'edge_info_t_dstoff_get', + 'edge_info_t_dstoff_set', + 'edge_info_t_layout_get', + 'edge_info_t_layout_set', + 'edge_info_t_reverse_layout', + 'edge_info_t_srcoff_get', + 'edge_info_t_srcoff_set', + 'edge_info_t_width_get', + 'edge_info_t_width_set', + 'edge_infos_wrapper_t_clear', + 'edge_infos_wrapper_t_ptr_get', + 'edge_infos_wrapper_t_ptr_set', + 'edge_layout_point_t___eq__', + 'edge_layout_point_t___ne__', + 'edge_layout_point_t_compare', + 'edge_layout_point_t_e_get', + 'edge_layout_point_t_e_set', + 'edge_layout_point_t_pidx_get', + 'edge_layout_point_t_pidx_set', + 'edge_segment_t___lt__', + 'edge_segment_t_e_get', + 'edge_segment_t_e_set', + 'edge_segment_t_length', + 'edge_segment_t_nseg_get', + 'edge_segment_t_nseg_set', + 'edge_segment_t_toright', + 'edge_segment_t_x0_get', + 'edge_segment_t_x0_set', + 'edge_segment_t_x1_get', + 'edge_segment_t_x1_set', + 'edge_t___eq__', + 'edge_t___lt__', + 'edge_t___ne__', + 'edge_t_dst_get', + 'edge_t_dst_set', + 'edge_t_src_get', + 'edge_t_src_set', 'edit_manual_regions', + 'enable_auto', 'enable_bblk_trace', 'enable_bpt', 'enable_bpt__SWIG_0', @@ -2421,7 +2400,6 @@ 'enable_func_trace', 'enable_insn_trace', 'enable_manual_regions', - 'enable_menu_item', 'enable_python_cli', 'enable_step_trace', 'encoding_from_strtype', @@ -2430,6 +2408,7 @@ 'enum_const_t_serial_set', 'enum_const_t_tid_get', 'enum_const_t_tid_set', + 'enum_flag', 'enum_import_names', 'enum_member_t___eq__', 'enum_member_t___ne__', @@ -2456,7 +2435,6 @@ 'enum_type_data_t_taenum_bits_get', 'enum_type_data_t_taenum_bits_set', 'enumerate_files', - 'enumflag', 'enumplace_t_bmask_get', 'enumplace_t_bmask_set', 'enumplace_t_idx_get', @@ -2468,10 +2446,10 @@ 'equal_bytes', 'error', 'error__varargs__', - 'eseek', - 'eseek64', 'eval_ctx_t_ea_get', 'eval_ctx_t_ea_set', + 'eval_expr', + 'eval_idc_expr', 'exception_info_t_break_on', 'exception_info_t_code_get', 'exception_info_t_code_set', @@ -2486,9 +2464,6 @@ 'excvec_t___len__', 'excvec_t___setitem__', 'excvec_t_at', - 'excvec_t_back', - 'excvec_t_back__SWIG_0', - 'excvec_t_back__SWIG_1', 'excvec_t_begin', 'excvec_t_begin__SWIG_0', 'excvec_t_begin__SWIG_1', @@ -2502,9 +2477,6 @@ 'excvec_t_erase__SWIG_0', 'excvec_t_erase__SWIG_1', 'excvec_t_extract', - 'excvec_t_front', - 'excvec_t_front__SWIG_0', - 'excvec_t_front__SWIG_1', 'excvec_t_grow', 'excvec_t_inject', 'excvec_t_insert', @@ -2520,53 +2492,42 @@ 'excvec_t_size', 'excvec_t_swap', 'excvec_t_truncate', - 'execute', + 'exec_idc_script', + 'exec_system_script', 'execute_sync', 'execute_ui_requests', 'exist', + 'exists_fixup', 'exit_process', - 'expand_argv', 'expand_struc', 'extend_sign', - 'extlang_call_method_exists', - 'extlang_compile_file_exists', - 'extlang_run_statements_exists', - 'extlang_set_attr_exists', - 'extlang_unload_procmod', - 'extract_and_convert_old_argloc', + 'extract_argloc', 'extract_module_from_archive', 'extract_name', - 'extract_name2', - 'extract_old_argloc', - 'extract_old_argloc__SWIG_0', - 'extract_old_argloc__SWIG_1', - 'extract_varloc', 'f_any', - 'f_hasRef', 'f_has_dummy_name', 'f_has_name', 'f_has_user_name', - 'f_is3byte', - 'f_isASCII', - 'f_isAlign', - 'f_isByte', - 'f_isCode', - 'f_isCustom', - 'f_isData', - 'f_isDouble', - 'f_isDwrd', - 'f_isFloat', - 'f_isHead', - 'f_isNotTail', - 'f_isOwrd', - 'f_isPackReal', - 'f_isQwrd', - 'f_isStruct', - 'f_isTail', - 'f_isTbyt', - 'f_isUnknown', - 'f_isWord', - 'f_isYwrd', + 'f_has_xref', + 'f_is_align', + 'f_is_byte', + 'f_is_code', + 'f_is_custom', + 'f_is_data', + 'f_is_double', + 'f_is_dword', + 'f_is_float', + 'f_is_head', + 'f_is_not_tail', + 'f_is_oword', + 'f_is_pack_real', + 'f_is_qword', + 'f_is_strlit', + 'f_is_struct', + 'f_is_tail', + 'f_is_tbyte', + 'f_is_word', + 'f_is_yword', 'file2base', 'find_binary', 'find_bpt', @@ -2575,43 +2536,74 @@ 'find_code', 'find_custom_data_format', 'find_custom_data_type', + 'find_custom_fixup', + 'find_custom_refinfo', 'find_data', 'find_defined', 'find_error', - 'find_extlang_by_ext', - 'find_extlang_by_name', 'find_free_selector', 'find_func_bounds', 'find_idc_class', + 'find_idc_func', 'find_idc_gvar', 'find_imm', 'find_not_func', 'find_notype', + 'find_plugin', 'find_regvar', 'find_regvar__SWIG_0', 'find_regvar__SWIG_1', 'find_selector', + 'find_suspop', 'find_text', - 'find_tform', 'find_tinfo_udt_member', 'find_unknown', - 'find_void', + 'find_widget', + 'first_idcv_attr', 'first_named_type', + 'fixup_data_t_calc_size', + 'fixup_data_t_clr_extdef', + 'fixup_data_t_clr_unused', 'fixup_data_t_displacement_get', 'fixup_data_t_displacement_set', + 'fixup_data_t_get', + 'fixup_data_t_get_base', + 'fixup_data_t_get_desc', + 'fixup_data_t_get_flags', + 'fixup_data_t_get_handler', 'fixup_data_t_get_type', + 'fixup_data_t_get_value', + 'fixup_data_t_has_base', 'fixup_data_t_is_custom', + 'fixup_data_t_is_extdef', + 'fixup_data_t_is_unused', 'fixup_data_t_off_get', 'fixup_data_t_off_set', + 'fixup_data_t_patch_value', 'fixup_data_t_sel_get', 'fixup_data_t_sel_set', - 'fixup_data_t_type_get', - 'fixup_data_t_type_set', - 'floatflag', - 'fltflag', + 'fixup_data_t_set', + 'fixup_data_t_set_base', + 'fixup_data_t_set_extdef', + 'fixup_data_t_set_sel', + 'fixup_data_t_set_target_sel', + 'fixup_data_t_set_type', + 'fixup_data_t_set_type_and_flags', + 'fixup_data_t_set_unused', + 'fixup_info_t_ea_get', + 'fixup_info_t_ea_set', + 'fixup_info_t_fd_get', + 'fixup_info_t_fd_set', + 'float_flag', + 'flt_flag', 'flush_buffers', + 'fnum_array___getitem__', + 'fnum_array___len__', + 'fnum_array___setitem__', + 'fnum_array_data_get', 'fnumber_t___eq__', 'fnumber_t___ge__', + 'fnumber_t___get_fnum', 'fnumber_t___gt__', 'fnumber_t___le__', 'fnumber_t___lt__', @@ -2632,11 +2624,9 @@ 'fopenWT', 'for_all_arglocs', 'for_all_const_arglocs', - 'for_all_const_varlocs', - 'for_all_consts', 'for_all_enum_members', - 'for_all_types', - 'for_all_varlocs', + 'force_name', + 'forget_problem', 'formchgcbfa_close', 'formchgcbfa_enable_field', 'formchgcbfa_get_field_value', @@ -2650,10 +2640,10 @@ 'frame_off_lvars', 'frame_off_retaddr', 'frame_off_savregs', - 'free_argv', + 'free_chunk', 'free_custom_icon', + 'free_idcv', 'free_til', - 'freechunk', 'func_contains', 'func_does_return', 'func_has_stkframe_hole', @@ -2682,7 +2672,6 @@ 'func_item_iterator_t_set', 'func_item_iterator_t_set_range', 'func_parent_iterator_set', - 'func_parent_iterator_set2', 'func_parent_iterator_t_first', 'func_parent_iterator_t_last', 'func_parent_iterator_t_next', @@ -2690,8 +2679,6 @@ 'func_parent_iterator_t_prev', 'func_parent_iterator_t_reset_fnt', 'func_parent_iterator_t_set', - 'func_setend', - 'func_setstart', 'func_t_analyzed_sp', 'func_t_argsize_get', 'func_t_argsize_set', @@ -2736,7 +2723,6 @@ 'func_t_tails_get', 'func_t_tails_set', 'func_tail_iterator_set', - 'func_tail_iterator_set2', 'func_tail_iterator_set_ea', 'func_tail_iterator_t_chunk', 'func_tail_iterator_t_first', @@ -2755,6 +2741,8 @@ 'func_type_data_t_get_call_method', 'func_type_data_t_guess_cc', 'func_type_data_t_is_high', + 'func_type_data_t_is_noret', + 'func_type_data_t_is_pure', 'func_type_data_t_is_vararg_cc', 'func_type_data_t_retloc_get', 'func_type_data_t_retloc_set', @@ -2765,30 +2753,6 @@ 'func_type_data_t_stkargs_get', 'func_type_data_t_stkargs_set', 'func_type_data_t_swap', - 'func_type_info_t_basetype_get', - 'func_type_info_t_basetype_set', - 'func_type_info_t_cc_get', - 'func_type_info_t_cc_set', - 'func_type_info_t_flags_get', - 'func_type_info_t_flags_set', - 'func_type_info_t_retfields_get', - 'func_type_info_t_retfields_set', - 'func_type_info_t_retloc_get', - 'func_type_info_t_retloc_set', - 'func_type_info_t_rettype_get', - 'func_type_info_t_rettype_set', - 'func_type_info_t_spoiled_get', - 'func_type_info_t_spoiled_set', - 'func_type_info_t_stkargs_get', - 'func_type_info_t_stkargs_set', - 'funcarg_info_t_argloc_get', - 'funcarg_info_t_argloc_set', - 'funcarg_info_t_fields_get', - 'funcarg_info_t_fields_set', - 'funcarg_info_t_name_get', - 'funcarg_info_t_name_set', - 'funcarg_info_t_type_get', - 'funcarg_info_t_type_set', 'funcarg_t___eq__', 'funcarg_t___ne__', 'funcarg_t_argloc_get', @@ -2809,9 +2773,6 @@ 'funcargvec_t__del', 'funcargvec_t_add_unique', 'funcargvec_t_at', - 'funcargvec_t_back', - 'funcargvec_t_back__SWIG_0', - 'funcargvec_t_back__SWIG_1', 'funcargvec_t_begin', 'funcargvec_t_begin__SWIG_0', 'funcargvec_t_begin__SWIG_1', @@ -2828,9 +2789,6 @@ 'funcargvec_t_find', 'funcargvec_t_find__SWIG_0', 'funcargvec_t_find__SWIG_1', - 'funcargvec_t_front', - 'funcargvec_t_front__SWIG_0', - 'funcargvec_t_front__SWIG_1', 'funcargvec_t_grow', 'funcargvec_t_has', 'funcargvec_t_inject', @@ -2847,48 +2805,28 @@ 'funcargvec_t_size', 'funcargvec_t_swap', 'funcargvec_t_truncate', - 'gen_abssym', - 'gen_cmt_line', - 'gen_cmt_line__varargs__', - 'gen_collapsed_line', - 'gen_collapsed_line__varargs__', + 'gcc_layout', 'gen_complex_call_chart', - 'gen_comvar', - 'gen_decorate_name3', + 'gen_decorate_name', 'gen_disasm_text', 'gen_exe_file', - 'gen_extern', 'gen_file', 'gen_fix_fixups', 'gen_flow_graph', 'gen_gdl', - 'gen_name_decl', 'gen_simple_call_chart', - 'gen_spcdef', 'gen_use_arg_tinfos', - 'generate_big_comment', 'generate_disasm_line', 'generate_disassembly', - 'generate_many_lines', - 'generic_linput64_t_blocksize_get', - 'generic_linput64_t_blocksize_set', - 'generic_linput64_t_filesize_get', - 'generic_linput64_t_filesize_set', - 'generic_linput64_t_read64', 'generic_linput_t_blocksize_get', 'generic_linput_t_blocksize_set', 'generic_linput_t_filesize_get', 'generic_linput_t_filesize_set', 'generic_linput_t_read', - 'getDefaultRadix', - 'getFlags', - 'getRadix', - 'getRadixEA', - 'getSR', 'get_16bit', 'get_32bit', - 'get_3byte', 'get_64bit', + 'get_abi_name', 'get_absbase', 'get_action_checkable', 'get_action_checked', @@ -2903,26 +2841,26 @@ 'get_aflags', 'get_alias_target', 'get_alignment', - 'get_argloc_r1', - 'get_argloc_r2', + 'get_archive_path', + 'get_arg_addrs', 'get_array_parameters', - 'get_ascii_contents', - 'get_ascii_contents2', 'get_asm_inc_file', - 'get_auto_plugins', + 'get_auto_display', + 'get_auto_state', 'get_base_type', 'get_basic_file_type', 'get_bblk_trace_options', 'get_best_fit_member', 'get_bmask_cmt', 'get_bmask_name', - 'get_bmask_node', 'get_bpt', 'get_bpt_group', 'get_bpt_qty', 'get_bpt_tev_ea', 'get_bptloc_string', 'get_byte', + 'get_bytes', + 'get_bytes_and_mask', 'get_c_header_path', 'get_c_macros', 'get_call_tev_callee', @@ -2930,72 +2868,59 @@ 'get_chooser_obj', 'get_cmt', 'get_colored_demangled_name', - 'get_colored_demangled_name__SWIG_0', - 'get_colored_demangled_name__SWIG_1', 'get_colored_long_name', 'get_colored_name', - 'get_colored_name__SWIG_0', - 'get_colored_name__SWIG_1', 'get_colored_short_name', 'get_comp', 'get_compiler_abbr', 'get_compiler_name', 'get_compilers', - 'get_complex_n', - 'get_const', - 'get_const_bmask', - 'get_const_by_name', - 'get_const_cmt', - 'get_const_enum', - 'get_const_name', - 'get_const_serial', - 'get_const_value', 'get_ctype_name', 'get_curline', 'get_current_idasgn', - 'get_current_tform', 'get_current_thread', 'get_current_viewer', + 'get_current_widget', 'get_cursor', 'get_custom_data_format', 'get_custom_data_formats', 'get_custom_data_type', 'get_custom_data_type_ids', 'get_custom_data_types', + 'get_custom_refinfo', 'get_custom_viewer_curline', 'get_custom_viewer_place', 'get_data_elsize', - 'get_data_type_size', 'get_data_value', 'get_db_byte', 'get_dbg_byte', 'get_dbg_memory_info', 'get_debug_event', - 'get_debug_name2', + 'get_debug_name', 'get_debug_name_ea', 'get_debug_names', 'get_debugger_event_cond', 'get_default_encoding_idx', + 'get_default_radix', 'get_default_reftype', 'get_defsr', 'get_demangled_name', - 'get_demangled_name__SWIG_0', - 'get_demangled_name__SWIG_1', - 'get_dtyp_by_size', - 'get_dtyp_flag', - 'get_dtyp_size', + 'get_dtype_by_size', + 'get_dtype_flag', + 'get_dtype_size', + 'get_dword', 'get_ea_name', 'get_ea_viewer_history_info', 'get_effective_spd', + 'get_encoding_bpu', 'get_encoding_name', - 'get_encodings_count', + 'get_encoding_qty', 'get_entry', 'get_entry_forwarder', 'get_entry_name', 'get_entry_ordinal', 'get_entry_qty', 'get_enum', - 'get_enum_base_type', 'get_enum_cmt', 'get_enum_flag', 'get_enum_id', @@ -3005,7 +2930,7 @@ 'get_enum_member_by_name', 'get_enum_member_cmt', 'get_enum_member_enum', - 'get_enum_member_expr2', + 'get_enum_member_expr', 'get_enum_member_name', 'get_enum_member_serial', 'get_enum_member_value', @@ -3022,7 +2947,6 @@ 'get_event_module_base', 'get_event_module_name', 'get_event_module_size', - 'get_extlang_fileext', 'get_extra_cmt', 'get_fchunk', 'get_fchunk_num', @@ -3032,7 +2956,6 @@ 'get_fileregion_ea', 'get_fileregion_offset', 'get_first_bmask', - 'get_first_const', 'get_first_cref_from', 'get_first_cref_to', 'get_first_dref_from', @@ -3042,23 +2965,19 @@ 'get_first_fcref_to', 'get_first_fixup_ea', 'get_first_free_extra_cmtidx', + 'get_first_hidden_range', 'get_first_module', 'get_first_seg', - 'get_first_serial_const', 'get_first_serial_enum_member', 'get_first_struc_idx', 'get_fixup', - 'get_fixup_base', 'get_fixup_desc', - 'get_fixup_extdef_ea', - 'get_fixup_extdef_ea__SWIG_0', - 'get_fixup_extdef_ea__SWIG_1', - 'get_fixup_segdef_sel', - 'get_fixup_segdef_sel__SWIG_0', - 'get_fixup_segdef_sel__SWIG_1', + 'get_fixup_handler', + 'get_fixup_value', + 'get_fixups', + 'get_flags', 'get_flags_by_size', 'get_flags_ex', - 'get_flags_novalue', 'get_float_type', 'get_forced_operand', 'get_frame', @@ -3067,50 +2986,46 @@ 'get_frame_part', 'get_frame_retsize', 'get_frame_size', - 'get_full_byte', 'get_full_data_elsize', - 'get_full_long', + 'get_full_flags', 'get_full_type', - 'get_full_word', 'get_func', 'get_func_bitness', 'get_func_bits', 'get_func_by_frame', 'get_func_bytes', - 'get_func_cc', 'get_func_chunknum', 'get_func_cmt', - 'get_func_cvtarg_map', - 'get_func_limits', 'get_func_name', - 'get_func_name2', - 'get_func_nargs', 'get_func_num', 'get_func_qty', - 'get_func_rettype', + 'get_func_ranges', 'get_func_trace_options', - 'get_funcarg_size', + 'get_gotea', + 'get_graph_viewer', 'get_group_selector', 'get_grp_bpts', 'get_hexdump_ea', 'get_hexrays_version', - 'get_hidden_area', - 'get_hidden_area_num', - 'get_hidden_area_qty', - 'get_highlighted_identifier', + 'get_hidden_range', + 'get_hidden_range_num', + 'get_hidden_range_qty', + 'get_highlight', 'get_ida_subdirs', 'get_idainfo_by_type', - 'get_idainfo_by_type2', - 'get_idainfo_by_type3', 'get_idasgn_desc', 'get_idasgn_desc_with_matches', 'get_idasgn_qty', 'get_idasgn_title', + 'get_idati', 'get_idc_filename', - 'get_idcpath', + 'get_idcv_attr', + 'get_idcv_class_name', + 'get_idcv_slice', 'get_idp_name', 'get_ids_modnode', 'get_imagebase', + 'get_immvals', 'get_import_module_name', 'get_import_module_qty', 'get_ind_purged', @@ -3121,31 +3036,31 @@ 'get_insn_tev_reg_val', 'get_insn_trace_options', 'get_int_type_by_width_and_sign', + 'get_ip_val', 'get_item_color', 'get_item_end', 'get_item_flag', 'get_item_head', 'get_item_size', - 'get_jumptable_info', 'get_kernel_version', 'get_key_code', 'get_last_bmask', - 'get_last_const', 'get_last_enum_member', + 'get_last_hidden_range', 'get_last_seg', - 'get_last_serial_const', 'get_last_serial_enum_member', 'get_last_struc_idx', 'get_linput_type', - 'get_long', 'get_long_name', - 'get_long_queue_name', + 'get_lookback', 'get_manual_insn', 'get_manual_regions', - 'get_many_bytes', - 'get_many_bytes_ex', - 'get_max_ascii_length', + 'get_mapping', + 'get_mappings_qty', + 'get_mark_comment', + 'get_marked_pos', 'get_max_offset', + 'get_max_strlit_length', 'get_member', 'get_member_by_fullname', 'get_member_by_id', @@ -3153,12 +3068,9 @@ 'get_member_cmt', 'get_member_fullname', 'get_member_name', - 'get_member_name2', 'get_member_size', 'get_member_struc', - 'get_member_ti', 'get_member_tinfo', - 'get_member_tinfo2', 'get_member_type', 'get_min_spd_ea', 'get_name', @@ -3166,12 +3078,10 @@ 'get_name_color', 'get_name_ea', 'get_name_expr', - 'get_name_of_named_type', 'get_name_value', 'get_named_type', 'get_named_type64', 'get_next_bmask', - 'get_next_const', 'get_next_cref_from', 'get_next_cref_to', 'get_next_dref_from', @@ -3183,11 +3093,10 @@ 'get_next_fixup_ea', 'get_next_func', 'get_next_func_addr', - 'get_next_hidden_area', + 'get_next_hidden_range', 'get_next_member_idx', 'get_next_module', 'get_next_seg', - 'get_next_serial_const', 'get_next_serial_enum_member', 'get_next_struc_idx', 'get_nice_colored_name', @@ -3196,59 +3105,56 @@ 'get_nlist_name', 'get_nlist_size', 'get_node_info', - 'get_node_info2', 'get_numbered_type', 'get_numbered_type_name', 'get_offbase', 'get_offset_expr', 'get_offset_expression', 'get_op_signness', - 'get_op_tinfo2', - 'get_operand_immvals', + 'get_op_tinfo', 'get_opinfo', 'get_opnum', 'get_optype_flags0', 'get_optype_flags1', 'get_or_guess_member_tinfo', - 'get_or_guess_member_tinfo2', - 'get_or_guess_member_type', 'get_ordinal_from_idb_type', 'get_ordinal_qty', 'get_original_byte', - 'get_original_long', + 'get_original_dword', 'get_original_qword', 'get_original_word', 'get_output_curline', 'get_output_cursor', 'get_output_selected_text', + 'get_path', 'get_place_class', 'get_place_class_id', 'get_place_class_template', 'get_plugin_options', + 'get_predef_insn_cmt', 'get_prev_bmask', - 'get_prev_const', 'get_prev_enum_member', 'get_prev_fchunk', 'get_prev_fixup_ea', 'get_prev_func', 'get_prev_func_addr', - 'get_prev_hidden_area', + 'get_prev_hidden_range', 'get_prev_member_idx', 'get_prev_seg', - 'get_prev_serial_const', 'get_prev_serial_enum_member', - 'get_prev_srarea', + 'get_prev_sreg_range', 'get_prev_struc_idx', - 'get_process_info', + 'get_problem', + 'get_problem_desc', + 'get_problem_name', 'get_process_options', - 'get_process_qty', 'get_process_state', - 'get_ptr_object_size', + 'get_processes', 'get_qword', - 'get_referred_ordinal', + 'get_radix', 'get_refinfo', 'get_reftype_by_size', - 'get_reg_info2', + 'get_reg_info', 'get_reg_name', 'get_reg_val', 'get_reg_vals', @@ -3257,68 +3163,47 @@ 'get_root_filename', 'get_running_notification', 'get_running_request', - 'get_scattered_varloc', + 'get_scalar_bt', 'get_screen_ea', 'get_segm_base', 'get_segm_by_name', 'get_segm_by_sel', 'get_segm_class', 'get_segm_name', - 'get_segm_name__SWIG_0', - 'get_segm_name__SWIG_1', + 'get_segm_num', 'get_segm_para', 'get_segm_qty', 'get_segment_alignment', 'get_segment_cmt', 'get_segment_combination', 'get_segment_translations', - 'get_segreg', 'get_selector_qty', 'get_short_name', - 'get_short_queue_name', - 'get_sig_filename', 'get_source_linnum', 'get_sourcefile', 'get_sp_delta', + 'get_sp_val', 'get_spd', 'get_special_folder', - 'get_spoil_cnt', 'get_sptr', - 'get_srarea', - 'get_srarea2', - 'get_srarea_num', - 'get_srareas_qty', - 'get_srareas_qty2', + 'get_sreg', + 'get_sreg_range', + 'get_sreg_range_num', + 'get_sreg_ranges_qty', 'get_step_trace_options', - 'get_stkarg_offset', 'get_stkvar', 'get_stock_tinfo', 'get_str_encoding_idx', 'get_str_term1', 'get_str_term2', + 'get_str_type', 'get_str_type_code', 'get_strlist_item', + 'get_strlist_options', 'get_strlist_qty', - 'get_strmem', - 'get_strmem2', - 'get_strmem_by_name', - 'get_strmem_t_delta_get', - 'get_strmem_t_delta_set', - 'get_strmem_t_flags_get', - 'get_strmem_t_flags_set', - 'get_strmem_t_fnames_get', - 'get_strmem_t_fnames_set', - 'get_strmem_t_ftype_get', - 'get_strmem_t_ftype_set', - 'get_strmem_t_index_get', - 'get_strmem_t_index_set', - 'get_strmem_t_name_get', - 'get_strmem_t_name_set', - 'get_strmem_t_offset_get', - 'get_strmem_t_offset_set', - 'get_strmem_t_sname_get', - 'get_strmem_t_sname_set', + 'get_strlit_contents', 'get_stroff_path', + 'get_strtype_bpu', 'get_struc', 'get_struc_by_idx', 'get_struc_cmt', @@ -3333,7 +3218,7 @@ 'get_struc_size', 'get_struc_size__SWIG_0', 'get_struc_size__SWIG_1', - 'get_switch_info_ex', + 'get_switch_info', 'get_switch_parent', 'get_tab_size', 'get_tev_ea', @@ -3341,19 +3226,10 @@ 'get_tev_info', 'get_tev_memory_info', 'get_tev_qty', - 'get_tev_reg_mem_ea', - 'get_tev_reg_mem_qty', - 'get_tev_reg_val', 'get_tev_tid', 'get_tev_type', - 'get_tform_idaview', - 'get_tform_title', - 'get_tform_type', - 'get_tform_vdui', 'get_thread_qty', - 'get_tilpath', 'get_tinfo', - 'get_tinfo2', 'get_tinfo_attr', 'get_tinfo_attrs', 'get_tinfo_details', @@ -3363,38 +3239,54 @@ 'get_trace_base_address', 'get_trace_file_desc', 'get_trace_platform', - 'get_true_name', - 'get_true_name__SWIG_0', - 'get_true_name__SWIG_1', - 'get_true_segm_name', + 'get_tryblks', 'get_type', 'get_type_flags', 'get_type_ordinal', - 'get_type_sign', - 'get_typeinfo', 'get_unk_type', 'get_user_idadir', 'get_user_strlist_options', 'get_utf8_char', 'get_view_renderer_type', + 'get_viewer_graph', 'get_viewer_place_type', 'get_viewer_user_data', 'get_visible_name', + 'get_visible_segm_name', + 'get_wide_byte', + 'get_wide_dword', + 'get_wide_word', + 'get_widget_title', + 'get_widget_type', + 'get_widget_vdui', 'get_word', - 'get_zero_areas', - 'getdspace', + 'get_zero_ranges', 'getn_bpt', 'getn_enum', 'getn_fchunk', 'getn_func', - 'getn_hidden_area', + 'getn_hidden_range', 'getn_selector', - 'getn_srarea', - 'getn_srarea2', + 'getn_sreg_range', 'getn_thread', + 'getnode', 'getnseg', 'getseg', 'getsysfile', + 'graph_item_t_b_get', + 'graph_item_t_b_set', + 'graph_item_t_e_get', + 'graph_item_t_e_set', + 'graph_item_t_elp_get', + 'graph_item_t_elp_set', + 'graph_item_t_is_edge', + 'graph_item_t_is_node', + 'graph_item_t_n_get', + 'graph_item_t_n_set', + 'graph_item_t_p_get', + 'graph_item_t_p_set', + 'graph_item_t_type_get', + 'graph_item_t_type_set', 'graph_location_info_t___eq__', 'graph_location_info_t___ne__', 'graph_location_info_t_orgx_get', @@ -3403,32 +3295,50 @@ 'graph_location_info_t_orgy_set', 'graph_location_info_t_zoom_get', 'graph_location_info_t_zoom_set', + 'graph_node_visitor_t_is_forbidden_edge', + 'graph_node_visitor_t_is_visited', + 'graph_node_visitor_t_reinit', + 'graph_node_visitor_t_set_visited', + 'graph_node_visitor_t_visit_node', + 'graph_path_visitor_t_path_get', + 'graph_path_visitor_t_path_set', + 'graph_path_visitor_t_prune_get', + 'graph_path_visitor_t_prune_set', + 'graph_path_visitor_t_walk_backward', + 'graph_path_visitor_t_walk_forward', 'graph_trace', + 'graph_visitor_t_visit_edge', + 'graph_visitor_t_visit_node', + 'group_crinfo_t_nodes_get', + 'group_crinfo_t_nodes_set', + 'group_crinfo_t_text_get', + 'group_crinfo_t_text_set', 'guess_func_cc', - 'guess_func_tinfo', - 'guess_func_tinfo2', 'guess_table_address', 'guess_table_size', 'guess_tinfo', - 'guess_tinfo2', 'handle_debug_event', - 'hasExtra', - 'hasRef', - 'hasValue', 'has_any_name', 'has_auto_name', 'has_cached_cfunc', + 'has_cf_chg', + 'has_cf_use', 'has_cmt', 'has_dummy_name', 'has_external_refs', + 'has_extra_cmts', + 'has_immd', + 'has_insn_feature', 'has_lname', 'has_name', 'has_ti', 'has_ti0', 'has_ti1', 'has_user_name', + 'has_value', + 'has_xref', 'have_set_options', - 'hexflag', + 'hex_flag', 'hexrays_failure_t_code_get', 'hexrays_failure_t_code_set', 'hexrays_failure_t_desc', @@ -3457,9 +3367,6 @@ 'hexwarns_t__del', 'hexwarns_t_add_unique', 'hexwarns_t_at', - 'hexwarns_t_back', - 'hexwarns_t_back__SWIG_0', - 'hexwarns_t_back__SWIG_1', 'hexwarns_t_begin', 'hexwarns_t_begin__SWIG_0', 'hexwarns_t_begin__SWIG_1', @@ -3476,9 +3383,6 @@ 'hexwarns_t_find', 'hexwarns_t_find__SWIG_0', 'hexwarns_t_find__SWIG_1', - 'hexwarns_t_front', - 'hexwarns_t_front__SWIG_0', - 'hexwarns_t_front__SWIG_1', 'hexwarns_t_grow', 'hexwarns_t_has', 'hexwarns_t_inject', @@ -3495,16 +3399,16 @@ 'hexwarns_t_size', 'hexwarns_t_swap', 'hexwarns_t_truncate', - 'hidden_area_t_color_get', - 'hidden_area_t_color_set', - 'hidden_area_t_description_get', - 'hidden_area_t_description_set', - 'hidden_area_t_footer_get', - 'hidden_area_t_footer_set', - 'hidden_area_t_header_get', - 'hidden_area_t_header_set', - 'hidden_area_t_visible_get', - 'hidden_area_t_visible_set', + 'hidden_range_t_color_get', + 'hidden_range_t_color_set', + 'hidden_range_t_description_get', + 'hidden_range_t_description_set', + 'hidden_range_t_footer_get', + 'hidden_range_t_footer_set', + 'hidden_range_t_header_get', + 'hidden_range_t_header_set', + 'hidden_range_t_visible_get', + 'hidden_range_t_visible_set', 'hide_all_bpts', 'hide_border', 'hide_item', @@ -3524,73 +3428,68 @@ 'ida_lowertype_helper_t_func_has_stkframe_hole', 'ida_lowertype_helper_t_get_func_purged_bytes', 'idadir', - 'idainfo_ASCIIbreak_get', - 'idainfo_ASCIIbreak_set', - 'idainfo_ASCIIpref_get', - 'idainfo_ASCIIpref_set', - 'idainfo_ASCIIsernum_get', - 'idainfo_ASCIIsernum_set', - 'idainfo_ASCIIzeroes_get', - 'idainfo_ASCIIzeroes_set', 'idainfo_abibits_get', 'idainfo_abibits_set', - 'idainfo_abiname_get', - 'idainfo_abiname_set', 'idainfo_af2_get', 'idainfo_af2_set', 'idainfo_af_get', 'idainfo_af_set', + 'idainfo_allow_nonmatched_ops', 'idainfo_appcall_options_get', 'idainfo_appcall_options_set', 'idainfo_apptype_get', 'idainfo_apptype_set', - 'idainfo_asciiflags_get', - 'idainfo_asciiflags_set', 'idainfo_asmtype_get', 'idainfo_asmtype_set', 'idainfo_baseaddr_get', 'idainfo_baseaddr_set', - 'idainfo_beginEA_get', - 'idainfo_beginEA_set', 'idainfo_big_arg_align', - 'idainfo_binSize_get', - 'idainfo_binSize_set', + 'idainfo_bin_prefix_size_get', + 'idainfo_bin_prefix_size_set', 'idainfo_cc_get', 'idainfo_cc_set', + 'idainfo_check_manual_ops', 'idainfo_comment_get', 'idainfo_comment_set', - 'idainfo_corestart_get', - 'idainfo_corestart_set', 'idainfo_database_change_count_get', 'idainfo_database_change_count_set', 'idainfo_datatypes_get', 'idainfo_datatypes_set', 'idainfo_demnames_get', 'idainfo_demnames_set', - 'idainfo_fcoresiz_get', - 'idainfo_fcoresiz_set', 'idainfo_filetype_get', 'idainfo_filetype_set', + 'idainfo_gen_lzero', + 'idainfo_gen_null', + 'idainfo_gen_tryblks', + 'idainfo_get_abiname', 'idainfo_get_demname_form', - 'idainfo_get_proc_name', - 'idainfo_graph_view_get', - 'idainfo_graph_view_set', + 'idainfo_get_maxEA', + 'idainfo_get_minEA', + 'idainfo_get_pack_mode', + 'idainfo_get_procName', 'idainfo_highoff_get', 'idainfo_highoff_set', 'idainfo_indent_get', 'idainfo_indent_set', 'idainfo_is_32bit', 'idainfo_is_64bit', + 'idainfo_is_auto_enabled', + 'idainfo_is_be', 'idainfo_is_dll', 'idainfo_is_flat_off32', + 'idainfo_is_graph_view', 'idainfo_is_hard_float', + 'idainfo_is_kernel_mode', 'idainfo_is_mem_aligned4', 'idainfo_is_snapshot', + 'idainfo_is_wide_high_byte_first', 'idainfo_lenxref_get', 'idainfo_lenxref_set', 'idainfo_lflags_get', 'idainfo_lflags_set', 'idainfo_like_binary', + 'idainfo_line_pref_with_seg', 'idainfo_listnames_get', 'idainfo_listnames_set', 'idainfo_loading_idc', @@ -3598,111 +3497,104 @@ 'idainfo_long_demnames_set', 'idainfo_lowoff_get', 'idainfo_lowoff_set', - 'idainfo_lprefix_get', - 'idainfo_lprefix_set', - 'idainfo_lprefixlen_get', - 'idainfo_lprefixlen_set', 'idainfo_main_get', 'idainfo_main_set', 'idainfo_margin_get', 'idainfo_margin_set', - 'idainfo_maxEA_get', - 'idainfo_maxEA_set', + 'idainfo_max_autoname_len_get', + 'idainfo_max_autoname_len_set', + 'idainfo_max_ea_get', + 'idainfo_max_ea_set', 'idainfo_maxref_get', 'idainfo_maxref_set', - 'idainfo_mf_get', - 'idainfo_mf_set', - 'idainfo_minEA_get', - 'idainfo_minEA_set', - 'idainfo_namelen_get', - 'idainfo_namelen_set', + 'idainfo_min_ea_get', + 'idainfo_min_ea_set', 'idainfo_nametype_get', 'idainfo_nametype_set', - 'idainfo_omaxEA_get', - 'idainfo_omaxEA_set', - 'idainfo_ominEA_get', - 'idainfo_ominEA_set', + 'idainfo_omax_ea_get', + 'idainfo_omax_ea_set', + 'idainfo_omin_ea_get', + 'idainfo_omin_ea_set', 'idainfo_ostype_get', 'idainfo_ostype_set', + 'idainfo_outflags_get', + 'idainfo_outflags_set', 'idainfo_pack_stkargs', - 'idainfo_procName_get', - 'idainfo_procName_set', + 'idainfo_procname_get', + 'idainfo_procname_set', 'idainfo_readonly_idb', 'idainfo_refcmtnum_get', 'idainfo_refcmtnum_set', - 'idainfo_reserved_get', - 'idainfo_reserved_set', - 'idainfo_s_assume_get', - 'idainfo_s_assume_set', - 'idainfo_s_auto_get', - 'idainfo_s_auto_set', - 'idainfo_s_checkarg_get', - 'idainfo_s_checkarg_set', 'idainfo_s_cmtflg_get', 'idainfo_s_cmtflg_set', - 'idainfo_s_entab_get', - 'idainfo_s_entab_set', 'idainfo_s_genflags_get', 'idainfo_s_genflags_set', 'idainfo_s_limiter_get', 'idainfo_s_limiter_set', - 'idainfo_s_null_get', - 'idainfo_s_null_set', - 'idainfo_s_org_get', - 'idainfo_s_org_set', - 'idainfo_s_packbase_get', - 'idainfo_s_packbase_set', 'idainfo_s_prefflag_get', 'idainfo_s_prefflag_set', - 'idainfo_s_prefseg_get', - 'idainfo_s_prefseg_set', - 'idainfo_s_reserved5_get', - 'idainfo_s_reserved5_set', - 'idainfo_s_showauto_get', - 'idainfo_s_showauto_set', - 'idainfo_s_showbads_get', - 'idainfo_s_showbads_set', - 'idainfo_s_showpref_get', - 'idainfo_s_showpref_set', - 'idainfo_s_void_get', - 'idainfo_s_void_set', 'idainfo_s_xrefflag_get', 'idainfo_s_xrefflag_set', - 'idainfo_set_proc_name', + 'idainfo_set_64bit', + 'idainfo_set_allow_nonmatched_ops', + 'idainfo_set_auto_enabled', + 'idainfo_set_be', + 'idainfo_set_check_manual_ops', + 'idainfo_set_gen_lzero', + 'idainfo_set_gen_null', + 'idainfo_set_gen_tryblks', + 'idainfo_set_graph_view', + 'idainfo_set_line_pref_with_seg', + 'idainfo_set_maxEA', + 'idainfo_set_minEA', + 'idainfo_set_pack_mode', + 'idainfo_set_show_auto', + 'idainfo_set_show_line_pref', + 'idainfo_set_show_void', + 'idainfo_set_wide_high_byte_first', 'idainfo_short_demnames_get', 'idainfo_short_demnames_set', - 'idainfo_size_ldbl_get', - 'idainfo_size_ldbl_set', + 'idainfo_show_auto', + 'idainfo_show_line_pref', + 'idainfo_show_void', 'idainfo_specsegs_get', 'idainfo_specsegs_set', 'idainfo_stack_ldbl', 'idainfo_stack_varargs', - 'idainfo_startIP_get', - 'idainfo_startIP_set', - 'idainfo_startSP_get', - 'idainfo_startSP_set', 'idainfo_start_cs_get', 'idainfo_start_cs_set', + 'idainfo_start_ea_get', + 'idainfo_start_ea_set', + 'idainfo_start_ip_get', + 'idainfo_start_ip_set', + 'idainfo_start_sp_get', + 'idainfo_start_sp_set', 'idainfo_start_ss_get', 'idainfo_start_ss_set', + 'idainfo_strlit_break_get', + 'idainfo_strlit_break_set', + 'idainfo_strlit_flags_get', + 'idainfo_strlit_flags_set', + 'idainfo_strlit_pref_get', + 'idainfo_strlit_pref_set', + 'idainfo_strlit_sernum_get', + 'idainfo_strlit_sernum_set', + 'idainfo_strlit_zeroes_get', + 'idainfo_strlit_zeroes_set', 'idainfo_strtype_get', 'idainfo_strtype_set', 'idainfo_tag_get', 'idainfo_tag_set', - 'idainfo_tribyte_order_get', - 'idainfo_tribyte_order_set', 'idainfo_type_xrefnum_get', 'idainfo_type_xrefnum_set', 'idainfo_use_allasm', + 'idainfo_use_gcc_layout', 'idainfo_version_get', 'idainfo_version_set', - 'idainfo_wide_high_byte_first_get', - 'idainfo_wide_high_byte_first_set', 'idainfo_xrefnum_get', 'idainfo_xrefnum_set', 'idaplace_t_ea_get', 'idaplace_t_ea_set', - 'idb2scr', 'idc_get_local_type', 'idc_get_local_type_name', 'idc_get_local_type_raw', @@ -3718,11 +3610,6 @@ 'idc_print_type', 'idc_set_local_type', 'idc_value_t__create_empty_string', - 'idc_value_t__set_long', - 'idc_value_t__set_string', - 'idc_value_t__set_string__SWIG_0', - 'idc_value_t__set_string__SWIG_1', - 'idc_value_t__set_string__SWIG_2', 'idc_value_t_c_str', 'idc_value_t_clear', 'idc_value_t_create_empty_string', @@ -3754,18 +3641,48 @@ 'idc_value_t_set_string__SWIG_0', 'idc_value_t_set_string__SWIG_1', 'idc_value_t_set_string__SWIG_2', - 'idc_value_t_str_get', - 'idc_value_t_str_set', 'idc_value_t_swap', 'idc_value_t_u_str', 'idc_value_t_vtype_get', 'idc_value_t_vtype_set', - 'idd_opinfo_old_t_addr_get', - 'idd_opinfo_old_t_addr_set', - 'idd_opinfo_old_t_modified_get', - 'idd_opinfo_old_t_modified_set', - 'idd_opinfo_old_t_value_get', - 'idd_opinfo_old_t_value_set', + 'idc_values_t___getitem__', + 'idc_values_t___len__', + 'idc_values_t___setitem__', + 'idc_values_t_at', + 'idc_values_t_begin', + 'idc_values_t_begin__SWIG_0', + 'idc_values_t_begin__SWIG_1', + 'idc_values_t_capacity', + 'idc_values_t_clear', + 'idc_values_t_empty', + 'idc_values_t_end', + 'idc_values_t_end__SWIG_0', + 'idc_values_t_end__SWIG_1', + 'idc_values_t_erase', + 'idc_values_t_erase__SWIG_0', + 'idc_values_t_erase__SWIG_1', + 'idc_values_t_extract', + 'idc_values_t_grow', + 'idc_values_t_inject', + 'idc_values_t_insert', + 'idc_values_t_pop_back', + 'idc_values_t_push_back', + 'idc_values_t_push_back__SWIG_0', + 'idc_values_t_push_back__SWIG_1', + 'idc_values_t_qclear', + 'idc_values_t_reserve', + 'idc_values_t_resize', + 'idc_values_t_resize__SWIG_0', + 'idc_values_t_resize__SWIG_1', + 'idc_values_t_size', + 'idc_values_t_swap', + 'idc_values_t_truncate', + 'idcv_float', + 'idcv_int64', + 'idcv_long', + 'idcv_num', + 'idcv_object', + 'idcv_string', 'idp_desc_t_checked_get', 'idp_desc_t_checked_set', 'idp_desc_t_family_get', @@ -3784,43 +3701,54 @@ 'idp_name_t_lname_set', 'idp_name_t_sname_get', 'idp_name_t_sname_set', - 'ids_array___getitem__', - 'ids_array___len__', - 'ids_array___setitem__', - 'ids_array_data_get', 'import_type', 'info', 'info__varargs__', 'init_hexrays_plugin', - 'init_output_buffer', - 'init_process', + 'insn_add_cref', + 'insn_add_dref', + 'insn_add_off_drefs', + 'insn_create_stkvar', + 'insn_t___get_auxpref__', + 'insn_t___get_operand__', + 'insn_t___get_ops__', + 'insn_t___set_auxpref__', + 'insn_t__from_ptrval__', + 'insn_t_add_cref', + 'insn_t_add_dref', + 'insn_t_add_off_drefs', 'insn_t_assign', - 'insn_t_create', - 'insn_t_destroy', - 'insn_t_get_auxpref', + 'insn_t_create_op_data', + 'insn_t_create_op_data__SWIG_0', + 'insn_t_create_op_data__SWIG_1', + 'insn_t_create_stkvar', + 'insn_t_cs_get', + 'insn_t_cs_set', + 'insn_t_ea_get', + 'insn_t_ea_set', + 'insn_t_flags_get', + 'insn_t_flags_set', 'insn_t_get_canon_feature', 'insn_t_get_canon_mnem', - 'insn_t_get_cs', - 'insn_t_get_ea', - 'insn_t_get_flags', - 'insn_t_get_insnpref', - 'insn_t_get_ip', - 'insn_t_get_itype', - 'insn_t_get_op_link', - 'insn_t_get_segpref', - 'insn_t_get_size', + 'insn_t_get_next_byte', + 'insn_t_get_next_dword', + 'insn_t_get_next_qword', + 'insn_t_get_next_word', + 'insn_t_insnpref_get', + 'insn_t_insnpref_set', + 'insn_t_ip_get', + 'insn_t_ip_set', 'insn_t_is_canon_insn', - 'insn_t_set_auxpref', - 'insn_t_set_cs', - 'insn_t_set_ea', - 'insn_t_set_flags', - 'insn_t_set_insnpref', - 'insn_t_set_ip', - 'insn_t_set_itype', - 'insn_t_set_segpref', - 'insn_t_set_size', + 'insn_t_is_macro', + 'insn_t_itype_get', + 'insn_t_itype_set', + 'insn_t_ops_get', + 'insn_t_ops_set', + 'insn_t_segpref_get', + 'insn_t_segpref_set', + 'insn_t_size_get', + 'insn_t_size_set', 'install_command_interpreter', - 'install_extlang', 'install_hexrays_callback', 'install_microcode_filter', 'instant_dbgopts_t__pass_get', @@ -3847,9 +3775,6 @@ 'int64vec_t__del', 'int64vec_t_add_unique', 'int64vec_t_at', - 'int64vec_t_back', - 'int64vec_t_back__SWIG_0', - 'int64vec_t_back__SWIG_1', 'int64vec_t_begin', 'int64vec_t_begin__SWIG_0', 'int64vec_t_begin__SWIG_1', @@ -3866,9 +3791,6 @@ 'int64vec_t_find', 'int64vec_t_find__SWIG_0', 'int64vec_t_find__SWIG_1', - 'int64vec_t_front', - 'int64vec_t_front__SWIG_0', - 'int64vec_t_front__SWIG_1', 'int64vec_t_has', 'int64vec_t_inject', 'int64vec_t_insert', @@ -3888,10 +3810,21 @@ 'int_pointer_cast', 'int_pointer_frompointer', 'int_pointer_value', - 'intel_data', 'internal_get_sreg_base', 'internal_ioctl', 'internal_register_place_class', + 'interval_t___eq__', + 'interval_t___ne__', + 'interval_t_contains', + 'interval_t_empty', + 'interval_t_intersect', + 'interval_t_length', + 'interval_t_make_union', + 'interval_t_move_by', + 'interval_t_x0_get', + 'interval_t_x0_set', + 'interval_t_x1_get', + 'interval_t_x1_set', 'intvec_t___eq__', 'intvec_t___getitem__', 'intvec_t___len__', @@ -3900,9 +3833,6 @@ 'intvec_t__del', 'intvec_t_add_unique', 'intvec_t_at', - 'intvec_t_back', - 'intvec_t_back__SWIG_0', - 'intvec_t_back__SWIG_1', 'intvec_t_begin', 'intvec_t_begin__SWIG_0', 'intvec_t_begin__SWIG_1', @@ -3919,9 +3849,6 @@ 'intvec_t_find', 'intvec_t_find__SWIG_0', 'intvec_t_find__SWIG_1', - 'intvec_t_front', - 'intvec_t_front__SWIG_0', - 'intvec_t_front__SWIG_1', 'intvec_t_grow', 'intvec_t_has', 'intvec_t_inject', @@ -3940,78 +3867,20 @@ 'intvec_t_truncate', 'invalidate_dbgmem_config', 'invalidate_dbgmem_contents', - 'invalidate_visea_cache', - 'is3byte', - 'isASCII', - 'isAlign', - 'isByte', - 'isChar', - 'isChar0', - 'isChar1', - 'isCode', - 'isCustFmt', - 'isCustFmt0', - 'isCustFmt1', - 'isCustom', - 'isData', - 'isDefArg', - 'isDefArg0', - 'isDefArg1', - 'isDouble', - 'isDwrd', - 'isEnabled', - 'isEnum', - 'isEnum0', - 'isEnum1', - 'isFloat', - 'isFloat0', - 'isFloat1', - 'isFlow', - 'isFltnum', - 'isFop', - 'isFunc', - 'isHead', - 'isImmd', - 'isLoaded', - 'isNotTail', - 'isNum', - 'isNum0', - 'isNum1', - 'isOff', - 'isOff0', - 'isOff1', - 'isOwrd', - 'isPackReal', - 'isQwrd', - 'isSeg', - 'isSeg0', - 'isSeg1', - 'isStkvar', - 'isStkvar0', - 'isStkvar1', - 'isStroff', - 'isStroff0', - 'isStroff1', - 'isStruct', - 'isTail', - 'isTbyt', - 'isUnknown', - 'isVar', - 'isVoid', - 'isWord', - 'isYwrd', - 'isZwrd', 'is__bnot0', 'is__bnot1', 'is__invsign0', 'is__invsign1', 'is_action_enabled', 'is_additive', + 'is_align', 'is_align_flow', 'is_align_insn', 'is_allowed_on_small_struni', 'is_anonymous_member_name', 'is_assignment', + 'is_attached_custom_data_format', + 'is_auto_enabled', 'is_autosync', 'is_autosync__SWIG_0', 'is_autosync__SWIG_1', @@ -4023,26 +3892,51 @@ 'is_bnot', 'is_bool_type', 'is_break_consumer', + 'is_byte', 'is_call_insn', - 'is_castable2', - 'is_chooser_tform', + 'is_char', + 'is_char0', + 'is_char1', + 'is_chooser_widget', + 'is_code', 'is_code_far', 'is_colored_item', 'is_commutative', 'is_comp_unsure', 'is_control_tty', + 'is_custfmt', + 'is_custfmt0', + 'is_custfmt1', + 'is_custom', + 'is_data', 'is_data_far', + 'is_database_flag', 'is_debugger_busy', 'is_debugger_memory', 'is_debugger_on', + 'is_defarg', + 'is_defarg0', + 'is_defarg1', + 'is_double', 'is_dummy_member_name', + 'is_dword', + 'is_enum', + 'is_enum0', + 'is_enum1', 'is_enum_fromtil', 'is_enum_hidden', 'is_finally_visible_func', 'is_finally_visible_item', 'is_finally_visible_segm', 'is_fixed_spd', + 'is_fixup_custom', + 'is_float', + 'is_float0', + 'is_float1', + 'is_flow', + 'is_fltnum', 'is_forced_operand', + 'is_func', 'is_func_entry', 'is_func_locked', 'is_func_tail', @@ -4052,15 +3946,19 @@ 'is_gcc32', 'is_gcc64', 'is_ghost_enum', + 'is_head', 'is_hidden_border', 'is_hidden_item', 'is_idaq', - 'is_ident_char', + 'is_ident', + 'is_ident_cp', 'is_in_nlist', 'is_indirect_jump_insn', + 'is_inplace_def', 'is_insn_trace_enabled', 'is_invsign', 'is_libitem', + 'is_loaded', 'is_logical', 'is_loop', 'is_lvalue', @@ -4068,7 +3966,9 @@ 'is_lzero0', 'is_lzero1', 'is_main_thread', + 'is_manual', 'is_manual_insn', + 'is_mapped', 'is_member_id', 'is_miniidb', 'is_msg_inited', @@ -4077,49 +3977,66 @@ 'is_nonbool_type', 'is_noret', 'is_noret_block', + 'is_not_tail', 'is_notcode', + 'is_notproc', + 'is_numop', + 'is_numop0', + 'is_numop1', + 'is_off', + 'is_off0', + 'is_off1', 'is_one_bit_mask', 'is_ordinal_name', + 'is_oword', + 'is_pack_real', 'is_paf', 'is_pascal', 'is_place_class_ea_capable', 'is_prepost', + 'is_problem_present', 'is_ptr_or_array', 'is_public_name', 'is_purging_cc', - 'is_reg2_argloc', - 'is_reg_argloc', + 'is_qword', + 'is_refresh_requested', + 'is_reftype_target_optional', 'is_reg_custom', 'is_reg_float', 'is_reg_integer', 'is_relational', - 'is_resolved_type_struni', - 'is_restype_array', - 'is_restype_bitfld', - 'is_restype_complex', - 'is_restype_const', 'is_restype_enum', - 'is_restype_floating', - 'is_restype_func', - 'is_restype_ptr', 'is_restype_struct', 'is_restype_struni', - 'is_restype_union', 'is_restype_void', 'is_ret_block', 'is_ret_insn', 'is_retfp', 'is_same_data_type', + 'is_same_func', 'is_sdacl_byte', + 'is_seg', + 'is_seg0', + 'is_seg1', 'is_segm_locked', - 'is_segreg_locked', 'is_small_struni', 'is_spec_ea', 'is_spec_segm', 'is_special_member', - 'is_stack_argloc', 'is_step_trace_enabled', + 'is_stkvar', + 'is_stkvar0', + 'is_stkvar1', + 'is_strlit', + 'is_strlit_cp', + 'is_stroff', + 'is_stroff0', + 'is_stroff1', + 'is_struct', + 'is_suspop', 'is_tah_byte', + 'is_tail', + 'is_tbyte', 'is_terse_struc', 'is_tilcmt', 'is_trusted_idb', @@ -4145,13 +4062,10 @@ 'is_type_int64', 'is_type_integral', 'is_type_ldouble', - 'is_type_only_size', 'is_type_paf', 'is_type_partial', 'is_type_ptr', 'is_type_ptr_or_array', - 'is_type_resolvable', - 'is_type_scalar2', 'is_type_struct', 'is_type_struni', 'is_type_sue', @@ -4163,41 +4077,37 @@ 'is_type_uint32', 'is_type_uint64', 'is_type_union', - 'is_type_unk', 'is_type_unknown', 'is_type_void', - 'is_type_void_obsolete', - 'is_type_voiddef', 'is_type_volatile', 'is_typeid_last', 'is_uname', 'is_unary', - 'is_unicode', 'is_union', + 'is_unknown', 'is_user_cc', 'is_usersp', 'is_userti', - 'is_valid_full_type', + 'is_valid_cp', 'is_valid_trace_file', 'is_valid_typename', 'is_vararg_cc', 'is_varmember', 'is_varsize_item', 'is_varstr', - 'is_visible_char', + 'is_visible_cp', 'is_visible_func', 'is_visible_item', 'is_visible_segm', 'is_weak_name', + 'is_word', + 'is_yword', 'is_zstroff', - 'isident', - 'jumptable_info_t_size_get', - 'jumptable_info_t_size_set', - 'jumptable_info_t_table_get', - 'jumptable_info_t_table_set', + 'is_zword', 'jumpto', 'jumpto__SWIG_0', 'jumpto__SWIG_1', + 'last_idcv_attr', 'leading_zero_important', 'lexcompare_tinfo', 'linput_buffer_t_eof', @@ -4209,21 +4119,14 @@ 'llabel_t_ea_set', 'llabel_t_name_get', 'llabel_t_name_set', - 'lnot', 'load_and_run_plugin', 'load_binary_file', 'load_dbg_dbginfo', 'load_debugger', 'load_ids_module', - 'load_loader_module', 'load_plugin', 'load_til', - 'load_til2', - 'load_til__SWIG_0', - 'load_til__SWIG_1', 'load_til_header', - 'load_til_header__SWIG_0', - 'load_til_header__SWIG_1', 'load_trace_file', 'loader_input_t___idc_cvt_id___get', 'loader_input_t___idc_cvt_id___set', @@ -4246,23 +4149,10 @@ 'loader_input_t_set_linput', 'loader_input_t_size', 'loader_input_t_tell', - 'loader_t__UNUSED1_was_init_loader_options_get', - 'loader_t__UNUSED1_was_init_loader_options_set', 'loader_t_flags_get', 'loader_t_flags_set', 'loader_t_version_get', 'loader_t_version_set', - 'location_t_copy_current_location', - 'location_t_get', - 'location_t_get_entry', - 'location_t_gli_get', - 'location_t_gli_set', - 'location_t_jump', - 'location_t_jump_nopush', - 'location_t_linkTo', - 'location_t_mark', - 'location_t_pop', - 'location_t_push_and_jump', 'locchange_md_t_is_sync', 'locchange_md_t_reason', 'lochist_entry_t___eq__', @@ -4297,9 +4187,10 @@ 'lochist_t_set', 'lochist_t_set_current', 'lochist_t_size', + 'lock_func_range', + 'lock_segm', 'lookup_key_code', 'lower_type', - 'lower_type2', 'lowertype_helper_t_func_has_stkframe_hole', 'lowertype_helper_t_get_func_purged_bytes', 'lvar_locator_t___eq__', @@ -4368,9 +4259,6 @@ 'lvar_saved_infos_t__del', 'lvar_saved_infos_t_add_unique', 'lvar_saved_infos_t_at', - 'lvar_saved_infos_t_back', - 'lvar_saved_infos_t_back__SWIG_0', - 'lvar_saved_infos_t_back__SWIG_1', 'lvar_saved_infos_t_begin', 'lvar_saved_infos_t_begin__SWIG_0', 'lvar_saved_infos_t_begin__SWIG_1', @@ -4387,9 +4275,6 @@ 'lvar_saved_infos_t_find', 'lvar_saved_infos_t_find__SWIG_0', 'lvar_saved_infos_t_find__SWIG_1', - 'lvar_saved_infos_t_front', - 'lvar_saved_infos_t_front__SWIG_0', - 'lvar_saved_infos_t_front__SWIG_1', 'lvar_saved_infos_t_grow', 'lvar_saved_infos_t_has', 'lvar_saved_infos_t_inject', @@ -4485,20 +4370,24 @@ 'lvars_t_find_input_lvar', 'lvars_t_find_lvar', 'lvars_t_find_stkvar', - 'make_array_type', - 'make_ascii_string', 'make_name_auto', 'make_name_non_public', 'make_name_non_weak', 'make_name_public', 'make_name_user', 'make_name_weak', - 'make_num', - 'make_old_argloc', 'make_pointer', - 'make_ref', - 'make_visible_name', + 'map_code_ea', + 'map_code_ea__SWIG_0', + 'map_code_ea__SWIG_1', + 'map_data_ea', + 'map_data_ea__SWIG_0', + 'map_data_ea__SWIG_1', + 'map_ea', + 'map_ea__SWIG_0', + 'map_ea__SWIG_1', 'mark_cfunc_dirty', + 'mark_position', 'may_create_stkvars', 'may_trace_sp', 'mem2base', @@ -4524,9 +4413,6 @@ 'memreg_infos_t___len__', 'memreg_infos_t___setitem__', 'memreg_infos_t_at', - 'memreg_infos_t_back', - 'memreg_infos_t_back__SWIG_0', - 'memreg_infos_t_back__SWIG_1', 'memreg_infos_t_begin', 'memreg_infos_t_begin__SWIG_0', 'memreg_infos_t_begin__SWIG_1', @@ -4540,9 +4426,6 @@ 'memreg_infos_t_erase__SWIG_0', 'memreg_infos_t_erase__SWIG_1', 'memreg_infos_t_extract', - 'memreg_infos_t_front', - 'memreg_infos_t_front__SWIG_0', - 'memreg_infos_t_front__SWIG_1', 'memreg_infos_t_grow', 'memreg_infos_t_inject', 'memreg_infos_t_insert', @@ -4571,9 +4454,70 @@ 'module_info_t_size_get', 'module_info_t_size_set', 'move_bpt_to_grp', + 'move_idcv', 'move_segm', 'move_segm_start', 'msg', + 'mutable_graph_t_belongs_get', + 'mutable_graph_t_belongs_set', + 'mutable_graph_t_calc_group_ea', + 'mutable_graph_t_change_group_visibility', + 'mutable_graph_t_clear', + 'mutable_graph_t_create_digraph_layout', + 'mutable_graph_t_create_group', + 'mutable_graph_t_del_custom_layout', + 'mutable_graph_t_delete_group', + 'mutable_graph_t_edges_get', + 'mutable_graph_t_edges_set', + 'mutable_graph_t_empty', + 'mutable_graph_t_exists', + 'mutable_graph_t_get_custom_layout', + 'mutable_graph_t_get_first_subgraph_node', + 'mutable_graph_t_get_graph_groups', + 'mutable_graph_t_get_next_subgraph_node', + 'mutable_graph_t_get_node_group', + 'mutable_graph_t_get_node_representative', + 'mutable_graph_t_gid_get', + 'mutable_graph_t_gid_set', + 'mutable_graph_t_is_collapsed_node', + 'mutable_graph_t_is_deleted_node', + 'mutable_graph_t_is_displayable_node', + 'mutable_graph_t_is_dot_node', + 'mutable_graph_t_is_group_node', + 'mutable_graph_t_is_simple_node', + 'mutable_graph_t_is_subgraph_node', + 'mutable_graph_t_is_uncollapsed_node', + 'mutable_graph_t_is_user_graph', + 'mutable_graph_t_is_visible_node', + 'mutable_graph_t_node_flags_get', + 'mutable_graph_t_node_flags_set', + 'mutable_graph_t_node_qty', + 'mutable_graph_t_nodes_get', + 'mutable_graph_t_nodes_set', + 'mutable_graph_t_npred', + 'mutable_graph_t_nrect', + 'mutable_graph_t_nrect__SWIG_0', + 'mutable_graph_t_nrect__SWIG_1', + 'mutable_graph_t_nsucc', + 'mutable_graph_t_org_preds_get', + 'mutable_graph_t_org_preds_set', + 'mutable_graph_t_org_succs_get', + 'mutable_graph_t_org_succs_set', + 'mutable_graph_t_pred', + 'mutable_graph_t_preds_get', + 'mutable_graph_t_preds_set', + 'mutable_graph_t_predset', + 'mutable_graph_t_reset', + 'mutable_graph_t_set_custom_layout', + 'mutable_graph_t_set_deleted_node', + 'mutable_graph_t_set_edge', + 'mutable_graph_t_set_graph_groups', + 'mutable_graph_t_set_node_group', + 'mutable_graph_t_size', + 'mutable_graph_t_succ', + 'mutable_graph_t_succs_get', + 'mutable_graph_t_succs_set', + 'mutable_graph_t_succset', 'nbits', 'negated_relation', 'netnode___eq__', @@ -4582,54 +4526,69 @@ 'netnode___ne__', 'netnode___ne____SWIG_0', 'netnode___ne____SWIG_1', - 'netnode_alt1st', - 'netnode_alt1st_idx8', 'netnode_altdel', 'netnode_altdel__SWIG_0', 'netnode_altdel__SWIG_1', 'netnode_altdel_all', + 'netnode_altdel_ea', 'netnode_altdel_idx8', + 'netnode_altfirst', + 'netnode_altfirst_idx8', 'netnode_altlast', 'netnode_altlast_idx8', - 'netnode_altnxt', - 'netnode_altnxt_idx8', + 'netnode_altnext', + 'netnode_altnext_idx8', 'netnode_altprev', 'netnode_altprev_idx8', 'netnode_altset', + 'netnode_altset_ea', 'netnode_altset_idx8', 'netnode_altshift', 'netnode_altval', + 'netnode_altval_ea', 'netnode_altval_idx8', 'netnode_blobsize', - 'netnode_char1st', - 'netnode_char1st_idx8', + 'netnode_blobsize_ea', 'netnode_chardel', + 'netnode_chardel_ea', 'netnode_chardel_idx8', + 'netnode_charfirst', + 'netnode_charfirst_idx8', 'netnode_charlast', 'netnode_charlast_idx8', - 'netnode_charnxt', - 'netnode_charnxt_idx8', + 'netnode_charnext', + 'netnode_charnext_idx8', 'netnode_charprev', 'netnode_charprev_idx8', 'netnode_charset', + 'netnode_charset_ea', 'netnode_charset_idx8', 'netnode_charshift', 'netnode_charval', + 'netnode_charval_ea', 'netnode_charval_idx8', 'netnode_copyto', 'netnode_create', 'netnode_create__SWIG_0', 'netnode_create__SWIG_1', 'netnode_delblob', + 'netnode_delblob_ea', 'netnode_delvalue', + 'netnode_eadel', + 'netnode_eadel_idx8', + 'netnode_eaget', + 'netnode_eaget_idx8', + 'netnode_easet', + 'netnode_easet_idx8', 'netnode_end', 'netnode_get_name', 'netnode_getblob', - 'netnode_hash1st', + 'netnode_getblob_ea', 'netnode_hashdel', 'netnode_hashdel_all', + 'netnode_hashfirst', 'netnode_hashlast', - 'netnode_hashnxt', + 'netnode_hashnext', 'netnode_hashprev', 'netnode_hashset', 'netnode_hashset_buf', @@ -4641,36 +4600,43 @@ 'netnode_index', 'netnode_kill', 'netnode_long_value', + 'netnode_lower_bound', + 'netnode_lower_bound_ea', + 'netnode_lower_bound_idx8', 'netnode_moveto', - 'netnode_name', 'netnode_next', 'netnode_prev', 'netnode_rename', 'netnode_set', 'netnode_set_long', 'netnode_setblob', + 'netnode_setblob_ea', 'netnode_start', - 'netnode_sup1st', - 'netnode_sup1st_idx8', 'netnode_supdel', 'netnode_supdel__SWIG_0', 'netnode_supdel__SWIG_1', 'netnode_supdel_all', + 'netnode_supdel_ea', 'netnode_supdel_idx8', 'netnode_supdel_range', 'netnode_supdel_range_idx8', + 'netnode_supfirst', + 'netnode_supfirst_idx8', 'netnode_suplast', 'netnode_suplast_idx8', - 'netnode_supnxt', - 'netnode_supnxt_idx8', + 'netnode_supnext', + 'netnode_supnext_idx8', 'netnode_supprev', 'netnode_supprev_idx8', 'netnode_supset', + 'netnode_supset_ea', 'netnode_supset_idx8', 'netnode_supshift', 'netnode_supstr', + 'netnode_supstr_ea', 'netnode_supstr_idx8', 'netnode_supval', + 'netnode_supval_ea', 'netnode_supval_idx8', 'netnode_valobj', 'netnode_valstr', @@ -4678,7 +4644,12 @@ 'new_DBG_Hooks', 'new_IDB_Hooks', 'new_IDP_Hooks', + 'new_TPointDouble', + 'new_TPointDouble__SWIG_0', + 'new_TPointDouble__SWIG_1', + 'new_TPointDouble__SWIG_2', 'new_UI_Hooks', + 'new_View_Hooks', 'new___qmutex_t', 'new___qsemaphore_t', 'new___qthread_t', @@ -4689,16 +4660,6 @@ 'new_action_update_ctx_t', 'new_addon_info_t', 'new_aloc_visitor_t', - 'new_area_t', - 'new_area_t__SWIG_0', - 'new_area_t__SWIG_1', - 'new_area_visitor2_t', - 'new_areacb_t', - 'new_areaset_t', - 'new_areaset_t__SWIG_0', - 'new_areaset_t__SWIG_1', - 'new_areaset_t__SWIG_2', - 'new_areavec_t', 'new_argloc_t', 'new_argloc_t__SWIG_0', 'new_argloc_t__SWIG_1', @@ -4711,7 +4672,6 @@ 'new_auto_display_t', 'new_bgcolors_t', 'new_bitfield_type_data_t', - 'new_block', 'new_boolvec_t', 'new_boolvec_t__SWIG_0', 'new_boolvec_t__SWIG_1', @@ -4738,17 +4698,16 @@ 'new_casm_t', 'new_casm_t__SWIG_0', 'new_casm_t__SWIG_1', + 'new_catch_t', + 'new_catchvec_t', + 'new_catchvec_t__SWIG_0', + 'new_catchvec_t__SWIG_1', 'new_cblock_t', 'new_ccase_t', 'new_ccases_t', 'new_cdo_t', 'new_ceinsn_t', 'new_cexpr_t', - 'new_cexpr_t__SWIG_0', - 'new_cexpr_t__SWIG_1', - 'new_cexpr_t__SWIG_2', - 'new_cexpr_t__SWIG_3', - 'new_cexpr_t__SWIG_4', 'new_cfor_t', 'new_cfunc_parentee_t', 'new_cfuncptr_t', @@ -4756,12 +4715,11 @@ 'new_cfuncptr_t__SWIG_1', 'new_cgoto_t', 'new_channel_redir_t', + 'new_chooser_item_attrs_t', 'new_cif_t', 'new_cif_t__SWIG_0', 'new_cif_t__SWIG_1', 'new_cinsn_t', - 'new_cinsn_t__SWIG_0', - 'new_cinsn_t__SWIG_1', 'new_cinsnptrvec_t', 'new_cinsnptrvec_t__SWIG_0', 'new_cinsnptrvec_t__SWIG_1', @@ -4771,7 +4729,6 @@ 'new_citem_locator_t', 'new_citem_locator_t__SWIG_0', 'new_citem_locator_t__SWIG_1', - 'new_citem_locator_t__SWIG_2', 'new_citem_t', 'new_citem_t__SWIG_0', 'new_citem_t__SWIG_1', @@ -4780,6 +4737,7 @@ 'new_cloop_t__SWIG_1', 'new_cloop_t__SWIG_2', 'new_cnumber_t', + 'new_codegen_t', 'new_compiler_info_t', 'new_const_aloc_visitor_t', 'new_creturn_t', @@ -4792,11 +4750,11 @@ 'new_ctree_items_t__SWIG_1', 'new_ctree_parentee_t', 'new_ctree_visitor_t', - 'new_curloc', - 'new_curloc__SWIG_0', - 'new_curloc__SWIG_1', + 'new_custom_data_type_ids_fids_array', 'new_custom_data_type_ids_t', 'new_cwhile_t', + 'new_data_format_t', + 'new_data_type_t', 'new_debapp_attrs_t', 'new_debug_event_t', 'new_disasm_line_t', @@ -4814,6 +4772,15 @@ 'new_ea_pointer', 'new_eamap_iterator_t', 'new_eamap_t', + 'new_edge_info_t', + 'new_edge_layout_point_t', + 'new_edge_layout_point_t__SWIG_0', + 'new_edge_layout_point_t__SWIG_1', + 'new_edge_layout_point_t__SWIG_2', + 'new_edge_segment_t', + 'new_edge_t', + 'new_edge_t__SWIG_0', + 'new_edge_t__SWIG_1', 'new_enum_const_t', 'new_enum_member_t', 'new_enum_member_visitor_t', @@ -4826,6 +4793,10 @@ 'new_excvec_t__SWIG_0', 'new_excvec_t__SWIG_1', 'new_fixup_data_t', + 'new_fixup_data_t__SWIG_0', + 'new_fixup_data_t__SWIG_1', + 'new_fixup_info_t', + 'new_fnum_array', 'new_fnumber_t', 'new_func_item_iterator_t', 'new_func_item_iterator_t__SWIG_0', @@ -4838,14 +4809,16 @@ 'new_func_tail_iterator_t__SWIG_0', 'new_func_tail_iterator_t__SWIG_1', 'new_func_type_data_t', - 'new_func_type_info_t', - 'new_funcarg_info_t', 'new_funcarg_t', 'new_funcargvec_t', 'new_funcargvec_t__SWIG_0', 'new_funcargvec_t__SWIG_1', - 'new_get_strmem_t', + 'new_graph_item_t', 'new_graph_location_info_t', + 'new_graph_node_visitor_t', + 'new_graph_path_visitor_t', + 'new_graph_visitor_t', + 'new_group_crinfo_t', 'new_hexrays_failure_t', 'new_hexrays_failure_t__SWIG_0', 'new_hexrays_failure_t__SWIG_1', @@ -4854,14 +4827,11 @@ 'new_hexwarns_t', 'new_hexwarns_t__SWIG_0', 'new_hexwarns_t__SWIG_1', - 'new_hidden_area_t', + 'new_hidden_range_t', 'new_highlighter_cbs_t', 'new_history_item_t', 'new_history_t', - 'new_ida_false_type', 'new_ida_lowertype_helper_t', - 'new_ida_true_type', - 'new_idainfo', 'new_idc_global_t', 'new_idc_global_t__SWIG_0', 'new_idc_global_t__SWIG_1', @@ -4870,36 +4840,36 @@ 'new_idc_value_t__SWIG_1', 'new_idc_value_t__SWIG_2', 'new_idc_value_t__SWIG_3', - 'new_idd_opinfo_old_t', + 'new_idc_values_t', + 'new_idc_values_t__SWIG_0', + 'new_idc_values_t__SWIG_1', 'new_idp_desc_t', 'new_idp_name_t', - 'new_ids_array', + 'new_insn_t', 'new_instant_dbgopts_t', 'new_int64vec_t', 'new_int64vec_t__SWIG_0', 'new_int64vec_t__SWIG_1', 'new_int_pointer', + 'new_interval_t', + 'new_interval_t__SWIG_0', + 'new_interval_t__SWIG_1', + 'new_interval_t__SWIG_2', 'new_intvec_t', 'new_intvec_t__SWIG_0', 'new_intvec_t__SWIG_1', - 'new_jumptable_info_t', 'new_linput_buffer_t', 'new_llabel_t', 'new_loader_input_t', 'new_loader_t', - 'new_location_t', - 'new_location_t__SWIG_0', - 'new_location_t__SWIG_1', 'new_locchange_md_t', 'new_lochist_entry_t', 'new_lochist_entry_t__SWIG_0', 'new_lochist_entry_t__SWIG_1', 'new_lochist_entry_t__SWIG_2', 'new_lochist_t', - 'new_lock_area', 'new_lock_func', 'new_lock_segment', - 'new_lock_segreg', 'new_lvar_locator_t', 'new_lvar_locator_t__SWIG_0', 'new_lvar_locator_t__SWIG_1', @@ -4924,14 +4894,24 @@ 'new_netnode__SWIG_2', 'new_node_info_t', 'new_node_iterator', + 'new_node_ordering_t', 'new_number_format_t', + 'new_op_t', 'new_operand_locator_t', - 'new_operand_locator_t__SWIG_0', - 'new_operand_locator_t__SWIG_1', + 'new_operands_array', 'new_operator_info_t', 'new_opinfo_t', 'new_plugin_info_t', + 'new_point_t', + 'new_point_t__SWIG_0', + 'new_point_t__SWIG_1', + 'new_pointseq_t', + 'new_predicate_t', + 'new_printop_t', 'new_process_info_t', + 'new_procinfo_vec_t', + 'new_procinfo_vec_t__SWIG_0', + 'new_procinfo_vec_t__SWIG_1', 'new_ptr_type_data_t', 'new_qbasic_block_t', 'new_qfile_t', @@ -4961,6 +4941,21 @@ 'new_qvector_snapshotvec_t', 'new_qvector_snapshotvec_t__SWIG_0', 'new_qvector_snapshotvec_t__SWIG_1', + 'new_range_t', + 'new_range_t__SWIG_0', + 'new_range_t__SWIG_1', + 'new_rangeset_t', + 'new_rangeset_t__SWIG_0', + 'new_rangeset_t__SWIG_1', + 'new_rangeset_t__SWIG_2', + 'new_rangevec_base_t', + 'new_rangevec_base_t__SWIG_0', + 'new_rangevec_base_t__SWIG_1', + 'new_rangevec_t', + 'new_rect_t', + 'new_rect_t__SWIG_0', + 'new_rect_t__SWIG_1', + 'new_rect_t__SWIG_2', 'new_refinfo_t', 'new_reg_info_t', 'new_regarg_t', @@ -4973,32 +4968,44 @@ 'new_regval_t__SWIG_0', 'new_regval_t__SWIG_1', 'new_regvar_t', + 'new_renderer_info_pos_t', 'new_renderer_info_t', 'new_renderer_pos_info_t', + 'new_row_info_t', 'new_rrel_t', 'new_scattered_aloc_t', - 'new_scattered_vloc_t', + 'new_scattered_segm_t', + 'new_screen_graph_selection_t', 'new_segm_move_info_t', 'new_segm_move_info_vec_t', 'new_segm_move_info_vec_t__SWIG_0', 'new_segm_move_info_vec_t__SWIG_1', 'new_segm_move_infos_t', 'new_segment_t', - 'new_segreg_area_t', - 'new_segreg_t', + 'new_seh_t', 'new_sel_array', 'new_sel_pointer', + 'new_selection_item_t', + 'new_selection_item_t__SWIG_0', + 'new_selection_item_t__SWIG_1', + 'new_selection_item_t__SWIG_2', + 'new_selection_item_t__SWIG_3', 'new_simd_info_t', 'new_simpleline_t', 'new_simpleline_t__SWIG_0', 'new_simpleline_t__SWIG_1', 'new_simpleline_t__SWIG_2', 'new_simpleline_t__SWIG_3', + 'new_sizevec_t', + 'new_sizevec_t__SWIG_0', + 'new_sizevec_t__SWIG_1', 'new_snapshot_t', + 'new_sreg_range_t', 'new_strarray_t', 'new_string_info_t', 'new_string_info_t__SWIG_0', 'new_string_info_t__SWIG_1', + 'new_strpath_ids_array', 'new_strpath_t', 'new_struct_field_visitor_t', 'new_strvec_t', @@ -5007,7 +5014,6 @@ 'new_strwinsetup_t', 'new_sval_pointer', 'new_tev_info_t', - 'new_text_options_t', 'new_text_sink_t', 'new_tid_array', 'new_til', @@ -5018,17 +5024,22 @@ 'new_tinfo_t__SWIG_1', 'new_tinfo_visitor_t', 'new_treeloc_t', + 'new_try_handler_t', + 'new_tryblk_t', + 'new_tryblk_t__SWIG_0', + 'new_tryblk_t__SWIG_1', + 'new_tryblks_t', + 'new_tryblks_t__SWIG_0', + 'new_tryblks_t__SWIG_1', 'new_twinpos_t', 'new_twinpos_t__SWIG_0', 'new_twinpos_t__SWIG_1', 'new_twinpos_t__SWIG_2', 'new_type_attr_t', + 'new_type_attrs_t', + 'new_type_attrs_t__SWIG_0', + 'new_type_attrs_t__SWIG_1', 'new_type_mods_t', - 'new_type_pair_t', - 'new_type_pair_t__SWIG_0', - 'new_type_pair_t__SWIG_1', - 'new_type_pair_t__SWIG_2', - 'new_type_pair_vec_t', 'new_typedef_type_data_t', 'new_typedef_type_data_t__SWIG_0', 'new_typedef_type_data_t__SWIG_1', @@ -5058,14 +5069,8 @@ 'new_uvalvec_t__SWIG_0', 'new_uvalvec_t__SWIG_1', 'new_valstr_t', - 'new_valstrs_deprecated2_t', - 'new_valstrs_deprecated_t', 'new_valstrs_t', 'new_var_ref_t', - 'new_varloc_t', - 'new_varloc_t__SWIG_0', - 'new_varloc_t__SWIG_1', - 'new_varpart_t', 'new_vc_printer_t', 'new_vd_failure_t', 'new_vd_failure_t__SWIG_0', @@ -5077,24 +5082,23 @@ 'new_vd_interr_t__SWIG_1', 'new_vd_printer_t', 'new_vdloc_t', + 'new_view_mouse_event_location_t', + 'new_view_mouse_event_t', 'new_xrefblk_t', 'new_xreflist_entry_t', 'new_xreflist_t', 'new_xreflist_t__SWIG_0', 'new_xreflist_t__SWIG_1', + 'next_addr', + 'next_chunk', 'next_head', + 'next_idcv_attr', 'next_inited', 'next_named_type', 'next_not_tail', + 'next_that', 'next_unknown', - 'nextaddr', - 'nextchunk', - 'nextthat', - 'noImmd', - 'noType', - 'noUsed', - 'noUsed__SWIG_0', - 'noUsed__SWIG_1', + 'node2ea', 'node_info_t_bg_color_get', 'node_info_t_bg_color_set', 'node_info_t_ea_get', @@ -5111,20 +5115,26 @@ 'node_iterator___eq__', 'node_iterator___ne__', 'node_iterator___ref__', + 'node_ordering_t_clear', + 'node_ordering_t_node', + 'node_ordering_t_resize', + 'node_ordering_t_set', + 'node_ordering_t_size', 'nomem', 'nomem__varargs__', 'notify_when', + 'num_flag', 'number_format_t_flags_get', 'number_format_t_flags_set', - 'number_format_t_getRadix', - 'number_format_t_isChar', - 'number_format_t_isDec', - 'number_format_t_isEnum', - 'number_format_t_isHex', - 'number_format_t_isNum', - 'number_format_t_isOct', - 'number_format_t_isStroff', + 'number_format_t_get_radix', + 'number_format_t_is_char', + 'number_format_t_is_dec', + 'number_format_t_is_enum', 'number_format_t_is_fixed', + 'number_format_t_is_hex', + 'number_format_t_is_numop', + 'number_format_t_is_oct', + 'number_format_t_is_stroff', 'number_format_t_needs_to_be_inverted', 'number_format_t_opnum_get', 'number_format_t_opnum_set', @@ -5136,9 +5146,8 @@ 'number_format_t_serial_set', 'number_format_t_type_name_get', 'number_format_t_type_name_set', - 'numflag', - 'octflag', - 'offflag', + 'oct_flag', + 'off_flag', 'op_adds_xrefs', 'op_bin', 'op_chr', @@ -5151,46 +5160,48 @@ 'op_oct', 'op_offset', 'op_offset_ex', + 'op_plain_offset', 'op_seg', 'op_stkvar', 'op_stroff', + 'op_t___get_addr__', + 'op_t___get_reg_phrase__', + 'op_t___get_specval__', + 'op_t___get_value__', + 'op_t___set_addr__', + 'op_t___set_reg_phrase__', + 'op_t___set_specval__', + 'op_t___set_value__', + 'op_t__from_ptrval__', 'op_t_assign', - 'op_t_create', - 'op_t_destroy', - 'op_t_get_addr', - 'op_t_get_dtyp', - 'op_t_get_flags', - 'op_t_get_n', - 'op_t_get_offb', - 'op_t_get_offo', - 'op_t_get_reg_phrase', - 'op_t_get_specflag1', - 'op_t_get_specflag2', - 'op_t_get_specflag3', - 'op_t_get_specflag4', - 'op_t_get_specval', - 'op_t_get_type', - 'op_t_get_value', - 'op_t_set_addr', - 'op_t_set_dtyp', - 'op_t_set_flags', - 'op_t_set_n', - 'op_t_set_offb', - 'op_t_set_offo', - 'op_t_set_reg_phrase', - 'op_t_set_specflag1', - 'op_t_set_specflag2', - 'op_t_set_specflag3', - 'op_t_set_specflag4', - 'op_t_set_specval', - 'op_t_set_type', - 'op_t_set_value', + 'op_t_clr_shown', + 'op_t_dtype_get', + 'op_t_dtype_set', + 'op_t_flags_get', + 'op_t_flags_set', + 'op_t_is_imm', + 'op_t_is_reg', + 'op_t_n_get', + 'op_t_n_set', + 'op_t_offb_get', + 'op_t_offb_set', + 'op_t_offo_get', + 'op_t_offo_set', + 'op_t_set_shown', + 'op_t_shown', + 'op_t_specflag1_get', + 'op_t_specflag1_set', + 'op_t_specflag2_get', + 'op_t_specflag2_set', + 'op_t_specflag3_get', + 'op_t_specflag3_set', + 'op_t_specflag4_get', + 'op_t_specflag4_set', + 'op_t_type_get', + 'op_t_type_set', 'op_uses_x', 'op_uses_y', 'op_uses_z', - 'openM', - 'openR', - 'openRT', 'open_bpts_window', 'open_calls_window', 'open_disasm_window', @@ -5215,7 +5226,6 @@ 'open_stack_window', 'open_strings_window', 'open_structs_window', - 'open_tform', 'open_threads_window', 'open_tils_window', 'open_trace_window', @@ -5232,6 +5242,10 @@ 'operand_locator_t_ea_set', 'operand_locator_t_opnum_get', 'operand_locator_t_opnum_set', + 'operands_array___getitem__', + 'operands_array___len__', + 'operands_array___setitem__', + 'operands_array_data_get', 'operator_info_t_fixtype_get', 'operator_info_t_fixtype_set', 'operator_info_t_flags_get', @@ -5255,53 +5269,125 @@ 'opinfo_t_tid_get', 'opinfo_t_tid_set', 'optimize_argloc', - 'optimize_varloc', - 'out_addr_tag', - 'out_colored_register_line', - 'out_keyword', - 'out_line', - 'out_long', - 'out_name_expr', - 'out_one_operand', - 'out_register', - 'out_symbol', - 'out_tagoff', - 'out_tagon', - 'owrdflag', + 'outctx_base_t__from_ptrval__', + 'outctx_base_t_close_comment', + 'outctx_base_t_clr_gen_label', + 'outctx_base_t_default_lnnum_get', + 'outctx_base_t_default_lnnum_set', + 'outctx_base_t_display_voids', + 'outctx_base_t_flush_buf', + 'outctx_base_t_flush_outbuf', + 'outctx_base_t_forbid_annotations', + 'outctx_base_t_force_code', + 'outctx_base_t_gen_block_cmt', + 'outctx_base_t_gen_border_line', + 'outctx_base_t_gen_cmt_line', + 'outctx_base_t_gen_cmt_line__varargs__', + 'outctx_base_t_gen_collapsed_line', + 'outctx_base_t_gen_collapsed_line__varargs__', + 'outctx_base_t_gen_empty_line', + 'outctx_base_t_gen_empty_line_without_annotations', + 'outctx_base_t_gen_printf', + 'outctx_base_t_gen_printf__varargs__', + 'outctx_base_t_gen_xref_lines', + 'outctx_base_t_get_stkvar', + 'outctx_base_t_init_lines_array', + 'outctx_base_t_insn_ea_get', + 'outctx_base_t_insn_ea_set', + 'outctx_base_t_multiline', + 'outctx_base_t_only_main_line', + 'outctx_base_t_out_addr_tag', + 'outctx_base_t_out_btoa', + 'outctx_base_t_out_char', + 'outctx_base_t_out_chars', + 'outctx_base_t_out_colored_register_line', + 'outctx_base_t_out_keyword', + 'outctx_base_t_out_line', + 'outctx_base_t_out_long', + 'outctx_base_t_out_name_expr', + 'outctx_base_t_out_printf', + 'outctx_base_t_out_printf__varargs__', + 'outctx_base_t_out_register', + 'outctx_base_t_out_spaces', + 'outctx_base_t_out_symbol', + 'outctx_base_t_out_tagoff', + 'outctx_base_t_out_tagon', + 'outctx_base_t_out_value', + 'outctx_base_t_outbuf_get', + 'outctx_base_t_outbuf_set', + 'outctx_base_t_print_label_now', + 'outctx_base_t_restore_ctxflags', + 'outctx_base_t_retrieve_cmt', + 'outctx_base_t_retrieve_name', + 'outctx_base_t_set_comment_addr', + 'outctx_base_t_set_gen_cmt', + 'outctx_base_t_set_gen_demangled_label', + 'outctx_base_t_set_gen_label', + 'outctx_base_t_set_gen_xrefs', + 'outctx_base_t_setup_outctx', + 'outctx_base_t_stack_view', + 'outctx_base_t_term_outctx', + 'outctx_t__from_ptrval__', + 'outctx_t_bin_ea_get', + 'outctx_t_bin_ea_set', + 'outctx_t_bin_state_get', + 'outctx_t_bin_state_set', + 'outctx_t_bin_width_get', + 'outctx_t_bin_width_set', + 'outctx_t_curlabel_get', + 'outctx_t_curlabel_set', + 'outctx_t_gen_func_footer', + 'outctx_t_gen_func_header', + 'outctx_t_gen_header', + 'outctx_t_gen_header_extra', + 'outctx_t_gen_xref_lines', + 'outctx_t_gl_bpsize_get', + 'outctx_t_gl_bpsize_set', + 'outctx_t_insn_get', + 'outctx_t_insn_set', + 'outctx_t_out_custom_mnem', + 'outctx_t_out_data', + 'outctx_t_out_immchar_cmts', + 'outctx_t_out_mnem', + 'outctx_t_out_mnemonic', + 'outctx_t_out_one_operand', + 'outctx_t_out_specea', + 'outctx_t_retrieve_cmt', + 'outctx_t_retrieve_name', + 'outctx_t_setup_outctx', + 'oword_flag', 'pack_idcobj_to_bv', 'pack_idcobj_to_idb', 'pack_object_to_bv', 'pack_object_to_idb', - 'packrealflag', + 'packreal_flag', 'parse_command_line3', 'parse_dbgopts', 'parse_decl', - 'parse_decl2', 'parse_decls', 'parse_reg_name', - 'parse_types2', 'parse_user_call', 'partial_type_num', 'patch_byte', - 'patch_long', - 'patch_many_bytes', + 'patch_bytes', + 'patch_dword', + 'patch_fixup_value', 'patch_qword', 'patch_word', 'peek_auto_queue', 'ph_get_cnbits', 'ph_get_dnbits', 'ph_get_flag', - 'ph_get_high_fixup_bits', 'ph_get_icode_return', 'ph_get_id', 'ph_get_instruc', 'ph_get_instruc_end', 'ph_get_instruc_start', 'ph_get_operand_info', - 'ph_get_regCodeSreg', - 'ph_get_regDataSreg', - 'ph_get_regFirstSreg', - 'ph_get_regLastSreg', + 'ph_get_reg_code_sreg', + 'ph_get_reg_data_sreg', + 'ph_get_reg_first_sreg', + 'ph_get_reg_last_sreg', 'ph_get_regnames', 'ph_get_segreg_size', 'ph_get_tbyte_size', @@ -5330,6 +5416,9 @@ 'place_t_rebase', 'place_t_toea', 'place_t_touval', + 'plan_and_wait', + 'plan_ea', + 'plan_range', 'plan_to_apply_idasgn', 'plgform_close', 'plgform_new', @@ -5356,30 +5445,80 @@ 'plugin_info_t_org_name_set', 'plugin_info_t_path_get', 'plugin_info_t_path_set', + 'point_t___eq__', + 'point_t___ne__', + 'point_t_add', + 'point_t_negate', + 'point_t_sub', + 'point_t_x_get', + 'point_t_x_set', + 'point_t_y_get', + 'point_t_y_set', + 'predicate_t_should_display', + 'prev_addr', + 'prev_chunk', 'prev_head', + 'prev_idcv_attr', 'prev_inited', 'prev_not_tail', + 'prev_that', 'prev_unknown', - 'prevaddr', - 'prevchunk', - 'prevthat', 'print_argloc', - 'print_ascii_string_type', 'print_decls', + 'print_idcv', + 'print_insn_mnem', + 'print_operand', + 'print_strlit_type', 'print_tinfo', 'print_type', - 'print_type2', - 'print_type3', - 'print_type_to_qstring', - 'print_varloc', 'print_vdloc', - 'printf_line', - 'printf_line__varargs__', + 'printop_t_flags_get', + 'printop_t_flags_set', + 'printop_t_get_ti', + 'printop_t_is_ti_valid_get', + 'printop_t_is_ti_valid_set', + 'printop_t_suspop_get', + 'printop_t_suspop_set', + 'printop_t_ti_get', + 'printop_t_ti_set', + 'process_archive', 'process_info_t_name_get', 'process_info_t_name_set', 'process_info_t_pid_get', 'process_info_t_pid_set', 'process_ui_action', + 'procinfo_vec_t___getitem__', + 'procinfo_vec_t___len__', + 'procinfo_vec_t___setitem__', + 'procinfo_vec_t_at', + 'procinfo_vec_t_begin', + 'procinfo_vec_t_begin__SWIG_0', + 'procinfo_vec_t_begin__SWIG_1', + 'procinfo_vec_t_capacity', + 'procinfo_vec_t_clear', + 'procinfo_vec_t_empty', + 'procinfo_vec_t_end', + 'procinfo_vec_t_end__SWIG_0', + 'procinfo_vec_t_end__SWIG_1', + 'procinfo_vec_t_erase', + 'procinfo_vec_t_erase__SWIG_0', + 'procinfo_vec_t_erase__SWIG_1', + 'procinfo_vec_t_extract', + 'procinfo_vec_t_grow', + 'procinfo_vec_t_inject', + 'procinfo_vec_t_insert', + 'procinfo_vec_t_pop_back', + 'procinfo_vec_t_push_back', + 'procinfo_vec_t_push_back__SWIG_0', + 'procinfo_vec_t_push_back__SWIG_1', + 'procinfo_vec_t_qclear', + 'procinfo_vec_t_reserve', + 'procinfo_vec_t_resize', + 'procinfo_vec_t_resize__SWIG_0', + 'procinfo_vec_t_resize__SWIG_1', + 'procinfo_vec_t_size', + 'procinfo_vec_t_swap', + 'procinfo_vec_t_truncate', 'ptr_type_data_t___eq__', 'ptr_type_data_t___ne__', 'ptr_type_data_t_based_ptr_size_get', @@ -5393,25 +5532,22 @@ 'ptr_type_data_t_taptr_bits_get', 'ptr_type_data_t_taptr_bits_set', 'put_byte', + 'put_bytes', 'put_dbg_byte', - 'put_long', - 'put_many_bytes', + 'put_dword', 'put_qword', 'put_word', - 'py_get_AskUsingForm', - 'py_get_OpenForm', + 'py_add_idc_func', + 'py_get_ask_form', 'py_get_call_idc_func', - 'py_get_global_cmd_link', + 'py_get_open_form', 'py_load_custom_icon_data', 'py_load_custom_icon_fn', - 'py_menu_item_callback', 'py_register_compiled_form', - 'py_set_idc_func_ex', 'py_ss_restore_callback', 'py_unregister_compiled_form', - 'pycim_get_tcustom_control', - 'pycim_get_tform', - 'pyg_add_command', + 'pycim_get_widget', + 'pycim_view_close', 'pyg_close', 'pyg_select_node', 'pyg_show', @@ -5428,9 +5564,7 @@ 'pyidag_bind', 'pyidag_unbind', 'pyscv_add_line', - 'pyscv_add_popup_menu', 'pyscv_clear_lines', - 'pyscv_clear_popup_menu', 'pyscv_close', 'pyscv_count', 'pyscv_del_line', @@ -5441,8 +5575,7 @@ 'pyscv_get_line', 'pyscv_get_pos', 'pyscv_get_selection', - 'pyscv_get_tcustom_control', - 'pyscv_get_tform', + 'pyscv_get_widget', 'pyscv_init', 'pyscv_insert_line', 'pyscv_is_focused', @@ -5451,9 +5584,11 @@ 'pyscv_refresh', 'pyscv_refresh_current', 'pyscv_show', + 'pyw_convert_defvals', 'pyw_register_idc_func', 'pyw_unregister_idc_func', 'qatoll', + 'qcleanline', 'qcontrol_tty', 'qdetach_tty', 'qexit', @@ -5506,10 +5641,7 @@ 'qflow_chart_t_succ', 'qflow_chart_t_title_get', 'qflow_chart_t_title_set', - 'qfsize', - 'qfsize64', 'qlgetz', - 'qlgetz64', 'qlist_cinsn_t___eq__', 'qlist_cinsn_t___ne__', 'qlist_cinsn_t_back', @@ -5546,13 +5678,9 @@ 'qlist_cinsn_t_rend__SWIG_1', 'qlist_cinsn_t_size', 'qlist_cinsn_t_swap', - 'qlseek64', - 'qlsize64', - 'qltell64', 'qrefcnt_obj_t_refcnt_get', 'qrefcnt_obj_t_refcnt_set', 'qrefcnt_obj_t_release', - 'qsplitpath', 'qstring_printer_t__print', 'qstring_printer_t__print__varargs__', 'qstring_printer_t_get_s', @@ -5584,9 +5712,6 @@ 'qvector_carg_t__del', 'qvector_carg_t_add_unique', 'qvector_carg_t_at', - 'qvector_carg_t_back', - 'qvector_carg_t_back__SWIG_0', - 'qvector_carg_t_back__SWIG_1', 'qvector_carg_t_begin', 'qvector_carg_t_begin__SWIG_0', 'qvector_carg_t_begin__SWIG_1', @@ -5603,9 +5728,6 @@ 'qvector_carg_t_find', 'qvector_carg_t_find__SWIG_0', 'qvector_carg_t_find__SWIG_1', - 'qvector_carg_t_front', - 'qvector_carg_t_front__SWIG_0', - 'qvector_carg_t_front__SWIG_1', 'qvector_carg_t_grow', 'qvector_carg_t_has', 'qvector_carg_t_inject', @@ -5630,9 +5752,6 @@ 'qvector_ccase_t__del', 'qvector_ccase_t_add_unique', 'qvector_ccase_t_at', - 'qvector_ccase_t_back', - 'qvector_ccase_t_back__SWIG_0', - 'qvector_ccase_t_back__SWIG_1', 'qvector_ccase_t_begin', 'qvector_ccase_t_begin__SWIG_0', 'qvector_ccase_t_begin__SWIG_1', @@ -5649,9 +5768,6 @@ 'qvector_ccase_t_find', 'qvector_ccase_t_find__SWIG_0', 'qvector_ccase_t_find__SWIG_1', - 'qvector_ccase_t_front', - 'qvector_ccase_t_front__SWIG_0', - 'qvector_ccase_t_front__SWIG_1', 'qvector_ccase_t_grow', 'qvector_ccase_t_has', 'qvector_ccase_t_inject', @@ -5676,9 +5792,6 @@ 'qvector_history_t__del', 'qvector_history_t_add_unique', 'qvector_history_t_at', - 'qvector_history_t_back', - 'qvector_history_t_back__SWIG_0', - 'qvector_history_t_back__SWIG_1', 'qvector_history_t_begin', 'qvector_history_t_begin__SWIG_0', 'qvector_history_t_begin__SWIG_1', @@ -5695,9 +5808,6 @@ 'qvector_history_t_find', 'qvector_history_t_find__SWIG_0', 'qvector_history_t_find__SWIG_1', - 'qvector_history_t_front', - 'qvector_history_t_front__SWIG_0', - 'qvector_history_t_front__SWIG_1', 'qvector_history_t_grow', 'qvector_history_t_has', 'qvector_history_t_inject', @@ -5722,9 +5832,6 @@ 'qvector_lvar_t__del', 'qvector_lvar_t_add_unique', 'qvector_lvar_t_at', - 'qvector_lvar_t_back', - 'qvector_lvar_t_back__SWIG_0', - 'qvector_lvar_t_back__SWIG_1', 'qvector_lvar_t_begin', 'qvector_lvar_t_begin__SWIG_0', 'qvector_lvar_t_begin__SWIG_1', @@ -5741,9 +5848,6 @@ 'qvector_lvar_t_find', 'qvector_lvar_t_find__SWIG_0', 'qvector_lvar_t_find__SWIG_1', - 'qvector_lvar_t_front', - 'qvector_lvar_t_front__SWIG_0', - 'qvector_lvar_t_front__SWIG_1', 'qvector_lvar_t_grow', 'qvector_lvar_t_has', 'qvector_lvar_t_inject', @@ -5769,9 +5873,6 @@ 'qvector_snapshotvec_t__del', 'qvector_snapshotvec_t_add_unique', 'qvector_snapshotvec_t_at', - 'qvector_snapshotvec_t_back', - 'qvector_snapshotvec_t_back__SWIG_0', - 'qvector_snapshotvec_t_back__SWIG_1', 'qvector_snapshotvec_t_begin', 'qvector_snapshotvec_t_begin__SWIG_0', 'qvector_snapshotvec_t_begin__SWIG_1', @@ -5788,9 +5889,6 @@ 'qvector_snapshotvec_t_find', 'qvector_snapshotvec_t_find__SWIG_0', 'qvector_snapshotvec_t_find__SWIG_1', - 'qvector_snapshotvec_t_front', - 'qvector_snapshotvec_t_front__SWIG_0', - 'qvector_snapshotvec_t_front__SWIG_1', 'qvector_snapshotvec_t_has', 'qvector_snapshotvec_t_inject', 'qvector_snapshotvec_t_insert', @@ -5806,19 +5904,142 @@ 'qvector_snapshotvec_t_size', 'qvector_snapshotvec_t_swap', 'qvector_snapshotvec_t_truncate', - 'qwait_timed', - 'qwrdflag', + 'qword_flag', + 'range_t___eq__', + 'range_t___gt__', + 'range_t___lt__', + 'range_t___ne__', + 'range_t__print', + 'range_t_clear', + 'range_t_compare', + 'range_t_contains', + 'range_t_contains__SWIG_0', + 'range_t_contains__SWIG_1', + 'range_t_empty', + 'range_t_end_ea_get', + 'range_t_end_ea_set', + 'range_t_extend', + 'range_t_intersect', + 'range_t_overlaps', + 'range_t_print', + 'range_t_size', + 'range_t_start_ea_get', + 'range_t_start_ea_set', + 'rangeset_t___eq__', + 'rangeset_t___ne__', + 'rangeset_t__print', + 'rangeset_t_add', + 'rangeset_t_add__SWIG_0', + 'rangeset_t_add__SWIG_1', + 'rangeset_t_add__SWIG_2', + 'rangeset_t_begin', + 'rangeset_t_begin__SWIG_0', + 'rangeset_t_begin__SWIG_1', + 'rangeset_t_cached_range', + 'rangeset_t_clear', + 'rangeset_t_contains', + 'rangeset_t_contains__SWIG_0', + 'rangeset_t_contains__SWIG_1', + 'rangeset_t_empty', + 'rangeset_t_end', + 'rangeset_t_end__SWIG_0', + 'rangeset_t_end__SWIG_1', + 'rangeset_t_find_range', + 'rangeset_t_getrange', + 'rangeset_t_has_common', + 'rangeset_t_has_common__SWIG_0', + 'rangeset_t_has_common__SWIG_1', + 'rangeset_t_includes', + 'rangeset_t_intersect', + 'rangeset_t_is_equal', + 'rangeset_t_is_subset_of', + 'rangeset_t_lastrange', + 'rangeset_t_next_addr', + 'rangeset_t_next_range', + 'rangeset_t_nranges', + 'rangeset_t_prev_addr', + 'rangeset_t_prev_range', + 'rangeset_t_sub', + 'rangeset_t_sub__SWIG_0', + 'rangeset_t_sub__SWIG_1', + 'rangeset_t_sub__SWIG_2', + 'rangeset_t_swap', + 'rangevec_base_t___eq__', + 'rangevec_base_t___getitem__', + 'rangevec_base_t___len__', + 'rangevec_base_t___ne__', + 'rangevec_base_t___setitem__', + 'rangevec_base_t__del', + 'rangevec_base_t_add_unique', + 'rangevec_base_t_at', + 'rangevec_base_t_begin', + 'rangevec_base_t_begin__SWIG_0', + 'rangevec_base_t_begin__SWIG_1', + 'rangevec_base_t_capacity', + 'rangevec_base_t_clear', + 'rangevec_base_t_empty', + 'rangevec_base_t_end', + 'rangevec_base_t_end__SWIG_0', + 'rangevec_base_t_end__SWIG_1', + 'rangevec_base_t_erase', + 'rangevec_base_t_erase__SWIG_0', + 'rangevec_base_t_erase__SWIG_1', + 'rangevec_base_t_extract', + 'rangevec_base_t_find', + 'rangevec_base_t_find__SWIG_0', + 'rangevec_base_t_find__SWIG_1', + 'rangevec_base_t_grow', + 'rangevec_base_t_has', + 'rangevec_base_t_inject', + 'rangevec_base_t_insert', + 'rangevec_base_t_pop_back', + 'rangevec_base_t_push_back', + 'rangevec_base_t_push_back__SWIG_0', + 'rangevec_base_t_push_back__SWIG_1', + 'rangevec_base_t_qclear', + 'rangevec_base_t_reserve', + 'rangevec_base_t_resize', + 'rangevec_base_t_resize__SWIG_0', + 'rangevec_base_t_resize__SWIG_1', + 'rangevec_base_t_size', + 'rangevec_base_t_swap', + 'rangevec_base_t_truncate', 'read_dbg_memory', + 'read_range_selection', 'read_regargs', 'read_selection', 'read_tinfo_bitfield_value', 'readbytes', - 'readsel2', 'reanalyze_callers', 'reanalyze_function', + 'reanalyze_noret_flag', 'rebase_program', 'rebuild_nlist', 'recalc_spd', + 'rect_t___eq__', + 'rect_t___ne__', + 'rect_t_area', + 'rect_t_bottom_get', + 'rect_t_bottom_set', + 'rect_t_bottomright', + 'rect_t_center', + 'rect_t_contains', + 'rect_t_empty', + 'rect_t_grow', + 'rect_t_height', + 'rect_t_intersect', + 'rect_t_is_intersection_empty', + 'rect_t_left_get', + 'rect_t_left_set', + 'rect_t_make_union', + 'rect_t_move_by', + 'rect_t_move_to', + 'rect_t_right_get', + 'rect_t_right_set', + 'rect_t_top_get', + 'rect_t_top_set', + 'rect_t_topleft', + 'rect_t_width', 'refinfo_t_base_get', 'refinfo_t_base_set', 'refinfo_t_flags_get', @@ -5829,6 +6050,7 @@ 'refinfo_t_is_rvaoff', 'refinfo_t_is_signed', 'refinfo_t_is_subtract', + 'refinfo_t_is_target_optional', 'refinfo_t_no_base_xref', 'refinfo_t_set_type', 'refinfo_t_target_get', @@ -5837,12 +6059,12 @@ 'refinfo_t_tdelta_set', 'refinfo_t_type', 'refresh_chooser', + 'refresh_choosers', 'refresh_debugger_memory', 'refresh_idaview', 'refresh_idaview_anyway', - 'refresh_lists', 'refresh_navband', - 'refresh_strlist', + 'refresh_viewer', 'reg_data_type', 'reg_delete', 'reg_delete_subkey', @@ -5889,9 +6111,6 @@ 'reginfovec_t__del', 'reginfovec_t_add_unique', 'reginfovec_t_at', - 'reginfovec_t_back', - 'reginfovec_t_back__SWIG_0', - 'reginfovec_t_back__SWIG_1', 'reginfovec_t_begin', 'reginfovec_t_begin__SWIG_0', 'reginfovec_t_begin__SWIG_1', @@ -5908,9 +6127,6 @@ 'reginfovec_t_find', 'reginfovec_t_find__SWIG_0', 'reginfovec_t_find__SWIG_1', - 'reginfovec_t_front', - 'reginfovec_t_front__SWIG_0', - 'reginfovec_t_front__SWIG_1', 'reginfovec_t_grow', 'reginfovec_t_has', 'reginfovec_t_inject', @@ -5978,17 +6194,25 @@ 'reload_file', 'reloc_value', 'relocate_relobj', + 'remember_problem', + 'remove_abi_opts', 'remove_command_interpreter', - 'remove_extlang', 'remove_func_tail', 'remove_hexrays_callback', 'remove_pointer', 'remove_tinfo_pointer', - 'remove_type_pointer', 'rename_bptgrp', + 'rename_encoding', 'rename_entry', - 'rename_named_type', 'rename_regvar', + 'renderer_info_pos_t___eq__', + 'renderer_info_pos_t___ne__', + 'renderer_info_pos_t_cx_get', + 'renderer_info_pos_t_cx_set', + 'renderer_info_pos_t_cy_get', + 'renderer_info_pos_t_cy_set', + 'renderer_info_pos_t_node_get', + 'renderer_info_pos_t_node_set', 'renderer_info_t___eq__', 'renderer_info_t___ne__', 'renderer_info_t_clear', @@ -6010,9 +6234,6 @@ 'renderer_pos_info_t_sx_set', 'reorder_dummy_names', 'repaint_custom_viewer', - 'replace_subtypes', - 'replace_subtypes2', - 'replace_tabs', 'replace_wait_box', 'replace_wait_box__varargs__', 'request_add_bpt', @@ -6049,8 +6270,7 @@ 'request_step_until_ret', 'request_suspend_process', 'request_suspend_thread', - 'resolve_complex_type2', - 'resolve_typedef2', + 'resolve_typedef', 'restore_database_snapshot', 'restore_user_cmts', 'restore_user_defined_calls', @@ -6066,19 +6286,24 @@ 'retrieve_input_file_sha256', 'retrieve_input_file_size', 'retrieve_member_info', + 'revert_byte', 'revert_ida_decisions', + 'row_info_t_bottom_get', + 'row_info_t_bottom_set', + 'row_info_t_height', + 'row_info_t_nodes_get', + 'row_info_t_nodes_set', + 'row_info_t_top_get', + 'row_info_t_top_set', 'rrel_t_off_get', 'rrel_t_off_set', 'rrel_t_reg_get', 'rrel_t_reg_set', 'run_plugin', 'run_requests', - 'run_statements', 'run_to', 'save_database', - 'save_database_ex', 'save_struc', - 'save_struc2', 'save_tinfo', 'save_trace_file', 'save_user_cmts', @@ -6088,10 +6313,21 @@ 'save_user_lvar_settings', 'save_user_numforms', 'save_user_unions', + 'scattered_segm_t_name_get', + 'scattered_segm_t_name_set', 'score_tinfo', - 'scr2idb', + 'screen_graph_selection_t_add', + 'screen_graph_selection_t_add_node', + 'screen_graph_selection_t_add_point', + 'screen_graph_selection_t_del_node', + 'screen_graph_selection_t_del_point', + 'screen_graph_selection_t_has', + 'screen_graph_selection_t_items_count', + 'screen_graph_selection_t_nodes_count', + 'screen_graph_selection_t_points_count', + 'screen_graph_selection_t_sub', 'search_down', - 'segflag', + 'seg_flag', 'segm_adjust_diff', 'segm_adjust_ea', 'segm_move_info_t___eq__', @@ -6110,9 +6346,6 @@ 'segm_move_info_vec_t__del', 'segm_move_info_vec_t_add_unique', 'segm_move_info_vec_t_at', - 'segm_move_info_vec_t_back', - 'segm_move_info_vec_t_back__SWIG_0', - 'segm_move_info_vec_t_back__SWIG_1', 'segm_move_info_vec_t_begin', 'segm_move_info_vec_t_begin__SWIG_0', 'segm_move_info_vec_t_begin__SWIG_1', @@ -6129,9 +6362,6 @@ 'segm_move_info_vec_t_find', 'segm_move_info_vec_t_find__SWIG_0', 'segm_move_info_vec_t_find__SWIG_1', - 'segm_move_info_vec_t_front', - 'segm_move_info_vec_t_front__SWIG_0', - 'segm_move_info_vec_t_front__SWIG_1', 'segm_move_info_vec_t_grow', 'segm_move_info_vec_t_has', 'segm_move_info_vec_t_inject', @@ -6164,8 +6394,8 @@ 'segment_t_comorg', 'segment_t_defsr_get', 'segment_t_defsr_set', - 'segment_t_endEA_get', - 'segment_t_endEA_set', + 'segment_t_end_ea_get', + 'segment_t_end_ea_set', 'segment_t_flags_get', 'segment_t_flags_set', 'segment_t_is_hidden_segtype', @@ -6188,24 +6418,21 @@ 'segment_t_set_loader_segm', 'segment_t_set_ob_ok', 'segment_t_set_visible_segm', - 'segment_t_startEA_get', - 'segment_t_startEA_set', + 'segment_t_start_ea_get', + 'segment_t_start_ea_set', 'segment_t_type_get', 'segment_t_type_set', 'segment_t_update', 'segment_t_use32', 'segment_t_use64', - 'segreg_area_t_tag_get', - 'segreg_area_t_tag_set', - 'segreg_area_t_val_get', - 'segreg_area_t_val_set', - 'segreg_t_reg', - 'segreg_t_setregs', - 'segreg_t_settags', - 'segreg_t_tag', - 'segreg_t_undefregs', 'segtype', + 'seh_t_clear', + 'seh_t_filter_get', + 'seh_t_filter_set', + 'seh_t_seh_code_get', + 'seh_t_seh_code_set', 'sel2ea', + 'sel2para', 'sel_array___getitem__', 'sel_array___setitem__', 'sel_array_cast', @@ -6214,13 +6441,19 @@ 'sel_pointer_cast', 'sel_pointer_frompointer', 'sel_pointer_value', - 'select_extlang', 'select_thread', + 'selection_item_t___eq__', + 'selection_item_t___lt__', + 'selection_item_t___ne__', + 'selection_item_t_compare', + 'selection_item_t_elp_get', + 'selection_item_t_elp_set', + 'selection_item_t_is_node_get', + 'selection_item_t_is_node_set', + 'selection_item_t_node_get', + 'selection_item_t_node_set', 'send_database', 'serialize_tinfo', - 'setBreak', - 'setFlags', - 'setStat', 'set__bnot0', 'set__bnot1', 'set__invsign0', @@ -6231,9 +6464,10 @@ 'set_aflags', 'set_align_flow', 'set_alignment', + 'set_archive_path', 'set_array_parameters', 'set_asm_inc_file', - 'set_auto_plugins', + 'set_auto_state', 'set_bblk_trace_options', 'set_bmask_cmt', 'set_bmask_name', @@ -6242,6 +6476,7 @@ 'set_bptloc_string', 'set_c_header_path', 'set_c_macros', + 'set_cancelled', 'set_cmt', 'set_code_viewer_handler', 'set_code_viewer_is_source', @@ -6252,14 +6487,12 @@ 'set_code_viewer_user_data', 'set_colored_item', 'set_compiler', - 'set_compiler2', 'set_compiler_id', - 'set_complex_n', - 'set_const_cmt', - 'set_const_name', + 'set_compiler_string', + 'set_cp_validity', 'set_custom_data_type_ids', - 'set_custom_fixup_ex', 'set_custom_viewer_qt_aware', + 'set_database_flag', 'set_dbg_default_options', 'set_dbg_options', 'set_dbg_options__SWIG_0', @@ -6269,7 +6502,7 @@ 'set_debugger_options', 'set_default_dataseg', 'set_default_encoding_idx', - 'set_default_segreg_value', + 'set_default_sreg_value', 'set_defsr', 'set_dock_pos', 'set_dummy_name', @@ -6288,25 +6521,31 @@ 'set_enum_width', 'set_fixed_spd', 'set_fixup', - 'set_fixup_ex', 'set_forced_operand', 'set_frame_size', 'set_func_cmt', + 'set_func_end', 'set_func_name_if_jumpfunc', + 'set_func_start', 'set_func_trace_options', + 'set_gotea', 'set_group_selector', 'set_has_lname', 'set_has_ti', 'set_has_ti0', 'set_has_ti1', 'set_header_path', + 'set_highlight', 'set_highlight_trace_options', + 'set_ida_state', + 'set_idcv_attr', + 'set_idcv_slice', 'set_ids_modnode', 'set_imagebase', + 'set_immd', 'set_insn_trace_options', 'set_int_dbg_options', 'set_item_color', - 'set_jumptable_info', 'set_libitem', 'set_lzero', 'set_lzero0', @@ -6314,26 +6553,20 @@ 'set_manual_insn', 'set_member_cmt', 'set_member_name', - 'set_member_ti', 'set_member_tinfo', - 'set_member_tinfo2', 'set_member_type', - 'set_menu_item_icon', 'set_name', - 'set_name__SWIG_0', - 'set_name__SWIG_1', - 'set_named_type64', 'set_nav_colorizer', 'set_node_info', - 'set_node_info2', 'set_noret', 'set_noret_insn', 'set_notcode', + 'set_notproc', 'set_numbered_type', - 'set_offset', - 'set_op_tinfo2', + 'set_op_tinfo', 'set_op_type', 'set_opinfo', + 'set_path', 'set_process_options', 'set_process_state', 'set_processor_type', @@ -6348,37 +6581,33 @@ 'set_resume_mode', 'set_retfp', 'set_root_filename', - 'set_scattered_varloc', 'set_script_timeout', 'set_segm_addressing', 'set_segm_base', 'set_segm_class', 'set_segm_end', 'set_segm_name', - 'set_segm_name__varargs__', 'set_segm_start', 'set_segment_cmt', 'set_segment_translations', 'set_selector', 'set_source_linnum', - 'set_spoils', 'set_sreg_at_next_code', 'set_step_trace_options', - 'set_strlist_options', + 'set_str_type', 'set_struc_align', 'set_struc_cmt', 'set_struc_hidden', 'set_struc_idx', 'set_struc_listed', 'set_struc_name', - 'set_switch_info_ex', + 'set_switch_info', 'set_switch_parent', 'set_tail_owner', 'set_target_assembler', 'set_terse_struc', 'set_tilcmt', 'set_tinfo', - 'set_tinfo2', 'set_tinfo_attr', 'set_tinfo_attrs', 'set_tinfo_property', @@ -6388,12 +6617,12 @@ 'set_trace_size', 'set_type', 'set_type_alias', - 'set_typeinfo', 'set_usemodsp', 'set_user_defined_prefix', 'set_usersp', 'set_userti', 'set_view_renderer_type', + 'set_viewer_graph', 'set_visible_func', 'set_visible_item', 'set_visible_segm', @@ -6401,12 +6630,12 @@ 'setup_selector', 'should_create_stkvars', 'should_trace_sp', - 'showAddr', - 'showAllComments', - 'showAuto', - 'showComments', - 'showRepeatables', + 'show_addr', + 'show_all_comments', + 'show_auto', + 'show_comments', 'show_name', + 'show_repeatables', 'show_wait_box', 'show_wait_box__varargs__', 'simd_info_t_match_pattern', @@ -6427,8 +6656,46 @@ 'simpleline_t_line_get', 'simpleline_t_line_set', 'sizeof_ldbl', - 'skip_spoiled_info', - 'skip_varloc', + 'sizevec_t___eq__', + 'sizevec_t___getitem__', + 'sizevec_t___len__', + 'sizevec_t___ne__', + 'sizevec_t___setitem__', + 'sizevec_t__del', + 'sizevec_t_add_unique', + 'sizevec_t_at', + 'sizevec_t_begin', + 'sizevec_t_begin__SWIG_0', + 'sizevec_t_begin__SWIG_1', + 'sizevec_t_capacity', + 'sizevec_t_clear', + 'sizevec_t_empty', + 'sizevec_t_end', + 'sizevec_t_end__SWIG_0', + 'sizevec_t_end__SWIG_1', + 'sizevec_t_erase', + 'sizevec_t_erase__SWIG_0', + 'sizevec_t_erase__SWIG_1', + 'sizevec_t_extract', + 'sizevec_t_find', + 'sizevec_t_find__SWIG_0', + 'sizevec_t_find__SWIG_1', + 'sizevec_t_grow', + 'sizevec_t_has', + 'sizevec_t_inject', + 'sizevec_t_insert', + 'sizevec_t_pop_back', + 'sizevec_t_push_back', + 'sizevec_t_push_back__SWIG_0', + 'sizevec_t_push_back__SWIG_1', + 'sizevec_t_qclear', + 'sizevec_t_reserve', + 'sizevec_t_resize', + 'sizevec_t_resize__SWIG_0', + 'sizevec_t_resize__SWIG_1', + 'sizevec_t_size', + 'sizevec_t_swap', + 'sizevec_t_truncate', 'snapshot_t___eq__', 'snapshot_t___ge__', 'snapshot_t___gt__', @@ -6446,21 +6713,21 @@ 'snapshot_t_flags_set', 'snapshot_t_id_get', 'snapshot_t_id_set', - 'splitSRarea1', - 'split_old_argloc', - 'split_srarea', + 'split_sreg_range', + 'sreg_range_t_tag_get', + 'sreg_range_t_tag_set', + 'sreg_range_t_val_get', + 'sreg_range_t_val_set', 'start_process', - 'std_gen_func_header', - 'std_gen_segm_footer', + 'std_out_segm_footer', 'step_into', 'step_over', 'step_until_ret', - 'stkvarflag', + 'stkvar_flag', 'store_exceptions', 'store_til', 'str2ea', 'str2reg', - 'str2regf', 'str2user', 'strarray', 'strarray_t_code_get', @@ -6474,9 +6741,13 @@ 'string_info_t_length_set', 'string_info_t_type_get', 'string_info_t_type_set', - 'strlwr', + 'strlit_flag', 'stroff_as_size', - 'stroffflag', + 'stroff_flag', + 'strpath_ids_array___getitem__', + 'strpath_ids_array___len__', + 'strpath_ids_array___setitem__', + 'strpath_ids_array_data_get', 'strpath_t___getIds', 'strpath_t_delta_get', 'strpath_t_delta_set', @@ -6484,6 +6755,7 @@ 'strpath_t_ids_set', 'strpath_t_len_get', 'strpath_t_len_set', + 'stru_flag', 'struc_t_age_get', 'struc_t_age_set', 'struc_t_from_til', @@ -6493,6 +6765,7 @@ 'struc_t_id_get', 'struc_t_id_set', 'struc_t_is_choosable', + 'struc_t_is_frame', 'struc_t_is_ghost', 'struc_t_is_hidden', 'struc_t_is_union', @@ -6512,15 +6785,10 @@ 'structplace_t_idx_set', 'structplace_t_offset_get', 'structplace_t_offset_set', - 'struflag', - 'strupr', 'strvec_t___getitem__', 'strvec_t___len__', 'strvec_t___setitem__', 'strvec_t_at', - 'strvec_t_back', - 'strvec_t_back__SWIG_0', - 'strvec_t_back__SWIG_1', 'strvec_t_begin', 'strvec_t_begin__SWIG_0', 'strvec_t_begin__SWIG_1', @@ -6534,9 +6802,6 @@ 'strvec_t_erase__SWIG_0', 'strvec_t_erase__SWIG_1', 'strvec_t_extract', - 'strvec_t_front', - 'strvec_t_front__SWIG_0', - 'strvec_t_front__SWIG_1', 'strvec_t_grow', 'strvec_t_inject', 'strvec_t_insert', @@ -6552,12 +6817,10 @@ 'strvec_t_size', 'strvec_t_swap', 'strvec_t_truncate', + 'strwinsetup_t__get_strtypes', + 'strwinsetup_t__set_strtypes', 'strwinsetup_t_display_only_existing_strings_get', 'strwinsetup_t_display_only_existing_strings_set', - 'strwinsetup_t_ea1_get', - 'strwinsetup_t_ea1_set', - 'strwinsetup_t_ea2_get', - 'strwinsetup_t_ea2_set', 'strwinsetup_t_ignore_heads_get', 'strwinsetup_t_ignore_heads_set', 'strwinsetup_t_is_initialized', @@ -6565,44 +6828,40 @@ 'strwinsetup_t_minlen_set', 'strwinsetup_t_only_7bit_get', 'strwinsetup_t_only_7bit_set', - 'strwinsetup_t_strtypes_get', - 'strwinsetup_t_strtypes_set', 'suspend_process', 'suspend_thread', 'sval_pointer_assign', 'sval_pointer_cast', 'sval_pointer_frompointer', 'sval_pointer_value', - 'switch_info_ex_t_assign', - 'switch_info_ex_t_create', - 'switch_info_ex_t_destroy', - 'switch_info_ex_t_get_custom', - 'switch_info_ex_t_get_defjump', - 'switch_info_ex_t_get_elbase', - 'switch_info_ex_t_get_flags', - 'switch_info_ex_t_get_flags2', - 'switch_info_ex_t_get_ind_lowcase', - 'switch_info_ex_t_get_jcases', - 'switch_info_ex_t_get_jumps', - 'switch_info_ex_t_get_ncases', - 'switch_info_ex_t_get_regdtyp', - 'switch_info_ex_t_get_regnum', - 'switch_info_ex_t_get_startea', - 'switch_info_ex_t_get_values_lowcase', - 'switch_info_ex_t_set_custom', - 'switch_info_ex_t_set_defjump', - 'switch_info_ex_t_set_elbase', - 'switch_info_ex_t_set_flags', - 'switch_info_ex_t_set_flags2', - 'switch_info_ex_t_set_ind_lowcase', - 'switch_info_ex_t_set_jcases', - 'switch_info_ex_t_set_jumps', - 'switch_info_ex_t_set_ncases', - 'switch_info_ex_t_set_regdtyp', - 'switch_info_ex_t_set_regnum', - 'switch_info_ex_t_set_startea', - 'switch_info_ex_t_set_values_lowcase', - 'switchto_tform', + 'swap_idcvs', + 'switch_info_t_assign', + 'switch_info_t_create', + 'switch_info_t_destroy', + 'switch_info_t_get_custom', + 'switch_info_t_get_defjump', + 'switch_info_t_get_elbase', + 'switch_info_t_get_flags', + 'switch_info_t_get_ind_lowcase', + 'switch_info_t_get_jcases', + 'switch_info_t_get_jumps', + 'switch_info_t_get_ncases', + 'switch_info_t_get_regdtype', + 'switch_info_t_get_regnum', + 'switch_info_t_get_startea', + 'switch_info_t_get_values_lowcase', + 'switch_info_t_set_custom', + 'switch_info_t_set_defjump', + 'switch_info_t_set_elbase', + 'switch_info_t_set_flags', + 'switch_info_t_set_ind_lowcase', + 'switch_info_t_set_jcases', + 'switch_info_t_set_jumps', + 'switch_info_t_set_ncases', + 'switch_info_t_set_regdtype', + 'switch_info_t_set_regnum', + 'switch_info_t_set_startea', + 'switch_info_t_set_values_lowcase', 'tag_addr', 'tag_advance', 'tag_remove', @@ -6611,21 +6870,14 @@ 'tag_strlen', 'take_database_snapshot', 'take_memory_snapshot', - 'tbytflag', + 'tbyte_flag', 'term_hexrays_plugin', - 'term_output_buffer', 'tev_info_t_ea_get', 'tev_info_t_ea_set', 'tev_info_t_tid_get', 'tev_info_t_tid_set', 'tev_info_t_type_get', 'tev_info_t_type_set', - 'text_options_t_copy_from_inf', - 'text_options_t_copy_to_inf', - 'text_options_t_graph_get', - 'text_options_t_graph_set', - 'text_options_t_text_get', - 'text_options_t_text_set', 'text_sink_t__print', 'textctrl_info_t_assign', 'textctrl_info_t_create', @@ -6642,7 +6894,6 @@ 'tid_array___setitem__', 'tid_array_cast', 'tid_array_frompointer', - 'til2idb', 'til_symbol_t_name_get', 'til_symbol_t_name_set', 'til_symbol_t_til_get', @@ -6772,6 +7023,7 @@ 'tinfo_t_is_decl_float', 'tinfo_t_is_decl_floating', 'tinfo_t_is_decl_func', + 'tinfo_t_is_decl_int', 'tinfo_t_is_decl_int128', 'tinfo_t_is_decl_int16', 'tinfo_t_is_decl_int32', @@ -6807,6 +7059,7 @@ 'tinfo_t_is_func', 'tinfo_t_is_funcptr', 'tinfo_t_is_high_func', + 'tinfo_t_is_int', 'tinfo_t_is_int128', 'tinfo_t_is_int16', 'tinfo_t_is_int32', @@ -6854,6 +7107,7 @@ 'tinfo_t_set_modifiers', 'tinfo_t_set_named_type', 'tinfo_t_set_numbered_type', + 'tinfo_t_set_symbol_type', 'tinfo_t_set_volatile', 'tinfo_t_swap', 'tinfo_t_write_bitfield_value', @@ -6862,7 +7116,7 @@ 'tinfo_visitor_t_state_get', 'tinfo_visitor_t_state_set', 'tinfo_visitor_t_visit_type', - 'toEA', + 'to_ea', 'toggle_bnot', 'toggle_lzero', 'toggle_sign', @@ -6872,19 +7126,107 @@ 'treeloc_t_ea_set', 'treeloc_t_itp_get', 'treeloc_t_itp_set', - 'tribyteflag', + 'try_handler_t_clear', + 'try_handler_t_disp_get', + 'try_handler_t_disp_set', + 'try_handler_t_fpreg_get', + 'try_handler_t_fpreg_set', 'try_to_add_libfunc', + 'tryblk_t_clear', + 'tryblk_t_cpp', + 'tryblk_t_empty', + 'tryblk_t_get_kind', + 'tryblk_t_is_cpp', + 'tryblk_t_is_seh', + 'tryblk_t_level_get', + 'tryblk_t_level_set', + 'tryblk_t_seh', + 'tryblk_t_set_cpp', + 'tryblk_t_set_seh', + 'tryblks_t___eq__', + 'tryblks_t___getitem__', + 'tryblks_t___len__', + 'tryblks_t___ne__', + 'tryblks_t___setitem__', + 'tryblks_t__del', + 'tryblks_t_add_unique', + 'tryblks_t_at', + 'tryblks_t_begin', + 'tryblks_t_begin__SWIG_0', + 'tryblks_t_begin__SWIG_1', + 'tryblks_t_capacity', + 'tryblks_t_clear', + 'tryblks_t_empty', + 'tryblks_t_end', + 'tryblks_t_end__SWIG_0', + 'tryblks_t_end__SWIG_1', + 'tryblks_t_erase', + 'tryblks_t_erase__SWIG_0', + 'tryblks_t_erase__SWIG_1', + 'tryblks_t_extract', + 'tryblks_t_find', + 'tryblks_t_find__SWIG_0', + 'tryblks_t_find__SWIG_1', + 'tryblks_t_grow', + 'tryblks_t_has', + 'tryblks_t_inject', + 'tryblks_t_insert', + 'tryblks_t_pop_back', + 'tryblks_t_push_back', + 'tryblks_t_push_back__SWIG_0', + 'tryblks_t_push_back__SWIG_1', + 'tryblks_t_qclear', + 'tryblks_t_reserve', + 'tryblks_t_resize', + 'tryblks_t_resize__SWIG_0', + 'tryblks_t_resize__SWIG_1', + 'tryblks_t_size', + 'tryblks_t_swap', + 'tryblks_t_truncate', 'twinpos_t___eq__', 'twinpos_t___ne__', 'twinpos_t_at_get', 'twinpos_t_at_set', 'twinpos_t_x_get', 'twinpos_t_x_set', + 'type_attr_t___ge__', + 'type_attr_t___lt__', 'type_attr_t_key_get', 'type_attr_t_key_set', 'type_attr_t_value_get', 'type_attr_t_value_set', - 'type_mapper_t_map_type', + 'type_attrs_t___getitem__', + 'type_attrs_t___len__', + 'type_attrs_t___setitem__', + 'type_attrs_t_at', + 'type_attrs_t_begin', + 'type_attrs_t_begin__SWIG_0', + 'type_attrs_t_begin__SWIG_1', + 'type_attrs_t_capacity', + 'type_attrs_t_clear', + 'type_attrs_t_empty', + 'type_attrs_t_end', + 'type_attrs_t_end__SWIG_0', + 'type_attrs_t_end__SWIG_1', + 'type_attrs_t_erase', + 'type_attrs_t_erase__SWIG_0', + 'type_attrs_t_erase__SWIG_1', + 'type_attrs_t_extract', + 'type_attrs_t_grow', + 'type_attrs_t_inject', + 'type_attrs_t_insert', + 'type_attrs_t_pop_back', + 'type_attrs_t_push_back', + 'type_attrs_t_push_back__SWIG_0', + 'type_attrs_t_push_back__SWIG_1', + 'type_attrs_t_qclear', + 'type_attrs_t_reserve', + 'type_attrs_t_resize', + 'type_attrs_t_resize__SWIG_0', + 'type_attrs_t_resize__SWIG_1', + 'type_attrs_t_size', + 'type_attrs_t_swap', + 'type_attrs_t_truncate', 'type_mods_t_clear', 'type_mods_t_cmt_get', 'type_mods_t_cmt_set', @@ -6901,11 +7243,6 @@ 'type_mods_t_set_new_type', 'type_mods_t_type_get', 'type_mods_t_type_set', - 'type_pair_t_type1_get', - 'type_pair_t_type1_set', - 'type_pair_t_type2_get', - 'type_pair_t_type2_set', - 'type_visitor_t_visit_type', 'typedef_type_data_t_is_ordref_get', 'typedef_type_data_t_is_ordref_set', 'typedef_type_data_t_resolve_get', @@ -6913,22 +7250,6 @@ 'typedef_type_data_t_swap', 'typedef_type_data_t_til_get', 'typedef_type_data_t_til_set', - 'ua_add_cref', - 'ua_add_dref', - 'ua_add_off_drefs', - 'ua_add_off_drefs2', - 'ua_ana0', - 'ua_code', - 'ua_dodata', - 'ua_dodata2', - 'ua_mnem', - 'ua_next_byte', - 'ua_next_long', - 'ua_next_qword', - 'ua_next_word', - 'ua_outop', - 'ua_outop2', - 'ua_stkvar2', 'uchar_array___getitem__', 'uchar_array___setitem__', 'uchar_array_cast', @@ -7017,9 +7338,6 @@ 'udtmembervec_t__del', 'udtmembervec_t_add_unique', 'udtmembervec_t_at', - 'udtmembervec_t_back', - 'udtmembervec_t_back__SWIG_0', - 'udtmembervec_t_back__SWIG_1', 'udtmembervec_t_begin', 'udtmembervec_t_begin__SWIG_0', 'udtmembervec_t_begin__SWIG_1', @@ -7036,9 +7354,6 @@ 'udtmembervec_t_find', 'udtmembervec_t_find__SWIG_0', 'udtmembervec_t_find__SWIG_1', - 'udtmembervec_t_front', - 'udtmembervec_t_front__SWIG_0', - 'udtmembervec_t_front__SWIG_1', 'udtmembervec_t_grow', 'udtmembervec_t_has', 'udtmembervec_t_inject', @@ -7057,7 +7372,6 @@ 'udtmembervec_t_truncate', 'ui_load_new_file', 'ui_run_debugger', - 'umsg', 'unhide_border', 'unhide_item', 'unmark_selection', @@ -7081,8 +7395,10 @@ 'update_extra_cmt', 'update_fpd', 'update_func', - 'update_hidden_area', + 'update_hidden_range', 'update_segm', + 'use_mapping', + 'user_cancelled', 'user_cmts_begin', 'user_cmts_clear', 'user_cmts_end', @@ -7102,6 +7418,8 @@ 'user_cmts_size', 'user_cmts_t_at', 'user_cmts_t_size', + 'user_graph_place_t_node_get', + 'user_graph_place_t_node_set', 'user_iflags_begin', 'user_iflags_clear', 'user_iflags_end', @@ -7192,9 +7510,6 @@ 'uvalvec_t__del', 'uvalvec_t_add_unique', 'uvalvec_t_at', - 'uvalvec_t_back', - 'uvalvec_t_back__SWIG_0', - 'uvalvec_t_back__SWIG_1', 'uvalvec_t_begin', 'uvalvec_t_begin__SWIG_0', 'uvalvec_t_begin__SWIG_1', @@ -7211,9 +7526,6 @@ 'uvalvec_t_find', 'uvalvec_t_find__SWIG_0', 'uvalvec_t_find__SWIG_1', - 'uvalvec_t_front', - 'uvalvec_t_front__SWIG_0', - 'uvalvec_t_front__SWIG_1', 'uvalvec_t_has', 'uvalvec_t_inject', 'uvalvec_t_insert', @@ -7231,8 +7543,6 @@ 'uvalvec_t_truncate', 'validate_idb_names', 'validate_name', - 'validate_name2', - 'validate_name3', 'valstr_t_info_get', 'valstr_t_info_set', 'valstr_t_length_get', @@ -7254,49 +7564,11 @@ 'var_ref_t_idx_set', 'var_ref_t_mba_get', 'var_ref_t_mba_set', - 'varloc_t__consume_scattered', - 'varloc_t__set_badloc', - 'varloc_t__set_reg1', - 'varloc_t__set_reg2', - 'varloc_t__set_stkoff', - 'varloc_t_advance', - 'varloc_t_calc_offset', - 'varloc_t_consume_scattered', - 'varloc_t_get_value', - 'varloc_t_is_badloc', - 'varloc_t_is_fragmented', - 'varloc_t_is_reg', - 'varloc_t_is_reg1', - 'varloc_t_is_reg2', - 'varloc_t_is_scattered', - 'varloc_t_is_stkoff', - 'varloc_t_reg1', - 'varloc_t_reg2', - 'varloc_t_regoff', - 'varloc_t_scattered', - 'varloc_t_scattered__SWIG_0', - 'varloc_t_scattered__SWIG_1', - 'varloc_t_set_badloc', - 'varloc_t_set_reg1', - 'varloc_t_set_reg2', - 'varloc_t_set_stkoff', - 'varloc_t_stkoff', - 'varloc_t_swap', - 'varloc_t_type', - 'varpart_t_bad_offset', - 'varpart_t_bad_size', - 'varpart_t_off_get', - 'varpart_t_off_set', - 'varpart_t_size_get', - 'varpart_t_size_set', - 'vaskqstr', 'vc_printer_t_func_get', 'vc_printer_t_func_set', 'vc_printer_t_lastchar_get', 'vc_printer_t_lastchar_set', 'vc_printer_t_oneliner', - 'vcall_helper', - 'vcreate_helper', 'vd_failure_t_desc', 'vd_failure_t_hf_get', 'vd_failure_t_hf_set', @@ -7318,15 +7590,11 @@ 'vdui_t_ct_get', 'vdui_t_ct_set', 'vdui_t_ctree_to_disasm', - 'vdui_t_cv_get', - 'vdui_t_cv_set', 'vdui_t_del_orphan_cmts', 'vdui_t_edit_cmt', 'vdui_t_edit_func_cmt', 'vdui_t_flags_get', 'vdui_t_flags_set', - 'vdui_t_form_get', - 'vdui_t_form_set', 'vdui_t_get_current_item', 'vdui_t_get_current_label', 'vdui_t_get_number', @@ -7365,6 +7633,8 @@ 'vdui_t_switch_to', 'vdui_t_tail_get', 'vdui_t_tail_set', + 'vdui_t_toplevel_get', + 'vdui_t_toplevel_set', 'vdui_t_ui_edit_lvar_cmt', 'vdui_t_ui_map_lvar', 'vdui_t_ui_rename_lvar', @@ -7376,19 +7646,46 @@ 'vdui_t_visible', 'verify_argloc', 'verify_tinfo', - 'verify_varloc', - 'vinterr', + 'view_mouse_event_location_t_ea_get', + 'view_mouse_event_location_t_ea_set', + 'view_mouse_event_location_t_item_get', + 'view_mouse_event_location_t_item_set', + 'view_mouse_event_t_button_get', + 'view_mouse_event_t_button_set', + 'view_mouse_event_t_location_get', + 'view_mouse_event_t_location_set', + 'view_mouse_event_t_renderer_pos_get', + 'view_mouse_event_t_renderer_pos_set', + 'view_mouse_event_t_rtype_get', + 'view_mouse_event_t_rtype_set', + 'view_mouse_event_t_state_get', + 'view_mouse_event_t_state_set', + 'view_mouse_event_t_x_get', + 'view_mouse_event_t_x_set', + 'view_mouse_event_t_y_get', + 'view_mouse_event_t_y_set', + 'viewer_attach_menu_item', + 'viewer_center_on', + 'viewer_create_groups', + 'viewer_del_node_info', + 'viewer_delete_groups', + 'viewer_fit_window', + 'viewer_get_curnode', + 'viewer_get_gli', + 'viewer_get_node_info', + 'viewer_get_selection', + 'viewer_set_gli', + 'viewer_set_groups_visibility', + 'viewer_set_node_info', + 'viewer_set_titlebar_height', 'visit_patched_bytes', 'visit_stroff_fields', 'visit_subtypes', - 'vloc_visitor_t_visit_location', - 'vumsg', 'wait_for_next_event', 'warning', 'warning__varargs__', - 'wasBreak', 'was_ida_decision', - 'wordflag', + 'word_flag', 'write_dbg_memory', 'write_tinfo_bitfield_value', 'writebytes', @@ -7427,9 +7724,6 @@ 'xreflist_t__del', 'xreflist_t_add_unique', 'xreflist_t_at', - 'xreflist_t_back', - 'xreflist_t_back__SWIG_0', - 'xreflist_t_back__SWIG_1', 'xreflist_t_begin', 'xreflist_t_begin__SWIG_0', 'xreflist_t_begin__SWIG_1', @@ -7446,9 +7740,6 @@ 'xreflist_t_find', 'xreflist_t_find__SWIG_0', 'xreflist_t_find__SWIG_1', - 'xreflist_t_front', - 'xreflist_t_front__SWIG_0', - 'xreflist_t_front__SWIG_1', 'xreflist_t_grow', 'xreflist_t_has', 'xreflist_t_inject', @@ -7465,5 +7756,5 @@ 'xreflist_t_size', 'xreflist_t_swap', 'xreflist_t_truncate', - 'ywrdflag', - 'zwrdflag']} \ No newline at end of file + 'yword_flag', + 'zword_flag']} diff --git a/build.py b/build.py index 4f18a8a..f513e3b 100644 --- a/build.py +++ b/build.py @@ -42,6 +42,7 @@ parser.add_argument("--debug", help="Build debug version of the plugin", default parser.add_argument("--python-home", help="Python home, where the 'include' directory can be found (linux only)", default=None) parser.add_argument("-j", "--parallel", action="store_true", help="Build in parallel", default=False) parser.add_argument("-v", "--verbose", help="Verbose mode", default=False, action="store_true") +parser.add_argument("-I", "--idc", required=True, help="IDA's idc.idc file (necessary for generating 6.95 compat API layer)", type=str) args = parser.parse_args() _probe = os.path.join("..", "..", "include", "pro.h") @@ -69,12 +70,15 @@ def main(): env["SWIGINCLUDES"] = " ".join(map(lambda p: "-I%s" % p, args.swig_inc.split(os.pathsep))) if args.with_hexrays: env["HAS_HEXRAYS"] = "1" - if not args.debug: + if args.debug: + env["__VC__"] = "1" # to enable PDB flags + else: env["NDEBUG"] = "1" if args.python_home: env["LINUX_PYTHON_HOME"] = args.python_home if args.verbose: argv.append("-d") + env["IDC_BC695_IDC_SOURCE"] = args.idc for ea64 in [False, True]: if ea64: env["__EA64__"] = "1" diff --git a/docs/bc695.md b/docs/bc695.md new file mode 100644 index 0000000..d7ade40 --- /dev/null +++ b/docs/bc695.md @@ -0,0 +1,46 @@ + +IDAPython for IDA 7.00: backward-compatibility with 6.95 APIs +============================================================= + +Availability of the backward-compatibility code +----------------------------------------------- + +* Backward-compatibility is provided by python.cfg's + `AUTOIMPORT_COMPAT_IDA695` directive. This directive is + currently turned on by default, but in the future it will: + 1. be turned off by default + 1. eventually disappear, and all the corresponding code will be removed + +* Consequently IDAPython script/plugin writers should try and port + their code, with the help of the porting guide XXX FIXME URL? XXX. + +* Once you have done the porting, please check that your code works + with `AUTOIMPORT_COMPAT_IDA695` set to `NO`. + +* If anything proves too hard or confusing, please let us know about + it on , and we will help you, either by fixing + IDAPython if needed, or by improving the documentation. + + +Coverage of the backward-compatibility code +------------------------------------------- + +* We did what was reasonably feasible, to provide an IDAPython API + that's as backward-compatible as possible with the IDA 6.95 API + +* However, we considered it unreasonable for some parts of the API + to be ported. Most notably: + * the "processor module" API: existing processor modules will + have to be ported to the new API. Please see the SDK's + `module/script/proctemplate.py` (or any other `*.py` file in + that directory) for examples how to use the new API. + * processor module-related notifications: some of those have either + been renamed, or have possibly changed signature + +* Most (all?) of the renamed functions, properties, etc... should be + covered, in all modules: `idaapi`, `idc`, ... + If something doesn't work/isn't there anymore, it's likely an + omission from our side. + +* Please let us know about any missing bits & pieces, that you + believe should be there and that we might have forgotten! diff --git a/docs/bc695.sh b/docs/bc695.sh new file mode 100755 index 0000000..9cc5f9d --- /dev/null +++ b/docs/bc695.sh @@ -0,0 +1,11 @@ +#!/bin/sh +TARGET_DIR=../../../../www/www.hex-rays.com/public_html/hex-rays/products/ida/7.0/docs +TARGET_FILE=$TARGET_DIR/idapython_backward_compat_695.html +p4 edit $TARGET_FILE +echo \\ > $TARGET_FILE +echo \ >> $TARGET_FILE +echo \ >> $TARGET_FILE +echo \\ >> $TARGET_FILE +markdown bc695.md >> $TARGET_FILE +echo \\ >> $TARGET_FILE +p4 revert -a $TARGET_FILE diff --git a/docs/notes.txt b/docs/notes.txt new file mode 100644 index 0000000..ab89347 --- /dev/null +++ b/docs/notes.txt @@ -0,0 +1,53 @@ +Assorted notes +-------------- + +Wrapped functions and constants: + +All the symbols from the idaapi module are listed in symbollist.txt. +Documentation for the plugin API functions functions is in the IDA +SDK header files. All function and symbol names directly translate +to the C++ counterparts. If you try to use a function that is not +wrapped yet you will get an exception like this: + + Traceback (most recent call last): + File "", line 1, in ? + NameError: name 'foobar' is not defined + +If this happens you can check the function in symbollist.txt. If it +is not included and it should be please report it to the author. + + +Data types: + +All the C++ data types are mapped to corresponding Python data types. +For example ea_t maps to a Python integer. Complex data types (like +structures and classes) are mapped to Python classes that have the +same attributes as the original type. + + +Arguments and return values: + +Generally all function arguments should be the same type as specified +by the original headers. Pointers to complex types (structures, classes) +are checked and must match the original declarations. + +For example comment = get_func_comment("aa", 0) will raise an exception: + + Traceback (most recent call last): + File "", line 1, in ? + TypeError: Type error. Got aa, expected _p_func_t + +When calling functions that return a string in a buffer (usually with +maximum size) the buffer and size parameter is omitted. These functions +return either the result in a string or None if the call fails and returns +NULL. The output buffers are maximized at MAXSTR. + + Example: + + C++: get_func_name(0x1234, buf, sizeof(buf)); + Python: name = get_func_name(0x1234) + +Any function that should return a char * is going to return either a +Python string (up to MAXSTR) or None. + + diff --git a/examples/chooser.py b/examples/chooser.py deleted file mode 100644 index b459063..0000000 --- a/examples/chooser.py +++ /dev/null @@ -1,50 +0,0 @@ -#--------------------------------------------------------------------- -# Chooser test -# -# This script demonstrates the usage of the class-based chooser. -# -# Author: Gergely Erdelyi -#--------------------------------------------------------------------- -from idaapi import Choose - -# -# Modal chooser -# - -# Get a modal Choose instance -chooser = Choose([], "MyChooser", 1) -# List to choose from -chooser.list = [ "First", "Second", "Third" ] -# Set the width -chooser.width = 50 -# Run the chooser -ch = chooser.choose() -# Print the results -if ch > 0: - print "You chose %d which is %s" % (ch, chooser.list[ch-1]) -else: - print "Escape from chooser" - -# -# Normal chooser -# -class MyChoose(Choose): - """ - You have to subclass Chooser to override the enter() method - """ - def __init__(self, list=[], name="Choose"): - Choose.__init__(self, list, name) - # Set the width - self.width = 50 - self.deflt = 1 - - def enter(self, n): - print "Enter called. Do some stuff here." - print "The chosen item is %d = %s" % (n, self.list[n-1]) - print "Now press ESC to leave." - -# Get a Choose instance -chooser = MyChoose([ "First", "Second", "Third" ], "MyChoose") - -# Run the chooser -ch = chooser.choose() diff --git a/examples/colours.py b/examples/colours.py index 49f0ce2..b1aa2e7 100644 --- a/examples/colours.py +++ b/examples/colours.py @@ -7,13 +7,13 @@ #--------------------------------------------------------------------- # Set the colour of the current segment to BLUE -SetColor(here(), CIC_SEGM, 0xc02020) +set_color(here(), CIC_SEGM, 0xc02020) # Set the colour of the current function to GREEN -SetColor(here(), CIC_FUNC, 0x208020) +set_color(here(), CIC_FUNC, 0x208020) # Set the colour of the current item to RED -SetColor(here(), CIC_ITEM, 0x2020c0) +set_color(here(), CIC_ITEM, 0x2020c0) # Print the colours just set -print "%x" % GetColor(here(), CIC_SEGM) -print "%x" % GetColor(here(), CIC_FUNC) -print "%x" % GetColor(here(), CIC_ITEM) +print "%x" % get_color(here(), CIC_SEGM) +print "%x" % get_color(here(), CIC_FUNC) +print "%x" % get_color(here(), CIC_ITEM) diff --git a/examples/debughook.py b/examples/debughook.py index d47f98d..99ccf4d 100644 --- a/examples/debughook.py +++ b/examples/debughook.py @@ -73,7 +73,7 @@ class MyDbgHook(DBG_Hooks): def dbg_step_over(self): - eip = GetRegValue("EIP") + eip = get_reg_value("EIP") print("0x%x %s" % (eip, GetDisasm(eip))) self.steps += 1 @@ -97,7 +97,7 @@ debughook.hook() debughook.steps = 0 # Stop at the entry point -ep = GetLongPrm(INF_START_IP) +ep = get_inf_attr(INF_START_IP) request_run_to(ep) # Step one instruction diff --git a/examples/ex1.idc b/examples/ex1.idc index e3c0aa7..cc5d7dc 100644 --- a/examples/ex1.idc +++ b/examples/ex1.idc @@ -12,22 +12,22 @@ static main() auto ea, func, ref; // Get current ea - ea = ScreenEA(); + ea = get_screen_ea(); // Loop from start to end in the current segment - for (func=SegStart(ea); - func != BADADDR && func < SegEnd(ea); - func=NextFunction(func)) + for (func=get_segm_start(ea); + func != BADADDR && func < get_segm_end(ea); + func=get_next_func(func)) { // If the current address is function process it - if (GetFunctionFlags(func) != -1) + if (get_func_flags(func) != -1) { - Message("Function %s at 0x%x\n", GetFunctionName(func), func); + msg("Function %s at 0x%x\n", get_func_name(func), func); // Find all code references to func - for (ref=RfirstB(func); ref != BADADDR; ref=RnextB(func, ref)) + for (ref=get_first_cref_to(func); ref != BADADDR; ref=get_next_cref_to(func, ref)) { - Message(" called from %s(0x%x)\n", GetFunctionName(ref), ref); + msg(" called from %s(0x%x)\n", get_func_name(ref), ref); } } diff --git a/examples/ex1_idaapi.py b/examples/ex1_idaapi.py index 4729554..172c0e0 100644 --- a/examples/ex1_idaapi.py +++ b/examples/ex1_idaapi.py @@ -23,10 +23,10 @@ def main(): # No function there, try to get the next one func = get_next_func(func_ea) - seg_end = seg.endEA - while func is not None and func.startEA < seg_end: - funcea = func.startEA - print "Function %s at 0x%x" % (GetFunctionName(funcea), funcea) + seg_end = seg.end_ea + while func is not None and func.start_ea < seg_end: + funcea = func.start_ea + print "Function %s at 0x%x" % (get_func_name(funcea), funcea) ref = get_first_cref_to(funcea) @@ -37,4 +37,4 @@ def main(): func = get_next_func(funcea) -main() \ No newline at end of file +main() diff --git a/examples/ex1_idautils.py b/examples/ex1_idautils.py index 5072f94..72c2e6c 100644 --- a/examples/ex1_idautils.py +++ b/examples/ex1_idautils.py @@ -9,18 +9,18 @@ from idautils import * def main(): # Get current ea - ea = ScreenEA() + ea = get_screen_ea() if ea == idaapi.BADADDR: print("Could not get get_screen_ea()") return # Loop from start to end in the current segment - for funcea in Functions(SegStart(ea), SegEnd(ea)): - print("Function %s at 0x%x" % (GetFunctionName(funcea), funcea)) + for funcea in Functions(get_segm_start(ea), get_segm_end(ea)): + print("Function %s at 0x%x" % (get_func_name(funcea), funcea)) # Find all code references to funcea for ref in CodeRefsTo(funcea, 1): - print(" called from %s(0x%x)" % (GetFunctionName(ref), ref)) + print(" called from %s(0x%x)" % (get_func_name(ref), ref)) if __name__=='__main__': diff --git a/examples/ex_actions.py b/examples/ex_actions.py index 265991a..2325bb4 100644 --- a/examples/ex_actions.py +++ b/examples/ex_actions.py @@ -12,7 +12,7 @@ class SayHi(idaapi.action_handler_t): # You can implement update(), to inform IDA when: # * your action is enabled # * update() should queried again - # E.g., returning 'idaapi.AST_ENABLE_FOR_FORM' will + # E.g., returning 'idaapi.AST_ENABLE_FOR_WIDGET' will # tell IDA that this action is available while the # user is in the current widget, and that update() # must be queried again once the user gives focus @@ -24,7 +24,7 @@ class SayHi(idaapi.action_handler_t): # querying update() anymore until the user has moved # to another view.. def update(self, ctx): - return idaapi.AST_ENABLE_FOR_FORM if ctx.form_type == idaapi.BWN_DISASM else idaapi.AST_DISABLE_FOR_FORM + return idaapi.AST_ENABLE_FOR_WIDGET if ctx.widget_type == idaapi.BWN_DISASM else idaapi.AST_DISABLE_FOR_WIDGET print "Creating a custom icon from raw data!" @@ -92,16 +92,16 @@ if idaapi.register_action(idaapi.action_desc_t( # when the popup for "IDA View-A" is being populated, right before # it is displayed. class Hooks(idaapi.UI_Hooks): - def finish_populating_tform_popup(self, form, popup): + def finish_populating_widget_popup(self, widget, popup): # We'll add our action to all "IDA View-*"s. # If we wanted to add it only to "IDA View-A", we could # also discriminate on the widget's title: # - # if idaapi.get_tform_title(form) == "IDA View-A": + # if idaapi.get_widget_title(widget) == "IDA View-A": # ... # - if idaapi.get_tform_type(form) == idaapi.BWN_DISASM: - idaapi.attach_action_to_popup(form, popup, act_name, None) + if idaapi.get_widget_type(widget) == idaapi.BWN_DISASM: + idaapi.attach_action_to_popup(widget, popup, act_name, None) hooks = Hooks() hooks.hook() diff --git a/examples/ex_askusingform.py b/examples/ex_askusingform.py index aef440d..5cb1d04 100644 --- a/examples/ex_askusingform.py +++ b/examples/ex_askusingform.py @@ -2,30 +2,22 @@ # This is an example illustrating how to use the Form class # (c) Hex-Rays # -from idaapi import Form +from ida_kernwin import Form, Choose, ask_str # -------------------------------------------------------------------------- -class TestEmbeddedChooserClass(Choose2): +class TestEmbeddedChooserClass(Choose): """ A simple chooser to be used as an embedded chooser """ - def __init__(self, title, nb = 5, flags=0): - Choose2.__init__(self, - title, - [ ["Address", 10], ["Name", 30] ], - embedded=True, width=30, height=20, flags=flags) - self.n = 0 - self.items = [ self.make_item() for x in xrange(0, nb+1) ] + def __init__(self, title, nb = 5, flags = 0): + Choose.__init__(self, + title, + [ ["Address", 10], ["Name", 30] ], + flags=flags, + embedded=True, width=30, height=6) + self.items = [ [str(x), "func_%04d" % x] + for x in xrange(nb + 1) ] self.icon = 5 - self.selcount = 0 - - def make_item(self): - r = [str(self.n), "func_%04d" % self.n] - self.n += 1 - return r - - def OnClose(self): - pass def OnGetLine(self, n): print("getline %d" % n) @@ -40,7 +32,7 @@ class TestEmbeddedChooserClass(Choose2): class MyForm(Form): def __init__(self): self.invert = False - self.EChooser = TestEmbeddedChooserClass("E1", flags=Choose2.CH_MULTI) + self.EChooser = TestEmbeddedChooserClass("E1", flags=Choose.CH_MULTI) Form.__init__(self, r"""STARTITEM {id:rNormal} BUTTON YES* Yeah BUTTON NO Nope @@ -48,44 +40,33 @@ BUTTON CANCEL Nevermind Form Test {FormChangeCb} -This is a string: +{cStr1}+ -This is an address: +{cAddr1}+ -This is some HTML: +{cHtml1}+ +This is a string: |+{cStr1}+ +This is an address:|+{cAddr1}+ +This is some HTML: |+{cHtml1}+ +This is a number: |+{cVal1}+ -Escape\{control} -This is a string: '{cStr2}' -This is a number: {cVal1} - -<#Hint1#Enter name:{iStr1}> +<#Hint1#Enter text :{iStr1}> <#Hint2#Select color:{iColor1}> Browse test <#Select a file to open#Browse to open:{iFileOpen}> <#Select a file to save#Browse to save:{iFileSave}> <#Select dir#Browse for dir:{iDir}> -Type -<#Select type#Write a type:{iType}> -Numbers +Misc <##Enter a selector value:{iSegment}> -<##Enter a raw hex:{iRawHex}> -<##Enter a character:{iChar}> -<##Enter an address:{iAddr}> -Button test -<##Button1:{iButton1}> <##Button2:{iButton2}> +<##Enter a raw hex :{iRawHex}> +<##Enter a character :{iChar}> +<##Enter an address :{iAddr}> +<##Write a type name :{iType}> +Button test: <##Button1:{iButton1}> <##Button2:{iButton2}> -Check boxes: - - -{cGroup1}> +<##Check boxes##Error output:{rError}> | <##Radio boxes##Green:{rGreen}> + | +{cGroup1}> | {cGroup2}> -Radio boxes: - - -{cGroup2}> The end! """, { 'cStr1': Form.StringLabel("Hello"), - 'cStr2': Form.StringLabel("StringTest"), 'cHtml1': Form.StringLabel("Is this red?", tp=Form.FT_HTML_LABEL), 'cAddr1': Form.NumericLabel(0x401000, Form.FT_ADDR), 'cVal1' : Form.NumericLabel(99, Form.FT_HEX), @@ -131,6 +112,13 @@ The end! elif fid == self.cEChooser.id: l = self.GetControlValue(self.cEChooser) print("Chooser: %s" % l) + elif fid in [self.rGreen.id, self.rRed.id, self.rBlue.id]: + color = { + self.rGreen.id : 0x00FF00, + self.rRed.id : 0x0000FF, + self.rBlue.id : 0xFF0000, + } + self.SetControlValue(self.iColor1, color[fid]) else: print(">>fid:%d" % fid) return 1 @@ -212,8 +200,8 @@ using address %$ # Use either StringArgument or NumericArgument to pass values to the function num = Form.NumericArgument('N', value=123) - ok = idaapi.AskUsingForm(s, - Form.StringArgument("PyAskUsingForm").arg, + ok = idaapi.ask_form(s, + Form.StringArgument("PyAskform").arg, Form.NumericArgument('$', 0x401000).arg, num.arg) if ok == 1: @@ -231,7 +219,7 @@ This is sample dialog box """ # Use either StringArgument or NumericArgument to pass values to the function ti = textctrl_info_t("Some initial value") - ok = idaapi.AskUsingForm(s, pointer(c_void_p.from_address(ti.clink_ptr))) + ok = idaapi.ask_form(s, pointer(c_void_p.from_address(ti.clink_ptr))) if ok == 1: print("You entered: %s" % ti.text) @@ -319,11 +307,11 @@ Dropdown list test def OnFormChange(self, fid): if fid == self.iButtonSetString.id: - s = idc.AskStr("none", "Enter value") + s = ask_str("none", 0, "Enter value") if s: self.SetControlValue(self.cbEditable, s) elif fid == self.iButtonSetIndex.id: - s = idc.AskStr("1", "Enter index value:") + s = ask_str("1", 0, "Enter index value:") if s: try: i = int(s) diff --git a/examples/ex_choose.py b/examples/ex_choose.py new file mode 100644 index 0000000..592ee88 --- /dev/null +++ b/examples/ex_choose.py @@ -0,0 +1,141 @@ +import ida_kernwin +from ida_kernwin import Choose + +class chooser_handler_t(ida_kernwin.action_handler_t): + def __init__(self, thing): + ida_kernwin.action_handler_t.__init__(self) + self.thing = thing + + def activate(self, ctx): + sel = [] + for idx in ctx.chooser_selection: + sel.append(str(idx)) + print "command %s selected @ %s" % (self.thing, ", ".join(sel)) + + def update(self, ctx): + return ida_kernwin.AST_ENABLE_FOR_WIDGET \ + if ida_kernwin.is_chooser_widget(ctx.widget_type) \ + else ida_kernwin.AST_DISABLE_FOR_WIDGET + + +class MyChoose(Choose): + + def __init__(self, title, nb = 5, flags = 0, + modal = False, + embedded = False, width = None, height = None): + Choose.__init__( + self, + title, + [ ["Address", 10], ["Name", 30] ], + flags = flags | (Choose.CH_CAN_INS + | Choose.CH_CAN_DEL + | Choose.CH_CAN_EDIT + | Choose.CH_CAN_REFRESH), + embedded = embedded, + width = width, + height = height) + self.n = 0 + self.items = [ self.make_item() for x in xrange(nb) ] + self.icon = 5 + self.selcount = 0 + self.modal = modal + self.popup_names = ["Inzert", "Del leet", "Ehdeet", "Ree frech"] + + print("created %s" % str(self)) + + def OnInit(self): + print "inited", str(self) + return True + + def OnGetSize(self): + n = len(self.items) + print("getsize -> %d" % n) + return n + + def OnGetLine(self, n): + print("getline %d" % n) + return self.items[n] + + def OnGetIcon(self, n): + r = self.items[n] + t = self.icon + r[1].count("*") + print "geticon", n, t + return t + + def OnGetLineAttr(self, n): + print("getlineattr %d" % n) + if n == 1: + return [0xFF0000, 0] + + def OnInsertLine(self, n): + # we ignore current selection + n = self.n # position at the just added item + self.items.append(self.make_item()) + print("insert line") + return (Choose.ALL_CHANGED, n) + + def OnDeleteLine(self, n): + print("del %d " % n) + del self.items[n] + return [Choose.ALL_CHANGED] + self.adjust_last_item(n) + + def OnEditLine(self, n): + self.items[n][1] = self.items[n][1] + "*" + print("editing %d" % n) + return (Choose.ALL_CHANGED, n) + + def OnRefresh(self, n): + print("refresh %d" % n) + return None # call standard refresh + + def OnSelectLine(self, n): + self.selcount += 1 + warning("[%02d] selectline '%d'" % (self.selcount, n)) + return (Choose.NOTHING_CHANGED, ) + + def OnClose(self): + print "closed", str(self) + + def OnPopup(self, form, popup_handle): + for c in ["A", "B"]: + actname = "choose:act%s" % c + desc = ida_kernwin.action_desc_t( + actname, + "command %s" % c, + chooser_handler_t(c)) + ida_kernwin.attach_dynamic_action_to_popup( + form, popup_handle, desc) + + def show(self): + return self.Show(self.modal) >= 0 + + def make_item(self): + r = [str(self.n), "func_%04d" % self.n] + self.n += 1 + return r + + +# ----------------------------------------------------------------------- +def test_choose(modal = False, nb = 10): + global c + c = MyChoose("Choose - sample 1", nb = nb, modal = modal) + c.show() + +# ----------------------------------------------------------------------- +def test_choose_embedded(): + global c + c = MyChoose("Choose - embedded", nb=12, embedded = True, width=123, height=222) + r = c.Embedded() + if r == 0: + try: + if test_embedded: + o, sel = _idaapi.choose_get_embedded(c) + print("o=%s, type(o)=%s" % (str(o), type(o))) + test_embedded(o) + finally: + c.Close() + +# ----------------------------------------------------------------------- +if __name__ == '__main__': + #test_choose_embedded() + test_choose(False) diff --git a/examples/ex_choose2.py b/examples/ex_choose2.py deleted file mode 100644 index d7915eb..0000000 --- a/examples/ex_choose2.py +++ /dev/null @@ -1,128 +0,0 @@ -import idaapi -from idaapi import Choose2 - -class chooser_handler_t(idaapi.action_handler_t): - def __init__(self, thing): - idaapi.action_handler_t.__init__(self) - self.thing = thing - - def activate(self, ctx): - sel = [] - for i in xrange(len(ctx.chooser_selection)): - sel.append(str(ctx.chooser_selection.at(i))) - print "command %s selected @ %s" % (self.thing, ", ".join(sel)) - - def update(self, ctx): - return idaapi.AST_ENABLE_FOR_FORM if idaapi.is_chooser_tform(ctx.form_type) else idaapi.AST_DISABLE_FOR_FORM - - -class MyChoose2(Choose2): - - def __init__(self, title, nb = 5, flags=0, width=None, height=None, embedded=False, modal=False): - Choose2.__init__( - self, - title, - [ ["Address", 10], ["Name", 30] ], - flags = flags, - width = width, - height = height, - embedded = embedded) - self.n = 0 - self.items = [ self.make_item() for x in xrange(0, nb+1) ] - self.icon = 5 - self.selcount = 0 - self.modal = modal - self.popup_names = ["Inzert", "Del leet", "Ehdeet", "Ree frech"] - - print("created %s" % str(self)) - - def OnClose(self): - print "closed", str(self) - - def OnEditLine(self, n): - self.items[n][1] = self.items[n][1] + "*" - print("editing %d" % n) - - def OnInsertLine(self): - self.items.append(self.make_item()) - print("insert line") - - def OnSelectLine(self, n): - self.selcount += 1 - Warning("[%02d] selectline '%s'" % (self.selcount, n)) - - def OnGetLine(self, n): - print("getline %d" % n) - return self.items[n] - - def OnGetSize(self): - n = len(self.items) - print("getsize -> %d" % n) - return n - - def OnDeleteLine(self, n): - print("del %d " % n) - del self.items[n] - return n - - def OnRefresh(self, n): - print("refresh %d" % n) - return n - - def OnGetIcon(self, n): - r = self.items[n] - t = self.icon + r[1].count("*") - print "geticon", n, t - return t - - def show(self): - return self.Show(self.modal) >= 0 - - def make_item(self): - r = [str(self.n), "func_%04d" % self.n] - self.n += 1 - return r - - def OnGetLineAttr(self, n): - print("getlineattr %d" % n) - if n == 1: - return [0xFF0000, 0] - - -# ----------------------------------------------------------------------- -def test_choose2(modal=False): - global c - c = MyChoose2("Choose2 - sample 1", nb=10, modal=modal) - r = c.show() - form = idaapi.get_current_tform() - for thing in ["A", "B"]: - idaapi.attach_action_to_popup(form, None, "choose2:act%s" % thing) - -# ----------------------------------------------------------------------- -def test_choose2_embedded(): - global c - c = MyChoose2("Choose2 - embedded", nb=12, embedded = True, width=123, height=222) - r = c.Embedded() - if r == 1: - try: - if test_embedded: - o, sel = _idaapi.choose2_get_embedded(c) - print("o=%s, type(o)=%s" % (str(o), type(o))) - test_embedded(o) - finally: - c.Close() - -# ----------------------------------------------------------------------- -if __name__ == '__main__': - - # Register actions - for thing in ["A", "B"]: - actname = "choose2:act%s" % thing - idaapi.register_action( - idaapi.action_desc_t( - actname, - "command %s" % thing, - chooser_handler_t(thing))) - - #test_choose2_embedded() - test_choose2(False) diff --git a/examples/ex_choose_multi.py b/examples/ex_choose_multi.py new file mode 100644 index 0000000..2ef2e5e --- /dev/null +++ b/examples/ex_choose_multi.py @@ -0,0 +1,40 @@ +from ida_kernwin import Choose + + +class MyChoose(Choose): + + def __init__(self, title, nb = 5): + Choose.__init__( + self, + title, + [ ["Bit", Choose.CHCOL_HEX | 10] ], + flags = Choose.CH_MULTI) + self.items = [ str(1 << x) for x in xrange(nb) ] + + def OnGetSize(self): + return len(self.items) + + def OnGetLine(self, n): + return [self.items[n]] + + def OnSelectLine(self, n): + self.deflt = n # save current selection + return (Choose.NOTHING_CHANGED, ) + + def show(self, num): + self.deflt = [x + for x in xrange(len(self.items)) + if (num & (1 << x)) != 0] + if self.Show(True) < 0: + return 0 + return sum([(1 << x) for x in self.deflt]) + + +# ----------------------------------------------------------------------- +def test_choose(num): + c = MyChoose("Choose - sample 2", nb = 5) + return c.show(num) + +# ----------------------------------------------------------------------- +if __name__ == '__main__': + print test_choose(11) diff --git a/examples/ex_custdata.py b/examples/ex_custdata.py index b78cbac..99aaa88 100644 --- a/examples/ex_custdata.py +++ b/examples/ex_custdata.py @@ -7,14 +7,16 @@ import struct import ctypes import platform -# - # ----------------------------------------------------------------------- class pascal_data_type(data_type_t): def __init__(self): - data_type_t.__init__(self, name="py_pascal_string", - value_size = 2, menu_name = "Pascal string", - asm_keyword = "pstr") + data_type_t.__init__( + self, + "py_pascal_string", + 2, + "Pascal string", + None, + "pstr") def calc_item_size(self, ea, maxsize): # Custom data types may be used in structure definitions. If this case @@ -34,7 +36,9 @@ class pascal_data_type(data_type_t): class pascal_data_format(data_format_t): FORMAT_NAME = "py_pascal_string_pstr" def __init__(self): - data_format_t.__init__(self, name=pascal_data_format.FORMAT_NAME) + data_format_t.__init__( + self, + pascal_data_format.FORMAT_NAME) def printf(self, value, current_ea, operand_num, dtid): # Take the length byte @@ -52,12 +56,19 @@ class pascal_data_format(data_format_t): # ----------------------------------------------------------------------- class simplevm_data_type(data_type_t): ASM_KEYWORD = "svm_emit" - def __init__(self): - data_type_t.__init__(self, - name="py_simple_vm", - value_size = 1, - menu_name = "SimpleVM", - asm_keyword = simplevm_data_type.ASM_KEYWORD) + def __init__( + self, + name="py_simple_vm", + value_size=1, + menu_name="SimpleVM", + asm_keyword=ASM_KEYWORD): + data_type_t.__init__( + self, + name, + value_size, + menu_name, + None, + asm_keyword) def calc_item_size(self, ea, maxsize): if _idaapi.is_member_id(ea): @@ -71,10 +82,15 @@ class simplevm_data_type(data_type_t): return n class simplevm_data_format(data_format_t): - def __init__(self): - data_format_t.__init__(self, - name="py_simple_vm_format", - menu_name = "SimpleVM") + def __init__( + self, + name="py_simple_vm_format", + menu_name="SimpleVM"): + data_format_t.__init__( + self, + name, + 0, + menu_name) # Some tables for the disassembler INST = {1: 'add', 2: 'mul', 3: 'sub', 4: 'xor', 5: 'mov'} @@ -114,10 +130,11 @@ class simplevm_data_format(data_format_t): # This format will display DWORD values as MAKE_DWORD(0xHI, 0xLO) class makedword_data_format(data_format_t): def __init__(self): - data_format_t.__init__(self, - name="py_makedword", - value_size = 4, - menu_name = "Make DWORD") + data_format_t.__init__( + self, + "py_makedword", + 4, + "Make DWORD") def printf(self, value, current_ea, operand_num, dtid): if len(value) != 4: return None @@ -138,10 +155,11 @@ class makedword_data_format(data_format_t): # DLL each time for a new string. It can be improved in many ways. class rsrc_string_format(data_format_t): def __init__(self): - data_format_t.__init__(self, - name="py_w32rsrcstring", - value_size = 1, - menu_name = "Resource string") + data_format_t.__init__( + self, + "py_w32rsrcstring", + 1, + "Resource string") self.cache_node = idaapi.netnode("$ py_w32rsrcstring", 0, 1) def get_rsrc_string(self, fn, id): @@ -186,19 +204,21 @@ new_formats = [ (pascal_data_type(), pascal_data_format()), (simplevm_data_type(), simplevm_data_format()), (makedword_data_format(),), - (simplevm_data_format(),) + (simplevm_data_format(),), ] -if platform.system() == 'Windows': - new_formats.append((rsrc_string_format(),)) - -# +try: + if platform.system() == 'Windows': + new_formats.append((rsrc_string_format(),)) +except: + pass # ----------------------------------------------------------------------- def nw_handler(code, old=0): # delete notifications if code == NW_OPENIDB: - idaapi.register_data_types_and_formats(new_formats) + if not idaapi.register_data_types_and_formats(new_formats): + print "Failed to register types!" elif code == NW_CLOSEIDB: idaapi.unregister_data_types_and_formats(new_formats) elif code == NW_TERMIDA: diff --git a/examples/ex_custview.py b/examples/ex_custview.py index 36a9997..2a11a40 100644 --- a/examples/ex_custview.py +++ b/examples/ex_custview.py @@ -98,7 +98,7 @@ class mycv_t(simplecustviewer_t): elif vkey == ord('G'): n = self.GetLineNo() if n is not None: - v = idc.AskLong(self.GetLineNo(), "Where to go?") + v = idaapi.ask_long(self.GetLineNo(), "Where to go?") if v: self.Jump(v, 0, 5) elif vkey == ord('R'): @@ -108,7 +108,7 @@ class mycv_t(simplecustviewer_t): print "refreshing current line..." self.RefreshCurrent() elif vkey == ord('A'): - s = idc.AskStr("NewLine%d" % self.Count(), "Append new line") + s = idaapi.ask_str("NewLine%d" % self.Count(), 0, "Append new line") self.AddLine(s) self.Refresh() elif vkey == ord('X'): @@ -117,7 +117,7 @@ class mycv_t(simplecustviewer_t): self.Refresh() elif vkey == ord('I'): n = self.GetLineNo() - s = idc.AskStr("InsertedLine%d" % n, "Insert new line") + s = idaapi.ask_str("InsertedLine%d" % n, 0, "Insert new line") self.InsertLine(n, s) self.Refresh() elif vkey == ord('E'): @@ -160,7 +160,7 @@ def show_win(): print "Failed to create!" return None x.Show() - tcc = x.GetTCustomControl() + tcc = x.GetWidget() # Register actions for thing in ["Hello", "World"]: diff --git a/examples/ex_dbg.py b/examples/ex_dbg.py index 1c04403..5716629 100644 --- a/examples/ex_dbg.py +++ b/examples/ex_dbg.py @@ -4,9 +4,9 @@ def test_getmeminfo(): L = tempo.getmeminfo() out = [] - # startEA endEA name sclass sbase bitness perm - for (startEA, endEA, name, sclass, sbase, bitness, perm) in L: - out.append("%x: %x name=<%s> sclass=<%s> sbase=%x bitness=%2x perm=%2x" % (startEA, endEA, name, sclass, sbase, bitness, perm)) + # start_ea end_ea name sclass sbase bitness perm + for (start_ea, end_ea, name, sclass, sbase, bitness, perm) in L: + out.append("%x: %x name=<%s> sclass=<%s> sbase=%x bitness=%2x perm=%2x" % (start_ea, end_ea, name, sclass, sbase, bitness, perm)) f = file(r"d:\temp\out.log", "w") f.write("\n".join(out)) @@ -16,7 +16,7 @@ def test_getmeminfo(): def test_getregs(): - # name flags class dtyp bit_strings bit_strings_default_mask + # name flags class dtype bit_strings bit_strings_default_mask L = tempo.getregs() out = [] for (name, flags, cls, dtype, bit_strings, bit_strings_default_mask) in L: diff --git a/examples/ex_debug_names.py b/examples/ex_debug_names.py index 68cb1b1..f59720d 100644 --- a/examples/ex_debug_names.py +++ b/examples/ex_debug_names.py @@ -8,7 +8,7 @@ def main(): print "Please suspend the debugger first!" return - dn = idaapi.get_debug_names(idaapi.cvar.inf.minEA, idaapi.cvar.inf.maxEA) + dn = idaapi.get_debug_names(idaapi.cvar.inf.min_ea, idaapi.cvar.inf.max_ea) for i in dn: print "%08x: %s" % (i, dn[i]) diff --git a/examples/ex_expr.py b/examples/ex_expr.py index a40e449..6ceed76 100644 --- a/examples/ex_expr.py +++ b/examples/ex_expr.py @@ -2,12 +2,18 @@ # This is an example illustrating how to extend IDC from Python # (c) Hex-Rays # -from idaapi import set_idc_func_ex +from idaapi import add_idc_func def py_power(n, e): return n ** e -ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0) +desc = ext_idcfunc_t +desc.name = "pow" +desc.func = py_power, +desc.args = (idaapi.VT_LONG, idaapi.VT_LONG), +desc.defvals = () +desc.flags = 0 +ok = add_idc_func(desc) if ok: print("Now the pow() will be present IDC!") else: diff --git a/examples/ex_func_chooser.py b/examples/ex_func_chooser.py index b489f5f..d3579d3 100644 --- a/examples/ex_func_chooser.py +++ b/examples/ex_func_chooser.py @@ -1,38 +1,45 @@ -import idaapi import idautils import idc +from ida_kernwin import Choose -class MyChoose2(Choose2): +class MyChoose(Choose): def __init__(self, title): - Choose2.__init__(self, title, [ ["Address", 10 | Choose2.CHCOL_HEX], ["Name", 30 | Choose2.CHCOL_PLAIN] ]) - self.n = 0 + Choose.__init__( + self, + title, + [ ["Address", 10 | Choose.CHCOL_HEX], + ["Name", 30 | Choose.CHCOL_PLAIN] ]) + self.items = [] self.icon = 41 - self.PopulateItems() - def PopulateItems(self): - self.items = [ [hex(x), GetFunctionName(x), x] for x in idautils.Functions() ] - - def OnClose(self): - print "closed ", self.title - - def OnSelectLine(self, n): - idc.Jump(self.items[n][2]) - - def OnGetLine(self, n): - return self.items[n] + def OnInit(self): + self.items = [ [hex(x), get_func_name(x), x] + for x in idautils.Functions() ] + return True def OnGetSize(self): return len(self.items) + def OnGetLine(self, n): + return self.items[n] + def OnDeleteLine(self, n): ea = self.items[n][2] - idc.DelFunction(ea) - return n + idc.del_func(ea) + return (Choose.ALL_CHANGED, n) + + def OnSelectLine(self, n): + idc.jumpto(self.items[n][2]) + return (Choose.NOTHING_CHANGED, ) def OnRefresh(self, n): - self.PopulateItems() - return n + self.OnInit() + # try to preserve the cursor + return [Choose.ALL_CHANGED] + self.adjust_last_item(n) -c = MyChoose2("My functions list") -c.Show() \ No newline at end of file + def OnClose(self): + print "closed ", self.title + +c = MyChoose("My functions list") +c.Show() diff --git a/examples/ex_gdl_qflow_chart.py b/examples/ex_gdl_qflow_chart.py index 8ee9c8e..38b0593 100644 --- a/examples/ex_gdl_qflow_chart.py +++ b/examples/ex_gdl_qflow_chart.py @@ -6,17 +6,17 @@ def raw_main(p=True): f = idaapi.get_func(here()) if not f: return - + q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS) for n in xrange(0, q.size()): b = q[n] if p: - print "%x - %x [%d]:" % (b.startEA, b.endEA, n) - + print "%x - %x [%d]:" % (b.start_ea, b.end_ea, n) + for ns in xrange(0, q.nsucc(n)): if p: print "SUCC: %d->%d" % (n, q.succ(n, ns)) - + for ns in xrange(0, q.npred(n)): if p: print "PRED: %d->%d" % (n, q.pred(n, ns)) @@ -27,14 +27,14 @@ def cls_main(p=True): f = idaapi.FlowChart(idaapi.get_func(here())) for block in f: if p: - print "%x - %x [%d]:" % (block.startEA, block.endEA, block.id) + print "%x - %x [%d]:" % (block.start_ea, block.end_ea, block.id) for succ_block in block.succs(): if p: - print " %x - %x [%d]:" % (succ_block.startEA, succ_block.endEA, succ_block.id) - + print " %x - %x [%d]:" % (succ_block.start_ea, succ_block.end_ea, succ_block.id) + for pred_block in block.preds(): if p: - print " %x - %x [%d]:" % (pred_block.startEA, pred_block.endEA, pred_block.id) + print " %x - %x [%d]:" % (pred_block.start_ea, pred_block.end_ea, pred_block.id) q = None f = None diff --git a/examples/ex_graph.py b/examples/ex_graph.py index dafeb6b..2fe9fc1 100644 --- a/examples/ex_graph.py +++ b/examples/ex_graph.py @@ -51,19 +51,16 @@ class MyGraph(GraphViewer): def OnGetText(self, node_id): return self[node_id] - def Show(self): - if not GraphViewer.Show(self): - return False + def OnPopup(self, form, popup_handle): # graph closer actname = "graph_closer:%s" % self.title - register_action(action_desc_t(actname, "Close: %s" % self.title, GraphCloser(self))) - attach_action_to_popup(self.GetTCustomControl(), None, actname) + desc = action_desc_t(actname, "Close: %s" % self.title, GraphCloser(self)) + attach_dynamic_action_to_popup(form, popup_handle, desc) # color changer actname = "color_changer:%s" % self.title - register_action(action_desc_t(actname, "Change colors: %s" % self.title, ColorChanger(self))) - attach_action_to_popup(self.GetTCustomControl(), None, actname) - return True + desc = action_desc_t(actname, "Change colors: %s" % self.title, ColorChanger(self)) + attach_dynamic_action_to_popup(form, popup_handle, desc) def show_graph(): @@ -73,14 +70,15 @@ def show_graph(): return # Iterate through all function instructions and take only call instructions result = {} - for x in [x for x in FuncItems(f.startEA) if idaapi.is_call_insn(x)]: + tmp = idaapi.insn_t() + for x in [x for x in FuncItems(f.start_ea) if (idaapi.decode_insn(tmp, x) and idaapi.is_call_insn(tmp))]: for xref in XrefsFrom(x, idaapi.XREF_FAR): if not xref.iscode: continue - t = GetFunctionName(xref.to) + t = get_func_name(xref.to) if not t: t = hex(xref.to) result[t] = True - g = MyGraph(GetFunctionName(f.startEA), result) + g = MyGraph(get_func_name(f.start_ea), result) if g.Show(): return g else: diff --git a/examples/ex_hexrays.py b/examples/ex_hexrays.py new file mode 100644 index 0000000..503d0af --- /dev/null +++ b/examples/ex_hexrays.py @@ -0,0 +1,40 @@ +# +# This example tries to load a decompiler plugin corresponding to the current +# architecture (and address size) right after auto-analysis is performed, +# and then tries to decompile the function at the first entrypoint. +# +# It is particularly suited for use with the '-S' flag. +# + +import ida_ida +import ida_auto +import ida_loader +import ida_hexrays +import ida_idp +import ida_entry + +ida_auto.auto_wait() +ALL_DECOMPILERS = { + ida_idp.PLFM_386 : ("hexrays", "hexx64"), + ida_idp.PLFM_ARM : ("hexarm", "hexarm64"), + ida_idp.PLFM_PPC : ("hexppc", "hexppc64"), +} +pair = ALL_DECOMPILERS.get(ida_idp.ph.id, None) +if pair: + decompiler = pair[1 if ida_ida.cvar.inf.is_64bit() else 0] + if ida_loader.load_plugin(decompiler) and ida_hexrays.init_hexrays_plugin(): + eqty = ida_entry.get_entry_qty() + if eqty: + ea = ida_entry.get_entry(ida_entry.get_entry_ordinal(0)) + print("Decompiling at: %X" % ea) + cf = ida_hexrays.decompile(ea) + if cf: + print(cf) + else: + print("Decompilation failed") + else: + print("No known entrypoint. Cannot decompile.") + else: + print("Couldn't load or initialize decompiler: \"%s\"" % decompiler) +else: + print("No known decompilers for architecture with ID: %d" % ida_idp.ph.id) diff --git a/examples/ex_procext.py b/examples/ex_procext.py new file mode 100644 index 0000000..d7a311b --- /dev/null +++ b/examples/ex_procext.py @@ -0,0 +1,43 @@ +# this script implements disassembly of BUG_INSTR used in Linux kernel BUG() macro +# normally it's architecturally undefined and is not disassembled by IDA's ARM module +# see Linux/arch/arm/include/asm/bug.h + +import idaapi + +ITYPE_BUGINSN = idaapi.CUSTOM_CMD_ITYPE + 10 +MNEM_WIDTH = 16 + +class MyHooks(idaapi.IDP_Hooks): + + def __init__(self): + idaapi.IDP_Hooks.__init__(self) + self.reported = [] + + def ev_ana_insn(self, insn): + t = get_sreg(insn.ea, "T") + if t==0 and get_wide_dword(insn.ea) == 0xE7F001F2: + insn.itype = ITYPE_BUGINSN + insn.size = 4 + elif t!=0 and get_wide_word(insn.ea) == 0xde02: + insn.itype = ITYPE_BUGINSN + insn.size = 2 + return insn.size + + def ev_emu_insn(self, insn): + if insn.ea == ITYPE_BUGINSN: + return 1 + return 0 + + def ev_out_mnem(self, outctx): + if outctx.insn.itype == ITYPE_BUGINSN: + outctx.out_custom_mnem("BUG_INSTR", MNEM_WIDTH) + return 1 + return 0 + +if idaapi.ph.id == idaapi.PLFM_ARM: + bahooks = MyHooks() + bahooks.hook() + print "BUG_INSTR processor extension installed" +else: + warning("This script only supports ARM files") + diff --git a/examples/ex_sync_graphs.py b/examples/ex_sync_graphs.py new file mode 100644 index 0000000..2f26150 --- /dev/null +++ b/examples/ex_sync_graphs.py @@ -0,0 +1,82 @@ + +from idaapi import * + +# +# Cleanup (in case the script is run more than once) +# +try: + wrap_a.Unbind() +except: + pass + + +wrap_a = None + +# +# The IDA View-A "monitor": changes will be reported into IDA View-B +# +class IDAViewA_monitor_t(IDAViewWrapper): + def __init__(self): + IDAViewWrapper.__init__(self, "IDA View-A") + + def OnViewLocationChanged(self, now, was): + self.update_widget_b() + + def update_widget_b(self): + + # Make sure we are in the same function + place_a, _, _ = get_custom_viewer_place(widget_a, False) + jumpto(widget_b, place_a, -1, -1) + + # and that we show the right place (slightly zoomed out) + widget_a_center_gli = graph_location_info_t() + if viewer_get_gli(widget_a_center_gli, widget_a, GLICTL_CENTER): + widget_b_center_gli = graph_location_info_t() + widget_b_center_gli.orgx = widget_a_center_gli.orgx + widget_b_center_gli.orgy = widget_a_center_gli.orgy + widget_b_center_gli.zoom = widget_a_center_gli.zoom * 0.5 + viewer_set_gli(widget_b, widget_b_center_gli, GLICTL_CENTER) + +# +# Make sure both views are opened... +# +for label in ["A", "B"]: + title = "IDA View-%s" % label + if not find_widget(title): + print("View %s not available. Opening." % title) + open_disasm_window(label) + +# +# ...and that they are both in graph mode +# +widget_a = find_widget("IDA View-A") +set_view_renderer_type(widget_a, TCCRT_GRAPH) + +widget_b = find_widget("IDA View-B") +set_view_renderer_type(widget_b, TCCRT_GRAPH) + +# +# Put view B to the right of view A +# +set_dock_pos("IDA View-B", "IDA View-A", DP_RIGHT) + +# +# Start monitoring IDA View-A +# +wrap_a = IDAViewA_monitor_t() +wrap_a.Bind() + +# +# This is to get a properly initialized set of views to begin with. +# At this point, all UI resize/move events resulting of 'set_dock_pos()' +# haven't yet been processed, and thus the views don't know their final +# geometries. We'll give them a bit of time to process those events, and +# then we'll request that "IDA View-A" shows the whole graph (and +# "IDA View-B" will obviously follow.) +# +def fit_widget_a(): + def do_fit_widget_a(): + viewer_fit_window(widget_a) + execute_sync(do_fit_widget_a, MFF_FAST) +import threading +threading.Timer(0.25, fit_widget_a).start() diff --git a/examples/ex_uihook.py b/examples/ex_uihook.py index 85f349a..f9dfd8e 100644 --- a/examples/ex_uihook.py +++ b/examples/ex_uihook.py @@ -22,7 +22,7 @@ class MyUiHook(idaapi.UI_Hooks): def postprocess(self): print("IDA finished processing command: %s" % self.cmdname) return 0 - + def saving(self): """ The kernel is saving the database. @@ -43,7 +43,7 @@ class MyUiHook(idaapi.UI_Hooks): """ IDA is terminated and the database is already closed. The UI may close its windows in this callback. - + This callback is best used with a plugin_t with flags PLUGIN_FIX """ print("IDA terminated") @@ -51,12 +51,12 @@ class MyUiHook(idaapi.UI_Hooks): def get_ea_hint(self, ea): """ The UI wants to display a simple hint for an address in the navigation band - + @param ea: The address @return: String with the hint or None """ print("get_ea_hint(%x)" % ea) - + #--------------------------------------------------------------------- # Remove an existing hook on second run diff --git a/examples/ex_uirequests.py b/examples/ex_uirequests.py index 292c6bb..cbd1566 100644 --- a/examples/ex_uirequests.py +++ b/examples/ex_uirequests.py @@ -67,7 +67,7 @@ class print_req_t(object): -if idc.AskYN(1,("HIDECANCEL\nDo you want to run execute_ui_requests() example?\n" +if idc.ask_yn(1,("HIDECANCEL\nDo you want to run execute_ui_requests() example?\n" "Press NO to execute ProcessUiActions() example\n")): idaapi.execute_ui_requests( (print_req_t("Hello"), print_req_t(" world\n")) ) diff --git a/examples/hotkey.py b/examples/hotkey.py index fdc8b5a..82dd078 100644 --- a/examples/hotkey.py +++ b/examples/hotkey.py @@ -13,12 +13,12 @@ def foo(): # IDA binds hotkeys to IDC functions so a trampoline IDC function # must be created -idaapi.CompileLine('static key_2() { RunPythonStatement("foo()"); }') +idaapi.compile_idc_text('static key_2() { RunPythonStatement("foo()"); }') # Add the hotkey -AddHotkey("2", 'key_2') +add_idc_hotkey("2", 'key_2') # Press 2 to activate foo() # The hotkey can be removed with -# DelHotkey('2') +# del_idc_hotkey('2') diff --git a/examples/idapythonrc.py b/examples/idapythonrc.py index 0d544ad..9c7b9b2 100644 --- a/examples/idapythonrc.py +++ b/examples/idapythonrc.py @@ -1,7 +1,7 @@ #--------------------------------------------------------------------- # Example user initialisation script: idapythonrc.py # -# Place this script to ~/.idapro/ or to +# Place this script to ~/.idapro/ or to # %APPDATA%\Hex-Rays\IDA Pro #--------------------------------------------------------------------- import idaapi diff --git a/examples/structure.py b/examples/structure.py index 1ebedd3..1fa9f92 100644 --- a/examples/structure.py +++ b/examples/structure.py @@ -8,42 +8,42 @@ #--------------------------------------------------------------------- from idaapi import stroffflag, offflag -sid = GetStrucIdByName("mystr1") +sid = get_struc_id("mystr1") if sid != -1: - DelStruc(sid) -sid = AddStrucEx(-1, "mystr1", 0) + del_struc(sid) +sid = add_struc(-1, "mystr1", 0) print "%x" % sid # Test simple data types -simple_types = [ FF_BYTE, FF_WORD, FF_DWRD, FF_QWRD, FF_TBYT, FF_OWRD, FF_FLOAT, FF_DOUBLE, FF_PACKREAL ] +simple_types = [ FF_BYTE, FF_WORD, FF_DWORD, FF_QWORD, FF_TBYTE, FF_OWORD, FF_FLOAT, FF_DOUBLE, FF_PACKREAL ] simple_sizes = [ 1, 2, 4, 8, 10, 16, 4, 8, 10 ] i = 0 for t,nsize in zip(simple_types, simple_sizes): - print "t%x:"% ((t|FF_DATA)&0xFFFFFFFF), AddStrucMember(sid, "t%02d"%i, BADADDR, (t|FF_DATA )&0xFFFFFFFF, -1, nsize) + print "t%x:"% ((t|FF_DATA)&0xFFFFFFFF), add_struc_member(sid, "t%02d"%i, BADADDR, (t|FF_DATA )&0xFFFFFFFF, -1, nsize) i+=1 - + # Test ASCII type -print "ASCII:", AddStrucMember(sid, "tascii", -1, FF_ASCI|FF_DATA, ASCSTR_C, 8) +print "ASCII:", add_struc_member(sid, "tascii", -1, FF_STRLIT|FF_DATA, STRTYPE_C, 8) # Test enum type - Add a defined enum name or load MACRO_WMI from a type library. -#eid = GetEnum("MACRO_WMI") -#print "Enum:", AddStrucMember(sid, "tenum", BADADDR, FF_0ENUM|FF_DATA|FF_DWRD, eid, 4) +#eid = get_enum("MACRO_WMI") +#print "Enum:", add_struc_member(sid, "tenum", BADADDR, FF_0ENUM|FF_DATA|FF_DWORD, eid, 4) # Test struc member type -msid = GetStrucIdByName("mystr2") +msid = get_struc_id("mystr2") if msid != -1: - DelStruc(msid) -msid = AddStrucEx(-1, "mystr2", 0) -print AddStrucMember(msid, "member1", -1, (FF_DWRD|FF_DATA )&0xFFFFFFFF, -1, 4) -print AddStrucMember(msid, "member2", -1, (FF_DWRD|FF_DATA )&0xFFFFFFFF, -1, 4) + del_struc(msid) +msid = add_struc(-1, "mystr2", 0) +print add_struc_member(msid, "member1", -1, (FF_DWORD|FF_DATA )&0xFFFFFFFF, -1, 4) +print add_struc_member(msid, "member2", -1, (FF_DWORD|FF_DATA )&0xFFFFFFFF, -1, 4) -msize = GetStrucSize(msid) -print "Struct:", AddStrucMember(sid, "tstruct", -1, FF_STRU|FF_DATA, msid, msize) -print "Stroff:", AddStrucMember(sid, "tstroff", -1, stroffflag()|FF_DWRD, msid, 4) +msize = get_struc_size(msid) +print "Struct:", add_struc_member(sid, "tstruct", -1, FF_STRUCT|FF_DATA, msid, msize) +print "Stroff:", add_struc_member(sid, "tstroff", -1, stroffflag()|FF_DWORD, msid, 4) # Test offset types -print "Offset:", AddStrucMember(sid, "toffset", -1, offflag()|FF_DATA|FF_DWRD, 0, 4) -print "Offset:", SetMemberType(sid, 0, offflag()|FF_DATA|FF_DWRD, 0, 4) +print "Offset:", add_struc_member(sid, "toffset", -1, offflag()|FF_DATA|FF_DWORD, 0, 4) +print "Offset:", set_member_type(sid, 0, offflag()|FF_DATA|FF_DWORD, 0, 4) print "Done" diff --git a/examples/vds3.py b/examples/vds3.py index 3057751..73fab14 100644 --- a/examples/vds3.py +++ b/examples/vds3.py @@ -3,19 +3,14 @@ Author: EiNSTeiN_ This is a rewrite in Python of the vds3 example that comes with hexrays sdk. - - -The main difference with the original C code is that when we create the inverted -condition object, the newly created cexpr_t instance is given to the hexrays and -must not be freed by swig. To achieve this, we have to change the 'thisown' flag -when appropriate. See http://www.swig.org/Doc1.3/Python.html#Python_nn35 - """ import idautils import idaapi import idc +import traceback + NETNODE_NAME = '$ hexrays-inverted-if' inverter_actname = "vds3:invert" @@ -26,16 +21,14 @@ class invert_action_handler_t(idaapi.action_handler_t): self.inverter = inverter def activate(self, ctx): - vdui = idaapi.get_tform_vdui(ctx.form) + vdui = idaapi.get_widget_vdui(ctx.widget) self.inverter.invert_if_event(vdui) return 1 def update(self, ctx): - vdui = idaapi.get_tform_vdui(ctx.form) - if vdui: - return idaapi.AST_ENABLE_FOR_FORM - else: - return idaapi.AST_DISABLE_FOR_FORM + return idaapi.AST_ENABLE_FOR_WIDGET if \ + ctx.widget_type == idaapi.BWN_PSEUDOCODE else \ + idaapi.AST_DISABLE_FOR_WIDGET class hexrays_callback_info(object): @@ -92,7 +85,6 @@ class hexrays_callback_info(object): idaapi.qswap(cif.ithen, cif.ielse) cond = idaapi.cexpr_t(cif.expr) notcond = idaapi.lnot(cond) - cond.thisown = 0 # the new wrapper 'notcond' now holds the reference to the cexpr_t cif.expr.swap(notcond) @@ -176,7 +168,7 @@ class hexrays_callback_info(object): def event_callback(self, event, *args): if event == idaapi.hxe_populating_popup: - form, phandle, vu = args + widget, phandle, vu = args res = idaapi.attach_action_to_popup(vu.ct, None, inverter_actname) elif event == idaapi.hxe_maturity: diff --git a/examples/vds4.py b/examples/vds4.py index 0cb666c..b19cff0 100644 --- a/examples/vds4.py +++ b/examples/vds4.py @@ -53,17 +53,17 @@ def run(): print "Number format at %a, operand %d: %s" % (ol.ea, ol.opnum, "negated " if (nf.props & NF_NEGATE) != 0 else "") - if nf.isEnum(): + if nf.is_enum(): print "enum %s (serial %d)" % (str(nf.type_name), nf.serial) - elif nf.isChar(): + elif nf.is_char(): print "char" - elif nf.isStroff(): + elif nf.is_stroff(): print "struct offset %s" % (str(nf.type_name), ) else: - print "number base=%d" % (idaapi.getRadix(nf.flags, ol.opnum), ) + print "number base=%d" % (idaapi.get_radix(nf.flags, ol.opnum), ) idaapi.user_numforms_free(numforms) diff --git a/examples/vds5.py b/examples/vds5.py new file mode 100644 index 0000000..51c24ec --- /dev/null +++ b/examples/vds5.py @@ -0,0 +1,308 @@ + +import ida_hexrays +import ida_kernwin +import ida_gdl +import ida_lines + +ACTION_NAME = "vds5.py:displaygraph" +ACTION_SHORTCUT = "Ctrl+Shift+G" + +CL_WHITE = ((255)+ (255<<8)+ (255<<16)) # 0 +CL_BLUE = ((0 )+ (0 <<8)+ (255<<16)) # 1 +CL_RED = ((255)+ (0 <<8)+ (0 <<16)) # 2 +CL_GREEN = ((0 )+ (255<<8)+ (0 <<16)) # 3 +CL_YELLOW = ((255)+ (255<<8)+ (0 <<16)) # 4 +CL_MAGENTA = ((255)+ (0 <<8)+ (255<<16)) # 5 +CL_CYAN = ((0 )+ (255<<8)+ (255<<16)) # 6 +CL_DARKGREY = ((85 )+ (85 <<8)+ (85 <<16)) # 7 +CL_DARKBLUE = ((0 )+ (0 <<8)+ (128<<16)) # 8 +CL_DARKRED = ((128)+ (0 <<8)+ (0 <<16)) # 9 +CL_DARKGREEN = ((0 )+ (128<<8)+ (0 <<16)) # 10 +CL_DARKYELLOW = ((128)+ (128<<8)+ (0 <<16)) # 11 +CL_DARKMAGENTA = ((128)+ (0 <<8)+ (128<<16)) # 12 +CL_DARKCYAN = ((0 )+ (128<<8)+ (128<<16)) # 13 +CL_GOLD = ((255)+ (215<<8)+ (0 <<16)) # 14 +CL_LIGHTGREY = ((170)+ (170<<8)+ (170<<16)) # 15 +CL_LIGHTBLUE = ((128)+ (128<<8)+ (255<<16)) # 16 +CL_LIGHTRED = ((255)+ (128<<8)+ (128<<16)) # 17 +CL_LIGHTGREEN = ((128)+ (255<<8)+ (128<<16)) # 18 +CL_LIGHTYELLOW = ((255)+ (255<<8)+ (128<<16)) # 19 +CL_LIGHTMAGENTA = ((255)+ (128<<8)+ (255<<16)) # 20 +CL_LIGHTCYAN = ((128)+ (255<<8)+ (255<<16)) # 21 +CL_LILAC = ((238)+ (130<<8)+ (238<<16)) # 22 +CL_TURQUOISE = ((64 )+ (224<<8)+ (208<<16)) # 23 +CL_AQUAMARINE = ((127)+ (255<<8)+ (212<<16)) # 24 +CL_KHAKI = ((240)+ (230<<8)+ (140<<16)) # 25 +CL_PURPLE = ((160)+ (32 <<8)+ (240<<16)) # 26 +CL_YELLOWGREEN = ((154)+ (205<<8)+ (50 <<16)) # 27 +CL_PINK = ((255)+ (192<<8)+ (203<<16)) # 28 +CL_ORANGE = ((255)+ (165<<8)+ (0 <<16)) # 29 +CL_ORCHID = ((218)+ (112<<8)+ (214<<16)) # 30 +CL_BLACK = ((0 )+ (0 <<8)+ (0 <<16)) # 31 + +COLORS_LUT = { + CL_WHITE : "white", + CL_BLUE : "blue", + CL_RED : "red", + CL_GREEN : "green", + CL_YELLOW : "yellow", + CL_MAGENTA : "magenta", + CL_CYAN : "cyan", + CL_DARKGREY : "darkgrey", + CL_DARKBLUE : "darkblue", + CL_DARKRED : "darkred", + CL_DARKGREEN : "darkgreen", + CL_DARKYELLOW : "darkyellow", + CL_DARKMAGENTA : "darkmagenta", + CL_DARKCYAN : "darkcyan", + CL_GOLD : "gold", + CL_LIGHTGREY : "lightgrey", + CL_LIGHTBLUE : "lightblue", + CL_LIGHTRED : "lightred", + CL_LIGHTGREEN : "lightgreen", + CL_LIGHTYELLOW : "lightyellow", + CL_LIGHTMAGENTA : "lightmagenta", + CL_LIGHTCYAN : "lightcyan", + CL_LILAC : "lilac", + CL_TURQUOISE : "turquoise", + CL_AQUAMARINE : "aquamarine", + CL_KHAKI : "khaki", + CL_PURPLE : "purple", + CL_YELLOWGREEN : "yellowgreen", + CL_PINK : "pink", + CL_ORANGE : "orange", + CL_ORCHID : "orchid", + CL_BLACK : "black", +} + +def get_color_name(c): + return COLORS_LUT[c] if c in COLORS_LUT.keys() else "?" + +class cfunc_graph_t: # alas we can't inherit gdl_graph_t + def __init__(self, highlight): + self.items = [] # list of citem_t + self.highlight = highlight + self.succs = [] # list of lists of next nodes + self.preds = [] # list of lists of previous nodes + + def nsucc(self, n): + return len(self.succs[n]) if self.size() else 0 + + def npred(self, n): + return len(self.preds[n]) if self.size() else 0 + + def succ(self, n, i): + return self.succs[n][i] + + def pred(self, n, i): + return self.preds[n][i] + + def size(self): + return len(self.preds) + + def add_node(self): + n = self.size() + + def resize(array, new_size): + if new_size > len(array): + while len(array) < new_size: + array.append([]) + else: + array = array[:new_size] + return array + + self.preds = resize(self.preds, n+1) + self.succs = resize(self.succs, n+1) + return n + + def add_edge(self, x, y): + self.preds[y].append(x) + self.succs[x].append(y) + + def get_expr_name(self, expr): + name = expr.print1(None) + name = ida_lines.tag_remove(name) + name = ida_pro.str2user(name) + return name + + def get_node_label(self, n): + item = self.items[n] + op = item.op + insn = item.cinsn + expr = item.cexpr + parts = [ida_hexrays.get_ctype_name(op)] + if op == ida_hexrays.cot_ptr: + parts.append(".%d" % expr.ptrsize) + elif op == ida_hexrays.cot_memptr: + parts.append(".%d (m=%d)" % (expr.ptrsize, expr.m)) + elif op == ida_hexrays.cot_memref: + parts.append(" (m=%d)" % (expr.m,)) + elif op in [ + ida_hexrays.cot_obj, + ida_hexrays.cot_var]: + name = self.get_expr_name(expr) + parts.append(".%d %s" % (expr.refwidth, name)) + elif op in [ + ida_hexrays.cot_num, + ida_hexrays.cot_helper, + ida_hexrays.cot_str]: + name = self.get_expr_name(expr) + parts.append(" %s" % (name,)) + elif op == ida_hexrays.cit_goto: + parts.append(" LABEL_%d" % insn.cgoto.label_num) + elif op == ida_hexrays.cit_asm: + parts.append("") + # parts.append(" %a.%d" % ()) + parts.append("\\n") + parts.append("ea: %08X" % item.ea) + if item.is_expr() and not expr.type.empty(): + parts.append("\\n") + tstr = expr.type._print() + parts.append(tstr if tstr else "?") + return "".join(parts) + + def get_node_color(self, n): + item = self.items[n] + if self.highlight is not None and item.obj_id == self.highlight.obj_id: + return CL_GREEN + return None + + def gen_gdl(self, fname): + with open(fname, "wb") as out: + out.write("graph: {\n") + + out.write("// *** nodes\n") + for n in xrange(len(self.items)): + item = self.items[n] + node_label = self.get_node_label(n) + node_props = [""] + if n == 0: + node_props.append("vertical_order: 0") + color = self.get_node_color(n) + if color is not None: + node_props.append("color: %s" % get_color_name(color)) + out.write("""node: { title: "%d" label: "%d: %s" %s}\n""" % ( + n, + n, + node_label, + " ".join(node_props))) + + out.write("// *** edges\n") + for n in xrange(len(self.items)): + item = self.items[n] + out.write("// edges %d -> ?\n" % n) + for i in xrange(self.nsucc(n)): + t = self.succ(n, i) + label = "" + if item.is_expr(): + target = self.items[t] + if item.x is not None and item.x == target: + label = "x" + elif item.y is not None and item.y == target: + label = "y" + elif item.z is not None and item.z == target: + label = "z" + if label: + label = """ label: "%s" """ % label + out.write("""edge: { sourcename: "%s" targetname: "%s"%s}\n""" % ( + str(n), str(t), label)) + + out.write("}\n") + + def dump(self): + print("%d items:" % len(self.items)) + for i in self.items: + print("\t%s (%08x)" % (i, i.ea)) + + print("succs:") + for s in self.succs: + print("\t%s" % s) + + print("preds:") + for p in self.preds: + print("\t%s" % p) + + +class graph_builder_t(ida_hexrays.ctree_parentee_t): + + def __init__(self, cg): + ida_hexrays.ctree_parentee_t.__init__(self) + self.cg = cg + self.reverse = {} # citem_t -> node# + + def add_node(self, i): + for k in self.reverse.keys(): + if i.obj_id == k.obj_id: + ida_kernwin.warning("bad ctree - duplicate nodes! (i.ea=%x)" % i.ea) + self.cg.dump() + return -1 + + n = self.cg.add_node() + if n <= len(self.cg.items): + self.cg.items.append(i) + self.cg.items[n] = i + self.reverse[i] = n + return n + + def process(self, i): + n = self.add_node(i) + if n < 0: + return n + if len(self.parents) > 1: + lp = self.parents.back().obj_id + for k, v in self.reverse.items(): + if k.obj_id == lp: + p = v + break + self.cg.add_edge(p, n) + return 0 + + def visit_insn(self, i): + return self.process(i) + + def visit_expr(self, e): + return self.process(e) + + +class display_graph_ah_t(ida_kernwin.action_handler_t): + def __init__(self): + ida_kernwin.action_handler_t.__init__(self) + + def activate(self, ctx): + vu = ida_hexrays.get_widget_vdui(ctx.widget) + vu.get_current_item(ida_hexrays.USE_KEYBOARD) + highlight = vu.item.e if vu.item.is_citem() else None + + cg = cfunc_graph_t(highlight) + gb = graph_builder_t(cg) + gb.apply_to(vu.cfunc.body, None) + + import tempfile + fname = tempfile.mktemp(suffix=".gdl") + cg.gen_gdl(fname) + ida_gdl.display_gdl(fname) + 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 + + +def cb(event, *args): + if event == ida_hexrays.hxe_populating_popup: + widget, phandle, vu = args + res = idaapi.attach_action_to_popup(vu.ct, None, ACTION_NAME) + return 0 + + +if ida_hexrays.init_hexrays_plugin(): + ida_kernwin.register_action( + ida_kernwin.action_desc_t( + ACTION_NAME, + "Hex-Rays show C graph (IDAPython)", + display_graph_ah_t(), + ACTION_SHORTCUT)) + idaapi.install_hexrays_callback(cb) +else: + print 'hexrays-graph: hexrays is not available.' diff --git a/examples/vds8.py b/examples/vds8.py new file mode 100644 index 0000000..0897ea2 --- /dev/null +++ b/examples/vds8.py @@ -0,0 +1,94 @@ + +# Hex-Rays Decompiler project +# Copyright (c) 2007-2017 by Hex-Rays, support@hex-rays.com +# ALL RIGHTS RESERVED. +# +# Sample plugin for Hex-Rays Decompiler usage of udc_filter_t +# class: decompile svc 0x900001 and svc 0x9000F8 as function calls to +# svc_exit() and svc_exit_group() respectively. +# NOTE: You will need to have an ARM + Linux IDB for this plugin to be usable +# +# It is also added into the right-click menu as "vds8.py:Toggle UDC" + +import ida_hexrays +import ida_kernwin +import ida_allins + +ACTION_NAME = "vds8.py:udcall" +ACTION_SHORTCUT = "Ctrl+Shift+U" + +# -------------------------------------------------------------------------- +class udc_exit_t(ida_hexrays.udc_filter_t): + def __init__(self, code, name): + ida_hexrays.udc_filter_t.__init__(self) + if not self.init("int __usercall %s@(int status@);" % name): + raise Exception("Couldn't initialize udc_exit_t instance") + self.code = code + self.installed = False + + def match(self, cdg): + return cdg.insn.itype == ida_allins.ARM_svc and cdg.insn.Op1.value == self.code + + def install(self): + ida_hexrays.install_microcode_filter(self, True); + self.installed = True + + def uninstall(self): + ida_hexrays.install_microcode_filter(self, False); + self.installed = False + + def toggle_install(self): + if self.installed: + self.uninstall() + else: + self.install() + + +# -------------------------------------------------------------------------- +class toggle_udc_ah_t(ida_kernwin.action_handler_t): + def __init__(self): + ida_kernwin.action_handler_t.__init__(self) + + def activate(self, ctx): + udc_exit.toggle_install(); + udc_exit_group.toggle_install(); + vu = ida_hexrays.get_widget_vdui(ctx.widget) + 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 + + +# -------------------------------------------------------------------------- +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) +my_hooks = my_hooks_t() +my_hooks.hook() + + +# -------------------------------------------------------------------------- +SVC_EXIT = 0x900001 +SVC_EXIT_GROUP = 0x9000f8 + +if ida_hexrays.init_hexrays_plugin(): + udc_exit = udc_exit_t(SVC_EXIT, "svc_exit") + udc_exit.toggle_install() + + udc_exit_group = udc_exit_t(SVC_EXIT_GROUP, "svc_exit_group") + udc_exit_group.toggle_install() + + ida_kernwin.register_action( + ida_kernwin.action_desc_t( + ACTION_NAME, + "vds8.py:Toggle UDC", + toggle_udc_ah_t(), + ACTION_SHORTCUT)) + diff --git a/examples/vds_create_hint.py b/examples/vds_create_hint.py new file mode 100644 index 0000000..860013d --- /dev/null +++ b/examples/vds_create_hint.py @@ -0,0 +1,32 @@ +"""'Hints' plugin for Hexrays Decompiler + +Hijack the 'hxe_create_hint' notification, to return our own. +If the object under the cursor is: + - a function call, prefix the original decompiler hint with "==> " + - a local variable declaration, replace the hint with our own in the form of "!{varname}" (where '{varname}' is replaced w/ the variable name) + - an 'if' statement, replace the hint with our own, saying "condition" +""" + +import ida_hexrays + +def create_hint_cb(event, *args): + if event == ida_hexrays.hxe_create_hint: + vu = args[0] + if vu.get_current_item(ida_hexrays.USE_MOUSE): + cit = vu.item.citype + if cit == ida_hexrays.VDI_LVAR: + return 1, "!%s" % vu.item.l.name, 1 + elif cit == ida_hexrays.VDI_EXPR: + ce = vu.item.e + if ce.op == ida_hexrays.cot_call: + return 2, "==> ", 1 + if ce.op == ida_hexrays.cit_if: + return 1, "condition", 1 + return 0 + return 0 + +if ida_hexrays.init_hexrays_plugin(): + ida_hexrays.install_hexrays_callback(create_hint_cb) +else: + print 'hexrays is not available.' + diff --git a/examples/vds_xrefs.py b/examples/vds_xrefs.py index b949b27..1fb55cb 100644 --- a/examples/vds_xrefs.py +++ b/examples/vds_xrefs.py @@ -60,15 +60,15 @@ class XrefsForm(idaapi.PluginForm): xtype.remove_ptr_or_array() typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, xtype, '', '') - sid = idc.GetStrucIdByName(typename) - member = idc.GetMemberName(sid, m) + sid = idc.get_struc_id(typename) + member = idc.get_member_name(sid, m) return '%s::%s' % (typename, member) - def OnCreate(self, form): + def OnCreate(self, widget): # Get parent widget - self.parent = self.FormToPyQtWidget(form) + self.parent = self.FormToPyQtWidget(widget) self.populate_form() @@ -144,7 +144,7 @@ class XrefsForm(idaapi.PluginForm): cfunc = idaapi.decompile(ea) self.functions.append(cfunc.entry_ea) - self.items.append((ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea))) + self.items.append((ea, idc.get_func_name(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea))) except Exception as e: print 'could not decompile: %s' % (str(e), ) @@ -210,7 +210,7 @@ class XrefsForm(idaapi.PluginForm): self.functions.append(cfunc.entry_ea) self.items.append(( parent.ea, - idc.GetFunctionName(cfunc.entry_ea), + idc.get_func_name(cfunc.entry_ea), self.get_decompiled_line(cfunc, parent.ea))) @@ -247,7 +247,7 @@ class XrefsForm(idaapi.PluginForm): return - def OnClose(self, form): + def OnClose(self, widget): pass @@ -257,7 +257,7 @@ class show_xrefs_ah_t(idaapi.action_handler_t): self.sel = None def activate(self, ctx): - vu = idaapi.get_tform_vdui(ctx.form) + vu = idaapi.get_widget_vdui(ctx.widget) if not vu or not self.sel: print "No vdui? Strange, since this action should be enabled only for pseudocode views." return 0 @@ -267,22 +267,21 @@ class show_xrefs_ah_t(idaapi.action_handler_t): return 1 def update(self, ctx): - vu = idaapi.get_tform_vdui(ctx.form) - if not vu: - return idaapi.AST_DISABLE_FOR_FORM - else: - vu.get_current_item(idaapi.USE_KEYBOARD) - item = vu.item - self.sel = None - if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'): - # if an expression is selected. verify that it's either a cot_obj, cot_memref or cot_memptr - self.sel = item.it.to_specific_type + if ctx.widget_type != idaapi.BWN_PSEUDOCODE: + return idaapi.AST_DISABLE_FOR_WIDGET + vu = idaapi.get_widget_vdui(ctx.widget) + vu.get_current_item(idaapi.USE_KEYBOARD) + item = vu.item + self.sel = None + if item.citype == idaapi.VDI_EXPR and item.it.to_specific_type.opname in ('obj', 'memref', 'memptr'): + # if an expression is selected. verify that it's either a cot_obj, cot_memref or cot_memptr + self.sel = item.it.to_specific_type - elif item.citype == idaapi.VDI_FUNC: - # if the function itself is selected, show xrefs to it. - self.sel = item.f + elif item.citype == idaapi.VDI_FUNC: + # if the function itself is selected, show xrefs to it. + self.sel = item.f - return idaapi.AST_ENABLE if self.sel else idaapi.AST_DISABLE + return idaapi.AST_ENABLE if self.sel else idaapi.AST_DISABLE class hexrays_callback_info(object): @@ -293,8 +292,8 @@ class hexrays_callback_info(object): try: if event == idaapi.hxe_populating_popup: - form, phandle, vu = args - idaapi.attach_action_to_popup(form, phandle, "vdsxrefs:show", None) + widget, phandle, vu = args + idaapi.attach_action_to_popup(widget, phandle, "vdsxrefs:show", None) except: traceback.print_exc() diff --git a/idapython.vcxproj b/idapython.vcxproj index 17090a7..2792f5d 100644 --- a/idapython.vcxproj +++ b/idapython.vcxproj @@ -110,6 +110,7 @@ EditAndContinue Cdecl 4102;4804;4800;4018;4005;%(DisableSpecificWarnings) + true _DEBUG;%(PreprocessorDefinitions) @@ -165,6 +166,7 @@ EditAndContinue Cdecl 4804;4800;4018;4005;%(DisableSpecificWarnings) + true _DEBUG;%(PreprocessorDefinitions) @@ -220,7 +222,7 @@ ProgramDatabase Cdecl 4102;4005;4804;4018;4800;%(DisableSpecificWarnings) - + true NDEBUG;%(PreprocessorDefinitions) 0x0419 @@ -276,6 +278,7 @@ EditAndContinue Cdecl 4102;4804;4800;4018;%(DisableSpecificWarnings) + true _DEBUG;%(PreprocessorDefinitions) @@ -318,7 +321,6 @@ - @@ -333,7 +335,6 @@ - @@ -352,7 +353,6 @@ - @@ -363,9 +363,10 @@ + - + @@ -450,4 +451,4 @@ - \ No newline at end of file + diff --git a/idapython.vcxproj.filters b/idapython.vcxproj.filters index 9da6bb5..886433a 100644 --- a/idapython.vcxproj.filters +++ b/idapython.vcxproj.filters @@ -98,9 +98,6 @@ swig_i - - swig_i - swig_i @@ -152,9 +149,6 @@ autogen - - swig_i - swig_i @@ -212,9 +206,6 @@ pywraps - - pywraps - pywraps @@ -248,13 +239,16 @@ swig_i + + swig_i + swig_i swig_i - + swig_i @@ -317,4 +311,4 @@ {b581ad45-b3f6-4591-baf0-306dab4e0590} - \ No newline at end of file + diff --git a/makefile b/makefile index 49b23fe..44b12a0 100644 --- a/makefile +++ b/makefile @@ -19,6 +19,13 @@ PROC=python API_CONTENTS=api_contents.txt PYDOC_INJECTIONS=pydoc_injections.txt +BC695=1 +ifdef BC695 + BC695_CFLAGS=-DBC695 + BC695_SWIGFLAGS=-DBC695 + BC695_DEPLOYFLAGS=--bc695 +endif + IDA_INCLUDE=../../include DIST=$(F)dist @@ -26,6 +33,8 @@ DIST=$(F)dist ifdef __NT__ SYSNAME=win MSRUNTIME=/MD + MSCLOPTS=/nologo + MSLDOPTS=/nologo endif ifdef __LINUX__ @@ -67,6 +76,11 @@ else endif endif +ifdef __NT__ + IDA_CMD=TVHEADLESS=1 $(R)idaw$(X64SUFF)$(SUFF64) +else + IDA_CMD=TVHEADLESS=1 $(R)idal$(X64SUFF)$(SUFF64) +endif ST_SWIG=$(F)swig ifeq ($(OUT_OF_TREE_BUILD),) @@ -86,10 +100,14 @@ DEPLOY_PYDIR=$(R)python DEPLOY_INIT_PY=$(DEPLOY_PYDIR)/init.py DEPLOY_IDC_PY=$(DEPLOY_PYDIR)/idc.py 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 ifeq ($(OUT_OF_TREE_BUILD),) TEST_IDC=test_idc DBLZIP_SCRIPT:=$(abspath ../../ida/build/dblzip.py) PKGBIN_SCRIPT:=$(abspath ../../ida/build/pkgbin.py) + IDC_BC695_IDC_SOURCE?=$(DEPLOY_PYDIR)/../idc/idc.idc endif # @@ -129,11 +147,12 @@ endif # We are building 'MODULES_NAMES' from subvars because it appears some versions # of make do not deal too well with '\'s, and introduce spaces, which later is # problematic when substituting ' ' for ',' & passing modules list to scripts -MNAMES_0=allins area auto bytes dbg diskio entry enum expr fixup -MNAMES_1=fpro frame funcs gdl graph $(HEXRAYS_MODNAME) ida idaapi idd idp ints -MNAMES_2=kernwin lines loader moves nalt name netnode offset pro queue -MNAMES_3=registry search segment srarea strlist struct typeinf ua xref -MODULES_NAMES=$(MNAMES_0) $(MNAMES_1) $(MNAMES_2) $(MNAMES_3) +MNAMES_0=allins range auto bytes dbg diskio entry enum expr fixup +MNAMES_1=fpro frame funcs gdl graph $(HEXRAYS_MODNAME) ida idaapi idd idp +MNAMES_2=kernwin lines loader moves nalt name netnode offset pro problems +MNAMES_3=registry search segment segregs strlist struct typeinf tryblks ua xref +MNAMES_EXTRA=idc +MODULES_NAMES=$(MNAMES_0) $(MNAMES_1) $(MNAMES_2) $(MNAMES_3) $(MNAMES_EXTRA) MODULES=$(MODULES_NAMES:%=$(F)_ida_%$(MODULE_SFX)) DEPLOYED_MODULES=$(MODULES_NAMES:%=$(DEPLOY_LIBDIR)/_ida_%$(MODULE_SFX)) @@ -154,7 +173,12 @@ ifdef __NT__ BINARY_LINKOPTS=/def:$(IDAPYTHON_IMPLIB_DEF) /IMPLIB:$(IDAPYTHON_IMPLIB_PATH) RESFILES=$(IDAPYTHON_IMPLIB_DEF) else - MODULE_LINKIDA=-L$(R) $(LINKIDA) $(BINARY) + ifeq ($(OUT_OF_TREE_BUILD),) + LIBIDA_DIR:=$(R) + else + LIBIDA_DIR:=$(L) + endif + MODULE_LINKIDA=-L$(LIBIDA_DIR) $(LINKIDA) $(BINARY) endif all: objdir pyfiles config $(DEPLOYED_MODULES) $(PYTHON_MODULES) $(ST_API_CONTENTS) $(IDAPYTHON_IMPLIB) $(ST_PYDOC_INJECTIONS) #$(TEST_IDC) @@ -193,6 +217,8 @@ else # unix/mac PRECOMPILED_COPY=$(R)$(LIBPYTHON_NAME) $(R)$(LIBPYTHON_NAME) $(patsubst precompiled/%,$(DEPLOY_PYDIR)/%,$(PYLIBFILES)) endif endif + PYTHON_LDFLAGS_RPATH_MAIN=-Wl,-rpath='$$ORIGIN/..' + PYTHON_LDFLAGS_RPATH_MODULE=-Wl,-rpath='$$$$ORIGIN/../../..' else MACDEFINES=-DMACSDKVER=$(MACSDKVER) endif @@ -208,21 +234,29 @@ endif # three modules will share type information. But any other project's # types will not interfere or clash with the types in your module. DEF_TYPE_TABLE=-DSWIG_TYPE_TABLE=idaapi -SWIGFLAGS=$(_SWIGFLAGS) $(SWIGINCLUDES) $(DEF_TYPE_TABLE) +SWIGFLAGS=$(_SWIGFLAGS) -Itools/typemaps-supplement $(SWIGINCLUDES) $(DEF_TYPE_TABLE) -D__IDP__ -D__PLUGIN__ $(BC695_SWIGFLAGS) + +ADDITIONAL_LIBS=$(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MAIN) +ifdef __LINUX__ + ADDITIONAL_LIBS_MODULE=$(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MODULE) +else + ADDITIONAL_LIBS_MODULE=$(ADDITIONAL_LIBS) +endif -ADDITIONAL_LIBS=$(PYTHON_LDFLAGS) PUBTREE_DIR=$(F)/public_tree .PHONY: pyfiles docs $(TEST_IDC) staging_dirs clean check_python package public_tree config: $(C)python.cfg -clean: +clean:: rm -rf obj/ -pyfiles: $(DEPLOY_PYDIR)/idautils.py \ - $(DEPLOY_PYDIR)/idc.py \ - $(DEPLOY_PYDIR)/init.py \ - $(DEPLOY_PYDIR)/idaapi.py +pyfiles: $(DEPLOY_IDAUTILS_PY) \ + $(DEPLOY_IDC_PY) \ + $(DEPLOY_IDC_BC695_PY) \ + $(DEPLOY_INIT_PY) \ + $(DEPLOY_IDAAPI_PY) \ + $(DEPLOY_IDADEX_PY) GENHOOKS=tools/genhooks/ _SPACE := $(null) # @@ -237,9 +271,15 @@ $(DEPLOY_IDC_PY): python/idc.py | $(DEPLOY_PYDIR) $(DEPLOY_IDAUTILS_PY): python/idautils.py | $(DEPLOY_PYDIR) $(CP) $? $@ -$(DEPLOY_PYDIR)/idaapi.py: python/idaapi.py tools/genidaapi.py | $(DEPLOY_PYDIR) +$(DEPLOY_IDC_BC695_PY): $(IDC_BC695_IDC_SOURCE) python/idc.py tools/gen_idc_bc695.py | $(DEPLOY_PYDIR) + $(PYTHON) tools/gen_idc_bc695.py --idc $(IDC_BC695_IDC_SOURCE) --output $@ + +$(DEPLOY_PYDIR)/idaapi.py: python/idaapi.py tools/genidaapi.py $(PYTHON_MODULES) | $(DEPLOY_PYDIR) $(PYTHON) tools/genidaapi.py -i $< -o $@ -m $(subst $(_SPACE),$(_COMMA),$(MODULES_NAMES)) +$(DEPLOY_PYDIR)/idadex.py: python/idadex.py | $(DEPLOY_PYDIR) + $(CP) $? $@ + $(DEPLOY_PYDIR)/lib/%: precompiled/lib/% mkdir -p $(@D) cp $< $@ @@ -299,7 +339,7 @@ $(ST_PYW)/py_idp.hpp: pywraps/py_idp.hpp \ $(GENHOOKS)recipe_idphooks.py \ $(GENERATED_HEADERS) | staging_dirs $(SDK_SOURCES) @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ - -x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e idp_notify \ + -x $(ST_PARSED_HEADERS)/structprocessor__t.xml -e event_t \ -r int -n 0 -m hookgenIDP -q "processor_t::" \ -R $(GENHOOKS)recipe_idphooks.py $(ST_PYW)/py_idp_idbhooks.hpp: pywraps/py_idp_idbhooks.hpp \ @@ -330,11 +370,24 @@ $(ST_PYW)/py_kernwin.hpp: pywraps/py_kernwin.hpp \ -r void -n 0 -m hookgenUI \ -R $(GENHOOKS)recipe_uihooks.py \ -d "ui_dbg_,ui_obsolete" -D "ui:" -s "ui_" +$(ST_PYW)/py_kernwin_viewhooks.hpp: pywraps/py_kernwin_viewhooks.hpp \ + $(I)kernwin.hpp \ + $(GENHOOKS)genhooks.py \ + $(GENHOOKS)recipe_viewhooks.py \ + $(GENERATED_HEADERS) | staging_dirs $(SDK_SOURCES) + @$(PYTHON) $(GENHOOKS)genhooks.py -i $< -o $@ \ + -x $(ST_PARSED_HEADERS)/kernwin_8hpp.xml -e view_notification_t \ + -r void -n 0 -m hookgenVIEW \ + -R $(GENHOOKS)recipe_viewhooks.py + CFLAGS= $(CCOPT) $(PLATFORM_CFLAGS) $(MSRUNTIME) -D__EXPR_SRC -I. -I$(ST_SWIG) -I$(ST_SDK) -I$(F) \ - -DVER_MAJOR="1" -DVER_MINOR="7" -DVER_PATCH="0" -D__IDP__ \ + -DVER_MAJOR="1" -DVER_MINOR="7" -DVER_PATCH="0" -D__IDP__ -D__PLUGIN__ \ -DUSE_STANDARD_FILE_FUNCTIONS $(IDAPYTHON_CFLAGS) \ - $(SWITCH64) $(SWITCHX64) $(ARCH_CFLAGS) $(WITH_HEXRAYS) $(DEF_TYPE_TABLE) + $(SWITCH64) $(SWITCHX64) $(ARCH_CFLAGS) $(WITH_HEXRAYS) $(DEF_TYPE_TABLE) $(BC695_CFLAGS) +ifdef TESTABLE_BUILD + CFLAGS+=-DTESTABLE_BUILD +endif ST_SWIG_HEADER=$(ST_SWIG)/header.i $(ST_SWIG)/header.i: tools/deploy/header.i.in tools/genswigheader.py $(ST_SDK_TARGETS) | staging_dirs @@ -342,24 +395,39 @@ $(ST_SWIG)/header.i: tools/deploy/header.i.in tools/genswigheader.py $(ST_SDK_TA ifdef __NT__ +PATCH_DIRECTORS_SCRIPT:=tools/patch_directors_cc.py + $(IDAPYTHON_IMPLIB_DEF): $(IDAPYTHON_IMPLIB_DEF_IN) sed s/%LIBNAME%/$(notdir $(BINARY))/ < $? > $@ + ifdef __X64__ + sed -i s/%PLUGIN_DATA_EXP%// $@ + else + sed -i s/%PLUGIN_DATA_EXP%/'PLUGIN DATA'/ $@ + endif +endif + +ifdef __X64__ + PATCH_CODEGEN_X64_OPTS=--apply-valist-patches endif find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $1))*.*) # Some .i files depend on some other .i files in order to be parseable by SWiG -# (e.g., srarea.i imports area.i). Declare the list of such dependencies here +# (e.g., segregs.i imports range.i). Declare the list of such dependencies here # so they will be picked by the auto-generated rules. -SWIG_IFACE_bytes=area +SWIG_IFACE_bytes=range SWIG_IFACE_dbg=idd -SWIG_IFACE_frame=area -SWIG_IFACE_funcs=area -SWIG_IFACE_gdl=area +SWIG_IFACE_frame=range +SWIG_IFACE_funcs=range +SWIG_IFACE_gdl=range SWIG_IFACE_hexrays=typeinf -SWIG_IFACE_segment=area -SWIG_IFACE_srarea=area +SWIG_IFACE_segment=range +SWIG_IFACE_segregs=range SWIG_IFACE_typeinf=idp +SWIG_IFACE_tryblks=range + +MODULE_LIFECYCLE_hexrays=--lifecycle-aware +MODULE_LIFECYCLE_bytes=--lifecycle-aware define make-module-rules @@ -384,19 +452,24 @@ define make-module-rules # obj/x86_linux_gcc/swig/X.i $(ST_SWIG)/$1.i: $(addprefix $(F),$(call find-pywraps-deps,$1)) swig/$1.i $(ST_SWIG_HEADER) $(SWIG_IFACE_$1:%=$(ST_SWIG)/%.i) $(ST_SWIG_HEADER) tools/deploy.py - $(PYTHON) tools/deploy.py --pywraps $(ST_PYW) --template $$(subst $(F),,$$@) --output $$@ --module $$(subst .i,,$$(notdir $$@)) --interface-dependencies=$(subst $(_SPACE),$(_COMMA),$(SWIG_IFACE_$1)) + $(PYTHON) tools/deploy.py \ + --pywraps $(ST_PYW) \ + --template $$(subst $(F),,$$@) \ + --output $$@ \ + --module $$(subst .i,,$$(notdir $$@)) \ + $(MODULE_LIFECYCLE_$1) \ + $(BC695_DEPLOYFLAGS) \ + --interface-dependencies=$(subst $(_SPACE),$(_COMMA),$(SWIG_IFACE_$1)) # obj/x86_linux_gcc/wrappers/X.cpp - $(ST_WRAP)/$1.cpp: $(ST_SWIG)/$1.i tools/patch_codegen.py + $(ST_WRAP)/$1.cpp: $(ST_SWIG)/$1.i tools/patch_codegen.py makefile $(PATCH_DIRECTORS_SCRIPT) tools/chkapi.py $(SWIG) -modern $(WITH_HEXRAYS) -python -threads -c++ -shadow \ $(MACDEFINES) -D__GNUC__ $(SWIGFLAGS) $(SWITCH64) $(SWITCHX64) -I$(ST_SWIG) \ -outdir $(ST_WRAP) -o $$@ -I$(ST_SDK) $$< @$(PYTHON) tools/patch_constants.py --file $(ST_WRAP)/$1.cpp - ifdef __X64__ - $(PYTHON) tools/patch_codegen.py --file $(ST_WRAP)/$1.cpp --patches tools/patch_codegen/$1.py - endif + $(PYTHON) tools/patch_codegen.py $(PATCH_CODEGEN_X64_OPTS) --file $(ST_WRAP)/$1.cpp --patches tools/patch_codegen/$1.py ifdef __NT__ - @$(PYTHON) tools/patch_directors_cc.py --file $(ST_WRAP)/$1.h + $(PYTHON) $(PATCH_DIRECTORS_SCRIPT) --file $(ST_WRAP)/$1.h endif # The copying of the .py will preserve attributes (including timestamps). # And, since we have patched $1.cpp, it'll be more recent than ida_$1.py, @@ -409,7 +482,7 @@ define make-module-rules ifdef __CODE_CHECKER__ touch $$@ else - $(CXX) $(CFLAGS) $(MSRUNTIME) $(NORTTI) -DPLUGIN_SUBMODULE -DSWIG_DIRECTOR_NORTTI -c $(OBJSW)$$@ $(ST_WRAP)/$1.cpp + $(CXX) $(CFLAGS) $(MSRUNTIME) $(MSCLOPTS) $(NORTTI) -DPLUGIN_SUBMODULE -DSWIG_DIRECTOR_NORTTI -c $(OBJSW)$$@ $(ST_WRAP)/$1.cpp ifndef __NT__ ifeq ($(OUT_OF_TREE_BUILD),) @$(STRIPSYM_TOOL) $$@ $(STRIPSYMS) > /dev/null || ($(RM) $$@; false) @@ -419,10 +492,10 @@ define make-module-rules # obj/x86_linux_gcc/_ida_X.so $(F)_ida_$1$(MODULE_SFX): $(F)$1$(O) $(BINARY) $(IDAPYTHON_IMPLIB_DEF) - ifdef __NT__ - $(LINKER) $(LINKOPTS) /OPT:ICF /OPT:REF /INCREMENTAL:NO /STUB:../../plugins/stub /OUT:$$@ $$< $(IDALIB) user32.lib $(ADDITIONAL_LIBS) $(IDAPYTHON_IMPLIB_PATH) + ifdef __NT__ # we repeat /map switch with the explicit file name because @F does not work inside macro + $(LINKER) $(LINKOPTS) /map:$(F)_ida_$1$(MODULE_SFX).map $(MSLDOPTS) /OPT:ICF /OPT:REF /INCREMENTAL:NO /STUB:../../plugins/stub /OUT:$$@ $$< $(IDALIB) user32.lib $(ADDITIONAL_LIBS_MODULE) $(IDAPYTHON_IMPLIB_PATH) else - $(CCL) $(OUTDLL) $(OUTSW)$$@ $$< $(MODULE_LINKIDA) $(PLUGIN_SCRIPT) $(ADDITIONAL_LIBS) $(STDLIBS) + $(CCL) $(OUTDLL) $(OUTSW)$$@ $$< $(MODULE_LINKIDA) $(PLUGIN_SCRIPT) $(ADDITIONAL_LIBS_MODULE) $(STDLIBS) endif # ../../bin/x86_linux_gcc/python/lib/lib-dynload/ida_32/_ida_X.so @@ -434,10 +507,12 @@ $(foreach mod,$(MODULES_NAMES),$(eval $(call make-module-rules,$(mod)))) $(ST_API_CONTENTS): $(ALL_ST_WRAP_CPP) $(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(_SPACE),$(_COMMA),$(ALL_ST_WRAP_CPP)) -p $(subst $(_SPACE),$(_COMMA),$(ALL_ST_WRAP_PY)) -r $(ST_API_CONTENTS) ifeq ($(OUT_OF_TREE_BUILD),) + ifdef BC695 # turn off comparison when bw-compat is off, or api_contents will differ @(diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null || \ (echo "API CONTENTS CHANGED! update api_contents.txt or fix the API" && \ echo "(New API: $(ST_API_CONTENTS)) ***" && \ (diff -U 1 -w $(API_CONTENTS) $(ST_API_CONTENTS) && false)) + endif endif # Check that doc injection is stable @@ -471,15 +546,6 @@ else $(R)idaq -Stools/docs/hrdoc.py -t endif -# Test that all functions that are present in ftable.cpp -# are present in idc.py (and therefore made available by -# the idapython). -ifdef __NT__ - IDA_CMD=TVHEADLESS=1 $(R)idaw$(X64SUFF)$(SUFF64) -else - IDA_CMD=TVHEADLESS=1 $(R)idal$(X64SUFF)$(SUFF64) -endif - # the demo version of ida does not have the -B command line option ifeq ($(OUT_OF_TREE_BUILD),) ISDEMO=$(shell grep "define DEMO$$" $(IDA_INCLUDE)/commerc.hpp) @@ -488,6 +554,9 @@ ifeq ($(OUT_OF_TREE_BUILD),) endif endif +# Test that all functions that are present in ftable.cpp +# are present in idc.py (and therefore made available by +# the idapython). $(TEST_IDC): $(F)idctest.log $(F)idctest.log: $(RS)idc/idc.idc | $(BINARY) pyfiles $(PRECOMPILED_COPY) ifneq ($(wildcard ../../tests),) @@ -523,9 +592,9 @@ echo_modules: @echo $(MODULES_NAMES) # MAKEDEP dependency list ------------------ -$(F)python$(O) : $(I)area.hpp $(I)bitrange.hpp $(I)bytes.hpp \ +$(F)python$(O) : $(I)range.hpp $(I)bitrange.hpp $(I)bytes.hpp \ $(I)diskio.hpp $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)config.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ $(I)netnode.hpp $(I)pro.h $(I)segment.hpp $(I)ua.hpp \ $(I)xref.hpp python.cpp pywraps.hpp pywraps.cpp | $(ST_SDK_TARGETS) diff --git a/out_of_tree/parsed_notifications.zip b/out_of_tree/parsed_notifications.zip index 847d62b..2cec574 100644 Binary files a/out_of_tree/parsed_notifications.zip and b/out_of_tree/parsed_notifications.zip differ diff --git a/pydoc_injections.txt b/pydoc_injections.txt index 74e4b0a..e735b3c 100644 --- a/pydoc_injections.txt +++ b/pydoc_injections.txt @@ -1,19 +1,16 @@ ### Processing allins.i -### Processing area.i +### Processing range.i ### Processing auto.i ### Processing bytes.i fix_fun: found info for visit_patched_bytes -fix_fun: found info for nextthat -fix_fun: found info for get_many_bytes -fix_fun: found info for get_many_bytes_ex -fix_fun: found info for get_ascii_contents2 -fix_fun: found info for get_ascii_contents +fix_fun: found info for next_that +fix_fun: found info for get_bytes +fix_fun: found info for get_bytes_and_mask +fix_fun: found info for get_strlit_contents fix_fun: found info for register_custom_data_type fix_fun: found info for unregister_custom_data_type fix_fun: found info for register_custom_data_format fix_fun: found info for unregister_custom_data_format -fix_fun: found info for get_custom_data_format -fix_fun: found info for get_custom_data_type ### Processing dbg.i fix_fun: found info for get_manual_regions fix_fun: found info for dbg_is_loaded @@ -42,13 +39,11 @@ fix_method: found info for write fix_method: found info for flush fix_method: found info for put_char ### Processing frame.i -fix_fun: found info for add_stkvar3 fix_fun: found info for get_stkvar ### Processing funcs.i fix_fun: found info for get_fchunk_referer fix_fun: found info for get_idasgn_desc fix_fun: found info for get_idasgn_desc_with_matches -fix_fun: found info for get_func_cmt ### Processing gdl.i ### Processing graph.i ### Processing hexrays.i @@ -90,12 +85,11 @@ fix_fun: found info for ph_get_version fix_fun: found info for ph_get_flag fix_fun: found info for ph_get_cnbits fix_fun: found info for ph_get_dnbits -fix_fun: found info for ph_get_regFirstSreg -fix_fun: found info for ph_get_regLastSreg +fix_fun: found info for ph_get_reg_first_sreg +fix_fun: found info for ph_get_reg_last_sreg fix_fun: found info for ph_get_segreg_size -fix_fun: found info for ph_get_regCodeSreg -fix_fun: found info for ph_get_regDataSreg -fix_fun: found info for ph_get_high_fixup_bits +fix_fun: found info for ph_get_reg_code_sreg +fix_fun: found info for ph_get_reg_data_sreg fix_fun: found info for ph_get_icode_return fix_fun: found info for ph_get_instruc_start fix_fun: found info for ph_get_instruc_end @@ -106,42 +100,29 @@ fix_fun: found info for ph_get_operand_info fix_class: found info for IDP_Hooks fix_method: found info for hook fix_method: found info for unhook -fix_method: found info for assemble -fix_method: found info for rename -fix_method: found info for closebase -fix_method: found info for load_idasgn -fix_method: found info for may_be_func -fix_method: found info for is_sane_insn -fix_method: found info for custom_ana -fix_method: found info for custom_out -fix_method: found info for custom_emu -fix_method: found info for custom_outop -fix_method: found info for custom_mnem -fix_method: found info for undefine -fix_method: found info for make_code -fix_method: found info for make_data -fix_method: found info for is_call_insn -fix_method: found info for is_ret_insn -fix_method: found info for savebase -fix_method: found info for renamed -fix_method: found info for add_func -fix_method: found info for del_func -### Processing ints.i +fix_method: found info for ev_ana_insn +fix_method: found info for ev_emu_insn +fix_method: found info for ev_out_insn +fix_method: found info for ev_out_operand +fix_method: found info for ev_undefine +fix_method: found info for ev_rename +fix_method: found info for ev_is_sane_insn +fix_method: found info for ev_is_call_insn +fix_method: found info for ev_is_ret_insn +fix_method: found info for ev_may_be_func +fix_method: found info for ev_assemble ### Processing kernwin.i fix_fun: found info for register_timer fix_fun: found info for unregister_timer fix_fun: found info for choose_idasgn -fix_fun: found info for get_highlighted_identifier -fix_fun: found info for umsg +fix_fun: found info for get_highlight fix_fun: found info for msg -fix_fun: found info for asktext +fix_fun: found info for ask_text +fix_fun: found info for ask_str fix_fun: found info for str2ea -fix_fun: found info for str2user fix_fun: found info for process_ui_action -fix_fun: found info for del_menu_item fix_fun: found info for del_hotkey fix_fun: found info for add_hotkey -fix_fun: found info for add_menu_item fix_fun: found info for execute_sync fix_fun: found info for execute_ui_requests fix_class: found info for UI_Hooks @@ -151,18 +132,18 @@ fix_method: found info for saving fix_method: found info for saved fix_method: found info for term fix_method: found info for get_ea_hint -fix_method: found info for preprocess -fix_method: found info for postprocess +fix_method: found info for preprocess_action +fix_method: found info for postprocess_action fix_method: found info for updating_actions fix_method: found info for updated_actions -fix_method: found info for populating_tform_popup -fix_method: found info for finish_populating_tform_popup +fix_method: found info for populating_widget_popup +fix_method: found info for finish_populating_widget_popup fix_fun: found info for set_nav_colorizer fix_fun: found info for call_nav_colorizer fix_fun: found info for set_dock_pos fix_fun: found info for free_custom_icon fix_fun: found info for is_idaq -fix_fun: found info for readsel2 +fix_fun: found info for read_selection ### Processing lines.i fix_fun: found info for tag_remove fix_fun: found info for set_user_defined_prefix @@ -174,42 +155,36 @@ fix_fun: found info for run_plugin ### Processing moves.i ### Processing nalt.i fix_fun: found info for get_import_module_name -fix_fun: found info for get_switch_info_ex -fix_fun: found info for set_switch_info_ex -fix_fun: found info for del_switch_info_ex +fix_fun: found info for get_switch_info +fix_fun: found info for set_switch_info +fix_fun: found info for del_switch_info fix_fun: found info for enum_import_names ### Processing name.i ### Processing netnode.i ### Processing offset.i ### Processing pro.i -### Processing queue.i +fix_fun: found info for str2user +### Processing problems.i ### Processing registry.i ### Processing search.i ### Processing segment.i -### Processing srarea.i +### Processing segregs.i ### Processing strlist.i ### Processing struct.i ### Processing typeinf.i fix_fun: found info for calc_type_size fix_fun: found info for apply_type -fix_fun: found info for print_type +fix_fun: found info for get_arg_addrs fix_fun: found info for unpack_object_from_bv fix_fun: found info for pack_object_to_idb fix_fun: found info for pack_object_to_bv fix_fun: found info for get_named_type -fix_fun: found info for apply_type_to_stkarg +### Processing tryblks.i ### Processing ua.i -fix_fun: found info for init_output_buffer -fix_fun: found info for term_output_buffer fix_fun: found info for decode_preceding_insn -fix_fun: found info for OutValue -fix_fun: found info for OutImmChar -fix_fun: found info for ua_stkvar2 -fix_fun: found info for ua_add_off_drefs -fix_fun: found info for ua_add_off_drefs2 -fix_fun: found info for out_name_expr fix_fun: found info for construct_macro ### Processing xref.i fix_fun: found info for create_switch_xrefs fix_fun: found info for calc_switch_cases fix_fun: found info for create_switch_table +### Processing idc.i diff --git a/python.cfg b/python.cfg index b2a1857..28af8c0 100644 --- a/python.cfg +++ b/python.cfg @@ -12,3 +12,7 @@ SCRIPT_TIMEOUT = 3 // Should the plugin automatically load a backward-compatibility-providing // 'idaapi' wrapper module? AUTOIMPORT_COMPAT_IDAAPI = YES + +// Should the plugin automatically load a 6.95 bw-compatibility layer? +AUTOIMPORT_COMPAT_IDA695 = YES + diff --git a/python.cpp b/python.cpp index a02a6a2..eb55d7b 100644 --- a/python.cpp +++ b/python.cpp @@ -58,9 +58,9 @@ static const char S_IDAPYTHON_DATA_NODE[] = "IDAPython_Data"; // enum script_run_when { - run_on_db_open = 0, // run script after opening database (default) - run_on_ui_ready = 1, // run script when UI is ready - run_on_init = 2, // run script immediately on plugin load (shortly after IDA starts) + RUN_ON_DB_OPEN = 0, // run script after opening database (default) + RUN_ON_UI_READY = 1, // run script when UI is ready + RUN_ON_INIT = 2, // run script immediately on plugin load (shortly after IDA starts) }; //------------------------------------------------------------------------- @@ -79,7 +79,7 @@ static char g_idapython_dir[QMAXPATH]; // extern "C" void init_idaapi(void); // Plugin run() callback -void idaapi run(int arg); +bool idaapi run(size_t); //------------------------------------------------------------------------- // This is a simple tracing code for debugging purposes. @@ -116,13 +116,14 @@ static bool g_alert_auto_scripts = true; static bool g_remove_cwd_sys_path = false; static bool g_use_local_python = false; static bool g_autoimport_compat_idaapi = true; +static bool g_autoimport_compat_ida695 = true; // Allowing the user to interrupt a script is not entirely trivial. // Imagine the following script, that is run in an IDB that uses // an IDAPython processor module (important!) : // --- // while True: -// gen_disasm_text(ea, ea + 4, dtext, False) +// gen_disasm_text(dtext, ea, ea + 4, False) // --- // This script will call the processor module's out/outop functions in // order to generate the text. If the processor module behaves @@ -157,11 +158,13 @@ struct execution_t int timeout; uint32 steps_before_action; bool waitdialog_shown; + bool interruptible_state; execution_t() : timeout(2), steps_before_action(0), - waitdialog_shown(false) + waitdialog_shown(false), + interruptible_state(true) { reset_steps(); } @@ -172,6 +175,7 @@ struct execution_t void stop_tracking(); void sync_to_present_time(); void maybe_hide_waitdialog(); + void set_interruptible(bool intr) { interruptible_state = intr; } static int on_trace(PyObject *obj, _frame *frame, int what, PyObject *arg); }; static execution_t execution; @@ -192,7 +196,7 @@ void execution_t::reset_steps() // E.g., imagine the following loop: // --- // while True: - // gen_disasm_text(ea, ea + 4, dtext, False) + // gen_disasm_text(dtext, ea, ea + 4, False) // --- // If we never hit the 'trace' callback while in the 'while True' loop // but always when performing the call to the processor module's 'out/outop' @@ -248,7 +252,7 @@ void execution_t::maybe_hide_waitdialog() bool execution_t::can_interrupt_current(time_t now) const { LEXEC("can_interrupt_current(): nentries: %d\n", int(entries.size())); - if ( entries.empty() || timeout <= 0 ) + if ( entries.empty() || timeout <= 0 || !interruptible_state ) return false; const exec_entry_t &last = entries.back(); bool can = (now - last.etime) > timeout; @@ -276,7 +280,7 @@ int execution_t::on_trace(PyObject *obj, _frame *frame, int what, PyObject *arg) int(execution.waitdialog_shown)); if ( execution.waitdialog_shown ) { - if ( wasBreak() ) + if ( user_cancelled() ) { LEXEC("on_trace()::INTERRUPTING\n"); PyErr_SetString(PyExc_KeyboardInterrupt, "User interrupted"); @@ -326,6 +330,12 @@ struct new_execution_t } }; +//------------------------------------------------------------------------- +void ida_export set_interruptible_state(bool interruptible) +{ + execution.set_interruptible(interruptible); +} + //------------------------------------------------------------------------- //lint -esym(714,disable_script_timeout) Symbol not referenced idaman void ida_export disable_script_timeout() @@ -353,20 +363,17 @@ idaman int ida_export set_script_timeout(int timeout) //------------------------------------------------------------------------ // Return a formatted error or just print it to the console static void handle_python_error( - char *errbuf, - size_t errbufsize, - bool clear_error = true) + qstring *errbuf, + bool clear_error = true) { - if ( errbufsize > 0 && errbuf != NULL ) - errbuf[0] = '\0'; + if ( errbuf != NULL ) + errbuf->clear(); // No exception? if ( !PyErr_Occurred() ) return; - qstring s; - if ( PyW_GetError(&s, clear_error) && errbuf != NULL ) - qstrncpy(errbuf, s.c_str(), errbufsize); + PyW_GetError(errbuf, clear_error); } //------------------------------------------------------------------------ @@ -380,8 +387,8 @@ static PyObject *GetMainGlobals() //------------------------------------------------------------------------ static void PythonEvalOrExec( - const char *str, - const char *filename = "") + const char *str, + const char *filename = "") { // Compile as an expression PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -418,7 +425,7 @@ static void PythonEvalOrExec( newref_t py_result_utf8(PyUnicode_AsUTF8String(py_result.o)); ok = py_result_utf8 != NULL; if ( ok ) - umsg("%s\n", PyString_AS_STRING(py_result_utf8.o)); + msg("%s\n", PyString_AS_STRING(py_result_utf8.o)); } else { @@ -437,10 +444,9 @@ static void PythonEvalOrExec( //------------------------------------------------------------------------ // Executes a simple string -static bool idaapi IDAPython_extlang_run_statements( - const char *str, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_eval_snippet( + const char *str, + qstring *errbuf) { PYW_GIL_GET; PyObject *globals = GetMainGlobals(); @@ -451,7 +457,7 @@ static bool idaapi IDAPython_extlang_run_statements( } else { - errbuf[0] = '\0'; + errbuf->clear(); PyErr_Clear(); { new_execution_t exec; @@ -462,23 +468,22 @@ static bool idaapi IDAPython_extlang_run_statements( globals)); ok = result != NULL && !PyErr_Occurred(); if ( !ok ) - handle_python_error(errbuf, errbufsize); + handle_python_error(errbuf); } } - if ( !ok && errbuf[0] == '\0' ) - qstrncpy(errbuf, "internal error", errbufsize); + if ( !ok && errbuf->empty() ) + *errbuf = "internal error"; return ok; } //------------------------------------------------------------------------ // Simple Python statement runner function for IDC -static const char idc_runpythonstatement_args[] = { VT_STR2, 0 }; static error_t idaapi idc_runpythonstatement( - idc_value_t *argv, - idc_value_t *res) + idc_value_t *argv, + idc_value_t *res) { - char errbuf[MAXSTR]; - bool ok = IDAPython_extlang_run_statements(argv[0].c_str(), errbuf, sizeof(errbuf)); + qstring errbuf; + bool ok = IDAPython_extlang_eval_snippet(argv[0].c_str(), &errbuf); if ( ok ) res->set_long(0); @@ -487,6 +492,16 @@ static error_t idaapi idc_runpythonstatement( return eOk; } +static const char idc_runpythonstatement_args[] = { VT_STR, 0 }; +static const ext_idcfunc_t idc_runpythonstatement_desc = +{ + S_IDC_RUNPYTHON_STATEMENT, + idc_runpythonstatement, + idc_runpythonstatement_args, + NULL, + 0, + 0 +}; //-------------------------------------------------------------------------- static const cfgopt_t opts[] = @@ -495,6 +510,7 @@ static const cfgopt_t opts[] = cfgopt_t("ALERT_AUTO_SCRIPTS", &g_alert_auto_scripts, true), cfgopt_t("REMOVE_CWD_SYS_PATH", &g_remove_cwd_sys_path, true), cfgopt_t("AUTOIMPORT_COMPAT_IDAAPI", &g_autoimport_compat_idaapi, true), + cfgopt_t("AUTOIMPORT_COMPAT_IDA695", &g_autoimport_compat_ida695, true), }; //------------------------------------------------------------------------- @@ -548,7 +564,7 @@ static int PyRunFile(const char *FileName) char curdir[QMAXPATH]; // check if the current directory is accessible. if not, qgetcwd won't return qgetcwd(curdir, sizeof(curdir)); - if ( getdspace(curdir) == 0 ) + if ( get_free_disk_space(curdir) == 0 ) { warning("No free disk space on %s, python will not be available", curdir); return 0; @@ -581,27 +597,23 @@ static int PyRunFile(const char *FileName) // Execute Python statement(s) from an editor window void IDAPython_RunStatement(void) { - char statement[16 * MAXSTR]; + qstring qbuf; netnode history; // Get the existing or create a new netnode in the database history.create(S_IDAPYTHON_DATA_NODE); + history.getblob(&qbuf, 0, 'A'); - // Fetch the previous statement - size_t statement_size = sizeof(statement); - - if ( history.getblob(statement, &statement_size, 0, 'A') == NULL ) - statement[0] = '\0'; - - if ( asktext(sizeof(statement), statement, statement, "ACCEPT TABS\nEnter Python expressions") != NULL ) + if ( ask_text(&qbuf, 0, qbuf.c_str(), "ACCEPT TABS\nEnter Python expressions") ) { { + PYW_GIL_GET; new_execution_t exec; - PyRun_SimpleString(statement); + PyRun_SimpleString(qbuf.c_str()); } // Store the statement to the database - history.setblob(statement, strlen(statement) + 1, 0, 'A'); + history.setblob(qbuf.c_str(), qbuf.size(), 0, 'A'); } } @@ -609,17 +621,16 @@ void IDAPython_RunStatement(void) // Convert return value from Python to IDC or report about an error. // This function also decrements the reference "result" (python variable) static bool return_python_result( - idc_value_t *idc_result, - const ref_t &py_result, - char *errbuf, - size_t errbufsize) + idc_value_t *idc_result, + const ref_t &py_result, + qstring *errbuf) { - if ( errbufsize > 0 ) - errbuf[0] = '\0'; + if ( errbuf != NULL ) + errbuf->clear(); if ( py_result == NULL ) { - handle_python_error(errbuf, errbufsize); + handle_python_error(errbuf); return false; } @@ -628,8 +639,8 @@ static bool return_python_result( { idc_result->clear(); cvt = pyvar_to_idcvar(py_result, idc_result); - if ( cvt < CIP_OK ) - qsnprintf(errbuf, errbufsize, "ERROR: bad return value"); + if ( cvt < CIP_OK && errbuf != NULL ) + *errbuf = "ERROR: bad return value"; } return cvt >= CIP_OK; @@ -643,8 +654,7 @@ static bool return_python_result( // module reloading. static bool IDAPython_ExecFile( const char *FileName, - char *errbuf, - size_t errbufsz, + qstring *errbuf, const char *idaapi_script = S_IDAAPI_EXECSCRIPT, idc_value_t *second_res = NULL, bool want_tuple = false) @@ -653,7 +663,7 @@ static bool IDAPython_ExecFile( ref_t py_execscript(get_idaapi_attr(idaapi_script)); if ( py_execscript == NULL ) { - qsnprintf(errbuf, errbufsz, "Could not find %s.%s ?!", S_IDA_IDAAPI_MODNAME, idaapi_script); + errbuf->sprnt("Could not find %s.%s ?!", S_IDA_IDAAPI_MODNAME, idaapi_script); return false; } @@ -672,14 +682,11 @@ static bool IDAPython_ExecFile( // Failure at this point means the script was interrupted bool interrupted = false; - qstring err; - if ( PyW_GetError(&err) || py_ret == NULL ) + if ( PyW_GetError(errbuf) || py_ret == NULL ) { PyErr_Clear(); - if ( err.empty() ) - qstrncpy(errbuf, "Script interrupted", errbufsz); - else - qstrncpy(errbuf, err.c_str(), errbufsz); + if ( errbuf->empty() ) + *errbuf = "Script interrupted"; interrupted = true; } @@ -710,7 +717,7 @@ static bool IDAPython_ExecFile( if ( want_tuple ) { borref_t ret2_o(PyTuple_GetItem(py_ret.o, 1)); - ok = return_python_result(second_res, ret2_o, errbuf, errbufsz); + ok = return_python_result(second_res, ret2_o, errbuf); } else { @@ -719,7 +726,7 @@ static bool IDAPython_ExecFile( } else if ( PyString_Check(ret_o) ) { - qstrncpy(errbuf, PyString_AsString(ret_o), errbufsz); + *errbuf = PyString_AsString(ret_o); } else { @@ -733,14 +740,14 @@ static bool IDAPython_ExecFile( // Execute the Python script from the plugin static bool RunScript(const char *script) { - char errbuf[MAXSTR]; + qstring errbuf; bool ok; { new_execution_t exec; - ok = IDAPython_ExecFile(script, errbuf, sizeof(errbuf)); + ok = IDAPython_ExecFile(script, &errbuf); } if ( !ok ) - warning("IDAPython: error executing '%s':\n%s", script, errbuf); + warning("IDAPython: error executing '%s':\n%s", script, errbuf.c_str()); return ok; } @@ -751,11 +758,11 @@ static bool RunScript(const char *script) // parse_py_modname("modname.attrname", mod_buf, attr_buf) // It splits the full name into two parts. static bool parse_py_modname( - const char *full_name, - char *modname, - char *attrname, - size_t sz, - const char *defmod = S_IDA_IDAAPI_MODNAME) + const char *full_name, + char *modname, + char *attrname, + size_t sz, + const char *defmod = S_IDA_IDAAPI_MODNAME) { const char *p = strchr(full_name, '.'); if ( p == NULL ) @@ -773,18 +780,17 @@ static bool parse_py_modname( //------------------------------------------------------------------------- // Run callback for Python external language evaluator -bool idaapi IDAPython_extlang_run( - const char *name, - int nargs, - const idc_value_t args[], - idc_value_t *result, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_call_func( + idc_value_t *result, + const char *name, + const idc_value_t args[], + size_t nargs, + qstring *errbuf) { PYW_GIL_GET; // Try to extract module name (if any) from the funcname - char modname[MAXSTR] = {0}; - char funcname[MAXSTR] = {0}; + char modname[MAXSTR]; + char funcname[MAXSTR]; bool imported_module = parse_py_modname(name, modname, funcname, MAXSTR); bool ok = true; @@ -793,7 +799,7 @@ bool idaapi IDAPython_extlang_run( do { // Convert arguments to python - ok = pyw_convert_idc_args(args, nargs, pargs, false, errbuf, errbufsize); + ok = pyw_convert_idc_args(args, nargs, pargs, 0, errbuf); if ( !ok ) break; @@ -813,7 +819,7 @@ bool idaapi IDAPython_extlang_run( PyObject *func = PyDict_GetItemString(globals, funcname); if ( func == NULL ) { - qsnprintf(errbuf, errbufsize, "undefined function %s", name); + errbuf->sprnt("undefined function %s", name); ok = false; break; } @@ -827,7 +833,7 @@ bool idaapi IDAPython_extlang_run( pargs_ptrs.begin(), nargs, NULL, 0, NULL, 0, NULL)); - ok = return_python_result(result, py_res, errbuf, errbufsize); + ok = return_python_result(result, py_res, errbuf); } while ( false ); if ( imported_module ) @@ -849,32 +855,31 @@ static void wrap_in_function(qstring *out, const qstring &body, const char *name //------------------------------------------------------------------------- // Compile callback for Python external language evaluator -bool idaapi IDAPython_extlang_compile( - const char *name, - ea_t /*current_ea*/, - const char *expr, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_compile_expr( + const char *name, + ea_t /*current_ea*/, + const char *expr, + qstring *errbuf) { PYW_GIL_GET; PyObject *globals = GetMainGlobals(); - bool is_func = false; + bool isfunc = false; PyCodeObject *code = (PyCodeObject *)Py_CompileString(expr, "", Py_eval_input); if ( code == NULL ) { // try compiling as a list of statements // wrap them into a function - handle_python_error(errbuf, errbufsize); + handle_python_error(errbuf); qstring func; wrap_in_function(&func, expr, name); code = (PyCodeObject *)Py_CompileString(func.c_str(), "", Py_file_input); if ( code == NULL ) { - handle_python_error(errbuf, errbufsize); + handle_python_error(errbuf); return false; } - is_func = true; + isfunc = true; } // Set the desired function name @@ -887,7 +892,7 @@ bool idaapi IDAPython_extlang_compile( if ( func == NULL ) { ERR: - handle_python_error(errbuf, errbufsize); + handle_python_error(errbuf); Py_XDECREF(code); return false; } @@ -898,44 +903,41 @@ ERR: if ( err ) goto ERR; - if ( is_func ) + if ( isfunc ) { - const idc_value_t args; idc_value_t result; - return IDAPython_extlang_run(name, 0, &args, &result, errbuf, errbufsize); + return IDAPython_extlang_call_func(&result, name, NULL, 0, errbuf); } return true; } //------------------------------------------------------------------------- // Compile callback for Python external language evaluator -bool idaapi IDAPython_extlang_compile_file( - const char *filename, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_compile_file( + const char *path, + qstring *errbuf) { PYW_GIL_GET; new_execution_t exec; - return IDAPython_ExecFile(filename, errbuf, errbufsize); + return IDAPython_ExecFile(path, errbuf); } //------------------------------------------------------------------------- // Load processor module callback for Python external language evaluator -static bool idaapi IDAPython_extlang_loadprocmod( - const char *filename, +static bool idaapi IDAPython_extlang_load_procmod( idc_value_t *procobj, - char *errbuf, - size_t errbufsize) + const char *path, + qstring *errbuf) { PYW_GIL_GET; bool ok; { new_execution_t exec; - ok = IDAPython_ExecFile(filename, errbuf, errbufsize, S_IDAAPI_LOADPROCMOD, procobj, true); + ok = IDAPython_ExecFile(path, errbuf, S_IDAAPI_LOADPROCMOD, procobj, true); } if ( ok && procobj->is_zero() ) { - errbuf[0] = '\0'; + errbuf->clear(); ok = false; } return ok; @@ -943,25 +945,24 @@ static bool idaapi IDAPython_extlang_loadprocmod( //------------------------------------------------------------------------- // Unload processor module callback for Python external language evaluator -static bool idaapi IDAPython_extlang_unloadprocmod( - const char *filename, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_unload_procmod( + const char *path, + qstring *errbuf) { PYW_GIL_GET; new_execution_t exec; - return IDAPython_ExecFile(filename, errbuf, errbufsize, S_IDAAPI_UNLOADPROCMOD); + return IDAPython_ExecFile(path, errbuf, S_IDAAPI_UNLOADPROCMOD); } //------------------------------------------------------------------------- // Create an object instance -bool idaapi IDAPython_extlang_create_object( - const char *name, // in: object class name - int nargs, // in: number of input arguments - const idc_value_t args[], // in: input arguments - idc_value_t *result, // out: created object or exception - char *errbuf, // out: error message if evaluation fails - size_t errbufsize) // in: size of the error buffer +//lint -e605 Increase in pointer capability +static bool idaapi IDAPython_extlang_create_object( + idc_value_t *result, // out: created object or exception + const char *name, // in: object class name + const idc_value_t args[], // in: input arguments + size_t nargs, // in: number of input arguments + qstring *errbuf) // out: error message if evaluation fails { PYW_GIL_GET; bool ok = false; @@ -969,34 +970,45 @@ bool idaapi IDAPython_extlang_create_object( do { // Parse the object name (to get the module and class name) - char modname[MAXSTR] = {0}; - char clsname[MAXSTR] = {0}; + char modname[MAXSTR]; + char clsname[MAXSTR]; parse_py_modname(name, modname, clsname, MAXSTR); // Get a reference to the module ref_t py_mod(PyW_TryImportModule(modname)); if ( py_mod == NULL ) { - qsnprintf(errbuf, errbufsize, "Could not import module '%s'!", modname); + errbuf->sprnt("Could not import module '%s'!", modname); break; } - // Get the class reference - ref_t py_cls(PyW_TryGetAttrString(py_mod.o, clsname)); - if ( py_cls == NULL ) + // If the class provides an wraper instantiator, use that + ref_t py_res; + if ( nargs == 1 && args[0].vtype == VT_PVOID ) + py_res = try_create_swig_wrapper(py_mod, clsname, args[0].pvoid); + if ( py_res != NULL ) { - qsnprintf(errbuf, errbufsize, "Could not find class type '%s'!", clsname); - break; + PyObject_SetAttrString(py_res.o, S_PY_IDCCVT_ID_ATTR, PyInt_FromLong(PY_ICID_OPAQUE)); } + else + { + // Get the class reference + ref_t py_cls(PyW_TryGetAttrString(py_mod.o, clsname)); + if ( py_cls == NULL ) + { + errbuf->sprnt("Could not find class type '%s'!", clsname); + break; + } - // Error during conversion? - ok = pyw_convert_idc_args(args, nargs, pargs, true, errbuf, errbufsize); - if ( !ok ) - break; + // Error during conversion? + ok = pyw_convert_idc_args(args, nargs, pargs, PYWCVTF_AS_TUPLE, errbuf); + if ( !ok ) + break; - // Call the constructor - newref_t py_res(PyObject_CallObject(py_cls.o, pargs.empty() ? NULL : pargs[0].o)); - ok = return_python_result(result, py_res, errbuf, errbufsize); + // Call the constructor + py_res = newref_t(PyObject_CallObject(py_cls.o, pargs.empty() ? NULL : pargs[0].o)); + } + ok = return_python_result(result, py_res, errbuf); } while ( false ); return ok; @@ -1004,10 +1016,10 @@ bool idaapi IDAPython_extlang_create_object( //------------------------------------------------------------------------- // Returns the attribute value of a given object from the global scope -bool idaapi IDAPython_extlang_get_attr( - const idc_value_t *obj, // in: object (may be NULL) - const char *attr, // in: attribute name - idc_value_t *result) +static bool idaapi IDAPython_extlang_get_attr( + idc_value_t *result, // out: result + const idc_value_t *obj, // in: object (may be NULL) + const char *attr) // in: attribute name { PYW_GIL_GET; int cvt = CIP_FAILED; @@ -1025,7 +1037,7 @@ bool idaapi IDAPython_extlang_get_attr( if ( obj != NULL ) { // (1) Get attribute from main module - if ( obj->vtype == VT_STR2 ) + if ( obj->vtype == VT_STR ) { py_obj = PyW_TryGetAttrString(py_mod.o, obj->c_str()); } @@ -1116,10 +1128,10 @@ bool idaapi IDAPython_extlang_get_attr( //------------------------------------------------------------------------- // Returns the attribute value of a given object from the global scope //lint -e{818} -bool idaapi IDAPython_extlang_set_attr( - idc_value_t *obj, // in: object name (may be NULL) - const char *attr, // in: attribute name - idc_value_t *value) +static bool idaapi IDAPython_extlang_set_attr( + idc_value_t *obj, // in: object name (may be NULL) + const char *attr, // in: attribute name + const idc_value_t &value) { PYW_GIL_GET; bool ok = false; @@ -1133,7 +1145,7 @@ bool idaapi IDAPython_extlang_set_attr( if ( obj != NULL ) { // Get the attribute reference (from just a name) - if ( obj->vtype == VT_STR2 ) + if ( obj->vtype == VT_STR ) { py_obj = PyW_TryGetAttrString(py_mod.o, obj->c_str()); } @@ -1154,7 +1166,7 @@ bool idaapi IDAPython_extlang_set_attr( } // Convert the value ref_t py_var; - int cvt = idcvar_to_pyvar(*value, &py_var); + int cvt = idcvar_to_pyvar(value, &py_var); if ( cvt >= CIP_OK ) { ok = PyObject_SetAttrString(py_obj.o, attr, py_var.o) != -1; @@ -1168,12 +1180,11 @@ bool idaapi IDAPython_extlang_set_attr( //------------------------------------------------------------------------- // Calculator callback for Python external language evaluator //lint -e{818} -bool idaapi IDAPython_extlang_calcexpr( - ea_t /*current_ea*/, - const char *expr, - idc_value_t *rv, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_eval_expr( + idc_value_t *rv, + ea_t /*current_ea*/, + const char *expr, + qstring *errbuf) { PYW_GIL_GET; PyObject *globals = GetMainGlobals(); @@ -1185,34 +1196,33 @@ bool idaapi IDAPython_extlang_calcexpr( new_execution_t exec; result = newref_t(PyRun_String(expr, Py_eval_input, globals, globals)); } - ok = return_python_result(rv, result, errbuf, errbufsize); + ok = return_python_result(rv, result, errbuf); } return ok; } //------------------------------------------------------------------------- -bool idaapi IDAPython_extlang_call_method( - const idc_value_t *idc_obj, - const char *method_name, - int nargs, - const idc_value_t args[], - idc_value_t *result, - char *errbuf, - size_t errbufsize) +static bool idaapi IDAPython_extlang_call_method( + idc_value_t *result, + const idc_value_t *idc_obj, + const char *method_name, + const idc_value_t args[], + size_t nargs, + qstring *errbuf) { PYW_GIL_GET; // Check for unsupported usage of call_method. // Mainly a method call requires an object and a method. if ( (idc_obj == NULL && method_name == NULL) || (idc_obj != NULL && method_name == NULL) ) { - qstrncpy(errbuf, "call_method does not support this operation", errbufsize); + *errbuf = "call_method does not support this operation"; return false; } // Behave like run() else if ( idc_obj == NULL && method_name != NULL ) { new_execution_t exec; - return IDAPython_extlang_run(method_name, nargs, args, result, errbuf, errbufsize); + return IDAPython_extlang_call_func(result, method_name, args, nargs, errbuf); } // Holds conversion status of input object @@ -1226,26 +1236,42 @@ bool idaapi IDAPython_extlang_call_method( obj_cvt = idcvar_to_pyvar(*idc_obj, &py_obj); if ( obj_cvt < CIP_OK ) { - qstrncpy(errbuf, "Failed to convert input object to Python value", errbufsize); + *errbuf = "Failed to convert input object to Python value"; break; } ref_t py_method(PyW_TryGetAttrString(py_obj.o, method_name)); if ( py_method == NULL || !PyCallable_Check(py_method.o) ) { - qsnprintf(errbuf, errbufsize, "The input object does not have a callable method called '%s'", method_name); + errbuf->sprnt("The input object does not have a callable method called '%s'", method_name); break; } // Convert arguments to python objects - ok = pyw_convert_idc_args(args, nargs, pargs, true, errbuf, errbufsize); + uint32 flags = PYWCVTF_AS_TUPLE; + // if we are running a ida_idaapi.plugin_t.run, we want the 'int64' + // to be converted to an unsigned python long + if ( streq(method_name, "run") ) + { + ref_t py_ida_idaapi_mod(PyW_TryImportModule(S_IDA_IDAAPI_MODNAME)); + if ( py_ida_idaapi_mod != NULL ) + { + ref_t py_plugin_t_cls(PyW_TryGetAttrString(py_ida_idaapi_mod.o, "plugin_t")); + if ( py_plugin_t_cls != NULL ) + { + if ( PyObject_IsInstance(py_obj.o, py_plugin_t_cls.o) ) + flags |= PYWCVTF_INT64_AS_UNSIGNED_PYLONG; + } + } + } + ok = pyw_convert_idc_args(args, nargs, pargs, flags, errbuf); if ( !ok ) break; { new_execution_t exec; newref_t py_res(PyObject_CallObject(py_method.o, pargs.empty() ? NULL : pargs[0].o)); - ok = return_python_result(result, py_res, errbuf, errbufsize); + ok = return_python_result(result, py_res, errbuf); } } while ( false ); @@ -1285,24 +1311,25 @@ struct python_highlighter_t : public ida_syntax_highlighter_t }; static python_highlighter_t python_highlighter; -const extlang_t extlang_python = +extlang_t extlang_python = { - sizeof(extlang_t), - 0, - "Python", - IDAPython_extlang_compile, - IDAPython_extlang_run, - IDAPython_extlang_calcexpr, - IDAPython_extlang_compile_file, - "py", - IDAPython_extlang_create_object, - IDAPython_extlang_get_attr, - IDAPython_extlang_set_attr, - IDAPython_extlang_call_method, - IDAPython_extlang_run_statements, - IDAPython_extlang_loadprocmod, - IDAPython_extlang_unloadprocmod, - &python_highlighter + sizeof(extlang_t), + 0, // flags + 0, // refcnt + "Python", // name + "py", // filext + &python_highlighter, + IDAPython_extlang_compile_expr, + IDAPython_extlang_compile_file, + IDAPython_extlang_call_func, + IDAPython_extlang_eval_expr, + IDAPython_extlang_eval_snippet, + IDAPython_extlang_create_object, + IDAPython_extlang_get_attr, + IDAPython_extlang_set_attr, + IDAPython_extlang_call_method, + IDAPython_extlang_load_procmod, + IDAPython_extlang_unload_procmod, }; //------------------------------------------------------------------------- @@ -1367,11 +1394,11 @@ bool idaapi IDAPython_cli_execute_line(const char *line) //------------------------------------------------------------------------- bool idaapi IDAPYthon_cli_complete_line( - qstring *completion, - const char *prefix, - int n, - const char *line, - int x) + qstring *completion, + const char *prefix, + int n, + const char *line, + int x) { PYW_GIL_GET; @@ -1428,7 +1455,7 @@ void parse_plugin_options() const char *p = strchr(options, ';'); if ( p == NULL ) { - g_run_when = run_on_db_open; + g_run_when = RUN_ON_DB_OPEN; p = options; } else @@ -1452,7 +1479,7 @@ void convert_idc_args() { idc_value_t attr; char attr_name[20] = { "0" }; - for ( int i=1; VarGetAttr(idc_args, attr_name, &attr) == eOk; i++ ) + for ( int i=1; get_idcv_attr(&attr, idc_args, attr_name) == eOk; i++ ) { PyList_Insert(py_args.o, i, PyString_FromString(attr.c_str())); qsnprintf(attr_name, sizeof(attr_name), "%d", i); @@ -1465,9 +1492,16 @@ 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 ) + //------------------------------------------------------------------------ //lint -esym(715,va) Symbol not referenced -static int idaapi on_ui_notification(void *, int code, va_list) +static ssize_t idaapi on_ui_notification(void *, int code, va_list) { switch ( code ) { @@ -1488,7 +1522,7 @@ static int idaapi on_ui_notification(void *, int code, va_list) PYW_GIL_GET; // See above g_ui_ready = true; PyRun_SimpleString("print_banner()"); - if ( g_run_when == run_on_ui_ready ) + if ( g_run_when == RUN_ON_UI_READY ) RunScript(g_run_script); } break; @@ -1497,7 +1531,7 @@ static int idaapi on_ui_notification(void *, int code, va_list) { PYW_GIL_GET; // See above convert_idc_args(); - if ( g_run_when == run_on_db_open ) + if ( g_run_when == RUN_ON_DB_OPEN ) RunScript(g_run_script); } break; @@ -1510,15 +1544,16 @@ static int idaapi on_ui_notification(void *, int code, va_list) //------------------------------------------------------------------------- //lint -esym(526,til_clear_python_tinfo_t_instances) not defined -static int idaapi on_idp_notification(void *, int code, va_list) +static ssize_t idaapi on_idb_notification(void *, int code, va_list) { switch ( code ) { - case processor_t::closebase: + case idb_event::closebase: // The til machinery is about to garbage-collect: We must go // through all the tinfo_t objects that are embedded in SWIG wrappers, // (i.e., that were created from Python) and clear those. til_clear_python_tinfo_t_instances(); + DISPATCH_TO_MODULES(closebase); break; } return 0; @@ -1528,7 +1563,7 @@ static int idaapi on_idp_notification(void *, int code, va_list) //------------------------------------------------------------------------ // extern int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag); extern PyThreadState *_PyThreadState_Current; -static int idaapi ui_debug_handler_cb(void *, int code, va_list) +static ssize_t idaapi ui_debug_handler_cb(void *, int code, va_list) { // This hook gets called from the kernel, but its very point is to // make sure that we don't hold the GIL. Thus: No PYW_GIL_GET here! @@ -1635,7 +1670,7 @@ bool IDAPython_Init(void) if ( !check_python_dir() ) return false; - char tmp[QMAXPATH]; + char path[QMAXPATH]; #ifdef __LINUX__ // Export symbols from libpython to resolve imported module deps // use the standard soname: libpython2.7.so.1.0 @@ -1673,9 +1708,14 @@ bool IDAPython_Init(void) read_config_file("python.cfg", opts, qnumber(opts)); if ( g_alert_auto_scripts ) { - if ( pywraps_check_autoscripts(tmp, sizeof(tmp)) - && askyn_c(0, "HIDECANCEL\nTITLE IDAPython\nThe script '%s' was found in the current directory and will be automatically executed by Python.\n\n" - "Do you want to continue loading IDAPython?", tmp) <= 0 ) + if ( pywraps_check_autoscripts(path, sizeof(path)) + && ask_yn(ASKBTN_NO, + "HIDECANCEL\n" + "TITLE IDAPython\n" + "The script '%s' was found in the current directory\n" + "and will be automatically executed by Python.\n" + "\n" + "Do you want to continue loading IDAPython?", path) <= 0 ) { return false; } @@ -1730,14 +1770,14 @@ bool IDAPython_Init(void) #endif // Set IDAPYTHON_VERSION in Python - qsnprintf( - tmp, - sizeof(tmp), + qstring init_code; + init_code.sprnt( "IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)\n" "IDAPYTHON_REMOVE_CWD_SYS_PATH = %s\n" "IDAPYTHON_DYNLOAD_BASE = r\"%s\"\n" - "IDAPYTHON_DYNLOAD_RELPATH = \"ida_%d\"\n" - "IDAPYTHON_COMPAT_AUTOIMPORT_MODULES = %s\n", + "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, @@ -1745,25 +1785,34 @@ bool IDAPython_Init(void) VER_SERIAL, g_remove_cwd_sys_path ? "True" : "False", idadir(NULL), -#ifdef __EA64__ - 64, + sizeof(ea_t)*8, + g_autoimport_compat_idaapi ? "True" : "False", +#ifdef BC695 + g_autoimport_compat_ida695 ? "True" : "False" #else - 32, + "False" #endif - g_autoimport_compat_idaapi ? "True" : "False"); - PyRun_SimpleString(tmp); + ); + + if ( PyRun_SimpleString(init_code.c_str()) != 0 ) + { + warning("IDAPython: error executing bootstrap code"); + return false; + } // Install extlang. Needs to be done before running init.py // in case it's calling idaapi.enable_extlang_python(1) install_extlang(&extlang_python); // Execute init.py (for Python side initialization) - qmakepath(tmp, MAXSTR, g_idapython_dir, S_INIT_PY, NULL); - if ( !PyRunFile(tmp) ) + qmakepath(path, MAXSTR, g_idapython_dir, S_INIT_PY, NULL); + if ( !PyRunFile(path) ) { + qstring errbuf; + // Try to fetch a one line error string. We must do it before printing // the traceback information. Make sure that the exception is not cleared - handle_python_error(tmp, sizeof(tmp), false); + handle_python_error(&errbuf, false); // Print the exception traceback PyRun_SimpleString("import traceback;traceback.print_exc();"); @@ -1771,7 +1820,7 @@ bool IDAPython_Init(void) warning("IDAPython: error executing " S_INIT_PY ":\n" "%s\n" "\n" - "Refer to the message window to see the full error log.", tmp); + "Refer to the message window to see the full error log.", errbuf.c_str()); remove_extlang(&extlang_python); return false; } @@ -1792,21 +1841,17 @@ bool IDAPython_Init(void) parse_plugin_options(); // Register a RunPythonStatement() function for IDC - set_idc_func_ex( - S_IDC_RUNPYTHON_STATEMENT, - idc_runpythonstatement, - idc_runpythonstatement_args, - 0); + add_idc_func(idc_runpythonstatement_desc); // A script specified on the command line is run - if ( g_run_when == run_on_init ) + if ( g_run_when == RUN_ON_INIT ) RunScript(g_run_script); #ifdef _DEBUG - hook_to_notification_point(HT_UI, ui_debug_handler_cb, NULL); + hook_to_notification_point(HT_UI, ui_debug_handler_cb); #endif - hook_to_notification_point(HT_UI, on_ui_notification, NULL); - hook_to_notification_point(HT_IDP, on_idp_notification, NULL); + hook_to_notification_point(HT_UI, on_ui_notification); + hook_to_notification_point(HT_IDB, on_idb_notification); // Enable the CLI by default enable_python_cli(true); @@ -1836,10 +1881,13 @@ void IDAPython_Term(void) PyGILState_Ensure(); } - unhook_from_notification_point(HT_IDP, on_idp_notification, NULL); - unhook_from_notification_point(HT_UI, on_ui_notification, NULL); + // Let all modules perform possible de-initialization + DISPATCH_TO_MODULES(term); + + unhook_from_notification_point(HT_IDB, on_idb_notification); + unhook_from_notification_point(HT_UI, on_ui_notification); #ifdef _DEBUG - unhook_from_notification_point(HT_UI, ui_debug_handler_cb, NULL); + unhook_from_notification_point(HT_UI, ui_debug_handler_cb); #endif // Notify about IDA closing @@ -1858,11 +1906,16 @@ void IDAPython_Term(void) deinit_pywraps(); // Uninstall IDC function - set_idc_func_ex(S_IDC_RUNPYTHON_STATEMENT, NULL, NULL, 0); + del_idc_func(idc_runpythonstatement_desc.name); // Shut the interpreter down Py_Finalize(); g_instance_initialized = false; + +#ifdef TESTABLE_BUILD + // Check that all hooks were unhooked + QASSERT(30509, hook_data_vec.empty()); +#endif } //------------------------------------------------------------------------- @@ -1884,7 +1937,7 @@ void idaapi term(void) //------------------------------------------------------------------------- // Plugin hotkey entry point -void idaapi run(int arg) +bool idaapi run(size_t arg) { try { @@ -1900,7 +1953,7 @@ void idaapi run(int arg) enable_extlang_python(false); break; default: - warning("IDAPython: unknown plugin argument %d", arg); + warning("IDAPython: unknown plugin argument %d", int(arg)); break; } } @@ -1910,6 +1963,7 @@ void idaapi run(int arg) IDAPython_Term(); IDAPython_Init(); } + return true; } //------------------------------------------------------------------------- diff --git a/python/idadex.py b/python/idadex.py new file mode 100644 index 0000000..dc97c92 --- /dev/null +++ b/python/idadex.py @@ -0,0 +1,428 @@ +#--------------------------------------------------------------------- +# IDAPython - Python plugin for Interactive Disassembler +# +# (c) The IDAPython Team +# +# All rights reserved. +# +# For detailed copyright information see the file COPYING in +# the root of the distribution archive. +#--------------------------------------------------------------------- +# +# dex.py - module to access DEX-file related information +# +#--------------------------------------------------------------------- +# pylint: disable=C0103, C0111, C0301, C0326, W0511, R0903 +import ctypes +import idaapi +import ida_idaapi +import ida_bytes + +uint8 = ctypes.c_ubyte +char = ctypes.c_char +uint32 = ctypes.c_uint +uint64 = ctypes.c_uint64 +uint16 = ctypes.c_ushort +ushort = uint16 +# __EA64__ is set if IDA is running in 64-bit mode +__EA64__ = ida_idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL +ea_t = uint64 if __EA64__ else uint32 + +# parse a ctypes struct from byte data in str_ at 'off' +def get_struct(str_, off, struct): + s = struct() + slen = ctypes.sizeof(s) + bytebuf = str_[off:off+slen] + fit = min(len(bytebuf), slen) + if fit < slen: + raise Exception("can't read struct: %d bytes available but %d required" % (fit, slen)) + ctypes.memmove(ctypes.addressof(s), bytebuf, fit) + return s + +#--------------------------------------------------------------------------- +# This structure is used both for imported methods and locally defined ones +# +class dex_method(ctypes.LittleEndianStructure): + # flags + IS_LOCAL = 1 + HAS_CODE = 2 + _fields_ = [ + ("flags", uint32), # Class type where this method is defined + ("defaddr", ea_t), # Address in file where the "definiton" (DexMethodId) is stored + ("cname", uint32), # Class type where this method is defined + ("id", uint32), # Id of method; key to look up name + ("proto_ret", uint32), # Name of return type + ("proto_shorty", uint32), # 'shorty' parameter descirptor name + ("nparams", ushort), # No of parameters to method. May be >32 + ("proto_params",uint32*32), # Name of types for the first 32 parameters + ("access_flags", uint32), # Access flags + ("startAddr", ea_t), # Function start and end address + ("endAddr", ea_t), # + ("reg_total", ushort), # Registers total, parameters and out + ("reg_params", ushort), # + ("reg_out", ushort), # + ("catchHData", ea_t), # offset to methods catch handler data + ] + def is_local(self): + return (self.flags & dex_method.IS_LOCAL) != 0 + + +""" +struct dex_field +{ + uint32 ctype, name, type; + ea_t maddr; // Address used for xrefs. +}; + +""" +class dex_field(ctypes.LittleEndianStructure): + # flags + _fields_ = [ + ("ctype", uint32), # + ("name", uint32), # + ("type", uint32), # + ("maddr", ea_t), # Address used for xrefs. + ] + +""" +struct longname_director_t +{ + char zero; + netnode node; +}; +""" +class longname_director_t(ctypes.LittleEndianStructure): + # flags + _pack_ = 1 + _fields_ = [ + ("zero", uint8), # + ("node", ea_t), # netnode index with the actual string blob + ] + + +class Dex(object): + + # meta-data + HASHVAL_MAGIC = "version" # Interface version + HASHVAL_OPTIMIZED = "optimized" # 1 for optimized dex files, 0 - for others + HASHVAL_DEXVERSION = "dex_version" # DEX File version + + # The dex string table; lookup from string id# to values + STRTAB_TAB = 1 # Lookup string id => address + STRTAB_RTAB = 2 # Lookup address => id + + # fields + FIELDTAB_DESCR = 1 # Field id => struct dex_field + FIELDTAB_NAMEDATA = 2 # Field id => char data, field name + + # The dex method table; lookup method meta-data based on index + METHTAB_BEGIN = 1 # Method id => start address + METHTAB_RBEGIN = 2 # Start address => method id + METHTAB_DESCR = 3 # Method id => struct dex_method + METHTAB_NAMEDATA = 4 # Method id => char data, method name + METHTAB_NAMEORGDATA = 5 # Method id => char data, method name from dex file + METHTAB_NTAB = 6 # Method id => String id of method name + + # debug info representation + DEBINFO_LINEINFO = 1 # Line start EA => dex_lineinfo_t + + # Try/Catches + TRYTAB_TRYLIST = 3 # key=methodIdx, value= tryItem data + TRYTAB_HANDLERLIST = 4 # key=ea (handler start), value=list of typeIdx, handled types + TRYTAB_HANDLERTRYLIST = 5 # key=ea (handler start), value=list of tryItemIdx + + # Types + TYPETAB_TAB = 1 # Type ID => String ID + TYPETAB_STRDATA = 2 # Type ID => String data (possible user redefined) + TYPETAB_STRORGDATA = 3 # Type ID => Original String data + TYPETAB_EA = 4 # Type ID => ea + + #--------------------------------------------------------------------------- + def __init__(self): + self.nn_meta = idaapi.netnode("$ dex_meta") + self.nn_strtab = idaapi.netnode("$ dex_strtab") + self.nn_fieldtab = idaapi.netnode("$ dex_fields") + self.nn_methtab = idaapi.netnode("$ dex_methtab") + self.nn_debinfo = idaapi.netnode("$ dex_debinfo") + self.nn_trytab = idaapi.netnode("$ dex_tries") + self.nn_typetab = idaapi.netnode("$ dex_types") + + #--------------------------------------------------------------------------- + ACCESS_FLAGS = { + "public" : 0x00000001, + "private" : 0x00000002, + "protected" : 0x00000004, + "static" : 0x00000008, + "final" : 0x00000010, + "synchronized" : 0x00000020, + "volatile" : 0x00000040, + "bridge" : 0x00000040, + "transient" : 0x00000080, + "varargs" : 0x00000080, + "native" : 0x00000100, + "interface" : 0x00000200, + "abstract" : 0x00000400, + "strictfp" : 0x00000800, + "synthetic" : 0x00001000, + "annotation" : 0x00002000, + "enum" : 0x00004000, + "constructor" : 0x00010000, + "dsynchronized" : 0x00020000, } + + #--------------------------------------------------------------------------- + @staticmethod + def access_string(flags): + res = "" + for access_bit in ("synchronized", "synthetic", "public", + "private", "protected", "interface", + "abstract", "strictfp", "final", + "native", "static"): + if flags & Dex.ACCESS_FLAGS[access_bit] != 0: + res += " " + access_bit + return res[1:] if res else "" + + #--------------------------------------------------------------------------- + def get_string(self, string_idx): + addr = self.nn_strtab.altval(string_idx, Dex.STRTAB_TAB) + if addr is 0: + return None + length = ida_bytes.get_max_strlit_length(addr, STRTYPE_C, ida_bytes.ALOPT_IGNHEADS|ida_bytes.ALOPT_IGNPRINT) + return ida_bytes.get_strlit_contents(addr, length, STRTYPE_C) + + def get_method_idx(self, ea): + return self.nn_methtab.altval(ea, Dex.METHTAB_RBEGIN) + + def get_method(self, method_idx): + val = self.nn_methtab.supval(method_idx, Dex.METHTAB_DESCR) + if len(val) != ctypes.sizeof(dex_method): + print "bad data in METHTAB_DESCR for index 0x%X" % method_idx + return None + method = get_struct(val,0, dex_method) + return method + + #--------------------------------------------------------------------------- + @staticmethod + def get_string_by_index(node, idx, tag): + if idx is None: + return None + val = node.supval(idx, tag) + # check for long line + if len(val) == ctypes.sizeof(longname_director_t): + longname_director = get_struct(val, 0, longname_director_t) + if longname_director.zero == 0: + nn = idaapi.netnode(longname_director.node) + return nn.getblob(0, tag)[:-1] + if len(val) > 0: + return val[:-1] + return "" + + #--------------------------------------------------------------------------- + # Converts a single-char primitive type into its human-readable equivalent + PRIMITVE_TYPES = { + 'B': "byte", + 'C': "char", + 'D': "double", + 'F': "float", + 'I': "int", + 'J': "long", + 'S': "short", + 'V': "void", + 'Z': "boolean", + 'L': "ref" } + @staticmethod + def _primitive_type_label(typechar): + if typechar in Dex.PRIMITVE_TYPES: + return Dex.PRIMITVE_TYPES[typechar] + return "UNKNOWN" + + @staticmethod + def is_wide_type(typechar): + return typechar[0] == 'J' or typechar[0] == 'D' + + #--------------------------------------------------------------------------- + # Converts a type descriptor to human-readable "dotted" form. For + # example, "Ljava/lang/String;" becomes "java.lang.String", and + # "[I" becomes "int[]". Also converts '$' to '.', which means this + # form can't be converted back to a descriptor. + @staticmethod + def decorate_java_typename(desc): + target_len = len(desc) + offset = 0 + # strip leading [s; will be added to end + while target_len > 1 and desc[offset] == '[': + offset += 1 + target_len -= 1 + array_depth = offset + if target_len == 1: + # primitive type + desc = Dex._primitive_type_label(desc[offset]) + offset = 0 + target_len = len(desc) + else: + # account for leading 'L' and trailing ';' + if target_len >= 2 and desc[offset] == 'L' and desc[offset + target_len - 1] == ';': + target_len -= 2 + offset += 1 + # copy class name over + res = "" + for _i in range(0, target_len): + ch = desc[offset + _i] + res += '.' if ch == '/' else ch + # add the appropriate number of brackets for arrays + res += "[]"*array_depth + return res + + #--------------------------------------------------------------------------- + def get_type_string(self, type_idx): + return Dex.get_string_by_index(self.nn_typetab, type_idx, Dex.TYPETAB_STRDATA) + + def get_method_name(self, method_idx): + return Dex.get_string_by_index(self.nn_methtab, method_idx, Dex.METHTAB_NAMEDATA) + + def get_field_name(self, field_idx): + return Dex.get_string_by_index(self.nn_fieldtab, field_idx, Dex.FIELDTAB_NAMEDATA) + + def get_parameter_name(self, idx): + return self.get_string(idx) + + #--------------------------------------------------------------------------- + @staticmethod + def get_short_type_name(longname): + if not longname: + return "unknown" + deco = Dex.decorate_java_typename(longname) + if not deco: + return "unknown" + start = deco.rfind('.') + if start == -1: + start = 0 + else: + start += 1 + return deco[start:].replace('<', '_').replace('>', '_') + + @staticmethod + def get_full_type_name(longname): + if not longname: + return "unknown" + return Dex.decorate_java_typename(longname) + + #--------------------------------------------------------------------------- + def get_short_method_name(self, method): + res = Dex.get_short_type_name(self.get_type_string(method.cname)) + res += '.' + res += self.get_method_name(method.id) + res += '@' + res += self.get_string(method.proto_shorty) + return res + + def get_full_method_name(self, method): + res = Dex.get_full_type_name(self.get_type_string(method.proto_ret)) + res += ' ' + res += self.get_full_type_name(self.get_type_string(method.cname)) + res += '.' + res += self.get_method_name(method.id) + + def get_call_method_name(self, method): + shorty = self.get_string(method.proto_shorty) + res = Dex._primitive_type_label(shorty[0]) + res += ' ' + res += Dex.get_short_type_name(self.get_type_string(method.cname)) + res += '.' + res += self.get_method_name(method.id) + res += '(' + last_idx = len(shorty) - 1 + for s in range(1, last_idx + 1): + res += Dex._primitive_type_label(shorty[s]) + if s != last_idx: + res += ", " + res += ')' + return res + + def get_field(self, method_idx): + val = self.nn_fieldtab.supval(method_idx, Dex.FIELDTAB_DESCR) + if len(val) != ctypes.sizeof(dex_field): + print "bad data in FIELDTAB_DESCR for index 0x%X" % method_idx + return None + field = get_struct(val,0, dex_field) + return field + + #--------------------------------------------------------------------------- + def get_full_field_name(self, field_idx, field, field_name): + res = Dex.get_full_type_name(self.get_type_string(field.type)) + res += ' ' + res += Dex.get_full_type_name(self.get_type_string(field_idx)) + res += '.' + res += field_name if field_name else self.get_field_name(field_idx) + return res + + #--------------------------------------------------------------------------- + def get_short_field_name(self, field_idx, field, field_name): + res = Dex.get_short_type_name(self.get_type_string(field.ctype)) + res += '_' + res += field_name if field_name else self.get_field_name(field_idx) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + dex = Dex() + # reproduce IDA function header + f = idaapi.get_func(here()) + if not f: + print "ERROR: must be in a function!" + exit(1) + + func_start_ea = f.start_ea + methno = dex.get_method_idx(func_start_ea) + func_method = dex.get_method(methno) + if func_method is None: + print "ERROR: Missing method info" + exit(1) + out = "" + # Return type + out += Dex.access_string(func_method.access_flags) + " " + method_proto = dex.get_type_string(func_method.proto_ret) + if method_proto: + out += Dex.get_full_type_name(method_proto) + else: + out += "%x" % func_method.proto_ret + out += ' ' + # Class name + method_classnm = dex.get_type_string(func_method.cname) + if method_classnm: + out += Dex.get_full_type_name(method_classnm) + else: + out += "%x" % func_method.cname + out += '.' + # Method name + method_name = dex.get_method_name(methno) + if method_name: + out += method_name + else: + out += "%x" % methno + # Method parameters + if func_method.nparams == 0: + print out + "()" + else: + print out + "(" + out = "" + maxp = min(func_method.nparams, 32) + start_reg = func_method.reg_total - func_method.reg_params + if func_method.access_flags & Dex.ACCESS_FLAGS["static"] == 0: + start_reg += 1 + for i in range(0, maxp): + ptype = dex.get_type_string(func_method.proto_params[i]) + + out = " %s " % dex.get_full_type_name(ptype) + regbuf = "v%u" % start_reg + start_reg += 1 + r = idaapi.find_regvar(f, f.start_ea, regbuf) + if r is None: + out += regbuf + if Dex.is_wide_type(ptype): + out += ':' + regbuf = "v%u" % start_reg + start_reg += 1 + else: + out += r.user + out += ')' if i + 1 == maxp else ',' + print out diff --git a/python/idautils.py b/python/idautils.py index 0e6e700..222569e 100644 --- a/python/idautils.py +++ b/python/idautils.py @@ -56,7 +56,7 @@ def CodeRefsTo(ea, flow): Example:: - for ref in CodeRefsTo(ScreenEA(), 1): + for ref in CodeRefsTo(get_screen_ea(), 1): print ref """ if flow == 1: @@ -77,7 +77,7 @@ def CodeRefsFrom(ea, flow): Example:: - for ref in CodeRefsFrom(ScreenEA(), 1): + for ref in CodeRefsFrom(get_screen_ea(), 1): print ref """ if flow == 1: @@ -96,7 +96,7 @@ def DataRefsTo(ea): Example:: - for ref in DataRefsTo(ScreenEA()): + for ref in DataRefsTo(get_screen_ea()): print ref """ return refs(ea, ida_xref.get_first_dref_to, ida_xref.get_next_dref_to) @@ -112,7 +112,7 @@ def DataRefsFrom(ea): Example:: - for ref in DataRefsFrom(ScreenEA()): + for ref in DataRefsFrom(get_screen_ea()): print ref """ return refs(ea, ida_xref.get_first_dref_from, ida_xref.get_next_dref_from) @@ -193,24 +193,24 @@ def XrefsTo(ea, flags=0): def Threads(): """Returns all thread IDs""" - for i in xrange(0, idc.GetThreadQty()): - yield idc.GetThreadId(i) + 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) - @param start: start address (default: inf.minEA) - @param end: end address (default: inf.maxEA) + @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.minEA - if not end: end = ida_ida.cvar.inf.maxEA + if not start: start = ida_ida.cvar.inf.min_ea + if not end: end = ida_ida.cvar.inf.max_ea ea = start - if not idc.isHead(idc.GetFlags(ea)): + if not idc.is_head(ida_bytes.get_flags(ea)): ea = ida_bytes.next_head(ea, end) while ea != ida_idaapi.BADADDR: yield ea @@ -221,8 +221,8 @@ def Functions(start=None, end=None): """ Get a list of functions - @param start: start address (default: inf.minEA) - @param end: end address (default: inf.maxEA) + @param start: start address (default: inf.min_ea) + @param end: end address (default: inf.max_ea) @return: list of heads between start and end @@ -231,19 +231,19 @@ def Functions(start=None, end=None): in multiple segments will be reported multiple times, once in each segment as they are listed. """ - if not start: start = ida_ida.cvar.inf.minEA - if not end: end = ida_ida.cvar.inf.maxEA + if not start: start = ida_ida.cvar.inf.min_ea + if not end: end = ida_ida.cvar.inf.max_ea # find first function head chunk in the range chunk = ida_funcs.get_fchunk(start) if not chunk: chunk = ida_funcs.get_next_fchunk(start) - while chunk and chunk.startEA < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0: - chunk = ida_funcs.get_next_fchunk(chunk.startEA) + while chunk and chunk.start_ea < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0: + chunk = ida_funcs.get_next_fchunk(chunk.start_ea) func = chunk - while func and func.startEA < end: - startea = func.startEA + while func and func.start_ea < end: + startea = func.start_ea yield startea func = ida_funcs.get_next_func(startea) @@ -261,7 +261,7 @@ def Chunks(start): status = func_iter.main() while status: chunk = func_iter.chunk() - yield (chunk.startEA, chunk.endEA) + yield (chunk.start_ea, chunk.end_ea) status = func_iter.next() @@ -297,7 +297,7 @@ def Segments(): for n in xrange(ida_segment.get_segm_qty()): seg = ida_segment.getnseg(n) if seg: - yield seg.startEA + yield seg.start_ea def Entries(): @@ -338,11 +338,11 @@ def Structs(): @return: List of tuples (idx, sid, name) """ - idx = idc.GetFirstStrucIdx() + idx = idc.get_first_struc_idx() while idx != ida_idaapi.BADADDR: - sid = idc.GetStrucId(idx) - yield (idx, sid, idc.GetStrucName(sid)) - idx = idc.GetNextStrucIdx(idx) + sid = idc.get_struc_by_idx(idx) + yield (idx, sid, idc.get_struc_name(sid)) + idx = idc.get_next_struc_idx(idx) def StructMembers(sid): @@ -358,14 +358,14 @@ def StructMembers(sid): @note: This will not return 'holes' in structures/stack frames; it only returns defined structure members. """ - m = idc.GetFirstMember(sid) + m = idc.get_first_member(sid) if m == -1: raise Exception("No structure with ID: 0x%x" % sid) while (m != ida_idaapi.BADADDR): - name = idc.GetMemberName(sid, m) + name = idc.get_member_name(sid, m) if name: - yield (m, name, idc.GetMemberSize(sid, m)) - m = idc.GetStrucNextOff(sid, m) + yield (m, name, idc.get_member_size(sid, m)) + m = idc.get_next_offset(sid, m) def DecodePrecedingInstruction(ea): @@ -376,12 +376,9 @@ def DecodePrecedingInstruction(ea): @return: (None or the decode instruction, farref) farref will contain 'true' if followed an xref, false otherwise """ - prev_addr, farref = ida_ua.decode_preceding_insn(ea) - if prev_addr == ida_idaapi.BADADDR: - return (None, False) - else: - return (ida_ua.cmd.copy(), farref) - + insn = ida_ua.insn_t() + prev_addr, farref = ida_ua.decode_preceding_insn(insn, ea) + return (insn, farref) if prev_addr != ida_idaapi.BADADDR else (None, False) def DecodePreviousInstruction(ea): @@ -391,11 +388,9 @@ def DecodePreviousInstruction(ea): @param ea: address to decode @return: None or a new insn_t instance """ - prev_addr = ida_ua.decode_prev_insn(ea) - if prev_addr == ida_idaapi.BADADDR: - return None - - return ida_ua.cmd.copy() + insn = ida_ua.insn_t() + prev_addr = ida_ua.decode_prev_insn(insn, ea) + return insn if prev_addr != ida_idaapi.BADADDR else None def DecodeInstruction(ea): @@ -405,11 +400,9 @@ def DecodeInstruction(ea): @param ea: address to decode @return: None or a new insn_t instance """ - inslen = ida_ua.decode_insn(ea) - if inslen == 0: - return None - - return ida_ua.cmd.copy() + insn = ida_ua.insn_t() + inslen = ida_ua.decode_insn(insn, ea) + return insn if inslen > 0 else None def GetDataList(ea, count, itemsize=1): @@ -421,7 +414,7 @@ def GetDataList(ea, count, itemsize=1): elif itemsize == 2: getdata = ida_bytes.get_word elif itemsize == 4: - getdata = ida_bytes.get_long + getdata = ida_bytes.get_dword elif itemsize == 8: getdata = ida_bytes.get_qword else: @@ -445,7 +438,7 @@ def PutDataList(ea, datalist, itemsize=1): if itemsize == 2: putdata = ida_bytes.patch_word if itemsize == 4: - putdata = ida_bytes.patch_long + putdata = ida_bytes.patch_dword assert putdata, "Invalid data size! Must be 1, 2 or 4" @@ -474,19 +467,21 @@ def GetInputFileMD5(): @return: MD5 string or None on error """ - return idc.GetInputMD5() + return idc.retrieve_input_file_md5() class Strings(object): """ - Allows iterating over the string list. The set of strings will not be modified. - , unless asked explicitly at setup()-time.. + Allows iterating over the string list. The set of strings will not be + modified, unless asked explicitly at setup()-time. This string list also + is used by the "String window" so it may be changed when this window is + updated. Example: s = Strings() for i in s: - print "%x: len=%d type=%d -> '%s'" % (i.ea, i.length, i.type, str(i)) + print "%x: len=%d type=%d -> '%s'" % (i.ea, i.length, i.strtype, str(i)) """ class StringItem(object): @@ -494,34 +489,19 @@ class Strings(object): Class representing each string item. """ def __init__(self, si): - self.ea = si.ea + self.ea = si.ea """String ea""" - self.type = si.type - """string type (ASCSTR_xxxxx)""" + self.strtype = si.type + """string type (STRTYPE_xxxxx)""" self.length = si.length """string length""" def is_1_byte_encoding(self): - return not self.is_2_bytes_encoding() and not self.is_4_bytes_encoding() - - def is_2_bytes_encoding(self): - return (self.type & 7) in [ida_nalt.ASCSTR_UTF16, ida_nalt.ASCSTR_ULEN2, ida_nalt.ASCSTR_ULEN4] - - def is_4_bytes_encoding(self): - return (self.type & 7) == ida_nalt.ASCSTR_UTF32 + return ida_nalt.get_strtype_bpu(self.strtype) == 1 def _toseq(self, as_unicode): - if self.is_2_bytes_encoding(): - conv = ida_bytes.ACFOPT_UTF16 - pyenc = "utf-16" - elif self.is_4_bytes_encoding(): - conv = ida_bytes.ACFOPT_UTF8 - pyenc = "utf-8" - else: - conv = ida_bytes.ACFOPT_ASCII - pyenc = 'ascii' - strbytes = ida_bytes.get_ascii_contents2(self.ea, self.length, self.type, conv) - return unicode(strbytes, pyenc, 'replace') if as_unicode else strbytes + strbytes = ida_bytes.get_strlit_contents(self.ea, self.length, self.strtype) + return unicode(strbytes, "UTF-8", 'replace') if as_unicode else strbytes def __str__(self): return self._toseq(False) @@ -529,25 +509,9 @@ class Strings(object): def __unicode__(self): return self._toseq(True) - - STR_C = 0x0001 - """C-style ASCII string""" - STR_PASCAL = 0x0002 - """Pascal-style ASCII string (length byte)""" - STR_LEN2 = 0x0004 - """Pascal-style, length is 2 bytes""" - STR_UNICODE = 0x0008 - """Unicode string""" - STR_LEN4 = 0x0010 - """Pascal-style, length is 4 bytes""" - STR_ULEN2 = 0x0020 - """Pascal-style Unicode, length is 2 bytes""" - STR_ULEN4 = 0x0040 - """Pascal-style Unicode, length is 4 bytes""" - def clear_cache(self): """Clears the strings list cache""" - self.refresh(0, 0) # when ea1=ea2 the kernel will clear the cache + ida_strlist.clear_strlist() def __init__(self, default_setup = False): """ @@ -559,54 +523,38 @@ class Strings(object): if default_setup: self.setup() else: - self.refresh() + # restore saved options + ida_strlist.get_strlist_options() + self.refresh() - self._si = ida_strlist.string_info_t() + self._si = ida_strlist.string_info_t() - def refresh(self, ea1=None, ea2=None): + + def refresh(self): """Refreshes the strings list""" - if ea1 is None: - ea1 = ida_ida.cvar.inf.minEA - if ea2 is None: - ea2 = ida_ida.cvar.inf.maxEA - - ida_strlist.refresh_strlist(ea1, ea2) + ida_strlist.build_strlist() self.size = ida_strlist.get_strlist_qty() def setup(self, - strtypes = STR_C, + strtypes = [ida_nalt.STRTYPE_C], minlen = 5, only_7bit = True, ignore_instructions = False, - ea1 = None, - ea2 = None, display_only_existing_strings = False): - if ea1 is None: - ea1 = ida_ida.cvar.inf.minEA - - if ea2 is None: - ea2 = ida_ida.cvar.inf.maxEA - - t = ida_strlist.strwinsetup_t() + t = ida_strlist.get_strlist_options() t.strtypes = strtypes t.minlen = minlen t.only_7bit = only_7bit - t.ea1 = ea1 - t.ea2 = ea2 t.display_only_existing_strings = display_only_existing_strings - ida_strlist.set_strlist_options(t) - - # Automatically refreshes self.refresh() def _get_item(self, index): - if not ida_strlist.get_strlist_item(index, self._si): + if not ida_strlist.get_strlist_item(self._si, index): return None - else: - return Strings.StringItem(self._si) + return Strings.StringItem(self._si) def __iter__(self): @@ -627,7 +575,7 @@ def GetIdbDir(): This function returns directory path of the current IDB database """ - return os.path.dirname(ida_loader.cvar.database_idb) + os.sep + return os.path.dirname(ida_loader.get_path(ida_loader.PATH_TYPE_IDB)) + os.sep # ----------------------------------------------------------------------- def GetRegisterList(): @@ -653,7 +601,7 @@ def _Assemble(ea, line): seg = ida_segment.getseg(ea) if not seg: return (False, "No segment at ea") - ip = ea - (ida_segment.ask_selector(seg.sel) << 4) + ip = ea - (ida_segment.sel2para(seg.sel) << 4) buf = ida_idp.AssembleLine(ea, seg.sel, ip, seg.bitness, line) if not buf: return (False, "Assembler failed: " + line) @@ -674,9 +622,9 @@ def Assemble(ea, line): @param ea: start address @return: (False, "Error message") or (True, asm_buf) or (True, [asm_buf1, asm_buf2, asm_buf3]) """ - old_batch = idc.Batch(1) + old_batch = idc.batch(1) ret = _Assemble(ea, line) - idc.Batch(old_batch) + idc.batch(old_batch) return ret def _copy_obj(src, dest, skip_list = None): @@ -711,21 +659,21 @@ class _reg_dtyp_t(object): This class describes a register's number and dtyp. The equal operator is overloaded so that two instances can be tested for equality """ - def __init__(self, reg, dtyp): - self.reg = reg - self.dtyp = dtyp + def __init__(self, reg, dtype): + self.reg = reg + self.dtype = dtype def __eq__(self, other): - return (self.reg == other.reg) and (self.dtyp == other.dtyp) + return (self.reg == other.reg) and (self.dtype == other.dtype) # ----------------------------------------------------------------------- class _procregs(object): """Utility class allowing the users to identify registers in a decoded instruction""" def __getattr__(self, attr): ri = ida_idp.reg_info_t() - if not ida_idp.parse_reg_name(attr, ri): + if not ida_idp.parse_reg_name(ri, attr): raise AttributeError() - r = _reg_dtyp_t(ri.reg, ord(ida_ua.get_dtyp_by_size(ri.size))) + r = _reg_dtyp_t(ri.reg, ida_ua.get_dtype_by_size(ri.size)) self.__dict__[attr] = r return r @@ -735,14 +683,14 @@ class _procregs(object): # ----------------------------------------------------------------------- class _cpu(object): - "Simple wrapper around GetRegValue/SetRegValue" + "Simple wrapper around get_reg_value/set_reg_value" def __getattr__(self, name): #print "cpu.get(%s)" % name - return idc.GetRegValue(name) + return idc.get_reg_value(name) def __setattr__(self, name, value): #print "cpu.set(%s)" % name - return idc.SetRegValue(value, name) + return idc.set_reg_value(value, name) # -------------------------------------------------------------------------- diff --git a/python/idc.py b/python/idc.py index ed9edc9..6d3183f 100644 --- a/python/idc.py +++ b/python/idc.py @@ -20,9 +20,7 @@ IDC compatibility module This file contains IDA built-in function declarations and internal bit definitions. Each byte of the program has 32-bit flags (low 8 bits keep -the byte value). These 32 bits are used in GetFlags/SetFlags functions. -You may freely examine these bits using GetFlags() but the use of the -SetFlags() function is strongly discouraged. +the byte value). These 32 bits are used in get_full_flags/get_flags functions. This file is subject to change without any notice. Future versions of IDA may use other definitions. @@ -40,6 +38,7 @@ import ida_frame import ida_funcs import ida_gdl import ida_ida +import ida_idc import ida_bytes import ida_idd import ida_idp @@ -54,7 +53,7 @@ import ida_offset import ida_pro import ida_search import ida_segment -import ida_srarea +import ida_segregs import ida_struct import ida_typeinf import ida_ua @@ -67,7 +66,9 @@ import re import struct import time import types +import sys +__X64__ = sys.maxsize > 0xFFFFFFFF __EA64__ = ida_idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL WORDMASK = 0xFFFFFFFFFFFFFFFF if __EA64__ else 0xFFFFFFFF class DeprecatedIDCError(Exception): @@ -109,7 +110,7 @@ BADSEL = ida_idaapi.BADSEL # Not allowed selector value/number MAXADDR = ida_ida.MAXADDR & WORDMASK SIZE_MAX = _ida_idaapi.SIZE_MAX # -# Flag bit definitions (for GetFlags()) +# Flag bit definitions (for get_full_flags()) # MS_VAL = ida_bytes.MS_VAL # Mask for byte value FF_IVL = ida_bytes.FF_IVL # Byte has value ? @@ -117,9 +118,9 @@ FF_IVL = ida_bytes.FF_IVL # Byte has value ? # Do flags contain byte value? (i.e. has the byte a value?) # if not, the byte is uninitialized. -def hasValue(F): return ((F & FF_IVL) != 0) # any defined value? +def has_value(F): return ((F & FF_IVL) != 0) # any defined value? -def byteValue(F): +def byte_value(F): """ Get byte value from flags Get value of byte provided that the byte is initialized. @@ -128,9 +129,9 @@ def byteValue(F): return (F & MS_VAL) -def isLoaded(ea): +def is_loaded(ea): """Is the byte initialized?""" - return hasValue(GetFlags(ea)) # any defined value? + return has_value(get_full_flags(ea)) # any defined value? MS_CLS = ida_bytes.MS_CLS # Mask for typing FF_CODE = ida_bytes.FF_CODE # Code ? @@ -138,11 +139,11 @@ FF_DATA = ida_bytes.FF_DATA # Data ? FF_TAIL = ida_bytes.FF_TAIL # Tail ? FF_UNK = ida_bytes.FF_UNK # Unknown ? -def isCode(F): return ((F & MS_CLS) == FF_CODE) # is code byte? -def isData(F): return ((F & MS_CLS) == FF_DATA) # is data byte? -def isTail(F): return ((F & MS_CLS) == FF_TAIL) # is tail byte? -def isUnknown(F): return ((F & MS_CLS) == FF_UNK) # is unexplored byte? -def isHead(F): return ((F & FF_DATA) != 0) # is start of code/data? +def is_code(F): return ((F & MS_CLS) == FF_CODE) # is code byte? +def is_data(F): return ((F & MS_CLS) == FF_DATA) # is data byte? +def is_tail(F): return ((F & MS_CLS) == FF_TAIL) # is tail byte? +def is_unknown(F): return ((F & MS_CLS) == FF_UNK) # is unexplored byte? +def is_head(F): return ((F & FF_DATA) != 0) # is start of code/data? # # Common bits @@ -154,11 +155,9 @@ FF_LINE = ida_bytes.FF_LINE # Has next or prev cmt lines ? FF_NAME = ida_bytes.FF_NAME # Has user-defined name ? FF_LABL = ida_bytes.FF_LABL # Has dummy name? FF_FLOW = ida_bytes.FF_FLOW # Exec flow from prev instruction? -FF_VAR = ida_bytes.FF_VAR # Is byte variable ? FF_ANYNAME = FF_LABL | FF_NAME -def isFlow(F): return ((F & FF_FLOW) != 0) -def isVar(F): return ((F & FF_VAR ) != 0) +def is_flow(F): return ((F & FF_FLOW) != 0) def isExtra(F): return ((F & FF_LINE) != 0) def isRef(F): return ((F & FF_REF) != 0) def hasName(F): return ((F & FF_NAME) != 0) @@ -196,8 +195,8 @@ FF_1STK = ida_bytes.FF_1STK # Stack variable? # 'is the 1st (or 2nd) operand of instruction or data of the given type'? # Please note that data items use only the 1st operand type (is...0) -def isDefArg0(F): return ((F & MS_0TYPE) != FF_0VOID) -def isDefArg1(F): return ((F & MS_1TYPE) != FF_1VOID) +def is_defarg0(F): return ((F & MS_0TYPE) != FF_0VOID) +def is_defarg1(F): return ((F & MS_1TYPE) != FF_1VOID) def isDec0(F): return ((F & MS_0TYPE) == FF_0NUMD) def isDec1(F): return ((F & MS_1TYPE) == FF_1NUMD) def isHex0(F): return ((F & MS_0TYPE) == FF_0NUMH) @@ -206,20 +205,20 @@ def isOct0(F): return ((F & MS_0TYPE) == FF_0NUMO) def isOct1(F): return ((F & MS_1TYPE) == FF_1NUMO) def isBin0(F): return ((F & MS_0TYPE) == FF_0NUMB) def isBin1(F): return ((F & MS_1TYPE) == FF_1NUMB) -def isOff0(F): return ((F & MS_0TYPE) == FF_0OFF) -def isOff1(F): return ((F & MS_1TYPE) == FF_1OFF) -def isChar0(F): return ((F & MS_0TYPE) == FF_0CHAR) -def isChar1(F): return ((F & MS_1TYPE) == FF_1CHAR) -def isSeg0(F): return ((F & MS_0TYPE) == FF_0SEG) -def isSeg1(F): return ((F & MS_1TYPE) == FF_1SEG) -def isEnum0(F): return ((F & MS_0TYPE) == FF_0ENUM) -def isEnum1(F): return ((F & MS_1TYPE) == FF_1ENUM) -def isFop0(F): return ((F & MS_0TYPE) == FF_0FOP) -def isFop1(F): return ((F & MS_1TYPE) == FF_1FOP) -def isStroff0(F): return ((F & MS_0TYPE) == FF_0STRO) -def isStroff1(F): return ((F & MS_1TYPE) == FF_1STRO) -def isStkvar0(F): return ((F & MS_0TYPE) == FF_0STK) -def isStkvar1(F): return ((F & MS_1TYPE) == FF_1STK) +def is_off0(F): return ((F & MS_0TYPE) == FF_0OFF) +def is_off1(F): return ((F & MS_1TYPE) == FF_1OFF) +def is_char0(F): return ((F & MS_0TYPE) == FF_0CHAR) +def is_char1(F): return ((F & MS_1TYPE) == FF_1CHAR) +def is_seg0(F): return ((F & MS_0TYPE) == FF_0SEG) +def is_seg1(F): return ((F & MS_1TYPE) == FF_1SEG) +def is_enum0(F): return ((F & MS_0TYPE) == FF_0ENUM) +def is_enum1(F): return ((F & MS_1TYPE) == FF_1ENUM) +def is_manual0(F): return ((F & MS_0TYPE) == FF_0FOP) +def is_manual1(F): return ((F & MS_1TYPE) == FF_1FOP) +def is_stroff0(F): return ((F & MS_0TYPE) == FF_0STRO) +def is_stroff1(F): return ((F & MS_1TYPE) == FF_1STRO) +def is_stkvar0(F): return ((F & MS_0TYPE) == FF_0STK) +def is_stkvar1(F): return ((F & MS_1TYPE) == FF_1STK) # # Bits for DATA bytes @@ -228,29 +227,29 @@ DT_TYPE = ida_bytes.DT_TYPE & 0xFFFFFFFF # Mask for DATA typing FF_BYTE = ida_bytes.FF_BYTE & 0xFFFFFFFF # byte FF_WORD = ida_bytes.FF_WORD & 0xFFFFFFFF # word -FF_DWRD = ida_bytes.FF_DWRD & 0xFFFFFFFF # dword -FF_QWRD = ida_bytes.FF_QWRD & 0xFFFFFFFF # qword -FF_TBYT = ida_bytes.FF_TBYT & 0xFFFFFFFF # tbyte -FF_ASCI = ida_bytes.FF_ASCI & 0xFFFFFFFF # ASCII ? -FF_STRU = ida_bytes.FF_STRU & 0xFFFFFFFF # Struct ? -FF_OWRD = ida_bytes.FF_OWRD & 0xFFFFFFFF # octaword (16 bytes) +FF_DWORD = ida_bytes.FF_DWORD & 0xFFFFFFFF # dword +FF_QWORD = ida_bytes.FF_QWORD & 0xFFFFFFFF # qword +FF_TBYTE = ida_bytes.FF_TBYTE & 0xFFFFFFFF # tbyte +FF_STRLIT = ida_bytes.FF_STRLIT & 0xFFFFFFFF # ASCII ? +FF_STRUCT = ida_bytes.FF_STRUCT & 0xFFFFFFFF # Struct ? +FF_OWORD = ida_bytes.FF_OWORD & 0xFFFFFFFF # octaword (16 bytes) FF_FLOAT = ida_bytes.FF_FLOAT & 0xFFFFFFFF # float FF_DOUBLE = ida_bytes.FF_DOUBLE & 0xFFFFFFFF # double FF_PACKREAL = ida_bytes.FF_PACKREAL & 0xFFFFFFFF # packed decimal real FF_ALIGN = ida_bytes.FF_ALIGN & 0xFFFFFFFF # alignment directive -def isByte(F): return (isData(F) and (F & DT_TYPE) == FF_BYTE) -def isWord(F): return (isData(F) and (F & DT_TYPE) == FF_WORD) -def isDwrd(F): return (isData(F) and (F & DT_TYPE) == FF_DWRD) -def isQwrd(F): return (isData(F) and (F & DT_TYPE) == FF_QWRD) -def isOwrd(F): return (isData(F) and (F & DT_TYPE) == FF_OWRD) -def isTbyt(F): return (isData(F) and (F & DT_TYPE) == FF_TBYT) -def isFloat(F): return (isData(F) and (F & DT_TYPE) == FF_FLOAT) -def isDouble(F): return (isData(F) and (F & DT_TYPE) == FF_DOUBLE) -def isPackReal(F): return (isData(F) and (F & DT_TYPE) == FF_PACKREAL) -def isASCII(F): return (isData(F) and (F & DT_TYPE) == FF_ASCI) -def isStruct(F): return (isData(F) and (F & DT_TYPE) == FF_STRU) -def isAlign(F): return (isData(F) and (F & DT_TYPE) == FF_ALIGN) +def is_byte(F): return (is_data(F) and (F & DT_TYPE) == FF_BYTE) +def is_word(F): return (is_data(F) and (F & DT_TYPE) == FF_WORD) +def is_dword(F): return (is_data(F) and (F & DT_TYPE) == FF_DWORD) +def is_qword(F): return (is_data(F) and (F & DT_TYPE) == FF_QWORD) +def is_oword(F): return (is_data(F) and (F & DT_TYPE) == FF_OWORD) +def is_tbyte(F): return (is_data(F) and (F & DT_TYPE) == FF_TBYTE) +def is_float(F): return (is_data(F) and (F & DT_TYPE) == FF_FLOAT) +def is_double(F): return (is_data(F) and (F & DT_TYPE) == FF_DOUBLE) +def is_pack_real(F): return (is_data(F) and (F & DT_TYPE) == FF_PACKREAL) +def is_strlit(F): return (is_data(F) and (F & DT_TYPE) == FF_STRLIT) +def is_struct(F): return (is_data(F) and (F & DT_TYPE) == FF_STRUCT) +def is_align(F): return (is_data(F) and (F & DT_TYPE) == FF_ALIGN) # # Bits for CODE bytes @@ -287,14 +286,14 @@ NEF_FLAT = ida_loader.NEF_FLAT # Autocreated FLAT group (PE) # ---------------------------------------------------------------------------- # M I S C E L L A N E O U S # ---------------------------------------------------------------------------- -def IsString(var): raise NotImplementedError, "this function is not needed in Python" -def IsLong(var): raise NotImplementedError, "this function is not needed in Python" -def IsFloat(var): raise NotImplementedError, "this function is not needed in Python" -def IsFunc(var): raise NotImplementedError, "this function is not needed in Python" -def IsPvoid(var): raise NotImplementedError, "this function is not needed in Python" -def IsInt64(var): raise NotImplementedError, "this function is not needed in Python" +def value_is_string(var): raise NotImplementedError, "this function is not needed in Python" +def value_is_long(var): raise NotImplementedError, "this function is not needed in Python" +def value_is_float(var): raise NotImplementedError, "this function is not needed in Python" +def value_is_func(var): raise NotImplementedError, "this function is not needed in Python" +def value_is_pvoid(var): raise NotImplementedError, "this function is not needed in Python" +def value_is_int64(var): raise NotImplementedError, "this function is not needed in Python" -def MK_FP(seg, off): +def to_ea(seg, off): """ Return value of expression: ((seg<<4) + off) """ @@ -374,13 +373,13 @@ def rotate_word(x, count): return rotate_left(x, count, 16, 0) def rotate_byte(x, count): return rotate_left(x, count, 8, 0) -# AddHotkey return codes +# add_idc_hotkey return codes IDCHK_OK = 0 # ok IDCHK_ARG = -1 # bad argument(s) IDCHK_KEY = -2 # bad hotkey name IDCHK_MAX = -3 # too many IDC hotkeys -def AddHotkey(hotkey, idcfunc): +def add_idc_hotkey(hotkey, idcfunc): """ Add hotkey for IDC function @@ -392,7 +391,7 @@ def AddHotkey(hotkey, idcfunc): return ida_kernwin.add_idc_hotkey(hotkey, idcfunc) -def DelHotkey(hotkey): +def del_idc_hotkey(hotkey): """ Delete IDC function hotkey @@ -401,7 +400,7 @@ def DelHotkey(hotkey): return ida_kernwin.del_idc_hotkey(hotkey) -def Jump(ea): +def jumpto(ea): """ Move cursor to the specifed linear address @@ -410,7 +409,7 @@ def Jump(ea): return ida_kernwin.jumpto(ea) -def Wait(): +def auto_wait(): """ Process all entries in the autoanalysis queue Wait for the end of autoanalysis @@ -418,35 +417,10 @@ def Wait(): @note: This function will suspend execution of the calling script till the autoanalysis queue is empty. """ - return ida_auto.autoWait() + return ida_auto.auto_wait() -def CompileEx(input, isfile): - """ - Compile an IDC script - - The input should not contain functions that are - currently executing - otherwise the behaviour of the replaced - functions is undefined. - - @param input: if isfile != 0, then this is the name of file to compile - otherwise it holds the text to compile - @param isfile: specify if 'input' holds a filename or the expression itself - - @return: 0 - ok, otherwise it returns an error message - """ - if isfile: - res = ida_expr.Compile(input) - else: - res = ida_expr.CompileLine(input) - - if res: - return res - else: - return 0 - - -def Eval(expr): +def eval_idc(expr): """ Evaluate an IDC expression @@ -459,32 +433,30 @@ def Eval(expr): """ rv = ida_expr.idc_value_t() - err = ida_expr.calc_idc_expr(BADADDR, expr, rv) + err = ida_expr.eval_idc_expr(rv, BADADDR, expr) if err: return "IDC_FAILURE: "+err else: - if rv.vtype == '\x01': # VT_STR - return rv.str - elif rv.vtype == '\x02': # long + if rv.vtype == '\x02': # long return rv.num - elif rv.vtype == '\x07': # VT_STR2 + elif rv.vtype == '\x07': # VT_STR return rv.c_str() else: - raise NotImplementedError, "Eval() supports only expressions returning strings or longs" + raise NotImplementedError, "eval_idc() supports only expressions returning strings or longs" def EVAL_FAILURE(code): """ - Check the result of Eval() for evaluation failures + Check the result of eval_idc() for evaluation failures - @param code: result of Eval() + @param code: result of eval_idc() @return: True if there was an evaluation error """ return type(code) == types.StringType and code.startswith("IDC_FAILURE: ") -def SaveBase(idbname, flags=0): +def save_database(idbname, flags=0): """ Save current database to the specified idb file @@ -493,25 +465,21 @@ def SaveBase(idbname, flags=0): @param flags: combination of ida_loader.DBFL_... bits or 0 """ if len(idbname) == 0: - idbname = GetIdbPath() - saveflags = ida_loader.cvar.database_flags + idbname = get_idb_path() mask = ida_loader.DBFL_KILL | ida_loader.DBFL_COMP | ida_loader.DBFL_BAK - ida_loader.cvar.database_flags &= ~mask - ida_loader.cvar.database_flags |= flags & mask - res = ida_loader.save_database(idbname, 0) - ida_loader.cvar.database_flags = saveflags + res = ida_loader.save_database_ex(idbname, flags & mask) return res DBFL_BAK = ida_loader.DBFL_BAK # for compatiblity with older versions, eventually delete this -def ValidateNames(): +def validate_idb_names(): """ check consistency of IDB name records @return: number of inconsistent name records """ return ida_nalt.validate_idb_names() -def Exit(code): +def qexit(code): """ Stop execution of IDC program, close the database and exit to OS @@ -522,7 +490,7 @@ def Exit(code): ida_pro.qexit(code) -def Exec(command): +def call_system(command): """ Execute an OS command. @@ -539,9 +507,9 @@ def Exec(command): return os.system(command) -def Sleep(milliseconds): +def qsleep(milliseconds): """ - Sleep the specified number of milliseconds + qsleep the specified number of milliseconds This function suspends IDA for the specified amount of time @param milliseconds: time to sleep @@ -549,7 +517,7 @@ def Sleep(milliseconds): time.sleep(float(milliseconds)/1000) -def RunPlugin(name, arg): +def load_and_run_plugin(name, arg): """ Load and run a plugin @@ -561,7 +529,7 @@ def RunPlugin(name, arg): return ida_loader.load_and_run_plugin(name, arg) -def ApplySig(name): +def plan_to_apply_idasgn(name): """ Load (plan to apply) a FLIRT signature file @@ -577,15 +545,15 @@ def ApplySig(name): #---------------------------------------------------------------------------- -def DeleteAll(): +def delete_all_segments(): """ Delete all segments, instructions, comments, i.e. everything except values of bytes. """ - ea = ida_ida.cvar.inf.minEA + ea = ida_ida.cvar.inf.min_ea # Brute-force nuke all info from all the heads - while ea != BADADDR and ea <= ida_ida.cvar.inf.maxEA: + while ea != BADADDR and ea <= ida_ida.cvar.inf.max_ea: ida_name.del_local_name(ea) ida_name.del_global_name(ea) func = ida_funcs.get_func(ea) @@ -593,17 +561,17 @@ def DeleteAll(): ida_funcs.del_func_cmt(func, False) ida_funcs.del_func_cmt(func, True) ida_funcs.del_func(ea) - ida_bytes.del_hidden_area(ea) + ida_bytes.del_hidden_range(ea) seg = ida_segment.getseg(ea) if seg: ida_segment.del_segment_cmt(seg, False) ida_segment.del_segment_cmt(seg, True) - ida_segment.del_segm(ea, ida_segment.SEGDEL_KEEP | ida_segment.SEGDEL_SILENT) + ida_segment.del_segm(ea, ida_segment.SEGMOD_KEEP | ida_segment.SEGMOD_SILENT) - ea = ida_bytes.next_head(ea, ida_ida.cvar.inf.maxEA) + ea = ida_bytes.next_head(ea, ida_ida.cvar.inf.max_ea) -def MakeCode(ea): +def create_insn(ea): """ Create an instruction at the specified address @@ -616,19 +584,20 @@ def MakeCode(ea): return ida_ua.create_insn(ea) -def AnalyzeArea(sEA, eEA): +def plan_and_wait(sEA, eEA, final_pass=True): """ - Perform full analysis of the area + Perform full analysis of the range @param sEA: starting linear address @param eEA: ending linear address (excluded) + @param final_pass: make the final pass over the specified range @return: 1-ok, 0-Ctrl-Break was pressed. """ - return ida_auto.analyze_area(sEA, eEA) + return ida_auto.plan_and_wait(sEA, eEA, final_pass) -def MakeNameEx(ea, name, flags): +def set_name(ea, name, flags=ida_name.SN_CHECK): """ Rename an address @@ -640,14 +609,12 @@ def MakeNameEx(ea, name, flags): """ return ida_name.set_name(ea, name, flags) -SN_CHECK = ida_name.SN_CHECK # Fail if the name contains invalid - # characters +SN_CHECK = ida_name.SN_CHECK +SN_NOCHECK = ida_name.SN_NOCHECK # Don't fail if the name contains invalid characters. # If this bit is clear, all invalid chars - # (those !is_ident_char()) will be replaced - # by SubstChar (usually '_') - # List of valid characters is defined in - # ida.cfg -SN_NOCHECK = ida_name.SN_NOCHECK # Replace invalid chars with SubstChar + # (those !is_ident_cp()) will be replaced + # by SUBSTCHAR (usually '_'). + # List of valid characters is defined in ida.cfg SN_PUBLIC = ida_name.SN_PUBLIC # if set, make name public SN_NON_PUBLIC = ida_name.SN_NON_PUBLIC # if set, make name non-public SN_WEAK = ida_name.SN_WEAK # if set, make name weak @@ -665,31 +632,20 @@ SN_LOCAL = ida_name.SN_LOCAL # create local name. a function should exis # also they are not included into the list # of names they can't have dummy prefixes -def MakeComm(ea, comment): +def set_cmt(ea, comment, rptble): """ Set an indented regular comment of an item @param ea: linear address @param comment: comment string + @param rptble: is repeatable? @return: None """ - return ida_bytes.set_cmt(ea, comment, 0) + return ida_bytes.set_cmt(ea, comment, rptble) -def MakeRptCmt(ea, comment): - """ - Set an indented repeatable comment of an item - - @param ea: linear address - @param comment: comment string - - @return: None - """ - return ida_bytes.set_cmt(ea, comment, 1) - - -def MakeArray(ea, nitems): +def make_array(ea, nitems): """ Create an array. @@ -700,32 +656,32 @@ def MakeArray(ea, nitems): the type of the item at 'ea'. If the byte at 'ea' is undefined, then this function will create an array of bytes. """ - flags = ida_bytes.getFlags(ea) + flags = ida_bytes.get_flags(ea) - if ida_bytes.isCode(flags) or ida_bytes.isTail(flags) or ida_bytes.isAlign(flags): + if ida_bytes.is_code(flags) or ida_bytes.is_tail(flags) or ida_bytes.is_align(flags): return False - if ida_bytes.isUnknown(flags): + if ida_bytes.is_unknown(flags): flags = ida_bytes.FF_BYTE - if ida_bytes.isStruct(flags): + if ida_bytes.is_struct(flags): ti = ida_nalt.opinfo_t() - assert ida_bytes.get_opinfo(ea, 0, flags, ti), "get_opinfo() failed" + assert ida_bytes.get_opinfo(ti, ea, 0, flags), "get_opinfo() failed" itemsize = ida_bytes.get_data_elsize(ea, flags, ti) tid = ti.tid else: itemsize = ida_bytes.get_item_size(ea) tid = BADADDR - return ida_bytes.do_data_ex(ea, flags, itemsize*nitems, tid) + return ida_bytes.create_data(ea, flags, itemsize*nitems, tid) -def MakeStr(ea, endea): +def create_strlit(ea, endea): """ Create a string. This function creates a string (the string type is determined by the - value of GetLongPrm(INF_STRTYPE)) + value of get_inf_attr(INF_STRTYPE)) @param ea: linear address @param endea: ending address of the string (excluded) @@ -734,26 +690,26 @@ def MakeStr(ea, endea): @return: 1-ok, 0-failure - @note: The type of an existing string is returned by GetStringType() + @note: The type of an existing string is returned by get_str_type() """ - return ida_bytes.make_ascii_string(ea, 0 if endea == BADADDR else endea - ea, GetLongPrm(INF_STRTYPE)) + return ida_bytes.create_strlit(ea, 0 if endea == BADADDR else endea - ea, get_inf_attr(INF_STRTYPE)) -def MakeData(ea, flags, size, tid): +def create_data(ea, flags, size, tid): """ Create a data item at the specified address @param ea: linear address @param flags: FF_BYTE..FF_PACKREAL @param size: size of item in bytes - @param tid: for FF_STRU the structure id + @param tid: for FF_STRUCT the structure id @return: 1-ok, 0-failure """ - return ida_bytes.do_data_ex(ea, flags, size, tid) + return ida_bytes.create_data(ea, flags, size, tid) -def MakeByte(ea): +def create_byte(ea): """ Convert the current item to a byte @@ -761,10 +717,10 @@ def MakeByte(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doByte(ea, 1) + return ida_bytes.create_byte(ea, 1) -def MakeWord(ea): +def create_word(ea): """ Convert the current item to a word (2 bytes) @@ -772,10 +728,10 @@ def MakeWord(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doWord(ea, 2) + return ida_bytes.create_word(ea, 2) -def MakeDword(ea): +def create_dword(ea): """ Convert the current item to a double word (4 bytes) @@ -783,10 +739,10 @@ def MakeDword(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doDwrd(ea, 4) + return ida_bytes.create_dword(ea, 4) -def MakeQword(ea): +def create_qword(ea): """ Convert the current item to a quadro word (8 bytes) @@ -794,10 +750,10 @@ def MakeQword(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doQwrd(ea, 8) + return ida_bytes.create_qword(ea, 8) -def MakeOword(ea): +def create_oword(ea): """ Convert the current item to an octa word (16 bytes/128 bits) @@ -805,10 +761,10 @@ def MakeOword(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doOwrd(ea, 16) + return ida_bytes.create_oword(ea, 16) -def MakeYword(ea): +def create_yword(ea): """ Convert the current item to a ymm word (32 bytes/256 bits) @@ -816,10 +772,10 @@ def MakeYword(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doYwrd(ea, 32) + return ida_bytes.create_yword(ea, 32) -def MakeFloat(ea): +def create_float(ea): """ Convert the current item to a floating point (4 bytes) @@ -827,10 +783,10 @@ def MakeFloat(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doFloat(ea, 4) + return ida_bytes.create_float(ea, 4) -def MakeDouble(ea): +def create_double(ea): """ Convert the current item to a double floating point (8 bytes) @@ -838,10 +794,10 @@ def MakeDouble(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doDouble(ea, 8) + return ida_bytes.create_double(ea, 8) -def MakePackReal(ea): +def create_pack_real(ea): """ Convert the current item to a packed real (10 or 12 bytes) @@ -849,10 +805,10 @@ def MakePackReal(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doPackReal(ea, ida_idp.ph_get_tbyte_size()) + return ida_bytes.create_packed_real(ea, ida_idp.ph_get_tbyte_size()) -def MakeTbyte(ea): +def create_tbyte(ea): """ Convert the current item to a tbyte (10 or 12 bytes) @@ -860,10 +816,10 @@ def MakeTbyte(ea): @return: 1-ok, 0-failure """ - return ida_bytes.doTbyt(ea, ida_idp.ph_get_tbyte_size()) + return ida_bytes.create_tbyte(ea, ida_idp.ph_get_tbyte_size()) -def MakeStructEx(ea, size, strname): +def create_struct(ea, size, strname): """ Convert the current item to a structure instance @@ -879,10 +835,10 @@ def MakeStructEx(ea, size, strname): if size == -1: size = ida_struct.get_struc_size(strid) - return ida_bytes.doStruct(ea, size, strid) + return ida_bytes.create_struct(ea, size, strid) -def MakeCustomDataEx(ea, size, dtid, fid): +def create_custom_data(ea, size, dtid, fid): """ Convert the item at address to custom data. @@ -893,11 +849,11 @@ def MakeCustomDataEx(ea, size, dtid, fid): @return: 1-ok, 0-failure """ - return ida_bytes.doCustomData(ea, size, dtid, fid) + return ida_bytes.create_custdata(ea, size, dtid, fid) -def MakeAlign(ea, count, align): +def create_align(ea, count, align): """ Convert the current item to an alignment directive @@ -909,10 +865,10 @@ def MakeAlign(ea, count, align): @return: 1-ok, 0-failure """ - return ida_bytes.doAlign(ea, count, align) + return ida_bytes.create_align(ea, count, align) -def MakeLocal(start, end, location, name): +def define_local_var(start, end, location, name): """ Create a local variable @@ -971,41 +927,29 @@ def MakeLocal(start, end, location, name): return ida_frame.add_regvar(func, start, end, location, name, None) -def MakeUnkn(ea, flags): +def del_items(ea, flags=0, size=1): """ Convert the current item to an explored item @param ea: linear address - @param flags: combination of DOUNK_* constants + @param flags: combination of DELIT_* constants + @param size: size of the range to undefine @return: None """ - return ida_bytes.do_unknown(ea, flags) + return ida_bytes.del_items(ea, flags, size) -def MakeUnknown(ea, size, flags): - """ - Convert the current item to an explored item - - @param ea: linear address - @param size: size of the range to undefine (for MakeUnknown) - @param flags: combination of DOUNK_* constants - - @return: None - """ - return ida_bytes.do_unknown_range(ea, size, flags) - - -DOUNK_SIMPLE = ida_bytes.DOUNK_SIMPLE # simply undefine the specified item -DOUNK_EXPAND = ida_bytes.DOUNK_EXPAND # propogate undefined items, for example +DELIT_SIMPLE = ida_bytes.DELIT_SIMPLE # simply undefine the specified item +DELIT_EXPAND = ida_bytes.DELIT_EXPAND # propogate undefined items, for example # if removing an instruction removes all # references to the next instruction, then # plan to convert to unexplored the next # instruction too. -DOUNK_DELNAMES = ida_bytes.DOUNK_DELNAMES # delete any names at the specified address(es) +DELIT_DELNAMES = ida_bytes.DELIT_DELNAMES # delete any names at the specified address(es) -def SetArrayFormat(ea, flags, litems, align): +def set_array_params(ea, flags, litems, align): """ Set array representation format @@ -1019,7 +963,7 @@ def SetArrayFormat(ea, flags, litems, align): @return: 1-ok, 0-failure """ - return Eval("SetArrayFormat(0x%X, 0x%X, %d, %d)"%(ea, flags, litems, align)) + return eval_idc("set_array_params(0x%X, 0x%X, %d, %d)"%(ea, flags, litems, align)) AP_ALLOWDUPS = 0x00000001L # use 'dup' construct AP_SIGNED = 0x00000002L # treats numbers as signed @@ -1031,7 +975,7 @@ AP_IDXHEX = 0x00000010L # display indexes in hex AP_IDXOCT = 0x00000020L # display indexes in octal AP_IDXBIN = 0x00000030L # display indexes in binary -def OpBinary(ea, n): +def op_bin(ea, n): """ Convert an operand of the item (instruction or data) to a binary number @@ -1048,7 +992,7 @@ def OpBinary(ea, n): return ida_bytes.op_bin(ea, n) -def OpOctal(ea, n): +def op_oct(ea, n): """ Convert an operand of the item (instruction or data) to an octal number @@ -1061,7 +1005,7 @@ def OpOctal(ea, n): return ida_bytes.op_oct(ea, n) -def OpDecimal(ea, n): +def op_dec(ea, n): """ Convert an operand of the item (instruction or data) to a decimal number @@ -1074,7 +1018,7 @@ def OpDecimal(ea, n): return ida_bytes.op_dec(ea, n) -def OpHex(ea, n): +def op_hex(ea, n): """ Convert an operand of the item (instruction or data) to a hexadecimal number @@ -1087,7 +1031,7 @@ def OpHex(ea, n): return ida_bytes.op_hex(ea, n) -def OpChr(ea, n): +def op_chr(ea, n): """ @param ea: linear address @param n: number of operand @@ -1098,10 +1042,10 @@ def OpChr(ea, n): return ida_bytes.op_chr(ea, n) -def OpOff(ea, n, base): +def op_plain_offset(ea, n, base): """ Convert operand to an offset - (for the explanations of 'ea' and 'n' please see OpBinary()) + (for the explanations of 'ea' and 'n' please see op_bin()) Example: ======== @@ -1116,7 +1060,7 @@ def OpOff(ea, n, base): Then you need to specify a linear address of the segment base to create a proper offset: - OpOff(["seg000",0x2000],0,0x10000); + op_plain_offset(["seg000",0x2000],0,0x10000); and you will have: @@ -1137,16 +1081,19 @@ def OpOff(ea, n, base): @param base: base of the offset as a linear address If base == BADADDR then the current operand becomes non-offset """ - return ida_offset.set_offset(ea, n, base) + if base == BADADDR: + return ida_bytes.clr_op_type(ea, n) + else: + return ida_offset.op_plain_offset(ea, n, base) OPND_OUTER = ida_bytes.OPND_OUTER # outer offset base -def OpOffEx(ea, n, reftype, target, base, tdelta): +def op_offset(ea, n, reftype, target, base, tdelta): """ Convert operand to a complex offset expression - This is a more powerful version of OpOff() function. + This is a more powerful version of op_plain_offset() function. It allows to explicitly specify the reference type (off8,off16, etc) and the expression target with a possible target delta. The complex expressions are represented by IDA in the following form: @@ -1160,7 +1107,7 @@ def OpOffEx(ea, n, reftype, target, base, tdelta): The target must be present for LOW.. and HIGH.. reference types @param ea: linear address of the instruction/data - @param n: number of operand to convert (the same as in OpOff) + @param n: number of operand to convert (the same as in op_plain_offset) @param reftype: one of REF_... constants @param target: an explicitly specified expression target. if you don't want to specify it, use -1. Please note that LOW... and @@ -1181,8 +1128,6 @@ REF_LOW8 = ida_nalt.REF_LOW8 # low 8bits of 16bit offset REF_LOW16 = ida_nalt.REF_LOW16 # low 16bits of 32bit offset REF_HIGH8 = ida_nalt.REF_HIGH8 # high 8bits of 16bit offset REF_HIGH16 = ida_nalt.REF_HIGH16 # high 16bits of 32bit offset -REF_VHIGH = ida_nalt.REF_VHIGH # high ph.high_fixup_bits of 32bit offset (processor dependent) -REF_VLOW = ida_nalt.REF_VLOW # low (32-ph.high_fixup_bits) of 32bit offset (processor dependent) REF_OFF64 = ida_nalt.REF_OFF64 # 64bit full offset REFINFO_RVA = 0x10 # based reference (rva) REFINFO_PASTEND = 0x20 # reference past an item it may point to an nonexistitng @@ -1197,7 +1142,7 @@ REFINFO_SUBTRACT = 0x0100 # the reference value is subtracted from REFINFO_SIGNEDOP = 0x0200 # the operand value is sign-extended (only # supported for REF_OFF8/16/32/64) -def OpSeg(ea, n): +def op_seg(ea, n): """ Convert operand to a segment expression @@ -1210,7 +1155,7 @@ def OpSeg(ea, n): return ida_bytes.op_seg(ea, n) -def OpNumber(ea, n): +def op_num(ea, n): """ Convert operand to a number (with default number base, radix) @@ -1223,7 +1168,7 @@ def OpNumber(ea, n): return ida_bytes.op_num(ea, n) -def OpFloat(ea, n): +def op_flt(ea, n): """ Convert operand to a floating-point number @@ -1238,7 +1183,7 @@ def OpFloat(ea, n): return ida_bytes.op_flt(ea, n) -def OpAlt(ea, n, opstr): +def op_man(ea, n, opstr): """ Specify operand represenation manually. @@ -1255,7 +1200,7 @@ def OpAlt(ea, n, opstr): return ida_bytes.set_forced_operand(ea, n, opstr) -def OpSign(ea, n): +def toggle_sign(ea, n): """ Change sign of the operand @@ -1268,7 +1213,7 @@ def OpSign(ea, n): return ida_bytes.toggle_sign(ea, n) -def OpNot(ea, n): +def toggle_bnot(ea, n): """ Toggle the bitwise not operator for the operand @@ -1282,7 +1227,7 @@ def OpNot(ea, n): return True -def OpEnumEx(ea, n, enumid, serial): +def op_enum(ea, n, enumid, serial): """ Convert operand to a symbolic constant @@ -1303,7 +1248,7 @@ def OpEnumEx(ea, n, enumid, serial): return ida_bytes.op_enum(ea, n, enumid, serial) -def OpStroffEx(ea, n, strid, delta): +def op_stroff(ea, n, strid, delta): """ Convert operand to an offset in a structure @@ -1322,7 +1267,7 @@ def OpStroffEx(ea, n, strid, delta): return ida_bytes.op_stroff(ea, n, path.cast(), 1, delta) -def OpStkvar(ea, n): +def op_stkvar(ea, n): """ Convert operand to a stack variable @@ -1335,7 +1280,7 @@ def OpStkvar(ea, n): return ida_bytes.op_stkvar(ea, n) -def OpHigh(ea, n, target): +def op_offset_high16(ea, n, target): """ Convert operand to a high offset High offset is the upper 16bits of an offset. @@ -1366,13 +1311,34 @@ def MakeVar(ea): """ ida_bytes.doVar(ea, 1) +# Every anterior/posterior line has its number. +# Anterior lines have numbers from E_PREV +# Posterior lines have numbers from E_NEXT +E_PREV = ida_lines.E_PREV +E_NEXT = ida_lines.E_NEXT -def ExtLinA(ea, n, line): +def get_extra_cmt(ea, n): """ - Specify an additional line to display before the generated ones. + Get extra comment line @param ea: linear address - @param n: number of anterior additional line (0..MAX_ITEM_LINES) + @param n: number of line (0..MAX_ITEM_LINES) + MAX_ITEM_LINES is defined in IDA.CFG + + To get anterior line #n use (E_PREV + n) + To get posterior line #n use (E_NEXT + n) + + @return: extra comment line string + """ + return ida_lines.get_extra_cmt(ea, n) + + +def update_extra_cmt(ea, n, line): + """ + Set or update extra comment line + + @param ea: linear address + @param n: number of additional line (0..MAX_ITEM_LINES) @param line: the line to display @return: None @@ -1381,55 +1347,29 @@ def ExtLinA(ea, n, line): additional line. So, if you specify additional line #150 and there is no additional line #149, your line will not be displayed. MAX_ITEM_LINES is defined in IDA.CFG + + To set anterior line #n use (E_PREV + n) + To set posterior line #n use (E_NEXT + n) """ - ida_lines.update_extra_cmt(ea, ida_lines.E_PREV + n, line) - ida_bytes.doExtra(ea) + ida_lines.update_extra_cmt(ea, n, line) -def ExtLinB(ea, n, line): +def del_extra_cmt(ea, n): """ - Specify an additional line to display after the generated ones. + Delete an extra comment line @param ea: linear address - @param n: number of posterior additional line (0..MAX_ITEM_LINES) - @param line: the line to display + @param n: number of anterior additional line (0..MAX_ITEM_LINES) @return: None - @note: IDA displays additional lines from number 0 up to the first - unexisting additional line. So, if you specify additional line #150 - and there is no additional line #149, your line will not be displayed. - MAX_ITEM_LINES is defined in IDA.CFG + To delete anterior line #n use (E_PREV + n) + To delete posterior line #n use (E_NEXT + n) """ - ida_lines.update_extra_cmt(ea, ida_lines.E_NEXT + n, line) - ida_bytes.doExtra(ea) + ida_lines.del_extra_cmt(ea, n) -def DelExtLnA(ea, n): - """ - Delete an additional anterior line - - @param ea: linear address - @param n: number of anterior additional line (0..500) - - @return: None - """ - ida_lines.del_extra_cmt(ea, ida_lines.E_PREV + n) - - -def DelExtLnB(ea, n): - """ - Delete an additional posterior line - - @param ea: linear address - @param n: number of posterior additional line (0..500) - - @return: None - """ - ida_lines.del_extra_cmt(ea, ida_lines.E_NEXT + n) - - -def SetManualInsn(ea, insn): +def set_manual_insn(ea, insn): """ Specify instruction represenation manually. @@ -1442,18 +1382,18 @@ def SetManualInsn(ea, insn): return ida_bytes.set_manual_insn(ea, insn) -def GetManualInsn(ea): +def get_manual_insn(ea): """ Get manual representation of instruction @param ea: linear address - @note: This function returns value set by SetManualInsn earlier. + @note: This function returns value set by set_manual_insn earlier. """ return ida_bytes.get_manual_insn(ea) -def PatchDbgByte(ea,value): +def patch_dbg_byte(ea,value): """ Change a byte in the debugged process memory only @@ -1465,7 +1405,7 @@ def PatchDbgByte(ea,value): return ida_dbg.put_dbg_byte(ea, value) -def PatchByte(ea, value): +def patch_byte(ea, value): """ Change value of a program byte If debugger was active then the debugged process memory will be patched too @@ -1482,7 +1422,7 @@ def PatchByte(ea, value): return ida_bytes.patch_byte(ea, value) -def PatchWord(ea, value): +def patch_word(ea, value): """ Change value of a program word (2 bytes) @@ -1498,7 +1438,7 @@ def PatchWord(ea, value): return ida_bytes.patch_word(ea, value) -def PatchDword(ea, value): +def patch_dword(ea, value): """ Change value of a double word @@ -1511,10 +1451,10 @@ def PatchDword(ea, value): or the debugger is not running, and the IDB has value 'value' at address 'ea already. """ - return ida_bytes.patch_long(ea, value) + return ida_bytes.patch_dword(ea, value) -def PatchQword(ea, value): +def patch_qword(ea, value): """ Change value of a quad word @@ -1530,19 +1470,12 @@ def PatchQword(ea, value): return ida_bytes.patch_qword(ea, value) -def SetFlags(ea, flags): - """ - Set new value of flags - This function should not used be used directly if possible. - It changes properties of a program byte and if misused, may lead to - very-very strange results. +SR_inherit = 1 # value is inherited from the previous range +SR_user = 2 # value is specified by the user +SR_auto = 3 # value is determined by IDA +SR_autostart = 4 # as SR_auto for segment starting address - @param ea: adress - @param flags: new flags value - """ - return ida_bytes.setFlags(ea, flags) - -def SetRegEx(ea, reg, value, tag): +def split_sreg_range(ea, reg, value, tag=SR_user): """ Set value of a segment register. @@ -1554,22 +1487,15 @@ def SetRegEx(ea, reg, value, tag): @note: IDA keeps tracks of all the points where segment register change their values. This function allows you to specify the correct value of a segment register if IDA is not able to find the corrent value. - - See also SetReg() compatibility macro. """ reg = ida_idp.str2reg(reg); if reg >= 0: - return ida_srarea.splitSRarea1(ea, reg, value, tag) + return ida_segregs.split_sreg_range(ea, reg, value, tag) else: return False -SR_inherit = 1 # value is inherited from the previous area -SR_user = 2 # value is specified by the user -SR_auto = 3 # value is determined by IDA -SR_autostart = 4 # as SR_auto for segment starting address - -def AutoMark2(start, end, queuetype): +def auto_mark_range(start, end, queuetype): """ Plan to perform an action in the future. This function will put your request to a special autoanalysis queue. @@ -1580,18 +1506,18 @@ def AutoMark2(start, end, queuetype): return ida_auto.auto_mark_range(start, end, queuetype) -def AutoUnmark(start, end, queuetype): +def auto_unmark(start, end, queuetype): """ Remove range of addresses from a queue. """ - return ida_auto.autoUnmark(start, end, queuetype) + return ida_auto.auto_unmark(start, end, queuetype) def AutoMark(ea,qtype): """ Plan to analyze an address """ - return AutoMark2(ea,ea+1,qtype) + return auto_mark_range(ea,ea+1,qtype) AU_UNK = ida_auto.AU_UNK # make unknown AU_CODE = ida_auto.AU_CODE # convert to instruction @@ -1605,7 +1531,7 @@ AU_FINAL = ida_auto.AU_FINAL # coagulate unexplored items # P R O D U C E O U T P U T F I L E S #---------------------------------------------------------------------------- -def GenerateFile(filetype, path, ea1, ea2, flags): +def gen_file(filetype, path, ea1, ea2, flags): """ Generate an output file @@ -1647,14 +1573,14 @@ GENFLG_ASMTYPE = ida_loader.GENFLG_ASMTYPE # asm&lst: gen information about type GENFLG_GENHTML = ida_loader.GENFLG_GENHTML # asm&lst: generate html (gui version only) GENFLG_ASMINC = ida_loader.GENFLG_ASMINC # asm&lst: gen information only about types -def GenFuncGdl(outfile, title, ea1, ea2, flags): +def gen_flow_graph(outfile, title, ea1, ea2, flags): """ Generate a flow chart GDL file @param outfile: output file name. GDL extension will be used @param title: graph title - @param ea1: beginning of the area to flow chart - @param ea2: end of the area to flow chart. + @param ea1: beginning of the range to flow chart + @param ea2: end of the range to flow chart. @param flags: combination of CHART_... constants @note: If ea2 == BADADDR then ea1 is treated as an address within a function. @@ -1669,7 +1595,7 @@ CHART_WINGRAPH = 0x8000 # call wingraph32 to display the graph CHART_NOLIBFUNCS = 0x0400 # don't include library functions in the graph -def GenCallGdl(outfile, title, flags): +def gen_simple_call_chart(outfile, title, flags): """ Generate a function call graph GDL file @@ -1683,7 +1609,7 @@ def GenCallGdl(outfile, title, flags): #---------------------------------------------------------------------------- # C O M M O N I N F O R M A T I O N #---------------------------------------------------------------------------- -def GetIdaDirectory(): +def idadir(): """ Get IDA directory @@ -1692,7 +1618,7 @@ def GetIdaDirectory(): return ida_diskio.idadir("") -def GetInputFile(): +def get_root_filename(): """ Get input file name @@ -1701,7 +1627,7 @@ def GetInputFile(): return ida_nalt.get_root_filename() -def GetInputFilePath(): +def get_input_file_path(): """ Get input file path @@ -1710,7 +1636,7 @@ def GetInputFilePath(): return ida_nalt.get_input_file_path() -def SetInputFilePath(path): +def set_root_filename(path): """ Set input file name This function updates the file name that is stored in the database @@ -1723,16 +1649,16 @@ def SetInputFilePath(path): return ida_nalt.set_root_filename(path) -def GetIdbPath(): +def get_idb_path(): """ Get IDB full path This function returns full path of the current IDB database """ - return ida_idaapi.as_cstr(ida_loader.cvar.database_idb) + return ida_loader.get_path(ida_loader.PATH_TYPE_IDB) -def GetInputMD5(): +def retrieve_input_file_md5(): """ Return the MD5 hash of the input binary file @@ -1741,7 +1667,7 @@ def GetInputMD5(): return ida_nalt.retrieve_input_file_md5() -def GetFlags(ea): +def get_full_flags(ea): """ Get internal flags @@ -1750,10 +1676,10 @@ def GetFlags(ea): @return: 32-bit value of internal flags. See start of IDC.IDC file for explanations. """ - return ida_bytes.getFlags(ea) + return ida_bytes.get_full_flags(ea) -def IdbByte(ea): +def get_db_byte(ea): """ Get one byte (8-bit) of the program at 'ea' from the database even if the debugger is active @@ -1762,12 +1688,12 @@ def IdbByte(ea): @return: byte value. If the byte has no value then 0xFF is returned. @note: If the current byte size is different from 8 bits, then the returned value may have more 1's. - To check if a byte has a value, use this expr: hasValue(GetFlags(ea)) + To check if a byte has a value, use is_loaded() """ return ida_bytes.get_db_byte(ea) -def GetManyBytes(ea, size, use_dbg = False): +def get_bytes(ea, size, use_dbg = False): """ Return the specified number of bytes of the program @@ -1783,10 +1709,10 @@ def GetManyBytes(ea, size, use_dbg = False): if use_dbg: return ida_idd.dbg_read_memory(ea, size) else: - return ida_bytes.get_many_bytes(ea, size) + return ida_bytes.get_bytes(ea, size) -def Byte(ea): +def get_wide_byte(ea): """ Get value of program byte @@ -1795,19 +1721,19 @@ def Byte(ea): @return: value of byte. If byte has no value then returns 0xFF If the current byte size is different from 8 bits, then the returned value might have more 1's. - To check if a byte has a value, use functions hasValue(GetFlags(ea)) + To check if a byte has a value, use is_loaded() """ - return ida_bytes.get_full_byte(ea) + return ida_bytes.get_wide_byte(ea) def __DbgValue(ea, len): if len not in ida_idaapi.__struct_unpack_table: return None r = ida_idd.dbg_read_memory(ea, len) - return None if r is None else struct.unpack((">" if ida_ida.cvar.inf.mf else "<") + ida_idaapi.__struct_unpack_table[len][1], r)[0] + return None if r is None else struct.unpack((">" if ida_ida.cvar.inf.is_be() else "<") + ida_idaapi.__struct_unpack_table[len][1], r)[0] -def DbgByte(ea): +def read_dbg_byte(ea): """ Get value of program byte using the debugger memory @@ -1817,7 +1743,7 @@ def DbgByte(ea): return __DbgValue(ea, 1) -def DbgWord(ea): +def read_dbg_word(ea): """ Get value of program word using the debugger memory @@ -1827,7 +1753,7 @@ def DbgWord(ea): return __DbgValue(ea, 2) -def DbgDword(ea): +def read_dbg_dword(ea): """ Get value of program double-word using the debugger memory @@ -1837,7 +1763,7 @@ def DbgDword(ea): return __DbgValue(ea, 4) -def DbgQword(ea): +def read_dbg_qword(ea): """ Get value of program quadro-word using the debugger memory @@ -1847,7 +1773,7 @@ def DbgQword(ea): return __DbgValue(ea, 8) -def DbgRead(ea, size): +def read_dbg_memory(ea, size): """ Read from debugger memory. @@ -1860,7 +1786,7 @@ def DbgRead(ea, size): return ida_idd.dbg_read_memory(ea, size) -def DbgWrite(ea, data): +def write_dbg_memory(ea, data): """ Write to debugger memory. @@ -1876,7 +1802,7 @@ def DbgWrite(ea, data): return ida_idd.dbg_write_memory(ea, data) -def GetOriginalByte(ea): +def get_original_byte(ea): """ Get original value of program byte @@ -1887,7 +1813,7 @@ def GetOriginalByte(ea): return ida_bytes.get_original_byte(ea) -def Word(ea): +def get_wide_word(ea): """ Get value of program word (2 bytes) @@ -1897,10 +1823,10 @@ def Word(ea): If the current byte size is different from 8 bits, then the returned value might have more 1's. """ - return ida_bytes.get_full_word(ea) + return ida_bytes.get_wide_word(ea) -def Dword(ea): +def get_wide_dword(ea): """ Get value of program double word (4 bytes) @@ -1908,10 +1834,10 @@ def Dword(ea): @return: the value of the double word. If failed returns -1 """ - return ida_bytes.get_full_long(ea) + return ida_bytes.get_wide_dword(ea) -def Qword(ea): +def get_qword(ea): """ Get value of program quadro word (8 bytes) @@ -1932,7 +1858,7 @@ def GetFloat(ea): @return: float """ - tmp = struct.pack("I", Dword(ea)) + tmp = struct.pack("I", get_wide_dword(ea)) return struct.unpack("f", tmp)[0] @@ -1946,11 +1872,11 @@ def GetDouble(ea): @return: double """ - tmp = struct.pack("Q", Qword(ea)) + tmp = struct.pack("Q", get_qword(ea)) return struct.unpack("d", tmp)[0] -def LocByName(name): +def get_name_ea_simple(name): """ Get linear address of a name @@ -1962,7 +1888,7 @@ def LocByName(name): return ida_name.get_name_ea(BADADDR, name) -def LocByNameEx(fromaddr, name): +def get_name_ea(fromaddr, name): """ Get linear address of a name @@ -1980,7 +1906,7 @@ def LocByNameEx(fromaddr, name): return ida_name.get_name_ea(fromaddr, name) -def SegByBase(base): +def get_segm_by_sel(base): """ Get segment by segment base @@ -1993,19 +1919,19 @@ def SegByBase(base): seg = ida_segment.get_segm_by_sel(sel) if seg: - return seg.startEA + return seg.start_ea else: return BADADDR -def ScreenEA(): +def get_screen_ea(): """ Get linear address of cursor """ return ida_kernwin.get_screen_ea() -def GetCurrentLine(): +def get_curline(): """ Get the disassembly line at the cursor @@ -2014,12 +1940,12 @@ def GetCurrentLine(): return ida_lines.tag_remove(ida_kernwin.get_curline()) -def SelStart(): +def read_selection_start(): """ - Get start address of the selected area - returns BADADDR - the user has not selected an area + Get start address of the selected range + returns BADADDR - the user has not selected an range """ - selection, startaddr, endaddr = ida_kernwin.read_selection() + selection, startaddr, endaddr = ida_kernwin.read_range_selection(None) if selection == 1: return startaddr @@ -2027,13 +1953,13 @@ def SelStart(): return BADADDR -def SelEnd(): +def read_selection_end(): """ - Get end address of the selected area + Get end address of the selected range - @return: BADADDR - the user has not selected an area + @return: BADADDR - the user has not selected an range """ - selection, startaddr, endaddr = ida_kernwin.read_selection() + selection, startaddr, endaddr = ida_kernwin.read_range_selection(None) if selection == 1: return endaddr @@ -2041,7 +1967,7 @@ def SelEnd(): return BADADDR -def GetReg(ea, reg): +def get_sreg(ea, reg): """ Get value of segment register at the specified address @@ -2052,15 +1978,15 @@ def GetReg(ea, reg): @note: The segment registers in 32bit program usually contain selectors, so to get paragraph pointed to by the segment register you need to - call AskSelector() function. + call sel2para() function. """ reg = ida_idp.str2reg(reg); if reg >= 0: - return ida_srarea.getSR(ea, reg) + return ida_segregs.get_sreg(ea, reg) else: return -1 -def NextAddr(ea): +def next_addr(ea): """ Get next address in the program @@ -2068,10 +1994,10 @@ def NextAddr(ea): @return: BADADDR - the specified address in the last used address """ - return ida_bytes.nextaddr(ea) + return ida_bytes.next_addr(ea) -def PrevAddr(ea): +def prev_addr(ea): """ Get previous address in the program @@ -2079,10 +2005,10 @@ def PrevAddr(ea): @return: BADADDR - the specified address in the first address """ - return ida_bytes.prevaddr(ea) + return ida_bytes.prev_addr(ea) -def NextHead(ea, maxea=BADADDR): +def next_head(ea, maxea=BADADDR): """ Get next defined item (instruction or data) in the program @@ -2095,7 +2021,7 @@ def NextHead(ea, maxea=BADADDR): return ida_bytes.next_head(ea, maxea) -def PrevHead(ea, minea=0): +def prev_head(ea, minea=0): """ Get previous defined item (instruction or data) in the program @@ -2108,7 +2034,7 @@ def PrevHead(ea, minea=0): return ida_bytes.prev_head(ea, minea) -def NextNotTail(ea): +def next_not_tail(ea): """ Get next not-tail address in the program This function searches for the next displayable address in the program. @@ -2121,7 +2047,7 @@ def NextNotTail(ea): return ida_bytes.next_not_tail(ea) -def PrevNotTail(ea): +def prev_not_tail(ea): """ Get previous not-tail address in the program This function searches for the previous displayable address in the program. @@ -2134,7 +2060,7 @@ def PrevNotTail(ea): return ida_bytes.prev_not_tail(ea) -def ItemHead(ea): +def get_item_head(ea): """ Get starting address of the item (instruction or data) @@ -2146,7 +2072,7 @@ def ItemHead(ea): return ida_bytes.get_item_head(ea) -def ItemEnd(ea): +def get_item_end(ea): """ Get address of the end of the item (instruction or data) @@ -2157,7 +2083,7 @@ def ItemEnd(ea): return ida_bytes.get_item_end(ea) -def ItemSize(ea): +def get_item_size(ea): """ Get size of instruction or data item in bytes @@ -2168,68 +2094,74 @@ def ItemSize(ea): return ida_bytes.get_item_end(ea) - ea -def NameEx(fromaddr, ea): +def func_contains(func_ea, ea): """ - Get visible name of program byte + Does the given function contain the given address? - This function returns name of byte as it is displayed on the screen. - If a name contains illegal characters, IDA replaces them by the - substitution character during displaying. See IDA.CFG for the - definition of the substitution character. + @param func_ea: any address belonging to the function + @param ea: linear address + + @return: success + """ + func = ida_funcs.get_func(func_ea) + + if func: + return ida_funcs.func_contains(func, ea) + return False + + +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_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 +GN_ISRET = ida_name.GN_ISRET # for dummy names: use retloc +GN_NOT_ISRET = ida_name.GN_NOT_ISRET # for dummy names: do not use retloc + + +def calc_gtn_flags(fromaddr, ea): + """ + Calculate flags for get_name() function @param fromaddr: the referring address. May be BADADDR. - Allows to retrieve local label addresses in functions. - If a local name is not found, then a global name is - returned. @param ea: linear address + @return: success + """ + return ida_name.calc_gtn_flags(fromaddr, ea) + + +def get_name(ea, gtn_flags=0): + """ + Get name at the specified address + + @param ea: linear address + @param gtn_flags: how exactly the name should be retrieved. + combination of GN_ bits + @return: "" - byte has no name """ - name = ida_name.get_name(fromaddr, ea) - - if not name: - return "" - else: - return name + return ida_name.get_ea_name(ea, gtn_flags) -def GetTrueNameEx(fromaddr, ea): +def demangle_name(name, disable_mask): """ - Get true name of program byte - - This function returns name of byte as is without any replacements. - - @param fromaddr: the referring address. May be BADADDR. - Allows to retrieve local label addresses in functions. - If a local name is not found, then a global name is returned. - @param ea: linear address - - @return: "" - byte has no name - """ - name = ida_name.get_true_name(fromaddr, ea) - - if not name: - return "" - else: - return name - - -def Demangle(name, disable_mask): - """ - Demangle a name + demangle_name a name @param name: name to demangle @param disable_mask: a mask that tells how to demangle the name it is a good idea to get this mask using - GetLongPrm(INF_SHORT_DN) or GetLongPrm(INF_LONG_DN) + get_inf_attr(INF_SHORT_DN) or get_inf_attr(INF_LONG_DN) @return: a demangled name If the input name cannot be demangled, returns None """ - return ida_name.demangle_name(name, disable_mask) + return ida_name.demangle_name(name, disable_mask, ida_name.DQT_FULL) -def GetDisasmEx(ea, flags): +def generate_disasm_line(ea, flags): """ Get disassembly line @@ -2248,7 +2180,7 @@ def GetDisasmEx(ea, flags): else: return "" -# flags for GetDisasmEx +# flags for generate_disasm_line # generate a disassembly line as if # there is an instruction at 'ea' GENDSM_FORCE_CODE = ida_lines.GENDSM_FORCE_CODE @@ -2268,9 +2200,9 @@ def GetDisasm(ea): @note: this function may not return exactly the same mnemonics as you see on the screen. """ - return GetDisasmEx(ea, 0) + return generate_disasm_line(ea, 0) -def GetMnem(ea): +def print_insn_mnem(ea): """ Get instruction mnemonics @@ -2289,11 +2221,11 @@ def GetMnem(ea): return res -def GetOpnd(ea, n): +def print_operand(ea, n): """ - Get operand of an instruction + Get operand of an instruction or data - @param ea: linear address of instruction + @param ea: linear address of the item @param n: number of operand: 0 - the first operand 1 - the second operand @@ -2301,10 +2233,7 @@ def GetOpnd(ea, n): @return: the current text representation of operand or "" """ - if not isCode(ida_bytes.get_flags_novalue(ea)): - return "" - - res = ida_ua.ua_outop2(ea, n) + res = ida_ua.print_operand(ea, n) if not res: return "" @@ -2312,7 +2241,7 @@ def GetOpnd(ea, n): return ida_lines.tag_remove(res) -def GetOpType(ea, n): +def get_operand_type(ea, n): """ Get type of instruction operand @@ -2323,8 +2252,9 @@ def GetOpType(ea, n): @return: any of o_* constants or -1 on error """ - inslen = ida_ua.decode_insn(ea) - return -1 if inslen == 0 else ida_ua.cmd.Operands[n].type + insn = ida_ua.insn_t() + inslen = ida_ua.decode_insn(insn, ea) + return -1 if inslen == 0 else insn.ops[n].type o_void = ida_ua.o_void # No Operand ---------- @@ -2355,9 +2285,9 @@ o_xmmreg = ida_ua.o_idpspec5 # xmm register o_reglist = ida_ua.o_idpspec1 # Register list (for LDM/STM) o_creglist = ida_ua.o_idpspec2 # Coprocessor register list (for CDP) o_creg = ida_ua.o_idpspec3 # Coprocessor register (for LDC/STC) -o_fpreg_arm = ida_ua.o_idpspec4 # Floating point register -o_fpreglist = ida_ua.o_idpspec5 # Floating point register list -o_text = (ida_ua.o_idpspec5+1) # Arbitrary text stored in the operand +o_fpreglist = ida_ua.o_idpspec4 # Floating point register list +o_text = ida_ua.o_idpspec5 # Arbitrary text stored in the operand +o_cond = (ida_ua.o_idpspec5+1) # ARM condition as an operand # ppc o_spr = ida_ua.o_idpspec0 # Special purpose register @@ -2367,7 +2297,7 @@ o_crf = ida_ua.o_idpspec3 # crfield x.reg o_crb = ida_ua.o_idpspec4 # crbit x.reg o_dcr = ida_ua.o_idpspec5 # Device control register -def GetOperandValue(ea, n): +def get_operand_value(ea, n): """ Get number used in the operand @@ -2384,10 +2314,11 @@ def GetOperandValue(ea, n): operand is a register phrase => phrase number otherwise => -1 """ - inslen = ida_ua.decode_insn(ea) + insn = ida_ua.insn_t() + inslen = ida_ua.decode_insn(insn, ea) if inslen == 0: return -1 - op = ida_ua.cmd.Operands[n] + op = insn.ops[n] if not op: return -1 @@ -2404,31 +2335,6 @@ def GetOperandValue(ea, n): return value -def LineA(ea, num): - """ - Get anterior line - - @param ea: linear address - @param num: number of anterior line (0..MAX_ITEM_LINES) - MAX_ITEM_LINES is defined in IDA.CFG - - @return: anterior line string - """ - return ida_lines.get_extra_cmt(ea, ida_lines.E_PREV + num) - - -def LineB(ea, num): - """ - Get posterior line - - @param ea: linear address - @param num: number of posterior line (0..MAX_ITEM_LINES) - - @return: posterior line string - """ - return ida_lines.get_extra_cmt(ea, ida_lines.E_NEXT + num) - - def GetCommentEx(ea, repeatable): """ Get regular indented comment @@ -2442,7 +2348,7 @@ def GetCommentEx(ea, repeatable): return ida_bytes.get_cmt(ea, repeatable) -def CommentEx(ea, repeatable): +def get_cmt(ea, repeatable): """ Get regular indented comment @@ -2455,7 +2361,7 @@ def CommentEx(ea, repeatable): return GetCommentEx(ea, repeatable) -def AltOp(ea, n): +def get_forced_operand(ea, n): """ Get manually entered operand string @@ -2468,42 +2374,41 @@ def AltOp(ea, n): """ return ida_bytes.get_forced_operand(ea, n) -ASCSTR_C = ida_nalt.ASCSTR_TERMCHR # C-style ASCII string -ASCSTR_PASCAL = ida_nalt.ASCSTR_PASCAL # Pascal-style ASCII string (length byte) -ASCSTR_LEN2 = ida_nalt.ASCSTR_LEN2 # Pascal-style, length is 2 bytes -ASCSTR_UNICODE = ida_nalt.ASCSTR_UNICODE # Unicode string -ASCSTR_LEN4 = ida_nalt.ASCSTR_LEN4 # Pascal-style, length is 4 bytes -ASCSTR_ULEN2 = ida_nalt.ASCSTR_ULEN2 # Pascal-style Unicode, length is 2 bytes -ASCSTR_ULEN4 = ida_nalt.ASCSTR_ULEN4 # Pascal-style Unicode, length is 4 bytes -ASCSTR_LAST = ida_nalt.ASCSTR_LAST # Last string type +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 -def GetString(ea, length = -1, strtype = ASCSTR_C): +def get_strlit_contents(ea, length = -1, strtype = STRTYPE_C): """ Get string contents @param ea: linear address @param length: string length. -1 means to calculate the max string length - @param strtype: the string type (one of ASCSTR_... constants) + @param strtype: the string type (one of STRTYPE_... constants) @return: string contents or empty string """ if length == -1: - length = ida_bytes.get_max_ascii_length(ea, strtype, ida_bytes.ALOPT_IGNHEADS) + length = ida_bytes.get_max_strlit_length(ea, strtype, ida_bytes.ALOPT_IGNHEADS) - return ida_bytes.get_ascii_contents2(ea, length, strtype) + return ida_bytes.get_strlit_contents(ea, length, strtype) -def GetStringType(ea): +def get_str_type(ea): """ Get string type @param ea: linear address - @return: One of ASCSTR_... constants + @return: One of STRTYPE_... constants """ - flags = ida_bytes.getFlags(ea) - if ida_bytes.isASCII(flags): + flags = ida_bytes.get_flags(ea) + if ida_bytes.is_strlit(flags): oi = ida_nalt.opinfo_t() - if ida_bytes.get_opinfo(ea, 0, flags, oi): + if ida_bytes.get_opinfo(oi, ea, 0, flags): return oi.strtype # The following functions search for the specified byte @@ -2511,24 +2416,24 @@ def GetStringType(ea): # flag is combination of the following bits # returns BADADDR - not found -def FindVoid (ea, flag): return ida_search.find_void(ea, flag) -def FindCode (ea, flag): return ida_search.find_code(ea, flag) -def FindData (ea, flag): return ida_search.find_data(ea, flag) -def FindUnexplored (ea, flag): return ida_search.find_unknown(ea, flag) -def FindExplored (ea, flag): return ida_search.find_defined(ea, flag) -def FindImmediate (ea, flag, value): return ida_search.find_imm(ea, flag, value) +def find_suspop (ea, flag): return ida_search.find_suspop(ea, flag) +def find_code (ea, flag): return ida_search.find_code(ea, flag) +def find_data (ea, flag): return ida_search.find_data(ea, flag) +def find_unknown (ea, flag): return ida_search.find_unknown(ea, flag) +def find_defined (ea, flag): return ida_search.find_defined(ea, flag) +def find_imm (ea, flag, value): return ida_search.find_imm(ea, flag, value) SEARCH_UP = ida_search.SEARCH_UP # search backward SEARCH_DOWN = ida_search.SEARCH_DOWN # search forward SEARCH_NEXT = ida_search.SEARCH_NEXT # start the search at the next/prev item - # useful only for FindText() and FindBinary() + # useful only for find_text() and find_binary() SEARCH_CASE = ida_search.SEARCH_CASE # search case-sensitive # (only for bin&txt search) SEARCH_REGEX = ida_search.SEARCH_REGEX # enable regular expressions (only for text) SEARCH_NOBRK = ida_search.SEARCH_NOBRK # don't test ctrl-break SEARCH_NOSHOW = ida_search.SEARCH_NOSHOW # don't display the search progress -def FindText(ea, flag, y, x, searchstr): +def find_text(ea, flag, y, x, searchstr): """ @param ea: start address @param flag: combination of SEARCH_* flags @@ -2541,7 +2446,7 @@ def FindText(ea, flag, y, x, searchstr): return ida_search.find_text(ea, y, x, searchstr, flag) -def FindBinary(ea, flag, searchstr, radix=16): +def find_binary(ea, flag, searchstr, radix=16): """ @param ea: start address @param flag: combination of SEARCH_* flags @@ -2552,14 +2457,14 @@ def FindBinary(ea, flag, searchstr, radix=16): @note: Example: "41 42" - find 2 bytes 41h,42h (radix is 16) """ - endea = flag & 1 and ida_ida.cvar.inf.maxEA or ida_ida.cvar.inf.minEA + endea = flag & 1 and ida_ida.cvar.inf.max_ea or ida_ida.cvar.inf.min_ea return ida_search.find_binary(ea, endea, searchstr, radix, flag) #---------------------------------------------------------------------------- # G L O B A L S E T T I N G S M A N I P U L A T I O N #---------------------------------------------------------------------------- -def ChangeConfig(directive): +def process_config_line(directive): """ Parse one or more ida.cfg config directives @param directive: directives to process, for example: PACK_DATABASE=2 @@ -2567,13 +2472,13 @@ def ChangeConfig(directive): @note: If the directives are erroneous, a fatal error will be generated. The settings are permanent: effective for the current session and the next ones """ - return Eval('ChangeConfig("%s")' % ida_kernwin.str2user(directive)) + return eval_idc('process_config_line("%s")' % ida_kernwin.str2user(directive)) # The following functions allow you to set/get common parameters. # Please note that not all parameters can be set directly. -def GetLongPrm(offset): +def get_inf_attr(offset): """ """ val = _IDC_GetAttr(ida_ida.cvar.inf, _INFMAP, offset) @@ -2582,418 +2487,413 @@ def GetLongPrm(offset): val = ida_idaapi.as_cstr(val) return val -def GetShortPrm(offset): - return GetLongPrm(offset) - - -def GetCharPrm (offset): - return GetLongPrm(offset) - - -def _invoke_idc_setprm(vtype, offset, value): +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("Set%sPrm(%d, %d)" % (vtype, offset, value)) + return eval_idc("set_inf_attr(%d, %d)" % (offset, value)) -def SetLongPrm (offset, value): - return _invoke_idc_setprm("Long", offset, value) +INF_VERSION = 4 # short; Version of database +INF_PROCNAME = 6 # char[8]; Name of current processor +INF_GENFLAGS = 22 # ushort; General flags: +INFFL_AUTO = 0x01 # Autoanalysis is enabled? +INFFL_ALLASM = 0x02 # May use constructs not supported by + # the target assembler +INFFL_LOADIDC = 0x04 # loading an idc file that contains database info +INFFL_NOUSER = 0x08 # do not store user info in the database +INFFL_READONLY = 0x10 # (internal) temporary interdiction to modify the database +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 +LFLG_PC_FPP = 0x00000001 # decode floating point processor + # instructions? +LFLG_PC_FLAT = 0x00000002 # Flat model? +LFLG_64BIT = 0x00000004 # 64-bit program? +LFLG_IS_DLL = 0x00000008 # is dynamic library? +LFLG_FLAT_OFF32= 0x00000010 # treat REF_OFF32 as 32-bit offset for 16bit segments (otherwise try SEG16:OFF16) +LFLG_MSF = 0x00000020 # byte order: is MSB first? +LFLG_WIDE_HBF = 0x00000040 # bit order of wide bytes: high byte first? +LFLG_DBG_NOPATH= 0x00000080 # do not store input full path +LFLG_SNAPSHOT = 0x00000100 # is memory snapshot? +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 -def SetShortPrm(offset, value): - return _invoke_idc_setprm("Short", offset, value) +INF_FILETYPE = 32 # 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 +FT_DRV = 3 # MS DOS Driver +FT_WIN = 4 # New Executable (NE) +FT_HEX = 5 # Intel Hex Object File +FT_MEX = 6 # MOS Technology Hex Object File +FT_LX = 7 # Linear Executable (LX) +FT_LE = 8 # Linear Executable (LE) +FT_NLM = 9 # Netware Loadable Module (NLM) +FT_COFF = 10 # Common Object File Format (COFF) +FT_PE = 11 # Portable Executable (PE) +FT_OMF = 12 # Object Module Format +FT_SREC = 13 # R-records +FT_ZIP = 14 # ZIP file (this file is never loaded to IDA database) +FT_OMFLIB = 15 # Library of OMF Modules +FT_AR = 16 # ar library +FT_LOADER = 17 # file is loaded using LOADER DLL +FT_ELF = 18 # Executable and Linkable Format (ELF) +FT_W32RUN = 19 # Watcom DOS32 Extender (W32RUN) +FT_AOUT = 20 # Linux a.out (AOUT) +FT_PRC = 21 # PalmPilot program file +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 +OSTYPE_MSDOS= 0x0001 +OSTYPE_WIN = 0x0002 +OSTYPE_OS2 = 0x0004 +OSTYPE_NETW = 0x0008 +INF_APPTYPE = 36 # short; FLIRT: Application type +APPT_CONSOLE= 0x0001 # console +APPT_GRAPHIC= 0x0002 # graphics +APPT_PROGRAM= 0x0004 # EXE +APPT_LIBRARY= 0x0008 # DLL +APPT_DRIVER = 0x0010 # DRIVER +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_AF = 40 # 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 +AF_PURDAT = 0x00000008 # Control flow to data segment is ignored +AF_USED = 0x00000010 # Analyze and create all xrefs +AF_UNK = 0x00000020 # Delete instructions with no xrefs -def SetCharPrm (offset, value): - return _invoke_idc_setprm("Char", offset, value) +AF_PROCPTR = 0x00000040 # Create function if data xref data->code32 exists +AF_PROC = 0x00000080 # Create functions if call is present +AF_FTAIL = 0x00000100 # Create function tails +AF_LVAR = 0x00000200 # Create stack variables +AF_STKARG = 0x00000400 # Propagate stack argument information +AF_REGARG = 0x00000800 # Propagate register argument information +AF_TRACE = 0x00001000 # Trace stack pointer +AF_VERSP = 0x00002000 # Perform full SP-analysis. (\ph{verify_sp}) +AF_ANORET = 0x00004000 # Perform 'no-return' analysis +AF_MEMFUNC = 0x00008000 # Try to guess member function types +AF_TRFUNC = 0x00010000 # Truncate functions upon code deletion +AF_STRLIT = 0x00020000 # Create string literal if data xref exists +AF_CHKUNI = 0x00040000 # Check for unicode strings +AF_FIXUP = 0x00080000 # Create offsets and segments using fixup info +AF_DREFOFF = 0x00100000 # Create offset if data xref to seg32 exists +AF_IMMOFF = 0x00200000 # Convert 32bit instruction operand to offset +AF_DATOFF = 0x00400000 # Automatically convert data to offsets -INF_VERSION = 3 # short; Version of database -INF_PROCNAME = 5 # char[8]; Name of current processor -INF_LFLAGS = 13 # char; IDP-dependent flags -LFLG_PC_FPP = 0x01 # decode floating point processor - # instructions? -LFLG_PC_FLAT = 0x02 # Flat model? -LFLG_64BIT = 0x04 # 64-bit program? -LFLG_DBG_NOPATH = 0x08 # do not store input full path -LFLG_SNAPSHOT = 0x10 # is memory snapshot? - # in debugger process options -INF_DEMNAMES = 14 # char; display demangled names as: -DEMNAM_CMNT = 0 # comments -DEMNAM_NAME = 1 # regular names -DEMNAM_NONE = 2 # don't display -INF_FILETYPE = 15 # 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 -FT_DRV = 3 # MS DOS Driver -FT_WIN = 4 # New Executable (NE) -FT_HEX = 5 # Intel Hex Object File -FT_MEX = 6 # MOS Technology Hex Object File -FT_LX = 7 # Linear Executable (LX) -FT_LE = 8 # Linear Executable (LE) -FT_NLM = 9 # Netware Loadable Module (NLM) -FT_COFF = 10 # Common Object File Format (COFF) -FT_PE = 11 # Portable Executable (PE) -FT_OMF = 12 # Object Module Format -FT_SREC = 13 # R-records -FT_ZIP = 14 # ZIP file (this file is never loaded to IDA database) -FT_OMFLIB = 15 # Library of OMF Modules -FT_AR = 16 # ar library -FT_LOADER = 17 # file is loaded using LOADER DLL -FT_ELF = 18 # Executable and Linkable Format (ELF) -FT_W32RUN = 19 # Watcom DOS32 Extender (W32RUN) -FT_AOUT = 20 # Linux a.out (AOUT) -FT_PRC = 21 # PalmPilot program file -FT_EXE = 22 # MS DOS EXE File -FT_COM = 23 # MS DOS COM File -FT_AIXAR = 24 # AIX ar library -INF_FCORESIZ = 17 -INF_CORESTART = 21 -INF_OSTYPE = 25 # short; FLIRT: OS type the program is for -OSTYPE_MSDOS = 0x0001 -OSTYPE_WIN = 0x0002 -OSTYPE_OS2 = 0x0004 -OSTYPE_NETW = 0x0008 -INF_APPTYPE = 27 # short; FLIRT: Application type -APPT_CONSOLE = 0x0001 # console -APPT_GRAPHIC = 0x0002 # graphics -APPT_PROGRAM = 0x0004 # EXE -APPT_LIBRARY = 0x0008 # DLL -APPT_DRIVER = 0x0010 # DRIVER -APPT_1THREAD = 0x0020 # Singlethread -APPT_MTHREAD = 0x0040 # Multithread -APPT_16BIT = 0x0080 # 16 bit application -APPT_32BIT = 0x0100 # 32 bit application -INF_START_SP = 29 # long; SP register value at the start of - # program execution -INF_START_AF = 33 # short; Analysis flags: -AF_FIXUP = 0x0001 # Create offsets and segments using fixup info -AF_MARKCODE = 0x0002 # Mark typical code sequences as code -AF_UNK = 0x0004 # Delete instructions with no xrefs -AF_CODE = 0x0008 # Trace execution flow -AF_PROC = 0x0010 # Create functions if call is present -AF_USED = 0x0020 # Analyze and create all xrefs -AF_FLIRT = 0x0040 # Use flirt signatures -AF_PROCPTR = 0x0080 # Create function if data xref data->code32 exists -AF_JFUNC = 0x0100 # Rename jump functions as j_... -AF_NULLSUB = 0x0200 # Rename empty functions as nullsub_... -AF_LVAR = 0x0400 # Create stack variables -AF_TRACE = 0x0800 # Trace stack pointer -AF_ASCII = 0x1000 # Create ascii string if data xref exists -AF_IMMOFF = 0x2000 # Convert 32bit instruction operand to offset -AF_DREFOFF = 0x4000 # Create offset if data xref to seg32 exists -AF_FINAL = 0x8000 # Final pass of analysis -INF_START_IP = 35 # long; IP register value at the start of - # program execution -INF_BEGIN_EA = 39 # long; Linear address of program entry point -INF_MIN_EA = 43 # long; The lowest address used - # in the program -INF_MAX_EA = 47 # long; The highest address used - # in the program - = 1 -INF_OMIN_EA = 51 -INF_OMAX_EA = 55 -INF_LOW_OFF = 59 # long; low limit of voids -INF_HIGH_OFF = 63 # long; high limit of voids -INF_MAXREF = 67 # long; max xref depth -INF_ASCII_BREAK = 71 # char; ASCII line break symbol -INF_WIDE_HIGH_BYTE_FIRST = 72 -INF_INDENT = 73 # char; Indention for instructions -INF_COMMENT = 74 # char; Indention for comments -INF_XREFNUM = 75 # char; Number of references to generate - # = 0 - xrefs wont be generated at all -INF_ENTAB = 76 # char; Use '\t' chars in the output file? -INF_SPECSEGS = 77 -INF_VOIDS = 78 # char; Display void marks? -INF_SHOWAUTO = 80 # char; Display autoanalysis indicator? -INF_AUTO = 81 # char; Autoanalysis is enabled? -INF_BORDER = 82 # char; Generate borders? -INF_NULL = 83 # char; Generate empty lines? -INF_GENFLAGS = 84 # char; General flags: -INFFL_LZERO = 0x01 # generate leading zeroes in numbers -INFFL_LOADIDC = 0x04 # Loading an idc file t -INF_SHOWPREF = 85 # char; Show line prefixes? -INF_PREFSEG = 86 # char; line prefixes with segment name? -INF_ASMTYPE = 87 # char; target assembler number (0..n) -INF_BASEADDR = 88 # long; base paragraph of the program -INF_XREFS = 92 # char; xrefs representation: -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-"...") -INF_BINPREF = 93 # short; # of instruction bytes to show - # in line prefix -INF_CMTFLAG = 95 # char; comments: -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 -SW_MICRO = 0x10 # show microcode (if implemented) -INF_NAMETYPE = 96 # char; dummy names represenation type -NM_REL_OFF = 0 -NM_PTR_OFF = 1 -NM_NAM_OFF = 2 -NM_REL_EA = 3 -NM_PTR_EA = 4 -NM_NAM_EA = 5 -NM_EA = 6 -NM_EA4 = 7 -NM_EA8 = 8 -NM_SHORT = 9 -NM_SERIAL = 10 -INF_SHOWBADS = 97 # char; show bad instructions? - # an instruction is bad if it appears - # in the ash.badworks array +AF_FLIRT = 0x00800000 # Use flirt signatures +AF_SIGCMT = 0x01000000 # Append a signature name comment for recognized anonymous library functions +AF_SIGMLT = 0x02000000 # Allow recognition of several copies of the same function +AF_HFLIRT = 0x04000000 # Automatically hide library functions -INF_PREFFLAG = 98 # char; line prefix type: -PREF_SEGADR = 0x01 # show segment addresses? -PREF_FNCOFF = 0x02 # show function offsets? -PREF_STACK = 0x04 # show stack pointer? +AF_JFUNC = 0x08000000 # Rename jump functions as j_... +AF_NULLSUB = 0x10000000 # Rename empty functions as nullsub_... -INF_PACKBASE = 99 # char; pack database? +AF_DODATA = 0x20000000 # Coagulate data segs at the final pass +AF_DOCODE = 0x40000000 # Coagulate code segs at the final pass +AF_FINAL = 0x80000000 # Final pass of analysis -INF_ASCIIFLAGS = 100 # uchar; ascii flags -ASCF_GEN = 0x01 # generate ASCII names? -ASCF_AUTO = 0x02 # ASCII names have 'autogenerated' bit? -ASCF_SERIAL = 0x04 # generate serial names? -ASCF_COMMENT = 0x10 # generate auto comment for ascii references? -ASCF_SAVECASE = 0x20 # preserve case of ascii strings for identifiers +INF_AF2 = 44 # uint32; Analysis flags 2 -INF_LISTNAMES = 101 # 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 +AF2_DOEH = 0x00000001 # Handle EH information -INF_ASCIIPREF = 102 # char[16];ASCII names prefix -INF_ASCIISERNUM = 118 # ulong; serial number -INF_ASCIIZEROES = 122 # char; leading zeroes -INF_TRIBYTE_ORDER = 125 # char; order of bytes in 3-byte items -TRIBYTE_123 = 0 # regular most significant byte first (big endian) - default -TRIBYTE_132 = 1 -TRIBYTE_213 = 2 -TRIBYTE_231 = 3 -TRIBYTE_312 = 4 -TRIBYTE_321 = 5 # regular least significant byte first (little endian) -INF_MF = 126 # uchar; Byte order: 1==MSB first -INF_ORG = 127 # char; Generate 'org' directives? -INF_ASSUME = 128 # char; Generate 'assume' directives? -INF_CHECKARG = 129 # char; Check manual operands? -INF_START_SS = 130 # long; value of SS at the start -INF_START_CS = 134 # long; value of CS at the start -INF_MAIN = 138 # long; address of main() -INF_SHORT_DN = 142 # long; short form of demangled names -INF_LONG_DN = 146 # long; long form of demangled names - # see demangle.h for definitions -INF_DATATYPES = 150 # long; data types allowed in data carousel -INF_STRTYPE = 154 # long; current ascii string type - # is considered as several bytes: - # low byte: -ASCSTR_TERMCHR = 0 # Character-terminated ASCII string -ASCSTR_C = 0 # C-string, zero terminated -ASCSTR_PASCAL = 1 # Pascal-style ASCII string (length byte) -ASCSTR_LEN2 = 2 # Pascal-style, length is 2 bytes -ASCSTR_UNICODE = 3 # Unicode string -ASCSTR_LEN4 = 4 # Delphi string, length is 4 bytes -ASCSTR_ULEN2 = 5 # Pascal-style Unicode, length is 2 bytes -ASCSTR_ULEN4 = 6 # Pascal-style Unicode, length is 4 bytes +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 + # 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 + # program execution +INF_MAIN = 72 # ea_t; address of main() +INF_MIN_EA = 76 # ea_t; The lowest address used + # in the program +INF_MAX_EA = 80 # 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) -# = 2nd byte - termination chracters for ASCSTR_TERMCHR: -#STRTERM1(strtype) ((strtype>>8)&0xFF) -# = 3d byte: -#STRTERM2(strtype) ((strtype>>16)&0xFF) - # The termination characters are kept in - # the = 2nd and 3d bytes of string type - # if the second termination character is - # '\0', then it is ignored. -INF_AF2 = 158 # ushort; Analysis flags 2 -AF2_JUMPTBL = 0x0001 # Locate and create jump tables -AF2_DODATA = 0x0002 # Coagulate data segs in final pass -AF2_HFLIRT = 0x0004 # Automatically hide library functions -AF2_STKARG = 0x0008 # Propagate stack argument information -AF2_REGARG = 0x0010 # Propagate register argument information -AF2_CHKUNI = 0x0020 # Check for unicode strings -AF2_SIGCMT = 0x0040 # Append a signature name comment for recognized anonymous library functions -AF2_SIGMLT = 0x0080 # Allow recognition of several copies of the same function -AF2_FTAIL = 0x0100 # Create function tails -AF2_DATOFF = 0x0200 # Automatically convert data to offsets -AF2_ANORET = 0x0400 # Perform 'no-return' analysis -AF2_VERSP = 0x0800 # Perform full stack pointer analysis -AF2_DOCODE = 0x1000 # Coagulate code segs at the final pass -AF2_TRFUNC = 0x2000 # Truncate functions upon code deletion -AF2_PURDAT = 0x4000 # Control flow to data segment is ignored -INF_NAMELEN = 160 # ushort; max name length (without zero byte) -INF_MARGIN = 162 # ushort; max length of data lines -INF_LENXREF = 164 # ushort; max length of line with xrefs -INF_LPREFIX = 166 # char[16];prefix of local names - # if a new name has this prefix, - # it will be automatically converted to a local name -INF_LPREFIXLEN = 182 # uchar; length of the lprefix -INF_COMPILER = 183 # uchar; compiler -COMP_MASK = 0x0F # mask to apply to get the pure compiler id -COMP_UNK = 0x00 # Unknown -COMP_MS = 0x01 # Visual C++ -COMP_BC = 0x02 # Borland C++ -COMP_WATCOM = 0x03 # Watcom C++ -COMP_GNU = 0x06 # GNU C++ -COMP_VISAGE = 0x07 # Visual Age C++ -COMP_BP = 0x08 # Delphi +INF_NETDELTA = 112 # 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 + # 0 - xrefs won't be generated at all +INF_TYPE_XREFS = 117 # 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 + # generate for refs to ASCII + # string or demangled name + # 0 - such comments won't be + # generated at all +INF_XREFS = 119 # char; xrefs representation: +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-"...") -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 = 192 # database change counter; keeps track of byte and segment modifications -INF_SIZEOF_LDBL = 196 # uchar; sizeof(long double) -INF_ABINAME = 201 # char[16]; ABI name -INF_ABIBITS = 217 # 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) -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 -INF_REFCMTS = 221 # uchar; number of comment lines to generate for refs - # to ASCII string or demangled name - # 0 - such comments won't be generated at all +# NAMES +INF_MAX_AUTONAME_LEN = 120 # ushort; max name length (without zero byte) +INF_NAMETYPE = 122 # char; dummy names represenation type +NM_REL_OFF = 0 +NM_PTR_OFF = 1 +NM_NAM_OFF = 2 +NM_REL_EA = 3 +NM_PTR_EA = 4 +NM_NAM_EA = 5 +NM_EA = 6 +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 + # see demangle.h for definitions +INF_DEMNAMES = 132 # 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? +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 +OFLG_SHOW_VOID = 0x0002 # Display void marks? +OFLG_SHOW_AUTO = 0x0004 # Display autoanalysis indicator? +OFLG_GEN_NULL = 0x0010 # Generate empty lines? +OFLG_SHOW_PREF = 0x0020 # Show line prefixes? +OFLG_PREF_SEG = 0x0040 # line prefixes with segment name? +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: +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 + # in line prefix +INF_PREFFLAG = 148 # 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 +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 + # 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<= 0: - return ida_srarea.SetDefaultRegisterValue(seg, reg, value) + return ida_segregs.set_default_sreg_value(seg, reg, value) else: return False -def SetSegmentType(segea, segtype): +def set_segm_type(segea, segtype): """ Set segment type @@ -3666,7 +3496,7 @@ SEG_COMM = ida_segment.SEG_COMM # * segment with communal definitions SEG_IMEM = ida_segment.SEG_IMEM # internal processor memory & sfr (8051) -def GetSegmentAttr(segea, attr): +def get_segm_attr(segea, attr): """ Get segment attribute @@ -3681,7 +3511,7 @@ def GetSegmentAttr(segea, attr): return _IDC_GetAttr(seg, _SEGATTRMAP, attr) -def SetSegmentAttr(segea, attr, value): +def set_segm_attr(segea, attr, value): """ Set segment attribute @@ -3690,7 +3520,7 @@ def SetSegmentAttr(segea, attr, value): @note: Please note that not all segment attributes are modifiable. Also some of them should be modified using special functions - like SetSegAddressing, etc. + like set_segm_addressing, etc. """ seg = ida_segment.getseg(segea) assert seg, "could not find segment at 0x%x" % segea @@ -3710,17 +3540,17 @@ SEGATTR_PERM = 22 # permissions SEGATTR_BITNESS = 23 # bitness (0: 16, 1: 32, 2: 64 bit segment) # Note: modifying the attribute directly does # not lead to the reanalysis of the segment. - # Using SetSegAddressing() is more correct. + # Using set_segm_addressing() is more correct. SEGATTR_FLAGS = 24 # segment flags -SEGATTR_SEL = 26 # segment selector -SEGATTR_ES = 30 # default ES value -SEGATTR_CS = 34 # default CS value -SEGATTR_SS = 38 # default SS value -SEGATTR_DS = 42 # default DS value -SEGATTR_FS = 46 # default FS value -SEGATTR_GS = 50 # default GS value -SEGATTR_TYPE = 94 # segment type -SEGATTR_COLOR = 95 # segment color +SEGATTR_SEL = 28 # segment selector +SEGATTR_ES = 32 # default ES value +SEGATTR_CS = 36 # default CS value +SEGATTR_SS = 40 # default SS value +SEGATTR_DS = 44 # default DS value +SEGATTR_FS = 48 # default FS value +SEGATTR_GS = 52 # default GS value +SEGATTR_TYPE = 96 # segment type +SEGATTR_COLOR = 100 # segment color # Redefining these for 64-bit if __EA64__: @@ -3732,19 +3562,19 @@ if __EA64__: SEGATTR_PERM = 42 SEGATTR_BITNESS = 43 SEGATTR_FLAGS = 44 - SEGATTR_SEL = 46 - SEGATTR_ES = 54 - SEGATTR_CS = 62 - SEGATTR_SS = 70 - SEGATTR_DS = 78 - SEGATTR_FS = 86 - SEGATTR_GS = 94 - SEGATTR_TYPE = 182 - SEGATTR_COLOR = 183 + SEGATTR_SEL = 48 + SEGATTR_ES = 56 + SEGATTR_CS = 64 + SEGATTR_SS = 72 + SEGATTR_DS = 80 + SEGATTR_FS = 88 + SEGATTR_GS = 96 + SEGATTR_TYPE = 184 + SEGATTR_COLOR = 188 _SEGATTRMAP = { - SEGATTR_START : (True, 'startEA'), - SEGATTR_END : (True, 'endEA'), + SEGATTR_START : (True, 'start_ea'), + SEGATTR_END : (True, 'end_ea'), SEGATTR_ORGBASE : (False, 'orgbase'), SEGATTR_ALIGN : (False, 'align'), SEGATTR_COMB : (False, 'comb'), @@ -3771,7 +3601,7 @@ SFL_LOADER = 0x10 # is the segment created by the loader? SFL_HIDETYPE = 0x20 # hide segment type (do not print it in the listing) -def MoveSegm(ea, to, flags): +def move_segm(ea, to, flags): """ Move a segment to a new address This function moves all information to the new address @@ -3818,17 +3648,17 @@ def rebase_program(delta, flags): return ida_segment.rebase_program(delta, flags) -def SetStorageType(startEA, endEA, stt): +def set_storage_type(start_ea, end_ea, stt): """ Set storage type - @param startEA: starting address - @param endEA: ending address + @param start_ea: starting address + @param end_ea: ending address @param stt: new storage type, one of STT_VA and STT_MM @returns: 0 - ok, otherwise internal error code """ - return ida_bytes.change_storage_type(startEA, endEA, stt) + return ida_bytes.change_storage_type(start_ea, end_ea, stt) STT_VA = 0 # regular storage: virtual arrays, an explicit flag for each byte @@ -3841,8 +3671,8 @@ STT_MM = 1 # memory map: sparse storage. useful for huge objects # Flow types (combine with XREF_USER!): fl_CF = 16 # Call Far fl_CN = 17 # Call Near -fl_JF = 18 # Jump Far -fl_JN = 19 # Jump Near +fl_JF = 18 # jumpto Far +fl_JN = 19 # jumpto Near fl_F = 21 # Ordinary flow XREF_USER = 32 # All user-specified xref types @@ -3850,13 +3680,13 @@ XREF_USER = 32 # All user-specified xref types # Mark exec flow 'from' 'to' -def AddCodeXref(From, To, flowtype): +def add_cref(From, To, flowtype): """ """ return ida_xref.add_cref(From, To, flowtype) -def DelCodeXref(From, To, undef): +def del_cref(From, To, undef): """ Unmark exec flow 'from' 'to' @@ -3869,28 +3699,28 @@ def DelCodeXref(From, To, undef): # The following functions include the ordinary flows: # (the ordinary flow references are returned first) -def Rfirst(From): +def get_first_cref_from(From): """ Get first code xref from 'From' """ return ida_xref.get_first_cref_from(From) -def Rnext(From, current): +def get_next_cref_from(From, current): """ Get next code xref from """ return ida_xref.get_next_cref_from(From, current) -def RfirstB(To): +def get_first_cref_to(To): """ Get first code xref to 'To' """ return ida_xref.get_first_cref_to(To) -def RnextB(To, current): +def get_next_cref_to(To, current): """ Get next code xref to 'To' """ @@ -3898,28 +3728,28 @@ def RnextB(To, current): # The following functions don't take into account the ordinary flows: -def Rfirst0(From): +def get_first_fcref_from(From): """ Get first xref from 'From' """ return ida_xref.get_first_fcref_from(From) -def Rnext0(From, current): +def get_next_fcref_from(From, current): """ Get next xref from """ return ida_xref.get_next_fcref_from(From, current) -def RfirstB0(To): +def get_first_fcref_to(To): """ Get first xref to 'To' """ return ida_xref.get_first_fcref_to(To) -def RnextB0(To, current): +def get_next_fcref_to(To, current): """ Get next xref to 'To' """ @@ -3948,35 +3778,35 @@ def del_dref(From, To): return ida_xref.del_dref(From, To) -def Dfirst(From): +def get_first_dref_from(From): """ Get first data xref from 'From' """ return ida_xref.get_first_dref_from(From) -def Dnext(From, current): +def get_next_dref_from(From, current): """ Get next data xref from 'From' """ return ida_xref.get_next_dref_from(From, current) -def DfirstB(To): +def get_first_dref_to(To): """ Get first data xref to 'To' """ return ida_xref.get_first_dref_to(To) -def DnextB(To, current): +def get_next_dref_to(To, current): """ Get next data xref to 'To' """ return ida_xref.get_next_dref_to(To, current) -def XrefType(): +def get_xref_type(): """ Return type of the last xref obtained by [RD]first/next[B0] functions. @@ -4086,7 +3916,7 @@ def writestr(handle, s): # F U N C T I O N S # ---------------------------------------------------------------------------- -def MakeFunction(start, end = ida_idaapi.BADADDR): +def add_func(start, end = ida_idaapi.BADADDR): """ Create a function @@ -4105,7 +3935,7 @@ def MakeFunction(start, end = ida_idaapi.BADADDR): return ida_funcs.add_func(start, end) -def DelFunction(ea): +def del_func(ea): """ Delete a function @@ -4116,7 +3946,7 @@ def DelFunction(ea): return ida_funcs.del_func(ea) -def SetFunctionEnd(ea, end): +def set_func_end(ea, end): """ Change function end address @@ -4125,10 +3955,10 @@ def SetFunctionEnd(ea, end): @return: !=0 - ok """ - return ida_funcs.func_setend(ea, end) + return ida_funcs.set_func_end(ea, end) -def NextFunction(ea): +def get_next_func(ea): """ Find next function @@ -4142,10 +3972,10 @@ def NextFunction(ea): if not func: return BADADDR else: - return func.startEA + return func.start_ea -def PrevFunction(ea): +def get_prev_func(ea): """ Find previous function @@ -4159,10 +3989,10 @@ def PrevFunction(ea): if not func: return BADADDR else: - return func.startEA + return func.start_ea -def GetFunctionAttr(ea, attr): +def get_func_attr(ea, attr): """ Get a function attribute @@ -4176,7 +4006,7 @@ def GetFunctionAttr(ea, attr): return _IDC_GetAttr(func, _FUNCATTRMAP, attr) if func else BADADDR -def SetFunctionAttr(ea, attr, value): +def set_func_attr(ea, attr, value): """ Set a function attribute @@ -4194,36 +4024,60 @@ def SetFunctionAttr(ea, attr, value): return 0 -FUNCATTR_START = 0 # function start address -FUNCATTR_END = 4 # function end address +FUNCATTR_START = 0 # readonly: function start address +FUNCATTR_END = 4 # readonly: function end address FUNCATTR_FLAGS = 8 # function flags -FUNCATTR_FRAME = 10 # function frame id -FUNCATTR_FRSIZE = 14 # size of local variables -FUNCATTR_FRREGS = 18 # size of saved registers area -FUNCATTR_ARGSIZE = 20 # number of bytes purged from the stack -FUNCATTR_FPD = 24 # frame pointer delta -FUNCATTR_COLOR = 28 # function color code -FUNCATTR_OWNER = 10 # chunk owner (valid only for tail chunks) -FUNCATTR_REFQTY = 14 # number of chunk parents (valid only for tail chunks) +FUNCATTR_FRAME = 12 # readonly: function frame id +FUNCATTR_FRSIZE = 16 # readonly: size of local variables +FUNCATTR_FRREGS = 20 # readonly: size of saved registers area +FUNCATTR_ARGSIZE = 24 # readonly: number of bytes purged from the stack +FUNCATTR_FPD = 28 # frame pointer delta +FUNCATTR_COLOR = 32 # function color code +FUNCATTR_OWNER = 12 # readonly: chunk owner (valid only for tail chunks) +FUNCATTR_REFQTY = 16 # readonly: number of chunk parents (valid only for tail chunks) + +if __X64__: + FUNCATTR_START = 0 + FUNCATTR_END = 4 + FUNCATTR_FLAGS = 8 + FUNCATTR_FRAME = 16 + FUNCATTR_FRSIZE = 20 + FUNCATTR_FRREGS = 24 + FUNCATTR_ARGSIZE = 28 + FUNCATTR_FPD = 32 + FUNCATTR_COLOR = 36 + FUNCATTR_OWNER = 16 + FUNCATTR_REFQTY = 20 # Redefining the constants for 64-bit if __EA64__: - FUNCATTR_START = 0 - FUNCATTR_END = 8 + FUNCATTR_START = 0 + FUNCATTR_END = 8 FUNCATTR_FLAGS = 16 - FUNCATTR_FRAME = 18 - FUNCATTR_FRSIZE = 26 - FUNCATTR_FRREGS = 34 - FUNCATTR_ARGSIZE = 36 - FUNCATTR_FPD = 44 - FUNCATTR_COLOR = 52 - FUNCATTR_OWNER = 18 - FUNCATTR_REFQTY = 26 - + FUNCATTR_FRAME = 20 + FUNCATTR_FRSIZE = 28 + FUNCATTR_FRREGS = 36 + FUNCATTR_ARGSIZE = 40 + FUNCATTR_FPD = 48 + FUNCATTR_COLOR = 56 + FUNCATTR_OWNER = 20 + FUNCATTR_REFQTY = 28 + if __X64__: + FUNCATTR_START = 0 + FUNCATTR_END = 8 + FUNCATTR_FLAGS = 16 + FUNCATTR_FRAME = 24 + FUNCATTR_FRSIZE = 32 + FUNCATTR_FRREGS = 40 + FUNCATTR_ARGSIZE = 48 + FUNCATTR_FPD = 56 + FUNCATTR_COLOR = 64 + FUNCATTR_OWNER = 24 + FUNCATTR_REFQTY = 32 _FUNCATTRMAP = { - FUNCATTR_START : (True, 'startEA'), - FUNCATTR_END : (True, 'endEA'), + FUNCATTR_START : (True, 'start_ea'), + FUNCATTR_END : (True, 'end_ea'), FUNCATTR_FLAGS : (False, 'flags'), FUNCATTR_FRAME : (True, 'frame'), FUNCATTR_FRSIZE : (True, 'frsize'), @@ -4236,7 +4090,7 @@ _FUNCATTRMAP = { } -def GetFunctionFlags(ea): +def get_func_flags(ea): """ Retrieve function flags @@ -4281,12 +4135,12 @@ FUNC_TAIL = ida_funcs.FUNC_TAIL # This is a function tail. # (except FUNC_HIDDEN) -def SetFunctionFlags(ea, flags): +def set_func_flags(ea, flags): """ Change function flags @param ea: any address belonging to the function - @param flags: see GetFunctionFlags() for explanations + @param flags: see get_func_flags() for explanations @return: !=0 - ok """ @@ -4300,7 +4154,7 @@ def SetFunctionFlags(ea, flags): return 1 -def GetFunctionName(ea): +def get_func_name(ea): """ Retrieve function name @@ -4317,7 +4171,7 @@ def GetFunctionName(ea): return name -def GetFunctionCmt(ea, repeatable): +def get_func_cmt(ea, repeatable): """ Retrieve function comment @@ -4340,7 +4194,7 @@ def GetFunctionCmt(ea, repeatable): return comment -def SetFunctionCmt(ea, cmt, repeatable): +def set_func_cmt(ea, cmt, repeatable): """ Set function comment @@ -4357,7 +4211,7 @@ def SetFunctionCmt(ea, cmt, repeatable): return ida_funcs.set_func_cmt(func, cmt, repeatable) -def ChooseFunction(title): +def choose_func(title): """ Ask the user to select a function @@ -4369,10 +4223,10 @@ def ChooseFunction(title): otherwise returns the selected function start address """ f = ida_kernwin.choose_func(title, ida_idaapi.BADADDR) - return BADADDR if f is None else f.startEA + return BADADDR if f is None else f.start_ea -def GetFuncOffset(ea): +def get_func_off_str(ea): """ Convert address to 'funcname+offset' string @@ -4382,10 +4236,12 @@ def GetFuncOffset(ea): formed as 'name+offset' where 'name' is a function name 'offset' is offset within the function else return null string """ - return ida_funcs.a2funcoff(ea) + + flags = ida_name.GNCN_NOCOLOR | ida_name.GNCN_REQFUNC + return ida_name.get_nice_colored_name(ea, flags) -def FindFuncEnd(ea): +def find_func_end(ea): """ Determine a new function boundaries @@ -4395,17 +4251,17 @@ def FindFuncEnd(ea): If a function end cannot be determined, the return BADADDR otherwise return the end address of the new function """ - func = ida_funcs.func_t() + func = ida_funcs.func_t(ea) - res = ida_funcs.find_func_bounds(ea, func, ida_funcs.FIND_FUNC_DEFINE) + res = ida_funcs.find_func_bounds(func, ida_funcs.FIND_FUNC_DEFINE) if res == ida_funcs.FIND_FUNC_UNDEF: return BADADDR else: - return func.endEA + return func.end_ea -def GetFrame(ea): +def get_frame_id(ea): """ Get ID of function frame structure @@ -4423,7 +4279,7 @@ def GetFrame(ea): return None -def GetFrameLvarSize(ea): +def get_frame_lvar_size(ea): """ Get size of local variables in function frame @@ -4433,10 +4289,10 @@ def GetFrameLvarSize(ea): If the function doesn't have a frame, return 0 If the function does't exist, return None """ - return GetFunctionAttr(ea, FUNCATTR_FRSIZE) + return get_func_attr(ea, FUNCATTR_FRSIZE) -def GetFrameRegsSize(ea): +def get_frame_regs_size(ea): """ Get size of saved registers in function frame @@ -4447,10 +4303,10 @@ def GetFrameRegsSize(ea): This value is used as offset for BP (if FUNC_FRAME is set) If the function does't exist, return None """ - return GetFunctionAttr(ea, FUNCATTR_FRREGS) + return get_func_attr(ea, FUNCATTR_FRREGS) -def GetFrameArgsSize(ea): +def get_frame_args_size(ea): """ Get size of arguments in function frame which are purged upon return @@ -4460,10 +4316,10 @@ def GetFrameArgsSize(ea): If the function doesn't have a frame, return 0 If the function does't exist, return -1 """ - return GetFunctionAttr(ea, FUNCATTR_ARGSIZE) + return get_func_attr(ea, FUNCATTR_ARGSIZE) -def GetFrameSize(ea): +def get_frame_size(ea): """ Get full size of function frame @@ -4484,7 +4340,7 @@ def GetFrameSize(ea): return ida_frame.get_frame_size(func) -def MakeFrame(ea, lvsize, frregs, argsize): +def set_frame_size(ea, lvsize, frregs, argsize): """ Make function frame @@ -4510,7 +4366,7 @@ def MakeFrame(ea, lvsize, frregs, argsize): return func.frame -def GetSpd(ea): +def get_spd(ea): """ Get current delta for the stack pointer @@ -4528,7 +4384,7 @@ def GetSpd(ea): return ida_frame.get_spd(func, ea) -def GetSpDiff(ea): +def get_sp_delta(ea): """ Get modification of SP made by the instruction @@ -4547,39 +4403,26 @@ def GetSpDiff(ea): return ida_frame.get_sp_delta(func, ea) -def SetSpDiff(ea, delta): - """ - Setup modification of SP made by the instruction - - @param ea: end address of the instruction - i.e.the last address of the instruction+1 - @param delta: the difference made by the current instruction. - - @return: 1-ok, 0-failed - """ - return ida_frame.add_user_stkpnt(ea, delta) - - # ---------------------------------------------------------------------------- # S T A C K # ---------------------------------------------------------------------------- -def AddAutoStkPnt2(func_ea, ea, delta): +def add_auto_stkpnt(func_ea, ea, delta): """ Add automatical SP register change point @param func_ea: function start @param ea: linear address where SP changes usually this is the end of the instruction which - modifies the stack pointer (cmd.ea+cmd.size) + modifies the stack pointer (insn.ea+insn.size) @param delta: difference between old and new values of SP @return: 1-ok, 0-failed """ pfn = ida_funcs.get_func(func_ea) if not pfn: return 0 - return ida_frame.add_auto_stkpnt2(pfn, ea, delta) + return ida_frame.add_auto_stkpnt(pfn, ea, delta) -def AddUserStkPnt(ea, delta): +def add_user_stkpnt(ea, delta): """ Add user-defined SP register change point. @@ -4590,7 +4433,7 @@ def AddUserStkPnt(ea, delta): """ return ida_frame.add_user_stkpnt(ea, delta); -def DelStkPnt(func_ea, ea): +def del_stkpnt(func_ea, ea): """ Delete SP register change point @@ -4603,7 +4446,7 @@ def DelStkPnt(func_ea, ea): return 0 return ida_frame.del_stkpnt(pfn, ea) -def GetMinSpd(func_ea): +def get_min_spd_ea(func_ea): """ Return the address with the minimal spd (stack pointer delta) If there are no SP change points, then return BADADDR. @@ -4616,7 +4459,7 @@ def GetMinSpd(func_ea): return BADADDR return ida_frame.get_min_spd_ea(pfn) -def RecalcSpd(cur_ea): +def recalc_spd(cur_ea): """ Recalculate SP delta for an instruction that stops execution. @@ -4633,7 +4476,7 @@ def RecalcSpd(cur_ea): # E N T R Y P O I N T S # ---------------------------------------------------------------------------- -def GetEntryPointQty(): +def get_entry_qty(): """ Retrieve number of entry points @@ -4642,7 +4485,7 @@ def GetEntryPointQty(): return ida_entry.get_entry_qty() -def AddEntryPoint(ordinal, ea, name, makecode): +def add_entry(ordinal, ea, name, makecode): """ Add entry point @@ -4661,11 +4504,11 @@ def AddEntryPoint(ordinal, ea, name, makecode): return ida_entry.add_entry(ordinal, ea, name, makecode) -def GetEntryOrdinal(index): +def get_entry_ordinal(index): """ Retrieve entry point ordinal number - @param index: 0..GetEntryPointQty()-1 + @param index: 0..get_entry_qty()-1 @return: 0 if entry point doesn't exist otherwise entry point ordinal @@ -4673,7 +4516,7 @@ def GetEntryOrdinal(index): return ida_entry.get_entry_ordinal(index) -def GetEntryPoint(ordinal): +def get_entry(ordinal): """ Retrieve entry point address @@ -4688,7 +4531,7 @@ def GetEntryPoint(ordinal): return ida_entry.get_entry(ordinal) -def GetEntryName(ordinal): +def get_entry_name(ordinal): """ Retrieve entry point name @@ -4699,7 +4542,7 @@ def GetEntryName(ordinal): return ida_entry.get_entry_name(ordinal) -def RenameEntryPoint(ordinal, name): +def rename_entry(ordinal, name): """ Rename entry point @@ -4714,7 +4557,7 @@ def RenameEntryPoint(ordinal, name): # ---------------------------------------------------------------------------- # F I X U P S # ---------------------------------------------------------------------------- -def GetNextFixupEA(ea): +def get_next_fixup_ea(ea): """ Find next address with fixup information @@ -4726,7 +4569,7 @@ def GetNextFixupEA(ea): return ida_fixup.get_next_fixup_ea(ea) -def GetPrevFixupEA(ea): +def get_prev_fixup_ea(ea): """ Find previous address with fixup information @@ -4738,26 +4581,24 @@ def GetPrevFixupEA(ea): return ida_fixup.get_prev_fixup_ea(ea) -def GetFixupTgtType(ea): +def get_fixup_target_type(ea): """ Get fixup target type @param ea: address to get information about - @return: -1 - no fixup at the specified address - otherwise returns fixup target type: + @return: 0 - no fixup at the specified address + otherwise returns fixup type """ fd = ida_fixup.fixup_data_t() - if not ida_fixup.get_fixup(ea, fd): - return -1 + if not fd.get(ea): + return 0 - return fd.type + return fd.get_type() -FIXUP_MASK = 0xF -FIXUP_OFF8 = 0 # 8-bit offset. -FIXUP_BYTE = FIXUP_OFF8 # 8-bit offset. +FIXUP_OFF8 = 13 # 8-bit offset. FIXUP_OFF16 = 1 # 16-bit offset. FIXUP_SEG16 = 2 # 16-bit base--logical segment base (selector). FIXUP_PTR32 = 3 # 32-bit long pointer (16-bit base:16-bit @@ -4768,96 +4609,108 @@ FIXUP_HI8 = 6 # high 8 bits of 16bit offset FIXUP_HI16 = 7 # high 16 bits of 32bit offset FIXUP_LOW8 = 8 # low 8 bits of 16bit offset FIXUP_LOW16 = 9 # low 16 bits of 32bit offset -FIXUP_REL = 0x10 # fixup is relative to the linear address - # specified in the 3d parameter to set_fixup() -FIXUP_SELFREL = 0x0 # self-relative? - # - disallows the kernel to convert operands - # in the first pass - # - this fixup is used during output - # This type of fixups is not used anymore. - # Anyway you can use it for commenting purposes - # in the loader modules -FIXUP_EXTDEF = 0x20 # target is a location (otherwise - segment) -FIXUP_UNUSED = 0x40 # fixup is ignored by IDA - # - disallows the kernel to convert operands - # - this fixup is not used during output -FIXUP_CREATED = 0x80 # fixup was not present in the input file +FIXUP_OFF64 = 12 # 64-bit offset +FIXUP_CUSTOM = 0x8000 # fixups with this bit are processed by + # processor module/plugin + +def get_fixup_target_flags(ea): + """ + Get fixup target flags + + @param ea: address to get information about + + @return: 0 - no fixup at the specified address + otherwise returns fixup target flags + """ + fd = ida_fixup.fixup_data_t() + + if not fd.get(ea): + return 0 + + return fd.get_flags() -def GetFixupTgtSel(ea): +FIXUPF_REL = 0x1 # fixup is relative to the linear address +FIXUPF_EXTDEF = 0x2 # target is a location (otherwise - segment) +FIXUPF_UNUSED = 0x4 # fixup is ignored by IDA +FIXUPF_CREATED = 0x8 # fixup was not present in the input file + + +def get_fixup_target_sel(ea): """ Get fixup target selector @param ea: address to get information about - @return: -1 - no fixup at the specified address - otherwise returns fixup target selector + @return: BADSEL - no fixup at the specified address + otherwise returns fixup target selector """ fd = ida_fixup.fixup_data_t() - if not ida_fixup.get_fixup(ea, fd): - return -1 + if not fd.get(ea): + return BADSEL return fd.sel -def GetFixupTgtOff(ea): +def get_fixup_target_off(ea): """ Get fixup target offset @param ea: address to get information about - @return: -1 - no fixup at the specified address - otherwise returns fixup target offset + @return: BADADDR - no fixup at the specified address + otherwise returns fixup target offset """ fd = ida_fixup.fixup_data_t() - if not ida_fixup.get_fixup(ea, fd): - return -1 + if not fd.get(ea): + return BADADDR return fd.off -def GetFixupTgtDispl(ea): +def get_fixup_target_dis(ea): """ Get fixup target displacement @param ea: address to get information about - @return: -1 - no fixup at the specified address - otherwise returns fixup target displacement + @return: 0 - no fixup at the specified address + otherwise returns fixup target displacement """ fd = ida_fixup.fixup_data_t() - if not ida_fixup.get_fixup(ea, fd): - return -1 + if not fd.get(ea): + return 0 return fd.displacement -def SetFixup(ea, fixuptype, targetsel, targetoff, displ): +def set_fixup(ea, fixuptype, fixupflags, targetsel, targetoff, displ): """ Set fixup information @param ea: address to set fixup information about - @param fixuptype: fixup type. see GetFixupTgtType() - for possible fixup types. - @param targetsel: target selector - @param targetoff: target offset - @param displ: displacement + @param fixuptype: fixup type. see get_fixup_target_type() + for possible fixup types. + @param fixupflags: fixup flags. see get_fixup_target_flags() + for possible fixup types. + @param targetsel: target selector + @param targetoff: target offset + @param displ: displacement @return: none """ - fd = ida_fixup.fixup_data_t() - fd.type = fixuptype - fd.sel = targetsel - fd.off = targetoff + fd = ida_fixup.fixup_data_t(fixuptype, fixupflags) + fd.sel = targetsel + fd.off = targetoff fd.displacement = displ - ida_fixup.set_fixup(ea, fd) + fd.set(ea) -def DelFixup(ea): +def del_fixup(ea): """ Delete fixup information @@ -4872,7 +4725,7 @@ def DelFixup(ea): # M A R K E D P O S I T I O N S #---------------------------------------------------------------------------- -def MarkPosition(ea, lnnum, x, y, slot, comment): +def put_bookmark(ea, lnnum, x, y, slot, comment): """ Mark position @@ -4887,15 +4740,10 @@ def MarkPosition(ea, lnnum, x, y, slot, comment): @return: None """ - curloc = ida_moves.curloc() - curloc.ea = ea - curloc.lnnum = lnnum - curloc.x = x - curloc.y = y - curloc.mark(slot, comment, comment) + ida_idc.mark_position(ea, lnnum, x, y, slot, comment) -def GetMarkedPos(slot): +def get_bookmark(slot): """ Get marked position @@ -4905,13 +4753,10 @@ def GetMarkedPos(slot): @return: BADADDR - the slot doesn't contain a marked address otherwise returns the marked address """ - curloc = ida_moves.curloc() - intp = ida_pro.int_pointer() - intp.assign(slot) - return curloc.markedpos(intp) + return ida_idc.get_marked_pos(slot) -def GetMarkComment(slot): +def get_bookmark_desc(slot): """ Get marked position comment @@ -4920,15 +4765,14 @@ def GetMarkComment(slot): @return: None if the slot doesn't contain a marked address otherwise returns the marked address comment """ - curloc = ida_moves.curloc() - return curloc.markdesc(slot) + return ida_idc.get_mark_comment(slot) # ---------------------------------------------------------------------------- # S T R U C T U R E S # ---------------------------------------------------------------------------- -def GetStrucQty(): +def get_struc_qty(): """ Get number of defined structure types @@ -4937,7 +4781,7 @@ def GetStrucQty(): return ida_struct.get_struc_qty() -def GetFirstStrucIdx(): +def get_first_struc_idx(): """ Get index of first structure type @@ -4958,19 +4802,19 @@ def GetFirstStrucIdx(): return ida_struct.get_first_struc_idx() -def GetLastStrucIdx(): +def get_last_struc_idx(): """ Get index of last structure type @return: BADADDR if no structure type is defined index of last structure type. - See GetFirstStrucIdx() for the explanation of + See get_first_struc_idx() for the explanation of structure indices and IDs. """ return ida_struct.get_last_struc_idx() -def GetNextStrucIdx(index): +def get_next_struc_idx(index): """ Get index of next structure type @@ -4978,13 +4822,13 @@ def GetNextStrucIdx(index): @return: BADADDR if no (more) structure type is defined index of the next structure type. - See GetFirstStrucIdx() for the explanation of + See get_first_struc_idx() for the explanation of structure indices and IDs. """ return ida_struct.get_next_struc_idx(index) -def GetPrevStrucIdx(index): +def get_prev_struc_idx(index): """ Get index of previous structure type @@ -4992,13 +4836,13 @@ def GetPrevStrucIdx(index): @return: BADADDR if no (more) structure type is defined index of the presiouvs structure type. - See GetFirstStrucIdx() for the explanation of + See get_first_struc_idx() for the explanation of structure indices and IDs. """ return ida_struct.get_prev_struc_idx(index) -def GetStrucIdx(sid): +def get_struc_idx(sid): """ Get structure index by structure ID @@ -5006,13 +4850,13 @@ def GetStrucIdx(sid): @return: BADADDR if bad structure ID is passed otherwise returns structure index. - See GetFirstStrucIdx() for the explanation of + See get_first_struc_idx() for the explanation of structure indices and IDs. """ return ida_struct.get_struc_idx(sid) -def GetStrucId(index): +def get_struc_by_idx(index): """ Get structure ID by structure index @@ -5020,12 +4864,12 @@ def GetStrucId(index): @return: BADADDR if bad structure index is passed otherwise returns structure ID. - @note: See GetFirstStrucIdx() for the explanation of structure indices and IDs. + @note: See get_first_struc_idx() for the explanation of structure indices and IDs. """ return ida_struct.get_struc_by_idx(index) -def GetStrucIdByName(name): +def get_struc_id(name): """ Get structure ID by structure name @@ -5037,7 +4881,7 @@ def GetStrucIdByName(name): return ida_struct.get_struc_id(name) -def GetStrucName(sid): +def get_struc_name(sid): """ Get structure type name @@ -5049,7 +4893,7 @@ def GetStrucName(sid): return ida_struct.get_struc_name(sid) -def GetStrucComment(sid, repeatable): +def get_struc_cmt(sid, repeatable): """ Get structure type comment @@ -5063,7 +4907,7 @@ def GetStrucComment(sid, repeatable): return ida_struct.get_struc_cmt(sid, repeatable) -def GetStrucSize(sid): +def get_struc_size(sid): """ Get size of a structure @@ -5075,7 +4919,7 @@ def GetStrucSize(sid): return ida_struct.get_struc_size(sid) -def GetMemberQty(sid): +def get_member_qty(sid): """ Get number of members of a structure @@ -5092,7 +4936,7 @@ def GetMemberQty(sid): return -1 if not s else s.memqty -def GetMemberId(sid, member_offset): +def get_member_id(sid, member_offset): """ @param sid: structure type ID @param member_offset:. The offset can be @@ -5116,7 +4960,7 @@ def GetMemberId(sid, member_offset): return m.id -def GetStrucPrevOff(sid, offset): +def get_prev_offset(sid, offset): """ Get previous offset in a structure @@ -5145,7 +4989,7 @@ def GetStrucPrevOff(sid, offset): return ida_struct.get_struc_prev_offset(s, offset) -def GetStrucNextOff(sid, offset): +def get_next_offset(sid, offset): """ Get next offset in a structure @@ -5171,7 +5015,7 @@ def GetStrucNextOff(sid, offset): return -1 if not s else ida_struct.get_struc_next_offset(s, offset) -def GetFirstMember(sid): +def get_first_member(sid): """ Get offset of the first member of a structure @@ -5196,7 +5040,7 @@ def GetFirstMember(sid): return ida_struct.get_struc_first_offset(s) -def GetLastMember(sid): +def get_last_member(sid): """ Get offset of the last member of a structure @@ -5221,7 +5065,7 @@ def GetLastMember(sid): return ida_struct.get_struc_last_offset(s) -def GetMemberOffset(sid, member_name): +def get_member_offset(sid, member_name): """ Get offset of a member of a structure by the member name @@ -5247,7 +5091,7 @@ def GetMemberOffset(sid, member_name): return m.get_soff() -def GetMemberName(sid, member_offset): +def get_member_name(sid, member_offset): """ Get name of a member of a structure @@ -5273,7 +5117,7 @@ def GetMemberName(sid, member_offset): return ida_struct.get_member_name(m.id) -def GetMemberComment(sid, member_offset, repeatable): +def get_member_cmt(sid, member_offset, repeatable): """ Get comment of a member @@ -5301,7 +5145,7 @@ def GetMemberComment(sid, member_offset, repeatable): return ida_struct.get_member_cmt(m.id, repeatable) -def GetMemberSize(sid, member_offset): +def get_member_size(sid, member_offset): """ Get size of a member @@ -5328,7 +5172,7 @@ def GetMemberSize(sid, member_offset): return ida_struct.get_member_size(m) -def GetMemberFlag(sid, member_offset): +def get_member_flag(sid, member_offset): """ Get type of a member @@ -5354,7 +5198,7 @@ def GetMemberFlag(sid, member_offset): return -1 if not m else m.flag -def GetMemberStrId(sid, member_offset): +def get_member_strid(sid, member_offset): """ Get structure id of a member @@ -5384,7 +5228,7 @@ def GetMemberStrId(sid, member_offset): return -1 -def IsUnion(sid): +def is_union(sid): """ Is a structure a union? @@ -5402,7 +5246,7 @@ def IsUnion(sid): return s.is_union() -def AddStrucEx(index, name, is_union): +def add_struc(index, name, is_union): """ Define a new structure type @@ -5412,7 +5256,7 @@ def AddStrucEx(index, name, is_union): structures will be incremented, freeing the specifed index. If index is == -1, then the biggest index number will be used. - See GetFirstStrucIdx() for the explanation of + See get_first_struc_idx() for the explanation of structure indices and IDs. @param name: name of the new structure type. @param is_union: 0: structure @@ -5429,7 +5273,7 @@ def AddStrucEx(index, name, is_union): return ida_struct.add_struc(index, name, is_union) -def DelStruc(sid): +def del_struc(sid): """ Delete a structure type @@ -5448,7 +5292,7 @@ def DelStruc(sid): return ida_struct.del_struc(s) -def SetStrucIdx(sid, index): +def set_struc_idx(sid, index): """ Change structure index @@ -5457,7 +5301,7 @@ def SetStrucIdx(sid, index): @return: != 0 - ok - @note: See GetFirstStrucIdx() for the explanation of + @note: See get_first_struc_idx() for the explanation of structure indices and IDs. """ s = ida_struct.get_struc(sid) @@ -5467,7 +5311,7 @@ def SetStrucIdx(sid, index): return ida_struct.set_struc_idx(s, index) -def SetStrucName(sid, name): +def set_struc_name(sid, name): """ Change structure name @@ -5479,7 +5323,7 @@ def SetStrucName(sid, name): return ida_struct.set_struc_name(sid, name) -def SetStrucComment(sid, comment, repeatable): +def set_struc_cmt(sid, comment, repeatable): """ Change structure comment @@ -5492,7 +5336,7 @@ def SetStrucComment(sid, comment, repeatable): return ida_struct.set_struc_cmt(sid, comment, repeatable) -def AddStrucMember(sid, name, offset, flag, typeid, nbytes, target=-1, tdelta=0, reftype=REF_OFF32): +def add_struc_member(sid, name, offset, flag, typeid, nbytes, target=-1, tdelta=0, reftype=REF_OFF32): """ Add structure member @@ -5503,11 +5347,11 @@ def AddStrucMember(sid, name, offset, flag, typeid, nbytes, target=-1, tdelta=0, @param flag: type of the new member. Should be one of FF_BYTE..FF_PACKREAL (see above) combined with FF_DATA @param typeid: if isStruc(flag) then typeid specifies the structure id for the member - if isOff0(flag) then typeid specifies the offset base. - if isASCII(flag) then typeid specifies the string type (ASCSTR_...). - if isStroff(flag) then typeid specifies the structure id - if isEnum(flag) then typeid specifies the enum id - if isCustom(flags) then typeid specifies the dtid and fid: dtid|(fid<<16) + if is_off0(flag) then typeid specifies the offset base. + if is_strlit(flag) then typeid specifies the string type (STRTYPE_...). + if is_stroff(flag) then typeid specifies the structure id + if is_enum(flag) then typeid specifies the enum id + if is_custom(flags) then typeid specifies the dtid and fid: dtid|(fid<<16) Otherwise typeid should be -1. @param nbytes: number of bytes in the new member @@ -5516,17 +5360,17 @@ def AddStrucMember(sid, name, offset, flag, typeid, nbytes, target=-1, tdelta=0, @param tdelta: offset target delta. usually 0 @param reftype: see REF_... definitions - @note: The remaining arguments are allowed only if isOff0(flag) and you want + @note: The remaining arguments are allowed only if is_off0(flag) and you want to specify a complex offset expression @return: 0 - ok, otherwise error code (one of STRUC_ERROR_*) """ - if isOff0(flag): - return Eval('AddStrucMember(%d, "%s", %d, %d, %d, %d, %d, %d, %d);' % (sid, ida_kernwin.str2user(name), offset, flag, typeid, nbytes, + if is_off0(flag): + return eval_idc('add_struc_member(%d, "%s", %d, %d, %d, %d, %d, %d, %d);' % (sid, ida_kernwin.str2user(name), offset, flag, typeid, nbytes, target, tdelta, reftype)) else: - return Eval('AddStrucMember(%d, "%s", %d, %d, %d, %d);' % (sid, ida_kernwin.str2user(name), offset, flag, typeid, nbytes)) + return eval_idc('add_struc_member(%d, "%s", %d, %d, %d, %d);' % (sid, ida_kernwin.str2user(name), offset, flag, typeid, nbytes)) STRUC_ERROR_MEMBER_NAME = -1 # already has member with this name (bad name) @@ -5538,7 +5382,7 @@ STRUC_ERROR_MEMBER_UNIVAR = -6 # unions can't have variable sized members STRUC_ERROR_MEMBER_VARLAST = -7 # variable sized member should be the last member in the structure -def DelStrucMember(sid, member_offset): +def del_struc_member(sid, member_offset): """ Delete structure member @@ -5558,7 +5402,7 @@ def DelStrucMember(sid, member_offset): return ida_struct.del_struc_member(s, member_offset) -def SetMemberName(sid, member_offset, name): +def set_member_name(sid, member_offset, name): """ Change structure member name @@ -5575,7 +5419,7 @@ def SetMemberName(sid, member_offset, name): return ida_struct.set_member_name(s, member_offset, name) -def SetMemberType(sid, member_offset, flag, typeid, nitems, target=-1, tdelta=0, reftype=REF_OFF32): +def set_member_type(sid, member_offset, flag, typeid, nitems, target=-1, tdelta=0, reftype=REF_OFF32): """ Change structure member type @@ -5584,11 +5428,11 @@ def SetMemberType(sid, member_offset, flag, typeid, nitems, target=-1, tdelta=0, @param flag: new type of the member. Should be one of FF_BYTE..FF_PACKREAL (see above) combined with FF_DATA @param typeid: if isStruc(flag) then typeid specifies the structure id for the member - if isOff0(flag) then typeid specifies the offset base. - if isASCII(flag) then typeid specifies the string type (ASCSTR_...). - if isStroff(flag) then typeid specifies the structure id - if isEnum(flag) then typeid specifies the enum id - if isCustom(flags) then typeid specifies the dtid and fid: dtid|(fid<<16) + if is_off0(flag) then typeid specifies the offset base. + if is_strlit(flag) then typeid specifies the string type (STRTYPE_...). + if is_stroff(flag) then typeid specifies the structure id + if is_enum(flag) then typeid specifies the enum id + if is_custom(flags) then typeid specifies the dtid and fid: dtid|(fid<<16) Otherwise typeid should be -1. @param nitems: number of items in the member @@ -5597,19 +5441,19 @@ def SetMemberType(sid, member_offset, flag, typeid, nitems, target=-1, tdelta=0, @param tdelta: offset target delta. usually 0 @param reftype: see REF_... definitions - @note: The remaining arguments are allowed only if isOff0(flag) and you want + @note: The remaining arguments are allowed only if is_off0(flag) and you want to specify a complex offset expression @return: !=0 - ok. """ - if isOff0(flag): - return Eval('SetMemberType(%d, %d, %d, %d, %d, %d, %d, %d);' % (sid, member_offset, flag, typeid, nitems, + if is_off0(flag): + return eval_idc('set_member_type(%d, %d, %d, %d, %d, %d, %d, %d);' % (sid, member_offset, flag, typeid, nitems, target, tdelta, reftype)) else: - return Eval('SetMemberType(%d, %d, %d, %d, %d);' % (sid, member_offset, flag, typeid, nitems)) + return eval_idc('set_member_type(%d, %d, %d, %d, %d);' % (sid, member_offset, flag, typeid, nitems)) -def SetMemberComment(sid, member_offset, comment, repeatable): +def set_member_cmt(sid, member_offset, comment, repeatable): """ Change structure member comment @@ -5632,7 +5476,7 @@ def SetMemberComment(sid, member_offset, comment, repeatable): return ida_struct.set_member_cmt(m, comment, repeatable) -def ExpandStruc(sid, offset, delta, recalc): +def expand_struc(sid, offset, delta, recalc): """ Expand or shrink a structure type @param id: structure type ID @@ -5649,7 +5493,7 @@ def ExpandStruc(sid, offset, delta, recalc): return ida_struct.expand_struc(s, offset, delta, recalc) -def GetFchunkAttr(ea, attr): +def get_fchunk_attr(ea, attr): """ Get a function chunk attribute @@ -5662,7 +5506,7 @@ def GetFchunkAttr(ea, attr): return _IDC_GetAttr(func, _FUNCATTRMAP, attr) if func else BADADDR -def SetFchunkAttr(ea, attr, value): +def set_fchunk_attr(ea, attr, value): """ Set a function chunk attribute @@ -5680,19 +5524,19 @@ def SetFchunkAttr(ea, attr, value): return 0 -def GetFchunkReferer(ea, idx): +def get_fchunk_referer(ea, idx): """ Get a function chunk referer @param ea: any address in the chunk - @param idx: referer index (0..GetFchunkAttr(FUNCATTR_REFQTY)) + @param idx: referer index (0..get_fchunk_attr(FUNCATTR_REFQTY)) @return: referer address or BADADDR """ return ida_funcs.get_fchunk_referer(ea, idx) -def NextFchunk(ea): +def get_next_fchunk(ea): """ Get next function chunk @@ -5705,12 +5549,12 @@ def NextFchunk(ea): func = ida_funcs.get_next_fchunk(ea) if func: - return func.startEA + return func.start_ea else: return BADADDR -def PrevFchunk(ea): +def get_prev_fchunk(ea): """ Get previous function chunk @@ -5723,12 +5567,12 @@ def PrevFchunk(ea): func = ida_funcs.get_prev_fchunk(ea) if func: - return func.startEA + return func.start_ea else: return BADADDR -def AppendFchunk(funcea, ea1, ea2): +def append_func_tail(funcea, ea1, ea2): """ Append a function chunk to the function @@ -5748,7 +5592,7 @@ def AppendFchunk(funcea, ea1, ea2): return ida_funcs.append_func_tail(func, ea1, ea2) -def RemoveFchunk(funcea, tailea): +def remove_fchunk(funcea, tailea): """ Remove a function chunk from the function @@ -5765,7 +5609,7 @@ def RemoveFchunk(funcea, tailea): return ida_funcs.remove_func_tail(func, tailea) -def SetFchunkOwner(tailea, funcea): +def set_tail_owner(tailea, funcea): """ Change the function chunk owner @@ -5784,7 +5628,7 @@ def SetFchunkOwner(tailea, funcea): return ida_funcs.set_tail_owner(tail, funcea) -def FirstFuncFchunk(funcea): +def first_func_chunk(funcea): """ Get the first function chunk of the specified function @@ -5797,12 +5641,12 @@ def FirstFuncFchunk(funcea): func = ida_funcs.get_func(funcea) fci = ida_funcs.func_tail_iterator_t(func, funcea) if fci.main(): - return fci.chunk().startEA + return fci.chunk().start_ea else: return BADADDR -def NextFuncFchunk(funcea, tailea): +def next_func_chunk(funcea, tailea): """ Get the next function chunk of the specified function @@ -5821,8 +5665,8 @@ def NextFuncFchunk(funcea, tailea): # Iterate and try to find the current chunk found = False while True: - if fci.chunk().startEA <= tailea and \ - fci.chunk().endEA > tailea: + if fci.chunk().start_ea <= tailea and \ + fci.chunk().end_ea > tailea: found = True break if not fci.next(): @@ -5830,7 +5674,7 @@ def NextFuncFchunk(funcea, tailea): # Return the next chunk, if there is one if found and fci.next(): - return fci.chunk().startEA + return fci.chunk().start_ea else: return BADADDR @@ -5838,7 +5682,7 @@ def NextFuncFchunk(funcea, tailea): # ---------------------------------------------------------------------------- # E N U M S # ---------------------------------------------------------------------------- -def GetEnumQty(): +def get_enum_qty(): """ Get number of enum types @@ -5847,29 +5691,29 @@ def GetEnumQty(): return ida_enum.get_enum_qty() -def GetnEnum(idx): +def getn_enum(idx): """ Get ID of the specified enum by its serial number - @param idx: number of enum (0..GetEnumQty()-1) + @param idx: number of enum (0..get_enum_qty()-1) @return: ID of enum or -1 if error """ return ida_enum.getn_enum(idx) -def GetEnumIdx(enum_id): +def get_enum_idx(enum_id): """ Get serial number of enum by its ID @param enum_id: ID of enum - @return: (0..GetEnumQty()-1) or -1 if error + @return: (0..get_enum_qty()-1) or -1 if error """ return ida_enum.get_enum_idx(enum_id) -def GetEnum(name): +def get_enum(name): """ Get enum ID by the name of enum @@ -5881,7 +5725,7 @@ def GetEnum(name): return ida_enum.get_enum(name) -def GetEnumName(enum_id): +def get_enum_name(enum_id): """ Get name of enum @@ -5892,7 +5736,7 @@ def GetEnumName(enum_id): return ida_enum.get_enum_name(enum_id) -def GetEnumCmt(enum_id, repeatable): +def get_enum_cmt(enum_id, repeatable): """ Get comment of enum @@ -5905,7 +5749,7 @@ def GetEnumCmt(enum_id, repeatable): return ida_enum.get_enum_cmt(enum_id, repeatable) -def GetEnumSize(enum_id): +def get_enum_size(enum_id): """ Get size of enum @@ -5917,21 +5761,19 @@ def GetEnumSize(enum_id): return ida_enum.get_enum_size(enum_id) -def GetEnumWidth(enum_id): +def get_enum_width(enum_id): """ Get width of enum elements @param enum_id: ID of enum - @return: log2(size of enum elements in bytes)+1 - possible returned values are 1..7 - 1-1byte,2-2bytes,3-4bytes,4-8bytes,etc - Returns 0 if enum_id is bad or the width is unknown. + @return: size of enum elements in bytes + (0 if enum_id is bad or the width is unknown). """ return ida_enum.get_enum_width(enum_id) -def GetEnumFlag(enum_id): +def get_enum_flag(enum_id): """ Get flag of enum @@ -5946,7 +5788,7 @@ def GetEnumFlag(enum_id): return ida_enum.get_enum_flag(enum_id) -def GetConstByName(name): +def get_enum_member_by_name(name): """ Get member of enum - a symbolic constant ID @@ -5957,7 +5799,7 @@ def GetConstByName(name): return ida_enum.get_enum_member_by_name(name) -def GetConstValue(const_id): +def get_enum_member_value(const_id): """ Get value of symbolic constant @@ -5968,7 +5810,7 @@ def GetConstValue(const_id): return ida_enum.get_enum_member_value(const_id) -def GetConstBmask(const_id): +def get_enum_member_bmask(const_id): """ Get bit mask of symbolic constant @@ -5980,7 +5822,7 @@ def GetConstBmask(const_id): return ida_enum.get_enum_member_bmask(const_id) -def GetConstEnum(const_id): +def get_enum_member_enum(const_id): """ Get id of enum by id of constant @@ -5992,16 +5834,16 @@ def GetConstEnum(const_id): return ida_enum.get_enum_member_enum(const_id) -def GetConstEx(enum_id, value, serial, bmask): +def get_enum_member(enum_id, value, serial, bmask): """ Get id of constant @param enum_id: id of enum @param value: value of constant @param serial: serial number of the constant in the - enumeration. See OpEnumEx() for details. + enumeration. See op_enum() for details. @param bmask: bitmask of the constant - ordinary enums accept only -1 as a bitmask + ordinary enums accept only ida_enum.DEFMASK as a bitmask @return: id of constant or -1 if error """ @@ -6010,7 +5852,7 @@ def GetConstEx(enum_id, value, serial, bmask): return ida_enum.get_enum_member(enum_id, value, serial, bmask) -def GetFirstBmask(enum_id): +def get_first_bmask(enum_id): """ Get first bitmask in the enum (bitfield) @@ -6024,7 +5866,7 @@ def GetFirstBmask(enum_id): return ida_enum.get_first_bmask(enum_id) -def GetLastBmask(enum_id): +def get_last_bmask(enum_id): """ Get last bitmask in the enum (bitfield) @@ -6036,7 +5878,7 @@ def GetLastBmask(enum_id): return ida_enum.get_last_bmask(enum_id) -def GetNextBmask(enum_id, value): +def get_next_bmask(enum_id, value): """ Get next bitmask in the enum (bitfield) @@ -6051,7 +5893,7 @@ def GetNextBmask(enum_id, value): return ida_enum.get_next_bmask(enum_id, value) -def GetPrevBmask(enum_id, value): +def get_prev_bmask(enum_id, value): """ Get prev bitmask in the enum (bitfield) @@ -6065,7 +5907,7 @@ def GetPrevBmask(enum_id, value): return ida_enum.get_prev_bmask(enum_id, value) -def GetBmaskName(enum_id, bmask): +def get_bmask_name(enum_id, bmask): """ Get bitmask name (only for bitfields) @@ -6079,7 +5921,7 @@ def GetBmaskName(enum_id, bmask): return ida_enum.get_bmask_name(enum_id, bmask) -def GetBmaskCmt(enum_id, bmask, repeatable): +def get_bmask_cmt(enum_id, bmask, repeatable): """ Get bitmask comment (only for bitfields) @@ -6094,7 +5936,7 @@ def GetBmaskCmt(enum_id, bmask, repeatable): return ida_enum.get_bmask_cmt(enum_id, bmask, repeatable) -def SetBmaskName(enum_id, bmask, name): +def set_bmask_name(enum_id, bmask, name): """ Set bitmask name (only for bitfields) @@ -6109,7 +5951,7 @@ def SetBmaskName(enum_id, bmask, name): return ida_enum.set_bmask_name(enum_id, bmask, name) -def SetBmaskCmt(enum_id, bmask, cmt, repeatable): +def set_bmask_cmt(enum_id, bmask, cmt, repeatable): """ Set bitmask comment (only for bitfields) @@ -6125,14 +5967,14 @@ def SetBmaskCmt(enum_id, bmask, cmt, repeatable): return ida_enum.set_bmask_cmt(enum_id, bmask, cmt, repeatable) -def GetFirstConst(enum_id, bmask): +def get_first_enum_member(enum_id, bmask): """ Get first constant in the enum @param enum_id: id of enum - @param bmask: bitmask of the constant (ordinary enums accept only -1 as a bitmask) + @param bmask: bitmask of the constant (ordinary enums accept only ida_enum.DEFMASK as a bitmask) - @return: value of constant or -1 no constants are defined + @return: value of constant or idaapi.BADNODE no constants are defined All constants are sorted by their values as unsigned longs. """ if bmask < 0: @@ -6140,14 +5982,14 @@ def GetFirstConst(enum_id, bmask): return ida_enum.get_first_enum_member(enum_id, bmask) -def GetLastConst(enum_id, bmask): +def get_last_enum_member(enum_id, bmask): """ Get last constant in the enum @param enum_id: id of enum - @param bmask: bitmask of the constant (ordinary enums accept only -1 as a bitmask) + @param bmask: bitmask of the constant (ordinary enums accept only ida_enum.DEFMASK as a bitmask) - @return: value of constant or -1 no constants are defined + @return: value of constant or idaapi.BADNODE no constants are defined All constants are sorted by their values as unsigned longs. """ @@ -6156,16 +5998,16 @@ def GetLastConst(enum_id, bmask): return ida_enum.get_last_enum_member(enum_id, bmask) -def GetNextConst(enum_id, value, bmask): +def get_next_enum_member(enum_id, value, bmask): """ Get next constant in the enum @param enum_id: id of enum - @param bmask: bitmask of the constant ordinary enums accept only -1 as a bitmask + @param bmask: bitmask of the constant ordinary enums accept only ida_enum.DEFMASK as a bitmask @param value: value of the current constant @return: value of a constant with value higher than the specified - value. -1 no such constants exist. + value. idaapi.BADNODE no such constants exist. All constants are sorted by their values as unsigned longs. """ if bmask < 0: @@ -6173,17 +6015,17 @@ def GetNextConst(enum_id, value, bmask): return ida_enum.get_next_enum_member(enum_id, value, bmask) -def GetPrevConst(enum_id, value, bmask): +def get_prev_enum_member(enum_id, value, bmask): """ Get prev constant in the enum @param enum_id: id of enum @param bmask : bitmask of the constant - ordinary enums accept only -1 as a bitmask + ordinary enums accept only ida_enum.DEFMASK as a bitmask @param value: value of the current constant @return: value of a constant with value lower than the specified - value. -1 no such constants exist. + value. idaapi.BADNODE no such constants exist. All constants are sorted by their values as unsigned longs. """ if bmask < 0: @@ -6191,7 +6033,7 @@ def GetPrevConst(enum_id, value, bmask): return ida_enum.get_prev_enum_member(enum_id, value, bmask) -def GetConstName(const_id): +def get_enum_member_name(const_id): """ Get name of a constant @@ -6207,7 +6049,7 @@ def GetConstName(const_id): return name -def GetConstCmt(const_id, repeatable): +def get_enum_member_cmt(const_id, repeatable): """ Get comment of a constant @@ -6224,7 +6066,7 @@ def GetConstCmt(const_id, repeatable): return cmt -def AddEnum(idx, name, flag): +def add_enum(idx, name, flag): """ Add a new enum type @@ -6235,7 +6077,7 @@ def AddEnum(idx, name, flag): serial numbers incremented (in other words, the new enum is put in the middle of the list of enums). - If idx >= GetEnumQty() or idx == -1 + If idx >= get_enum_qty() or idx == idaapi.BADNODE then the new enum is created at the end of the list of enums. @@ -6250,7 +6092,7 @@ def AddEnum(idx, name, flag): return ida_enum.add_enum(idx, name, flag) -def DelEnum(enum_id): +def del_enum(enum_id): """ Delete enum type @@ -6261,7 +6103,7 @@ def DelEnum(enum_id): ida_enum.del_enum(enum_id) -def SetEnumIdx(enum_id, idx): +def set_enum_idx(enum_id, idx): """ Give another serial number to a enum @@ -6273,7 +6115,7 @@ def SetEnumIdx(enum_id, idx): serial numbers incremented (in other words, the new enum is put in the middle of the list of enums). - If idx >= GetEnumQty() then the enum is + If idx >= get_enum_qty() then the enum is moved to the end of the list of enums. @return: comment string @@ -6281,7 +6123,7 @@ def SetEnumIdx(enum_id, idx): return ida_enum.set_enum_idx(enum_id, idx) -def SetEnumName(enum_id, name): +def set_enum_name(enum_id, name): """ Rename enum @@ -6293,7 +6135,7 @@ def SetEnumName(enum_id, name): return ida_enum.set_enum_name(enum_id, name) -def SetEnumCmt(enum_id, cmt, repeatable): +def set_enum_cmt(enum_id, cmt, repeatable): """ Set comment of enum @@ -6308,7 +6150,7 @@ def SetEnumCmt(enum_id, cmt, repeatable): return ida_enum.set_enum_cmt(enum_id, cmt, repeatable) -def SetEnumFlag(enum_id, flag): +def set_enum_flag(enum_id, flag): """ Set flag of enum @@ -6321,7 +6163,7 @@ def SetEnumFlag(enum_id, flag): return ida_enum.set_enum_flag(enum_id, flag) -def SetEnumBf(enum_id, flag): +def set_enum_bf(enum_id, flag): """ Set bitfield property of enum @@ -6335,21 +6177,19 @@ def SetEnumBf(enum_id, flag): return ida_enum.set_enum_bf(enum_id, flag) -def SetEnumWidth(enum_id, width): +def set_enum_width(enum_id, width): """ Set width of enum elements @param enum_id: id of enum - @param width: element width in bytes - allowed values: 0-unknown - or 1..7: (log2 of the element size)+1 + @param width: element width in bytes (0-unknown) @return: 1-ok, 0-failed """ return ida_enum.set_enum_width(enum_id, width) -def IsBitfield(enum_id): +def is_bf(enum_id): """ Is enum a bitfield? @@ -6360,7 +6200,7 @@ def IsBitfield(enum_id): return ida_enum.is_bf(enum_id) -def AddConstEx(enum_id, name, value, bmask): +def add_enum_member(enum_id, name, value, bmask): """ Add a member of enum - a symbolic constant @@ -6368,7 +6208,7 @@ def AddConstEx(enum_id, name, value, bmask): @param name: name of symbolic constant. Must be unique in the program. @param value: value of symbolic constant. @param bmask: bitmask of the constant - ordinary enums accept only -1 as a bitmask + ordinary enums accept only ida_enum.DEFMASK as a bitmask all bits set in value should be set in bmask too @return: 0-ok, otherwise error code (one of ENUM_MEMBER_ERROR_*) @@ -6385,16 +6225,16 @@ ENUM_MEMBER_ERROR_MASK = ida_enum.ENUM_MEMBER_ERROR_MASK # bad bmask ENUM_MEMBER_ERROR_ILLV = ida_enum.ENUM_MEMBER_ERROR_ILLV # bad bmask and value combination (~bmask & value != 0) -def DelConstEx(enum_id, value, serial, bmask): +def del_enum_member(enum_id, value, serial, bmask): """ Delete a member of enum - a symbolic constant @param enum_id: id of enum @param value: value of symbolic constant. @param serial: serial number of the constant in the - enumeration. See OpEnumEx() for for details. + enumeration. See op_enum() for for details. @param bmask: bitmask of the constant ordinary enums accept - only -1 as a bitmask + only ida_enum.DEFMASK as a bitmask @return: 1-ok, 0-failed """ @@ -6403,7 +6243,7 @@ def DelConstEx(enum_id, value, serial, bmask): return ida_enum.del_enum_member(enum_id, value, serial, bmask) -def SetConstName(const_id, name): +def set_enum_member_name(const_id, name): """ Rename a member of enum - a symbolic constant @@ -6415,7 +6255,7 @@ def SetConstName(const_id, name): return ida_enum.set_enum_member_name(const_id, name) -def SetConstCmt(const_id, cmt, repeatable): +def set_enum_member_cmt(const_id, cmt, repeatable): """ Set a comment of a symbolic constant @@ -6477,12 +6317,12 @@ class __dummy_netnode(object): def supval(self, *args): return 0 def altdel(self, *args): return 0 def supdel(self, *args): return 0 - def alt1st(self, *args): return -1 - def sup1st(self, *args): return -1 + def altfirst(self, *args): return -1 + def supfirst(self, *args): return -1 def altlast(self, *args): return -1 def suplast(self, *args): return -1 - def altnxt(self, *args): return -1 - def supnxt(self, *args): return -1 + def altnext(self, *args): return -1 + def supnext(self, *args): return -1 def altprev(self, *args): return -1 def supprev(self, *args): return -1 def hashset(self, *args): return 0 @@ -6493,8 +6333,8 @@ class __dummy_netnode(object): def hashset_buf(self, *args): return 0 def hashval_long(self, *args): return 0 def hashdel(self, *args): return 0 - def hash1st(self, *args): return 0 - def hashnxt(self, *args): return 0 + def hashfirst(self, *args): return 0 + def hashnext(self, *args): return 0 def hashprev(self, *args): return 0 def hashlast(self, *args): return 0 __dummy_netnode.instance = __dummy_netnode() @@ -6514,7 +6354,7 @@ def __GetArrayById(array_id): """ try: node = ida_netnode.netnode(array_id) - nodename = node.name() + nodename = node.get_name() if nodename is None or not nodename.startswith(_IDC_ARRAY_PREFIX): return __dummy_netnode.instance else: @@ -6523,7 +6363,7 @@ def __GetArrayById(array_id): return __dummy_netnode.instance -def CreateArray(name): +def create_array(name): """ Create array. @@ -6539,7 +6379,7 @@ def CreateArray(name): return node.index() -def GetArrayId(name): +def get_array_id(name): """ Get array array_id, by name. @@ -6551,7 +6391,7 @@ def GetArrayId(name): return __l2m1(ida_netnode.netnode(_IDC_ARRAY_PREFIX + name, 0, False).index()) -def RenameArray(array_id, newname): +def rename_array(array_id, newname): """ Rename array, by its ID. @@ -6563,7 +6403,7 @@ def RenameArray(array_id, newname): return __GetArrayById(array_id).rename(_IDC_ARRAY_PREFIX + newname) == 1 -def DeleteArray(array_id): +def delete_array(array_id): """ Delete array, by its ID. @@ -6572,7 +6412,7 @@ def DeleteArray(array_id): __GetArrayById(array_id).kill() -def SetArrayLong(array_id, idx, value): +def set_array_long(array_id, idx, value): """ Sets the long value of an array element. @@ -6585,7 +6425,7 @@ def SetArrayLong(array_id, idx, value): return __GetArrayById(array_id).altset(idx, value) -def SetArrayString(array_id, idx, value): +def set_array_string(array_id, idx, value): """ Sets the string value of an array element. @@ -6598,7 +6438,7 @@ def SetArrayString(array_id, idx, value): return __GetArrayById(array_id).supset(idx, value) -def GetArrayElement(tag, array_id, idx): +def get_array_element(tag, array_id, idx): """ Get value of array element. @@ -6620,7 +6460,7 @@ def GetArrayElement(tag, array_id, idx): return 0 -def DelArrayElement(tag, array_id, idx): +def del_array_element(tag, array_id, idx): """ Delete an array element. @@ -6639,7 +6479,7 @@ def DelArrayElement(tag, array_id, idx): return 0 -def GetFirstIndex(tag, array_id): +def get_first_index(tag, array_id): """ Get index of the first existing array element. @@ -6651,14 +6491,14 @@ def GetFirstIndex(tag, array_id): """ node = __GetArrayById(array_id) if tag == AR_LONG: - return __l2m1(node.alt1st(tag)) + return __l2m1(node.altfirst(tag)) elif tag == AR_STR: - return __l2m1(node.sup1st(tag)) + return __l2m1(node.supfirst(tag)) else: return -1 -def GetLastIndex(tag, array_id): +def get_last_index(tag, array_id): """ Get index of last existing array element. @@ -6677,7 +6517,7 @@ def GetLastIndex(tag, array_id): return -1 -def GetNextIndex(tag, array_id, idx): +def get_next_index(tag, array_id, idx): """ Get index of the next existing array element. @@ -6691,9 +6531,9 @@ def GetNextIndex(tag, array_id, idx): node = __GetArrayById(array_id) try: if tag == AR_LONG: - return __l2m1(node.altnxt(idx, tag)) + return __l2m1(node.altnext(idx, tag)) elif tag == AR_STR: - return __l2m1(node.supnxt(idx, tag)) + return __l2m1(node.supnext(idx, tag)) else: return -1 except OverflowError: @@ -6701,7 +6541,7 @@ def GetNextIndex(tag, array_id, idx): return -1 -def GetPrevIndex(tag, array_id, idx): +def get_prev_index(tag, array_id, idx): """ Get index of the previous existing array element. @@ -6727,7 +6567,7 @@ def GetPrevIndex(tag, array_id, idx): # -------------------- hashes ----------------------- -def SetHashLong(hash_id, key, value): +def set_hash_long(hash_id, key, value): """ Sets the long value of a hash element. @@ -6740,7 +6580,7 @@ def SetHashLong(hash_id, key, value): return __GetArrayById(hash_id).hashset_idx(key, value) -def GetHashLong(hash_id, key): +def get_hash_long(hash_id, key): """ Gets the long value of a hash element. @@ -6753,7 +6593,7 @@ def GetHashLong(hash_id, key): return __GetArrayById(hash_id).hashval_long(key); -def SetHashString(hash_id, key, value): +def set_hash_string(hash_id, key, value): """ Sets the string value of a hash element. @@ -6766,7 +6606,7 @@ def SetHashString(hash_id, key, value): return __GetArrayById(hash_id).hashset_buf(key, value) -def GetHashString(hash_id, key): +def get_hash_string(hash_id, key): """ Gets the string value of a hash element. @@ -6779,7 +6619,7 @@ def GetHashString(hash_id, key): return __GetArrayById(hash_id).hashstr_buf(key); -def DelHashElement(hash_id, key): +def del_hash_string(hash_id, key): """ Delete a hash element. @@ -6791,7 +6631,7 @@ def DelHashElement(hash_id, key): return __GetArrayById(hash_id).hashdel(key) -def GetFirstHashKey(hash_id): +def get_first_hash_key(hash_id): """ Get the first key in the hash. @@ -6799,11 +6639,11 @@ def GetFirstHashKey(hash_id): @return: the key, 0 otherwise. """ - r = __GetArrayById(hash_id).hash1st() + r = __GetArrayById(hash_id).hashfirst() return 0 if r is None else r -def GetLastHashKey(hash_id): +def get_last_hash_key(hash_id): """ Get the last key in the hash. @@ -6815,7 +6655,7 @@ def GetLastHashKey(hash_id): return 0 if r is None else r -def GetNextHashKey(hash_id, key): +def get_next_hash_key(hash_id, key): """ Get the next key in the hash. @@ -6824,11 +6664,11 @@ def GetNextHashKey(hash_id, key): @return: the next key, 0 otherwise """ - r = __GetArrayById(hash_id).hashnxt(key) + r = __GetArrayById(hash_id).hashnext(key) return 0 if r is None else r -def GetPrevHashKey(hash_id, key): +def get_prev_hash_key(hash_id, key): """ Get the previous key in the hash. @@ -6846,7 +6686,7 @@ def GetPrevHashKey(hash_id, key): #---------------------------------------------------------------------------- # S O U R C E F I L E / L I N E N U M B E R S #---------------------------------------------------------------------------- -def AddSourceFile(ea1, ea2, filename): +def add_sourcefile(ea1, ea2, filename): """ Mark a range of address as belonging to a source file An address range may belong only to one source file. @@ -6865,7 +6705,7 @@ def AddSourceFile(ea1, ea2, filename): return ida_lines.add_sourcefile(ea1, ea2, filename) -def GetSourceFile(ea): +def get_sourcefile(ea): """ Get name of source file occupying the given address @@ -6877,7 +6717,7 @@ def GetSourceFile(ea): return ida_lines.get_sourcefile(ea) -def DelSourceFile(ea): +def del_sourcefile(ea): """ Delete information about the source file @@ -6889,7 +6729,7 @@ def DelSourceFile(ea): return ida_lines.del_sourcefile(ea) -def SetLineNumber(ea, lnnum): +def set_source_linnum(ea, lnnum): """ Set source line number @@ -6901,7 +6741,7 @@ def SetLineNumber(ea, lnnum): ida_nalt.set_source_linnum(ea, lnnum) -def GetLineNumber(ea): +def get_source_linnum(ea): """ Get source line number @@ -6912,7 +6752,7 @@ def GetLineNumber(ea): return ida_nalt.get_source_linnum(ea) -def DelLineNumber(ea): +def del_source_linnum(ea): """ Delete information about source line number @@ -6927,21 +6767,21 @@ def DelLineNumber(ea): # T Y P E L I B R A R I E S #---------------------------------------------------------------------------- -def LoadTil(name): +def add_default_til(name): """ Load a type library @param name: name of type library. @return: 1-ok, 0-failed. """ - til = ida_typeinf.add_til2(name, ida_typeinf.ADDTIL_DEFAULT) + til = ida_typeinf.add_til(name, ida_typeinf.ADDTIL_DEFAULT) if til: return 1 else: return 0 -def Til2Idb(idx, type_name): +def import_type(idx, type_name): """ Copy information from type library to database Copy structure, union, or enum definition from the type library @@ -6953,10 +6793,10 @@ def Til2Idb(idx, type_name): @return: BADNODE-failed, otherwise the type id (structure id or enum id) """ - return ida_typeinf.import_type(ida_typeinf.cvar.idati, idx, type_name) + return ida_typeinf.import_type(None, idx, type_name) -def GetType(ea): +def get_type(ea): """ Get type of function/variable @@ -6969,12 +6809,12 @@ def GetType(ea): def SizeOf(typestr): """ Returns the size of the type. It is equivalent to IDC's sizeof(). - Use name, tp, fld = idc.ParseType() ; SizeOf(tp) to retrieve the size + Use name, tp, fld = idc.parse_decl() ; SizeOf(tp) to retrieve the size @return: -1 if typestring is not valid otherwise the size of the type """ - return ida_typeinf.calc_type_size(ida_typeinf.cvar.idati, typestr) + return ida_typeinf.calc_type_size(None, typestr) -def GetTinfo(ea): +def get_tinfo(ea): """ Get type information of function/variable as 'typeinfo' object @@ -6983,7 +6823,7 @@ def GetTinfo(ea): """ return ida_typeinf.idc_get_type_raw(ea) -def GetLocalTinfo(ordinal): +def get_local_tinfo(ordinal): """ Get local type information as 'typeinfo' object @@ -6992,7 +6832,7 @@ def GetLocalTinfo(ordinal): """ return ida_typeinf.idc_get_local_type_raw(ordinal) -def GuessType(ea): +def guess_type(ea): """ Guess type of function/variable @@ -7008,17 +6848,16 @@ TINFO_DELAYFUNC = 0x0002 # if type is a function and no function exists at ea, # schedule its creation and argument renaming to # auto-analysis otherwise try to create it immediately -def ApplyType(ea, py_type, flags = TINFO_DEFINITE): +def apply_type(ea, py_type, flags = TINFO_DEFINITE): """ Apply the specified type to the address - @param ti: Type info. 'ida_typeinf.cvar.idati' can be passed. - @param py_type: typeinfo tuple (type, fields) as GetTinfo() returns - or tuple (name, type, fields) as ParseType() returns + @param ea: the address of the object + @param py_type: typeinfo tuple (type, fields) as get_tinfo() returns + or tuple (name, type, fields) as parse_decl() returns or None if specified as None, then the item associated with 'ea' will be deleted. - @param ea: the address of the object @param flags: combination of TINFO_... constants or 0 @return: Boolean """ @@ -7032,7 +6871,7 @@ def ApplyType(ea, py_type, flags = TINFO_DEFINITE): pt = py_type[1:] # skip name component else: pt = py_type - return ida_typeinf.apply_type(ida_typeinf.cvar.idati, pt[0], pt[1], ea, flags) + return ida_typeinf.apply_type(None, pt[0], pt[1], ea, flags) def SetType(ea, newtype): """ @@ -7047,15 +6886,15 @@ def SetType(ea, newtype): @return: 1-ok, 0-failed. """ if newtype is not '': - pt = ParseType(newtype, 1) # silent + pt = parse_decl(newtype, 1) # silent if pt is None: # parsing failed return None else: pt = None - return ApplyType(ea, pt, TINFO_DEFINITE) + return apply_type(ea, pt, TINFO_DEFINITE) -def ParseType(inputtype, flags): +def parse_decl(inputtype, flags): """ Parse type declaration @@ -7066,9 +6905,9 @@ def ParseType(inputtype, flags): """ if len(inputtype) != 0 and inputtype[-1] != ';': inputtype = inputtype + ';' - return ida_typeinf.idc_parse_decl(ida_typeinf.cvar.idati, inputtype, flags) + return ida_typeinf.idc_parse_decl(None, inputtype, flags) -def ParseTypes(inputtype, flags = 0): +def parse_decls(inputtype, flags = 0): """ Parse type declarations @@ -7093,7 +6932,7 @@ PT_HIGH = 0x0080 # assume high level prototypes PT_LOWER = 0x0100 # lower the function prototypes -def PrintLocalTypes(ordinals, flags): +def print_decls(ordinals, flags): """ Print types in a format suitable for use in a header file @@ -7114,7 +6953,7 @@ def PrintLocalTypes(ordinals, flags): sink = def_sink() py_ordinals = map(lambda l : int(l), ordinals.split(",")) - ida_typeinf.print_decls(sink, ida_typeinf.cvar.idati, py_ordinals, flags) + ida_typeinf.print_decls(sink, None, py_ordinals, flags) return sink.text @@ -7125,16 +6964,16 @@ PDF_DEF_BASE = 0x4 # include base types: __int8, __int16, etc.. PDF_HEADER_CMT = 0x8 # prepend output with a descriptive comment -def GetMaxLocalType(): +def get_ordinal_qty(): """ Get number of local types + 1 @return: value >= 1. 1 means that there are no local types. """ - return ida_typeinf.get_ordinal_qty(ida_typeinf.cvar.idati) + return ida_typeinf.get_ordinal_qty(None) -def SetLocalType(ordinal, input, flags): +def set_local_type(ordinal, input, flags): """ Parse one type declaration and store it in the specified slot @@ -7155,9 +6994,9 @@ def GetLocalType(ordinal, flags): @param flags: any of PRTYPE_* constants @return: local type as a C declaration or "" """ - (type, fields) = GetLocalTinfo(ordinal) + (type, fields) = get_local_tinfo(ordinal) if type: - name = GetLocalTypeName(ordinal) + name = get_numbered_type_name(ordinal) return ida_typeinf.idc_print_type(type, fields, name, flags) return "" @@ -7167,7 +7006,7 @@ PRTYPE_TYPE = 0x0002 # print type declaration (not variable declaration) PRTYPE_PRAGMA = 0x0004 # print pragmas for alignment -def GetLocalTypeName(ordinal): +def get_numbered_type_name(ordinal): """ Retrieve a local type name @@ -7181,56 +7020,56 @@ def GetLocalTypeName(ordinal): # ---------------------------------------------------------------------------- # H I D D E N A R E A S # ---------------------------------------------------------------------------- -def HideArea(start, end, description, header, footer, color): +def add_hidden_range(start, end, description, header, footer, color): """ - Hide an area + Hide a range - Hidden areas - address ranges which can be replaced by their descriptions + Hidden ranges - address ranges which can be replaced by their descriptions - @param start: area start - @param end: area end - @param description: description to display if the area is collapsed - @param header: header lines to display if the area is expanded - @param footer: footer lines to display if the area is expanded + @param start: range start + @param end: range end + @param description: description to display if the range is collapsed + @param header: header lines to display if the range is expanded + @param footer: footer lines to display if the range is expanded @param color: RGB color code (-1 means default color) @returns: !=0 - ok """ - return ida_bytes.add_hidden_area(start, end, description, header, footer, color) + return ida_bytes.add_hidden_range(start, end, description, header, footer, color) -def SetHiddenArea(ea, visible): +def update_hidden_range(ea, visible): """ - Set hidden area state + Set hidden range state - @param ea: any address belonging to the hidden area - @param visible: new state of the area + @param ea: any address belonging to the hidden range + @param visible: new state of the range @return: != 0 - ok """ - ha = ida_bytes.get_hidden_area(ea) + ha = ida_bytes.get_hidden_range(ea) if not ha: return 0 else: ha.visible = visible - return ida_bytes.update_hidden_area(ha) + return ida_bytes.update_hidden_range(ha) -def DelHiddenArea(ea): +def del_hidden_range(ea): """ - Delete a hidden area + Delete a hidden range - @param ea: any address belonging to the hidden area + @param ea: any address belonging to the hidden range @returns: != 0 - ok """ - return ida_bytes.del_hidden_area(ea) + return ida_bytes.del_hidden_range(ea) #-------------------------------------------------------------------------- # D E B U G G E R I N T E R F A C E #-------------------------------------------------------------------------- -def LoadDebugger(dbgname, use_remote): +def load_debugger(dbgname, use_remote): """ Load the debugger @@ -7243,7 +7082,7 @@ def LoadDebugger(dbgname, use_remote): return ida_dbg.load_debugger(dbgname, use_remote) -def StartDebugger(path, args, sdir): +def start_process(path, args, sdir): """ Launch the debugger @@ -7254,12 +7093,12 @@ def StartDebugger(path, args, sdir): @return: -1-failed, 0-cancelled by the user, 1-ok @note: For all args: if empty, the default value from the database will be used - See the important note to the StepInto() function + See the important note to the step_into() function """ return ida_dbg.start_process(path, args, sdir) -def StopDebugger(): +def exit_process(): """ Stop the debugger Kills the currently debugger process and returns to the disassembly mode @@ -7269,57 +7108,30 @@ def StopDebugger(): return ida_dbg.exit_process() -def PauseProcess(): +def suspend_process(): """ Suspend the running process Tries to suspend the process. If successful, the PROCESS_SUSPEND - debug event will arrive (see GetDebuggerEvent) + debug event will arrive (see wait_for_next_event) @return: success - @note: To resume a suspended process use the GetDebuggerEvent function. - See the important note to the StepInto() function + @note: To resume a suspended process use the wait_for_next_event function. + See the important note to the step_into() function """ return ida_dbg.suspend_process() -def GetProcessQty(): +def get_processes(): """ - Take a snapshot of running processes and return their number. + Take a snapshot of running processes and return their description. + + @return: -1:network error, 0-failed, 1-ok """ - return ida_dbg.get_process_qty() + return ida_dbg.get_processes() -def GetProcessPid(idx): - """ - Get the process ID of a running process - - @param idx: number of process, is in range 0..GetProcessQty()-1 - - @return: 0 if failure - """ - pinfo = ida_idd.process_info_t() - pid = ida_dbg.get_process_info(idx, pinfo) - if pid != ida_idd.NO_PROCESS: - return pinfo.pid - else: - return 0 - - -def GetProcessName(idx): - """ - Get the name of a running process - - @param idx: number of process, is in range 0..GetProcessQty()-1 - - @return: None if failure - """ - pinfo = ida_idd.process_info_t() - pid = ida_dbg.get_process_info(idx, pinfo) - return None if pid == ida_idd.NO_PROCESS else pinfo.name - - -def AttachProcess(pid, event_id): +def attach_process(pid, event_id): """ Attach the debugger to a running process @@ -7333,12 +7145,12 @@ def AttachProcess(pid, event_id): needed, not supported by the debugger plugin, ...) - 0: the user cancelled the attaching to the process - 1: the debugger properly attached to the process - @note: See the important note to the StepInto() function + @note: See the important note to the step_into() function """ return ida_dbg.attach_process(pid, event_id) -def DetachProcess(): +def detach_process(): """ Detach the debugger from the debugged process. @@ -7347,7 +7159,7 @@ def DetachProcess(): return ida_dbg.detach_process() -def GetThreadQty(): +def get_thread_qty(): """ Get number of threads. @@ -7356,18 +7168,18 @@ def GetThreadQty(): return ida_dbg.get_thread_qty() -def GetThreadId(idx): +def getn_thread(idx): """ Get the ID of a thread - @param idx: number of thread, is in range 0..GetThreadQty()-1 + @param idx: number of thread, is in range 0..get_thread_qty()-1 @return: -1 if failure """ return ida_dbg.getn_thread(idx) -def GetCurrentThreadId(): +def get_current_thread(): """ Get current thread ID @@ -7376,7 +7188,7 @@ def GetCurrentThreadId(): return ida_dbg.get_current_thread() -def SelectThread(tid): +def select_thread(tid): """ Select the given thread as the current debugged thread. @@ -7389,7 +7201,7 @@ def SelectThread(tid): return ida_dbg.select_thread(tid) -def SuspendThread(tid): +def suspend_thread(tid): """ Suspend thread @@ -7403,7 +7215,7 @@ def SuspendThread(tid): return ida_dbg.suspend_thread(tid) -def ResumeThread(tid): +def resume_thread(tid): """ Resume thread @@ -7425,7 +7237,7 @@ def _get_modules(): result = ida_dbg.get_next_module(module) -def GetFirstModule(): +def get_first_module(): """ Enumerate process modules @@ -7437,7 +7249,7 @@ def GetFirstModule(): return None -def GetNextModule(base): +def get_next_module(base): """ Enumerate process modules @@ -7455,7 +7267,7 @@ def GetNextModule(base): return None -def GetModuleName(base): +def get_module_name(base): """ Get process module name @@ -7470,7 +7282,7 @@ def GetModuleName(base): return 0 -def GetModuleSize(base): +def get_module_size(base): """ Get process module size @@ -7485,14 +7297,14 @@ def GetModuleSize(base): return -1 -def StepInto(): +def step_into(): """ Execute one instruction in the current thread. Other threads are kept suspended. @return: success - @note: You must call GetDebuggerEvent() after this call + @note: You must call wait_for_next_event() after this call in order to find out what happened. Normally you will get the STEP event but other events are possible (for example, an exception might occur or the process might exit). @@ -7502,42 +7314,42 @@ def StepInto(): return ida_dbg.step_into() -def StepOver(): +def step_over(): """ Execute one instruction in the current thread, but without entering into functions Others threads keep suspended. - See the important note to the StepInto() function + See the important note to the step_into() function @return: success """ return ida_dbg.step_over() -def RunTo(ea): +def run_to(ea): """ Execute the process until the given address is reached. If no process is active, a new process is started. - See the important note to the StepInto() function + See the important note to the step_into() function @return: success """ return ida_dbg.run_to(ea) -def StepUntilRet(): +def step_until_ret(): """ Execute instructions in the current thread until a function return instruction is reached. Other threads are kept suspended. - See the important note to the StepInto() function + See the important note to the step_into() function @return: success """ return ida_dbg.step_until_ret() -def GetDebuggerEvent(wfne, timeout): +def wait_for_next_event(wfne, timeout): """ Wait for the next event This function (optionally) resumes the process @@ -7551,15 +7363,15 @@ def GetDebuggerEvent(wfne, timeout): return ida_dbg.wait_for_next_event(wfne, timeout) -def ResumeProcess(): - return GetDebuggerEvent(WFNE_CONT|WFNE_NOWAIT, 0) +def resume_process(): + return wait_for_next_event(WFNE_CONT|WFNE_NOWAIT, 0) -def SendDbgCommand(cmd): +def send_dbg_command(cmd): """Sends a command to the debugger module and returns the output string. An exception will be raised if the debugger is not running or the current debugger does not export - the 'SendDbgCommand' IDC command. + the 'send_dbg_command' IDC command. """ - s = Eval('SendDbgCommand("%s");' % ida_kernwin.str2user(cmd)) + s = eval_idc('send_dbg_command("%s");' % ida_kernwin.str2user(cmd)) if s.startswith("IDC_FAILURE"): raise Exception, "Debugger command is available only when the debugger is active!" return s @@ -7568,7 +7380,7 @@ def SendDbgCommand(cmd): WFNE_ANY = 0x0001 # return the first event (even if it doesn't suspend the process) # if the process is still running, the database # does not reflect the memory state. you might want - # to call RefreshDebuggerMemory() in this case + # to call refresh_debugger_memory() in this case WFNE_SUSP = 0x0002 # wait until the process gets suspended WFNE_SILENT = 0x0004 # 1: be slient, 0:display modal boxes if necessary WFNE_CONT = 0x0008 # continue from the suspended state @@ -7596,9 +7408,9 @@ PROCESS_DETACH = 0x00002000 # Detached from process PROCESS_SUSPEND = 0x00004000 # Process has been suspended -def RefreshDebuggerMemory(): +def refresh_debugger_memory(): """ - Refresh debugger memory + refresh_idaview_anyway debugger memory Upon this call IDA will forget all cached information about the debugged process. This includes the segmentation information and memory contents (register cache is managed @@ -7611,7 +7423,7 @@ def RefreshDebuggerMemory(): return ida_dbg.refresh_debugger_memory() -def TakeMemorySnapshot(only_loader_segs): +def take_memory_snapshot(only_loader_segs): """ Take memory snapshot of the debugged process @@ -7621,7 +7433,7 @@ def TakeMemorySnapshot(only_loader_segs): return ida_segment.take_memory_snapshot(only_loader_segs) -def GetProcessState(): +def get_process_state(): """ Get debugged process state @@ -7644,7 +7456,7 @@ DSTATE_RUN_WAIT_END = 3 # process is running, but the user asked to kill/det # For all events: -def GetEventId(): +def get_event_id(): """ Get ID of debug event @@ -7655,7 +7467,7 @@ def GetEventId(): return ev.eid -def GetEventPid(): +def get_event_pid(): """ Get process ID for debug event @@ -7666,7 +7478,7 @@ def GetEventPid(): return ev.pid -def GetEventTid(): +def get_event_tid(): """ Get type ID for debug event @@ -7677,7 +7489,7 @@ def GetEventTid(): return ev.tid -def GetEventEa(): +def get_event_ea(): """ Get ea for debug event @@ -7688,7 +7500,7 @@ def GetEventEa(): return ev.ea -def IsEventHandled(): +def is_event_handled(): """ Is the debug event handled? @@ -7701,7 +7513,7 @@ def IsEventHandled(): # For PROCESS_START, PROCESS_ATTACH, LIBRARY_LOAD events: -def GetEventModuleName(): +def get_event_module_name(): """ Get module name for debug event @@ -7712,7 +7524,7 @@ def GetEventModuleName(): return ida_idd.get_event_module_name(ev) -def GetEventModuleBase(): +def get_event_module_base(): """ Get module base for debug event @@ -7723,7 +7535,7 @@ def GetEventModuleBase(): return ida_idd.get_event_module_base(ev) -def GetEventModuleSize(): +def get_event_module_size(): """ Get module size for debug event @@ -7734,7 +7546,7 @@ def GetEventModuleSize(): return ida_idd.get_event_module_size(ev) -def GetEventExitCode(): +def get_event_exit_code(): """ Get exit code for debug event @@ -7745,7 +7557,7 @@ def GetEventExitCode(): return ev.exit_code -def GetEventInfo(): +def get_event_info(): """ Get debug event info @@ -7757,7 +7569,7 @@ def GetEventInfo(): return ida_idd.get_event_info(ev) -def GetEventBptHardwareEa(): +def get_event_bpt_hea(): """ Get hardware address for BREAKPOINT event @@ -7768,7 +7580,7 @@ def GetEventBptHardwareEa(): return ida_idd.get_event_bpt_hea(ev) -def GetEventExceptionCode(): +def get_event_exc_code(): """ Get exception code for EXCEPTION event @@ -7779,7 +7591,7 @@ def GetEventExceptionCode(): return ida_idd.get_event_exc_code(ev) -def GetEventExceptionEa(): +def get_event_exc_ea(): """ Get address for EXCEPTION event @@ -7790,7 +7602,7 @@ def GetEventExceptionEa(): return ida_idd.get_event_exc_ea(ev) -def CanExceptionContinue(): +def can_exc_continue(): """ Can it continue after EXCEPTION event? @@ -7801,7 +7613,7 @@ def CanExceptionContinue(): return ida_idd.can_exc_continue(ev) -def GetEventExceptionInfo(): +def get_event_exc_info(): """ Get info for EXCEPTION event @@ -7812,7 +7624,7 @@ def GetEventExceptionInfo(): return ida_idd.get_event_exc_info(ev) -def SetDebuggerOptions(opt): +def set_debugger_options(opt): """ Get/set debugger options @@ -7844,21 +7656,21 @@ EXCDLG_ALWAYS = 0x00006000 # always display DOPT_LOAD_DINFO = 0x00008000 # automatically load debug files (pdb) -def GetDebuggerEventCondition(): +def get_debugger_event_cond(): """ Return the debugger event condition """ return ida_dbg.get_debugger_event_cond() -def SetDebuggerEventCondition(cond): +def set_debugger_event_cond(cond): """ Set the debugger event condition """ return ida_dbg.set_debugger_event_cond(cond) -def SetRemoteDebugger(hostname, password, portnum): +def set_remote_debugger(hostname, password, portnum): """ Set remote debugging options @@ -7871,7 +7683,7 @@ def SetRemoteDebugger(hostname, password, portnum): return ida_dbg.set_remote_debugger(hostname, password, portnum) -def DefineException(code, name, desc, flags): +def define_exception(code, name, desc, flags): """ Add exception handling information @@ -7888,7 +7700,7 @@ EXC_BREAK = 0x0001 # break on the exception EXC_HANDLE = 0x0002 # should be handled by the debugger? -def GetRegValue(name): +def get_reg_value(name): """ Get register value @@ -7907,7 +7719,7 @@ def GetRegValue(name): return rv.ival -def SetRegValue(value, name): +def set_reg_value(value, name): """ Set register value @@ -7922,7 +7734,7 @@ def SetRegValue(value, name): if type(value) == types.StringType: value = int(value, 16) elif type(value) != types.IntType and type(value) != types.LongType: - print "SetRegValue: value must be integer!" + print "set_reg_value: value must be integer!" return BADADDR if value < 0: @@ -7933,7 +7745,7 @@ def SetRegValue(value, name): return ida_dbg.set_reg_val(name, rv) -def GetBptQty(): +def get_bpt_qty(): """ Get number of breakpoints. @@ -7942,13 +7754,13 @@ def GetBptQty(): return ida_dbg.get_bpt_qty() -def GetBptEA(n): +def get_bpt_ea(n): """ Get breakpoint address - @param n: number of breakpoint, is in range 0..GetBptQty()-1 + @param n: number of breakpoint, is in range 0..get_bpt_qty()-1 - @return: addresss of the breakpoint or BADADDR + @return: address of the breakpoint or BADADDR """ bpt = ida_dbg.bpt_t() @@ -7958,7 +7770,7 @@ def GetBptEA(n): return BADADDR -def GetBptAttr(ea, bptattr): +def get_bpt_attr(ea, bptattr): """ Get the characteristics of a breakpoint @@ -8028,13 +7840,13 @@ BPLT_SYM = 2 # Symbolic name. The name will be resolved on DLL load/unload # - locinfo: offset from the symbol base address -def SetBptAttr(address, bptattr, value): +def set_bpt_attr(address, bptattr, value): """ modifiable characteristics of a breakpoint @param address: any address in the breakpoint range @param bptattr: the attribute code, one of BPTATTR_* constants - BPTATTR_CND is not allowed, see SetBptCnd() + BPTATTR_CND is not allowed, see set_bpt_cond() @param value: the attibute value @return: success @@ -8057,7 +7869,8 @@ def SetBptAttr(address, bptattr, value): return ida_dbg.update_bpt(bpt) -def SetBptCndEx(ea, cnd, is_lowcnd): + +def set_bpt_cond(ea, cnd, is_lowcnd=0): """ Set breakpoint condition @@ -8081,19 +7894,7 @@ def SetBptCndEx(ea, cnd, is_lowcnd): return ida_dbg.update_bpt(bpt) -def SetBptCnd(ea, cnd): - """ - Set breakpoint condition - - @param ea: any address in the breakpoint range - @param cnd: breakpoint condition - - @return: success - """ - return SetBptCndEx(ea, cnd, 0) - - -def AddBptEx(ea, size, bpttype): +def add_bpt(ea, size=0, bpttype=BPT_DEFAULT): """ Add a new breakpoint @@ -8108,11 +7909,7 @@ def AddBptEx(ea, size, bpttype): return ida_dbg.add_bpt(ea, size, bpttype) -def AddBpt(ea): - return AddBptEx(ea, 0, BPT_DEFAULT) - - -def DelBpt(ea): +def del_bpt(ea): """ Delete breakpoint @@ -8123,7 +7920,7 @@ def DelBpt(ea): return ida_dbg.del_bpt(ea) -def EnableBpt(ea, enable): +def enable_bpt(ea, enable): """ Enable/disable breakpoint @@ -8136,7 +7933,7 @@ def EnableBpt(ea, enable): return ida_dbg.enable_bpt(ea, enable) -def CheckBpt(ea): +def check_bpt(ea): """ Check a breakpoint @@ -8152,7 +7949,7 @@ BPTCK_YES = 1 # breakpoint is enabled BPTCK_ACT = 2 # breakpoint is active (written to the process) -def EnableTracing(trace_level, enable): +def enable_tracing(trace_level, enable): """ Enable step tracing @@ -8180,7 +7977,7 @@ TRACE_INSN = 0x1 # instruction level trace TRACE_FUNC = 0x2 # function level trace (calls & rets) -def GetStepTraceOptions(): +def get_step_trace_options(): """ Get step current tracing options @@ -8189,7 +7986,7 @@ def GetStepTraceOptions(): return ida_dbg.get_step_trace_options() -def SetStepTraceOptions(options): +def set_step_trace_options(options): """ Set step current tracing options. @param options: combination of ST_... constants @@ -8202,14 +7999,14 @@ ST_OVER_LIB_FUNC = 0x02 # step tracing will be disabled when IP is in a library ST_ALREADY_LOGGED = 0x04 # step tracing will be disabled when IP is already logged ST_SKIP_LOOPS = 0x08 # step tracing will try to skip loops already recorded -def LoadTraceFile(filename): +def load_trace_file(filename): """ Load a previously recorded binary trace file @param filename: trace file """ return ida_dbg.load_trace_file(filename) -def SaveTraceFile(filename, description): +def save_trace_file(filename, description): """ Save current trace to a binary trace file @param filename: trace file @@ -8217,34 +8014,34 @@ def SaveTraceFile(filename, description): """ return ida_dbg.save_trace_file(filename, description) -def CheckTraceFile(filename): +def is_valid_trace_file(filename): """ Check the given binary trace file @param filename: trace file """ return ida_dbg.is_valid_trace_file(filename) -def DiffTraceFile(filename): +def diff_trace_file(filename): """ Diff current trace buffer against given trace @param filename: trace file """ return ida_dbg.diff_trace_file(filename) -def ClearTraceFile(filename): +def clear_trace(filename): """ Clear the current trace buffer """ return ida_dbg.clear_trace() -def GetTraceDesc(filename): +def get_trace_file_desc(filename): """ Get the trace description of the given binary trace file @param filename: trace file """ return ida_dbg.get_trace_file_desc(filename) -def SetTraceDesc(filename, description): +def set_trace_file_desc(filename, description): """ Update the trace description of the given binary trace file @param filename: trace file @@ -8252,13 +8049,13 @@ def SetTraceDesc(filename, description): """ return ida_dbg.set_trace_file_desc(filename, description) -def GetMaxTev(): +def get_tev_qty(): """ Return the total number of recorded events """ return ida_dbg.get_tev_qty() -def GetTevEa(tev): +def get_tev_ea(tev): """ Return the address of the specified event @param tev: event number @@ -8273,21 +8070,21 @@ TEV_BPT = 4 # write, read/write, execution trace TEV_MEM = 5 # memory layout changed TEV_EVENT = 6 # debug event -def GetTevType(tev): +def get_tev_type(tev): """ Return the type of the specified event (TEV_... constants) @param tev: event number """ return ida_dbg.get_tev_type(tev) -def GetTevTid(tev): +def get_tev_tid(tev): """ Return the thread id of the specified event @param tev: event number """ return ida_dbg.get_tev_tid(tev) -def GetTevRegVal(tev, reg): +def get_tev_reg(tev, reg): """ Return the register value for the specified event @param tev: event number @@ -8295,7 +8092,7 @@ def GetTevRegVal(tev, reg): """ return ida_dbg.get_tev_reg_val(tev, reg) -def GetTevRegMemQty(tev): +def get_tev_mem_qty(tev): """ Return the number of blobs of memory recorded, for the specified event @@ -8305,7 +8102,7 @@ def GetTevRegMemQty(tev): """ return ida_dbg.get_tev_reg_mem_qty(tev) -def GetTevRegMem(tev, idx): +def get_tev_mem(tev, idx): """ Return the blob of memory pointed to by 'index', for the specified event @@ -8316,7 +8113,7 @@ def GetTevRegMem(tev, idx): """ return ida_dbg.get_tev_reg_mem(tev, idx) -def GetTevRegMemEa(tev, idx): +def get_tev_mem_ea(tev, idx): """ Return the address of the blob of memory pointed to by 'index' for the specified event @@ -8327,21 +8124,21 @@ def GetTevRegMemEa(tev, idx): """ return ida_dbg.get_tev_reg_mem_ea(tev, idx) -def GetTevCallee(tev): +def get_call_tev_callee(tev): """ Return the address of the callee for the specified event @param tev: event number """ return ida_dbg.get_call_tev_callee(tev) -def GetTevReturn(tev): +def get_ret_tev_return(tev): """ Return the return address for the specified event @param tev: event number """ return ida_dbg.get_ret_tev_return(tev) -def GetBptTevEa(tev): +def get_bpt_tev_ea(tev): """ Return the address of the specified TEV_BPT event @param tev: event number @@ -8353,7 +8150,7 @@ def GetBptTevEa(tev): # C O L O R S #-------------------------------------------------------------------------- -def GetColor(ea, what): +def get_color(ea, what): """ Get item color @@ -8390,7 +8187,7 @@ CIC_SEGM = 3 # segment DEFCOLOR = 0xFFFFFFFF # Default color -def SetColor(ea, what, color): +def set_color(ea, what, color): """ Set item color @@ -8426,7 +8223,7 @@ def SetColor(ea, what, color): #---------------------------------------------------------------------------- # A R M S P E C I F I C #---------------------------------------------------------------------------- -def ArmForceBLJump(ea): +def force_bl_jump(ea): """ Some ARM compilers in Thumb mode use BL (branch-and-link) instead of B (branch) for long jumps, since BL has more range. @@ -8440,10 +8237,10 @@ def ArmForceBLJump(ea): @return: 1-ok, 0-failed """ - return Eval("ArmForceBLJump(0x%x)"%ea) + return eval_idc("force_bl_jump(0x%x)"%ea) -def ArmForceBLCall(ea): +def force_bl_call(ea): """ Force BL instruction to be a call @@ -8451,126 +8248,99 @@ def ArmForceBLCall(ea): @return: 1-ok, 0-failed """ - return Eval("ArmForceBLCall(0x%x)"%ea) + return eval_idc("force_bl_call(0x%x)"%ea) #-------------------------------------------------------------------------- -# Compatibility macros: -def Compile(file): return CompileEx(file, 1) -def OpOffset(ea,base): return OpOff(ea,-1,base) -def OpNum(ea): return OpNumber(ea,-1) -def OpChar(ea): return OpChr(ea,-1) -def OpSegment(ea): return OpSeg(ea,-1) -def OpDec(ea): return OpDecimal(ea,-1) -def OpAlt1(ea, opstr): return OpAlt(ea, 0, opstr) -def OpAlt2(ea, opstr): return OpAlt(ea, 1, opstr) -def StringStp(x): return SetCharPrm(INF_ASCII_BREAK,x) -def LowVoids(x): return SetLongPrm(INF_LOW_OFF,x) -def HighVoids(x): return SetLongPrm(INF_HIGH_OFF,x) -def TailDepth(x): return SetLongPrm(INF_MAXREF,x) -def Analysis(x): return SetCharPrm(INF_AUTO,x) -def Tabs(x): return SetCharPrm(INF_ENTAB,x) -#def Comments(x): SetCharPrm(INF_CMTFLAG,((x) ? (SW_ALLCMT|GetCharPrm(INF_CMTFLAG)) : (~SW_ALLCMT&GetCharPrm(INF_CMTFLAG)))) -def Voids(x): return SetCharPrm(INF_VOIDS,x) -def XrefShow(x): return SetCharPrm(INF_XREFNUM,x) -def Indent(x): return SetCharPrm(INF_INDENT,x) -def CmtIndent(x): return SetCharPrm(INF_COMMENT,x) -def AutoShow(x): return SetCharPrm(INF_SHOWAUTO,x) -def MinEA(): return GetLongPrm(INF_MIN_EA) -def MaxEA(): return GetLongPrm(INF_MAX_EA) -def BeginEA(): return GetLongPrm(INF_BEGIN_EA) -def set_start_cs(x): return SetLongPrm(INF_START_CS,x) -def set_start_ip(x): return SetLongPrm(INF_START_IP,x) +def set_flag(off, bit, value): + v = get_inf_attr(off) + if value: + v = v | bit + else: + v = v & ~bit + set_inf_attr(off, v) -def WriteMap(filepath): - return GenerateFile(OFILE_MAP, filepath, 0, BADADDR, GENFLG_MAPSEG|GENFLG_MAPNAME) +#-------------------------------------------------------------------------- +# Compatibility macros (auto-generated part. Comes first so +# that any re-definition below will override auto-generated part) +if sys.modules["__main__"].IDAPYTHON_COMPAT_695_API: -def WriteTxt(filepath, ea1, ea2): - return GenerateFile(OFILE_ASM, filepath, ea1, ea2, 0) + # see header.i.in + bc695redef = ida_idaapi.bc695redef -def WriteExe(filepath): - return GenerateFile(OFILE_EXE, filepath, 0, BADADDR, 0) + # although many things have changed in the 'inf' structure, + # let's still try and do the best we can here even though + # some INF_* accessor enumerators don't exist anymore + GetCharPrm=get_inf_attr + GetLongPrm=get_inf_attr + GetShortPrm=get_inf_attr + SetCharPrm=set_inf_attr + SetLongPrm=set_inf_attr + SetShortPrm=set_inf_attr + + #-------------------------------------------------------------------------- + # Compatibility macros (non-auto-generated part) + def CompileEx(inp, isfile): return compile_idc_file(inp) if isfile else compile_idc_text(inp) + + def WriteMap(filepath): + return gen_file(OFILE_MAP, filepath, 0, BADADDR, GENFLG_MAPSEG|GENFLG_MAPNAME) + + def WriteTxt(filepath, ea1, ea2): + return gen_file(OFILE_ASM, filepath, ea1, ea2, 0) + + def WriteExe(filepath): + return gen_file(OFILE_EXE, filepath, 0, BADADDR, 0) + + UTP_STRUCT = ida_typeinf.UTP_STRUCT + UTP_ENUM = ida_typeinf.UTP_ENUM -UTP_STRUCT = ida_typeinf.UTP_STRUCT -UTP_ENUM = ida_typeinf.UTP_ENUM + def begin_type_updating(utp): + """ + Begin type updating. Use this function if you + plan to call AddEnumConst or similar type modification functions + many times or from inside a loop + + @param utp: one of UTP_xxxx consts + @return: None + """ + return ida_typeinf.begin_type_updating(utp) -def BeginTypeUpdating(utp): - """ - Begin type updating. Use this function if you - plan to call AddEnumConst or similar type modification functions - many times or from inside a loop + def end_type_updating(utp): + """ + End type updating. Refreshes the type system + at the end of type modification operations - @param utp: one of UTP_xxxx consts - @return: None - """ - return ida_typeinf.begin_type_updating(utp) + @param utp: one of ida_typeinf.UTP_xxxx consts + @return: None + """ + return ida_typeinf.end_type_updating(utp) + from idc_bc695 import * -def EndTypeUpdating(utp): - """ - End type updating. Refreshes the type system - at the end of type modification operations + SendDbgCommand=send_dbg_command - @param utp: one of ida_typeinf.UTP_xxxx consts - @return: None - """ - return ida_typeinf.end_type_updating(utp) - - -def AddConst(enum_id, name,value): return AddConstEx(enum_id, name, value, ida_idaapi.BADADDR) -def AddStruc(index, name): return AddStrucEx(index,name, 0) -def AddUnion(index, name): return AddStrucEx(index,name, 1) -def OpStroff(ea, n, strid): return OpStroffEx(ea,n,strid, 0) -def OpEnum(ea, n, enumid): return OpEnumEx(ea,n,enumid, 0) -def DelConst(constid, v, mask): return DelConstEx(constid, v, 0, mask) -def GetConst(constid, v, mask): return GetConstEx(constid, v, 0, mask) -def AnalyseArea(sEA, eEA): return AnalyzeArea(sEA,eEA) - -def MakeStruct(ea, name): return MakeStructEx(ea, -1, name) -def MakeCustomData(ea, size, dtid, fid): return MakeCustomDataEx(ea, size, dtid, fid) -def Name(ea): return NameEx(BADADDR, ea) -def GetTrueName(ea): return GetTrueNameEx(BADADDR, ea) -def MakeName(ea, name): return MakeNameEx(ea,name,SN_CHECK) - -#def GetFrame(ea): return GetFunctionAttr(ea, FUNCATTR_FRAME) -#def GetFrameLvarSize(ea): return GetFunctionAttr(ea, FUNCATTR_FRSIZE) -#def GetFrameRegsSize(ea): return GetFunctionAttr(ea, FUNCATTR_FRREGS) -#def GetFrameArgsSize(ea): return GetFunctionAttr(ea, FUNCATTR_ARGSIZE) -#def GetFunctionFlags(ea): return GetFunctionAttr(ea, FUNCATTR_FLAGS) -#def SetFunctionFlags(ea, flags): return SetFunctionAttr(ea, FUNCATTR_FLAGS, flags) - -#def SegStart(ea): return GetSegmentAttr(ea, SEGATTR_START) -#def SegEnd(ea): return GetSegmentAttr(ea, SEGATTR_END) -#def SetSegmentType(ea, type): return SetSegmentAttr(ea, SEGATTR_TYPE, type) - -def SegCreate(a1, a2, base, use32, align, comb): return AddSeg(a1, a2, base, use32, align, comb) -def SegDelete(ea, flags): return DelSeg(ea, flags) -def SegBounds(ea, startea, endea, flags): return SetSegBounds(ea, startea, endea, flags) -def SegRename(ea, name): return RenameSeg(ea, name) -def SegClass(ea, segclass): return SetSegClass(ea, segclass) -def SegAddrng(ea, bitness): return SetSegAddressing(ea, bitness) -def SegDefReg(ea, reg, value): return SetSegDefReg(ea, reg, value) - - -def Comment(ea): return GetCommentEx(ea, 0) -"""Returns the regular comment or None""" - -def RptCmt(ea): return GetCommentEx(ea, 1) -"""Returns the repeatable comment or None""" - -def SetReg(ea, reg, value): return SetRegEx(ea, reg, value, SR_user) + def MakeFunction(start, end=ida_idaapi.BADADDR): + return ida_funcs.add_func(start, end) + ApplyType = apply_type + GetManyBytes = get_bytes + GetString = get_strlit_contents + ClearTraceFile = clear_trace + FindBinary = find_binary + NextHead = next_head + ParseTypes = parse_decls + PrevHead = prev_head + ProcessUiAction = process_ui_action + SaveBase = save_database + Eval = eval_idc + def MakeStr(ea, endea): + return create_strlit(ea, endea) # Convenience functions: -def here(): return ScreenEA() -def isEnabled(ea): return (PrevAddr(ea+1)==ea) - -# Obsolete segdel macros: -SEGDEL_PERM = 0x0001 # permanently, i.e. disable addresses -SEGDEL_KEEP = 0x0002 # keep information (code & data, etc) -SEGDEL_SILENT = 0x0004 # be silent +def here(): return get_screen_ea() +def is_mapped(ea): return (prev_addr(ea+1)==ea) ARGV = [] """The command line arguments passed to IDA via the -S switch.""" diff --git a/python/init.py b/python/init.py index 3649343..8f818e9 100644 --- a/python/init.py +++ b/python/init.py @@ -17,7 +17,26 @@ import time import warnings # Prepare sys.path so loading of the shared objects works -sys.path.append(os.path.join(sys.executable, IDAPYTHON_DYNLOAD_BASE, "python", "lib", "python2.7", "lib-dynload", IDAPYTHON_DYNLOAD_RELPATH)) +lib_dynload = os.path.join( + sys.executable, + IDAPYTHON_DYNLOAD_BASE, + "python", "lib", "python2.7", "lib-dynload") + +is_x64 = sys.maxint >= 0x100000000L +if is_x64: + # x64 python requires our lib_dynload to be added; sys.path seems + # to be composed differently than x86 builds. + # In addition, we always want our own lib-dynload to come first: + # the PyQt (& sip) modules that might have to be loaded, should + # be the ones shipped with IDA and not those possibly available + # on the system. + sys.path.insert(0, os.path.join(lib_dynload, IDAPYTHON_DYNLOAD_RELPATH)) + sys.path.insert(0, lib_dynload) +else: + # for non-x64 platforms, make sure everything works as it used to, + # by appending our own lib-dynload to sys.argv.. + sys.path.append(os.path.join(lib_dynload, IDAPYTHON_DYNLOAD_RELPATH)) + try: import ida_idaapi import ida_kernwin @@ -40,7 +59,7 @@ class IDAPythonStdOut: """ def write(self, text): # NB: in case 'text' is Unicode, msg() will decode it - # and call umsg() to print it + # and call msg() to print it ida_kernwin.msg(text) def flush(self): @@ -88,7 +107,7 @@ sys.stdout = sys.stderr = IDAPythonStdOut() import pydoc class IDAPythonHelpPrompter: def readline(self): - return ida_kernwin.askstr(0, '', 'Help topic?') + return ida_kernwin.ask_str('', 0, 'Help topic?') help = pydoc.Helper(input = IDAPythonHelpPrompter(), output = sys.stdout) # Assign a default sys.argv @@ -110,7 +129,9 @@ if not IDAPYTHON_REMOVE_CWD_SYS_PATH: if IDAPYTHON_COMPAT_AUTOIMPORT_MODULES: # Import all the required modules - from idaapi import Choose, get_user_idadir, cvar, Choose2, Appcall, Form + from idaapi import get_user_idadir, cvar, Appcall, Form + if IDAPYTHON_COMPAT_695_API: + from idaapi import Choose2 from idc import * from idautils import * import idaapi diff --git a/pywraps.cpp b/pywraps.cpp index 4abd294..b05e7c3 100644 --- a/pywraps.cpp +++ b/pywraps.cpp @@ -6,6 +6,9 @@ #include "pywraps.hpp" +#undef hook_to_notification_point +#undef unhook_from_notification_point + //lint -esym(843,pywraps_initialized) could be declared const //lint -esym(843,g_nw) could be declared const //lint -esym(844,g_nw) could be declared const @@ -15,8 +18,8 @@ // String constants used static const char S_PY_IDCCVT_VALUE_ATTR[] = "__idc_cvt_value__"; static const char S_PY_IDCCVT_ID_ATTR[] = "__idc_cvt_id__"; -static const char S_PY_IDC_OPAQUE_T[] = "py_idc_cvt_helper_t"; static const char S_PY_IDC_GLOBAL_VAR_FMT[] = "__py_cvt_gvar_%d"; +#define S_PY_IDC_OPAQUE_T "py_idc_cvt_helper_t" // Constants used by get_idaapi_class_reference() #define PY_CLSID_CVT_INT64 0 @@ -133,12 +136,23 @@ ref_t ida_export PyW_IntVecToPyList(const intvec_t &intvec) } //--------------------------------------------------------------------------- -static int idaapi pylist_to_intvec_cb( +ref_t ida_export PyW_SizeVecToPyList(const sizevec_t &vec) +{ + size_t n = vec.size(); + PYW_GIL_CHECK_LOCKED_SCOPE(); + newref_t py_list(PyList_New(n)); + for ( size_t i = 0; i < n; ++i ) + PyList_SetItem(py_list.o, i, PyInt_FromSize_t(vec[i])); + return ref_t(py_list); +} + +//--------------------------------------------------------------------------- +static int idaapi pylist_to_sizevec_cb( const ref_t &py_item, Py_ssize_t /*index*/, void *ud) { - intvec_t &intvec = *(intvec_t *) ud; + sizevec_t &vec = *static_cast(ud); uint64 num; { PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -146,15 +160,15 @@ static int idaapi pylist_to_intvec_cb( num = 0; } - intvec.push_back(int(num)); + vec.push_back(size_t(num)); return CIP_OK; } //--------------------------------------------------------------------------- -bool ida_export PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec) +bool ida_export PyW_PyListToSizeVec(PyObject *py_list, sizevec_t &vec) { - intvec.clear(); - return pyvar_walk_list(py_list, pylist_to_intvec_cb, &intvec) != CIP_FAILED; + vec.clear(); + return pyvar_walk_list(py_list, pylist_to_sizevec_cb, &vec) != CIP_FAILED; } //------------------------------------------------------------------------- @@ -231,24 +245,24 @@ bool ida_export PyWStringOrNone_Check(PyObject *tp) } //------------------------------------------------------------------------- -PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &areas) +PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &ranges) { PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_list = PyList_New(areas.size()); - meminfo_vec_t::const_iterator it, it_end(areas.end()); + PyObject *py_list = PyList_New(ranges.size()); + meminfo_vec_t::const_iterator it, it_end(ranges.end()); Py_ssize_t i = 0; - for ( it=areas.begin(); it != it_end; ++it, ++i ) + for ( it=ranges.begin(); it != it_end; ++it, ++i ) { const memory_info_t &mi = *it; - // startEA endEA name sclass sbase bitness perm + // start_ea end_ea name sclass sbase bitness perm PyList_SetItem(py_list, i, - Py_BuildValue("(" PY_FMT64 PY_FMT64 "ss" PY_FMT64 "II)", - pyul_t(mi.startEA), - pyul_t(mi.endEA), + Py_BuildValue("(" PY_BV_EA PY_BV_EA "ss" PY_BV_EA "II)", + bvea_t(mi.start_ea), + bvea_t(mi.end_ea), mi.name.c_str(), mi.sclass.c_str(), - pyul_t(mi.sbase), + bvea_t(mi.sbase), (unsigned int)(mi.bitness), (unsigned int)mi.perm)); } @@ -332,18 +346,18 @@ static bool wrap_PyObject_ptr(const ref_t &py_var, idc_value_t *idc_var) PYW_GIL_CHECK_LOCKED_SCOPE(); // Create an IDC object of this special helper class - if ( VarObject(idc_var, get_py_idc_cvt_opaque()) != eOk ) + if ( idcv_object(idc_var, get_py_idc_cvt_opaque()) != eOk ) return false; // Store the CVT id idc_value_t idc_val; idc_val.set_long(PY_ICID_OPAQUE); - VarSetAttr(idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val); + set_idcv_attr(idc_var, S_PY_IDCCVT_ID_ATTR, idc_val); // Store the value as a PVOID referencing the given Python object py_var.incref(); idc_val.set_pvoid(py_var.o); - VarSetAttr(idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val); + set_idcv_attr(idc_var, S_PY_IDCCVT_VALUE_ATTR, idc_val); return true; } @@ -351,10 +365,9 @@ static bool wrap_PyObject_ptr(const ref_t &py_var, idc_value_t *idc_var) //------------------------------------------------------------------------ // IDC Opaque object destructor: when the IDC object dies we kill the // opaque Python object along with it -static const char py_idc_cvt_helper_dtor_args[] = { VT_OBJ, 0 }; static error_t idaapi py_idc_opaque_dtor( - idc_value_t *argv, - idc_value_t * /*res*/) + idc_value_t *argv, + idc_value_t * /*res*/) { // This can be called at plugin registration time, when a // 'script_plugin_t' instance is ::free()'d. It is @@ -363,16 +376,28 @@ static error_t idaapi py_idc_opaque_dtor( // Get the value from the object idc_value_t idc_val; - VarGetAttr(&argv[0], S_PY_IDCCVT_VALUE_ATTR, &idc_val); + get_idcv_attr(&idc_val, &argv[0], S_PY_IDCCVT_VALUE_ATTR); // Extract the Python object reference PyObject *py_obj = (PyObject *)idc_val.pvoid; // Decrease its reference (and eventually destroy it) - Py_DECREF(py_obj); - + { + uninterruptible_op_t op; + Py_DECREF(py_obj); + } return eOk; } +static const char py_idc_cvt_helper_dtor_args[] = { VT_OBJ, 0 }; +static const ext_idcfunc_t opaque_dtor_desc = +{ + S_PY_IDC_OPAQUE_T ".dtor_name", + py_idc_opaque_dtor, + py_idc_cvt_helper_dtor_args, + NULL, + 0, + 0 +}; //------------------------------------------------------------------------- // Converts a Python variable into an IDC variable @@ -420,7 +445,7 @@ int ida_export pyvar_to_idcvar( else if ( PyList_CheckExact(py_var.o) || PyW_IsSequenceType(py_var.o) ) { // Create the object - VarObject(idc_var); + idcv_object(idc_var); // Determine list size and type bool is_seq = !PyList_CheckExact(py_var.o); @@ -449,7 +474,7 @@ int ida_export pyvar_to_idcvar( if ( !ok ) break; // Store the attribute - VarSetAttr(idc_var, attr_name.c_str(), &v); + set_idcv_attr(idc_var, attr_name.c_str(), v); } if ( !ok ) break; @@ -460,7 +485,7 @@ int ida_export pyvar_to_idcvar( else if ( PyDict_Check(py_var.o) ) { // Create an empty IDC object - VarObject(idc_var); + idcv_object(idc_var); // Get the dict.items() list newref_t py_items(PyDict_Items(py_var.o)); @@ -487,7 +512,7 @@ int ida_export pyvar_to_idcvar( if ( ok ) { // Store the attribute - VarSetAttr(idc_var, key_name.c_str(), &v); + set_idcv_attr(idc_var, key_name.c_str(), v); } if ( !ok ) break; @@ -547,7 +572,7 @@ int ida_export pyvar_to_idcvar( { (*gvar_sn)++; // Create a reference to this global variable - VarRef(idc_var, gvar); + create_idcv_ref(idc_var, gvar); } return ok ? CIP_OK : CIP_FAILED; } @@ -570,7 +595,7 @@ int ida_export pyvar_to_idcvar( if ( py_dir == NULL || !PyList_Check(py_dir.o) || size == 0 ) return CIP_FAILED; // Create the IDC object - VarObject(idc_var); + idcv_object(idc_var); for ( Py_ssize_t i=0; i < size; i++ ) { borref_t item(PyList_GetItem(py_dir.o, i)); @@ -599,7 +624,7 @@ int ida_export pyvar_to_idcvar( } // Store the attribute - VarSetAttr(idc_var, field_name, &v); + set_idcv_attr(idc_var, field_name, v); } } } @@ -623,8 +648,9 @@ inline PyObject *cvt_to_pylong(int64 v) // If py_var points to an existing immutable object then ZERO is returned // Returns one of CIP_xxxx. Check pywraps.hpp int ida_export idcvar_to_pyvar( - const idc_value_t &idc_var, - ref_t *py_var) + const idc_value_t &idc_var, + ref_t *py_var, + uint32 flags) { PYW_GIL_CHECK_LOCKED_SCOPE(); switch ( idc_var.vtype ) @@ -643,33 +669,37 @@ int ida_export idcvar_to_pyvar( case VT_INT64: { - // Recycle? - if ( *py_var != NULL ) + bool as_pylong = (flags & PYWCVTF_INT64_AS_UNSIGNED_PYLONG) != 0; + if ( as_pylong ) { - // Recycling an int64 object? - int t = get_pyidc_cvt_type(py_var->o); - if ( t != PY_ICID_INT64 ) - return CIP_IMMUTABLE; // Cannot recycle immutable object - // Update the attribute - PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64)); + QASSERT(30513, *py_var == NULL); // recycling not supported in this case + *py_var = newref_t(PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) idc_var.i64)); return CIP_OK; } - ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_INT64)); - if ( py_cls == NULL ) - return CIP_FAILED; - *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, PyLong_FromLongLong(idc_var.i64), NULL)); - if ( PyW_GetError() || *py_var == NULL ) - return CIP_FAILED; + else + { + // Recycle? + if ( *py_var != NULL ) + { + // Recycling an int64 object? + int t = get_pyidc_cvt_type(py_var->o); + if ( t != PY_ICID_INT64 ) + return CIP_IMMUTABLE; // Cannot recycle immutable object + // Update the attribute + PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64)); + return CIP_OK; + } + ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_INT64)); + if ( py_cls == NULL ) + return CIP_FAILED; + *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, PyLong_FromLongLong(idc_var.i64), NULL)); + if ( PyW_GetError() || *py_var == NULL ) + return CIP_FAILED; + } break; } -#if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC) case VT_STR: - *py_var = newref_t(PyString_FromString(idc_var.str)); - break; - -#endif - case VT_STR2: if ( *py_var == NULL ) { const qstring &s = idc_var.qstr(); @@ -688,7 +718,7 @@ int ida_export idcvar_to_pyvar( if ( *py_var == NULL ) { double x; - if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 0 ) + if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 1 ) INTERR(30160); *py_var = newref_t(PyFloat_FromDouble(x)); @@ -716,7 +746,7 @@ int ida_export idcvar_to_pyvar( // Dereference // (Since we are not using VREF_COPY flag, we can safely const_cast) - idc_value_t *dref_v = VarDeref(const_cast(&idc_var), VREF_LOOP); + idc_value_t *dref_v = deref_idcv(const_cast(&idc_var), VREF_LOOP); if ( dref_v == NULL ) return CIP_FAILED; @@ -749,8 +779,8 @@ int ida_export idcvar_to_pyvar( { // Check if this IDC object has __cvt_id__ and the __idc_cvt_value__ fields idc_value_t idc_val; - if ( VarGetAttr(&idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val) == eOk - && VarGetAttr(&idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val) == eOk ) + if ( get_idcv_attr(&idc_val, &idc_var, S_PY_IDCCVT_ID_ATTR) == eOk + && get_idcv_attr(&idc_val, &idc_var, S_PY_IDCCVT_VALUE_ATTR) == eOk ) { // Extract the object *py_var = borref_t((PyObject *) idc_val.pvoid); @@ -781,13 +811,13 @@ int ida_export idcvar_to_pyvar( } // Walk the IDC attributes and store into python - for ( const char *attr_name = VarFirstAttr(&idc_var); + for ( const char *attr_name = first_idcv_attr(&idc_var); attr_name != NULL; - attr_name = VarNextAttr(&idc_var, attr_name) ) + attr_name = next_idcv_attr(&idc_var, attr_name) ) { // Get the attribute idc_value_t v; - VarGetAttr(&idc_var, attr_name, &v, true); + get_idcv_attr(&v, &idc_var, attr_name, true); // Convert attribute to a python value (recursively) ref_t py_attr; @@ -817,9 +847,8 @@ bool ida_export pyw_convert_idc_args( const idc_value_t args[], int nargs, ref_vec_t &pargs, - bool as_tupple, - char *errbuf, - size_t errbufsize) + uint32 flags, + qstring *errbuf) { PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -827,13 +856,14 @@ bool ida_export pyw_convert_idc_args( pargs.qclear(); - if ( as_tupple ) + bool as_tuple = (flags & PYWCVTF_AS_TUPLE) != 0; + if ( as_tuple ) { py_tuple = newref_t(PyTuple_New(nargs)); if ( py_tuple == NULL ) { - if ( errbuf != 0 && errbufsize > 0 ) - qstrncpy(errbuf, "Failed to create a new tuple to store arguments!", errbufsize); + if ( errbuf != NULL ) + *errbuf = "Failed to create a new tuple to store arguments!"; return false; } } @@ -841,15 +871,15 @@ bool ida_export pyw_convert_idc_args( for ( int i=0; i < nargs; i++ ) { ref_t py_obj; - int cvt = idcvar_to_pyvar(args[i], &py_obj); + int cvt = idcvar_to_pyvar(args[i], &py_obj, flags); if ( cvt < CIP_OK ) { - if ( errbuf != 0 && errbufsize > 0 ) - qsnprintf(errbuf, errbufsize, "arg#%d has wrong type %d", i, args[i].vtype); + if ( errbuf != NULL ) + errbuf->sprnt("arg#%d has wrong type %d", i, args[i].vtype); return false; } - if ( as_tupple ) + if ( as_tuple ) { // PyTuple_SetItem() steals the reference. py_obj.incref(); @@ -864,7 +894,7 @@ bool ida_export pyw_convert_idc_args( // Add the tuple to the list of args only now. Doing so earlier will // cause the py_tuple.o->ob_refcnt to be 2 and not 1, and that will // cause 'PyTuple_SetItem()' to fail. - if ( as_tupple ) + if ( as_tuple ) pargs.push_back(py_tuple); return true; @@ -921,12 +951,12 @@ static bool pywraps_check_autoscripts(char *buf, size_t bufsize) error_t ida_export PyW_CreateIdcException(idc_value_t *res, const char *msg) { // Create exception object - VarObject(res, find_idc_class("exception")); + idcv_object(res, find_idc_class("exception")); // Set the message field idc_value_t v; v.set_string(msg); - VarSetAttr(res, "message", &v); + set_idcv_attr(res, "message", v); // Throw exception return set_qerrno(eExecThrow); @@ -934,10 +964,9 @@ error_t ida_export PyW_CreateIdcException(idc_value_t *res, const char *msg) //------------------------------------------------------------------------ // Calls a Python callable encoded in IDC.pvoid member -static const char idc_py_invoke0_args[] = { VT_PVOID, 0 }; static error_t idaapi idc_py_invoke0( - idc_value_t *argv, - idc_value_t *res) + idc_value_t *argv, + idc_value_t *res) { PYW_GIL_GET; PyObject *pyfunc = (PyObject *) argv[0].pvoid; @@ -950,6 +979,11 @@ static error_t idaapi idc_py_invoke0( err_code = PyW_CreateIdcException(res, err.c_str()); return err_code; } +static const char idc_py_invoke0_args[] = { VT_PVOID, 0 }; +static const ext_idcfunc_t idc_py_invoke0_desc = +{ + S_PYINVOKE0, idc_py_invoke0, idc_py_invoke0_args, NULL, 0, 0 +}; //------------------------------------------------------------------------ // This function must be called on initialization @@ -969,7 +1003,7 @@ static bool init_pywraps() } // Register the IDC PyInvoke0 method (helper function for add_idc_hotkey()) - if ( !set_idc_func_ex(S_PYINVOKE0, idc_py_invoke0, idc_py_invoke0_args, 0) ) + if ( !add_idc_func(idc_py_invoke0_desc) ) return false; // IDC opaque class not registered? @@ -980,16 +1014,12 @@ static bool init_pywraps() if ( idc_cvt_opaque == NULL ) return false; - // Form the dtor name - char dtor_name[MAXSTR]; - qsnprintf(dtor_name, sizeof(dtor_name), "%s.dtor", S_PY_IDC_OPAQUE_T); - // Register the dtor function - if ( !set_idc_func_ex(dtor_name, py_idc_opaque_dtor, py_idc_cvt_helper_dtor_args, 0) ) + if ( !add_idc_func(opaque_dtor_desc) ) return false; // Link the dtor function to the class - set_idc_dtor(idc_cvt_opaque, dtor_name); + set_idc_dtor(idc_cvt_opaque, opaque_dtor_desc.name); } pywraps_initialized = true; @@ -1011,7 +1041,7 @@ static void deinit_pywraps() } // Unregister the IDC PyInvoke0 method (helper function for add_idc_hotkey()) - set_idc_func_ex(S_PYINVOKE0, NULL, idc_py_invoke0_args, 0); + del_idc_func(idc_py_invoke0_desc.name); } //------------------------------------------------------------------------ @@ -1071,9 +1101,9 @@ static ref_t get_idaapi_attr(const char *attrname) //------------------------------------------------------------------------ // Returns a qstring from an object attribute bool ida_export PyW_GetStringAttr( - PyObject *py_obj, - const char *attr_name, - qstring *str) + PyObject *py_obj, + const char *attr_name, + qstring *str) { PYW_GIL_CHECK_LOCKED_SCOPE(); ref_t py_attr(PyW_TryGetAttrString(py_obj, attr_name)); @@ -1112,44 +1142,26 @@ ref_t ida_export PyW_TryImportModule(const char *name) //------------------------------------------------------------------------- // Converts a Python number into an IDC value (32 or 64bits) -// The function will first try to convert the number into a 32bit value +// The function will try to convert the number into a 32bit value // If the number does not fit then VT_INT64 will be used -// NB: This function cannot properly detect if the Python value should be -// converted to a VT_INT64 or not. For example: 2**32-1 = 0xffffffff which -// can fit in a C long but Python creates a PyLong object for it. -// And because of that we are confused as to whether to convert to 32 or 64 bool ida_export PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var) { PYW_GIL_CHECK_LOCKED_SCOPE(); - bool rc = true; - do - { - if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) ) - { - rc = false; - break; - } + if ( !(PyInt_CheckExact(py_var) || PyLong_CheckExact(py_var)) ) + return false; - // Can we convert to C long? - long l = PyInt_AsLong(py_var); - if ( !PyErr_Occurred() ) - { - idc_var->set_long(l); - break; - } - // Clear last error - PyErr_Clear(); - // Can be fit into a C unsigned long? - l = (long) PyLong_AsUnsignedLong(py_var); - if ( !PyErr_Occurred() ) - { - idc_var->set_long(l); - break; - } - PyErr_Clear(); - idc_var->set_int64(PyLong_AsLongLong(py_var)); - } while ( false ); - return rc; + PY_LONG_LONG pyll = PyLong_AsLongLong(py_var); + if ( PyErr_Occurred() ) + return false; + + bool as_i64 = pyll >= 0 + ? pyll > (PY_LONG_LONG) SVAL_MAX + : pyll < (PY_LONG_LONG) SVAL_MIN; + if ( as_i64 ) + idc_var->set_int64(int64(pyll)); + else + idc_var->set_long(sval_t(pyll)); + return true; } //------------------------------------------------------------------------- @@ -1386,13 +1398,13 @@ void *ida_export pyobj_get_clink(PyObject *pyobj) } //------------------------------------------------------------------------ -int idaapi pywraps_notify_when_t::idp_callback(void *ud, int event_id, va_list va) +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::newfile: - case processor_t::oldfile: + 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 @@ -1400,12 +1412,23 @@ int idaapi pywraps_notify_when_t::idp_callback(void *ud, int event_id, va_list v // 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::oldfile ? 1 : 0; + int old = event_id == processor_t::ev_oldfile ? 1 : 0; char *dbname = va_arg(va, char *); _this->notify(NW_OPENIDB_SLOT, old); } break; - case processor_t::closebase: + } + // 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); @@ -1466,6 +1489,7 @@ void pywraps_notify_when_t::unregister_callback(int slot, PyObject *py_callable) 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); } //------------------------------------------------------------------------ @@ -1479,7 +1503,8 @@ bool pywraps_notify_when_t::deinit() unregister_callback(slot, it->o); } // ...and remove the notification - return unhook_from_notification_point(HT_IDP, idp_callback, this); + bool ok = unhook_from_notification_point(HT_IDP, idp_callback, this); + return unhook_from_notification_point(HT_IDB, idb_callback, this) && ok; } //------------------------------------------------------------------------ @@ -1565,7 +1590,6 @@ bool pywraps_notify_when_t::notify_va(int slot, va_list va) ok = false; } } - in_notify = false; // Process any delayed notify_when() calls that @@ -1651,61 +1675,51 @@ static bool pywraps_nw_term() //------------------------------------------------------------------------- lookup_entry_t &ida_export lookup_info_t_new_entry(lookup_info_t *_this, py_customidamemo_t *py_view) { - QASSERT(30454, py_view != NULL && !_this->find_by_py_view(NULL, NULL, py_view)); + QASSERT(30454, py_view != NULL && !_this->find_by_py_view(NULL, py_view)); lookup_entry_t &e = _this->entries.push_back(); e.py_view = py_view; return e; } //------------------------------------------------------------------------- -void ida_export lookup_info_t_commit(lookup_info_t *_this, lookup_entry_t &e, TForm *form, TCustomControl *view) +void ida_export lookup_info_t_commit(lookup_info_t *_this, lookup_entry_t &e, TWidget *view) { QASSERT(30455, &e >= _this->entries.begin() && &e < _this->entries.end()); - QASSERT(30456, form != NULL && view != NULL && e.py_view != NULL - && !_this->find_by_form(NULL, NULL, form) - && !_this->find_by_view(NULL, NULL, view) - && _this->find_by_py_view(NULL, NULL, e.py_view)); - e.form = form; + QASSERT(30456, view != NULL && e.py_view != NULL + && !_this->find_by_view(NULL, view) + && _this->find_by_py_view(NULL, e.py_view)); e.view = view; } //------------------------------------------------------------------------- -#define FIND_BY__BODY(self, crit, res1, res2) \ - { \ - for ( lookup_entries_t::const_iterator it = self->entries.begin(); it != self->entries.end(); ++it ) \ - { \ - const lookup_entry_t &e = *it; \ - if ( e.crit == crit ) \ - { \ - if ( out_##res1 != NULL ) \ - *out_##res1 = e.res1; \ - if ( out_##res2 != NULL ) \ - *out_##res2 = e.res2; \ - return true; \ - } \ - } \ - return false; \ - } - -bool ida_export lookup_info_t_find_by_form( - const lookup_info_t *_this, - TCustomControl **out_view, - py_customidamemo_t **out_py_view, - const TForm *form) - FIND_BY__BODY(_this, form, view, py_view); +#define FIND_BY__BODY(self, crit, res) \ + for ( lookup_entries_t::const_iterator it = self->entries.begin(); it != self->entries.end(); ++it ) \ + { \ + const lookup_entry_t &e = *it; \ + if ( e.crit == crit ) \ + { \ + if ( out_##res != NULL ) \ + *out_##res = e.res; \ + return true; \ + } \ + } \ + return false; \ bool ida_export lookup_info_t_find_by_py_view( const lookup_info_t *_this, - TForm **out_form, - TCustomControl **out_view, + TWidget **out_view, const py_customidamemo_t *py_view) - FIND_BY__BODY(_this, py_view, view, form); +{ + FIND_BY__BODY(_this, py_view, view); +} -bool lookup_info_t::find_by_view( - TForm **out_form, +bool ida_export lookup_info_t_find_by_view( + const lookup_info_t *_this, py_customidamemo_t **out_py_view, - const TCustomControl *view) const - FIND_BY__BODY(this, view, form, py_view); + const TWidget *view) +{ + FIND_BY__BODY(_this, view, py_view); +} #undef FIND_BY__BODY //------------------------------------------------------------------------- @@ -1759,77 +1773,6 @@ void py_customidamemo_t::convert_node_info( #undef COPY_PROP } -//------------------------------------------------------------------------- -void ida_export py_customidamemo_t_ensure_view_callbacks_installed() -{ - static bool installed = false; - if ( !installed ) - { - struct ida_local lambda_t - { - static int idaapi callback(void * /*ud*/, int code, va_list va) - { - py_customidamemo_t *py_view; - if ( pycim_lookup_info.find_by_view(NULL, &py_view, va_arg(va, TCustomControl *)) ) - { - PYW_GIL_GET; - switch ( code ) - { - case view_activated: - py_view->on_view_activated(); - break; - case view_deactivated: - py_view->on_view_deactivated(); - break; - case view_keydown: - { - int key = va_arg(va, int); - int state = va_arg(va, int); - py_view->on_view_keydown(key, state); - } - break; - case obsolete_view_popup: - py_view->on_view_popup(); - break; - case view_click: - case view_dblclick: - { - const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*); - if ( code == view_click ) - py_view->on_view_click(event); - else - py_view->on_view_dblclick(event); - } - break; - case view_curpos: - py_view->on_view_curpos(); - break; - case view_close: - py_view->on_view_close(); - delete py_view; - break; - case view_switched: - { - tcc_renderer_type_t rt = (tcc_renderer_type_t) va_arg(va, int); - py_view->on_view_switched(rt); - } - break; - case view_mouse_over: - { - const view_mouse_event_t *event = va_arg(va, view_mouse_event_t*); - py_view->on_view_mouse_over(event); - } - break; - } - } - return 0; - } - }; - hook_to_notification_point(HT_VIEW, lambda_t::callback, NULL); - installed = true; - } -} - //------------------------------------------------------------------------- void ida_export py_customidamemo_t_set_node_info( py_customidamemo_t *_this, @@ -2028,11 +1971,11 @@ PyObject *ida_export py_customidamemo_t_set_groups_visibility( } //------------------------------------------------------------------------- -bool ida_export py_customidamemo_t_bind(py_customidamemo_t *_this, PyObject *self, TCustomControl *view) +bool ida_export py_customidamemo_t_bind(py_customidamemo_t *_this, PyObject *self, TWidget *view) { if ( _this->self != NULL || _this->view != NULL ) return false; - PYGLOG("%p: py_customidamemo_t::bind(self=%p, view=%p)\n", this, _this->_self, _this->view); + PYGLOG("%p: py_customidamemo_t::bind(self=%p, view=%p)\n", _this, _this->self.o, _this->view); PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_cobj(PyCObject_FromVoidPtr(_this, NULL)); @@ -2057,50 +2000,11 @@ void ida_export py_customidamemo_t_unbind(py_customidamemo_t *_this, bool clear_ _this->view = NULL; } -//------------------------------------------------------------------------- -void idaapi py_customidamemo_t::s_on_view_mouse_moved( - TCustomControl *cv, - int shift, - view_mouse_event_t *e, - void *ud) -{ - PYW_GIL_GET; - py_customidamemo_t *_this = (py_customidamemo_t *) ud; - _this->on_view_mouse_moved(e); -} - -//------------------------------------------------------------------------- -int py_customidamemo_t::get_py_method_arg_count(char *method_name) -{ - newref_t method(PyObject_GetAttrString(self.o, method_name)); - if ( method != NULL && PyCallable_Check(method.o) ) - { - newref_t fc(PyObject_GetAttrString(method.o, "func_code")); - if ( fc != NULL ) - { - newref_t ac(PyObject_GetAttrString(fc.o, "co_argcount")); - if ( ac != NULL ) - return PyInt_AsLong(ac.o); - } - } - return -1; -} - //------------------------------------------------------------------------- void ida_export py_customidamemo_t_collect_class_callbacks_ids( py_customidamemo_t *_this, pycim_callbacks_ids_t *out) { - out->add(S_ON_VIEW_ACTIVATED, _this->GRBASE_HAVE_VIEW_ACTIVATED); - out->add(S_ON_VIEW_DEACTIVATED, _this->GRBASE_HAVE_VIEW_DEACTIVATED); - out->add(S_ON_VIEW_KEYDOWN, _this->GRBASE_HAVE_KEYDOWN); - out->add(S_ON_POPUP, _this->GRBASE_HAVE_POPUP); - out->add(S_ON_VIEW_CLICK, _this->GRBASE_HAVE_VIEW_CLICK); - out->add(S_ON_VIEW_DBLCLICK, _this->GRBASE_HAVE_VIEW_DBLCLICK); - out->add(S_ON_VIEW_CURPOS, _this->GRBASE_HAVE_VIEW_CURPOS); - out->add(S_ON_CLOSE, _this->GRBASE_HAVE_CLOSE); - out->add(S_ON_VIEW_SWITCHED, _this->GRBASE_HAVE_VIEW_SWITCHED); - out->add(S_ON_VIEW_MOUSE_OVER, _this->GRBASE_HAVE_VIEW_MOUSE_OVER); out->add(S_ON_VIEW_MOUSE_MOVED, _this->GRBASE_HAVE_VIEW_MOUSE_MOVED); } @@ -2131,275 +2035,6 @@ bool ida_export py_customidamemo_t_collect_pyobject_callbacks( return true; } -//------------------------------------------------------------------------- -void ida_export py_customidamemo_t_install_custom_viewer_handlers( - py_customidamemo_t *_this) -{ - if ( _this->has_callback(_this->GRBASE_HAVE_VIEW_MOUSE_MOVED) ) - { - // Set user-data - set_custom_viewer_handler(_this->view, CVH_USERDATA, (void *)_this); - - // - set_custom_viewer_handler(_this->view, CVH_MOUSEMOVE, (void *) py_customidamemo_t::s_on_view_mouse_moved); - } -} - -//------------------------------------------------------------------------- -#define CHK_EVT(flag_needed) \ - if ( self == NULL || !has_callback(flag_needed) ) \ - return; \ - PYW_GIL_CHECK_LOCKED_SCOPE() - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_activated() -{ - CHK_EVT(GRBASE_HAVE_VIEW_ACTIVATED); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_ACTIVATED, - NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_deactivated() -{ - CHK_EVT(GRBASE_HAVE_VIEW_DEACTIVATED); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_DEACTIVATED, - NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_keydown(int key, int state) -{ - CHK_EVT(GRBASE_HAVE_KEYDOWN); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_KEYDOWN, - "ii", - key, state)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_popup() -{ - CHK_EVT(GRBASE_HAVE_POPUP); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_POPUP, - NULL)); -} - -//------------------------------------------------------------------------- -static PyObject *build_renderer_pos_swig_proxy(const view_mouse_event_t *event) -{ - newref_t py_module(PyImport_ImportModule(S_IDA_KERNWIN_MODNAME)); - ref_t py_result; - if ( py_module != NULL ) - { - ref_t py_class = PyW_TryGetAttrString(py_module.o, "renderer_pos_info_t"); - if ( py_class != NULL ) - { - ref_t py_obj = newref_t(PyObject_CallFunctionObjArgs(py_class.o, NULL)); - if ( py_obj != NULL ) - { - newref_t py_node(PyInt_FromLong(event->renderer_pos.node)); - PyObject_SetAttrString(py_obj.o, "node", py_node.o); - newref_t py_cx(PyInt_FromLong(event->renderer_pos.cx)); - PyObject_SetAttrString(py_obj.o, "cx", py_cx.o); - newref_t py_cy(PyInt_FromLong(event->renderer_pos.cy)); - PyObject_SetAttrString(py_obj.o, "cy", py_cy.o); - newref_t py_sx(PyInt_FromLong(event->renderer_pos.sx)); - PyObject_SetAttrString(py_obj.o, "sx", py_sx.o); - py_result = py_obj; - } - } - } - if ( py_result != NULL ) - { - py_result.incref(); - return py_result.o; - } - else - { - return NULL; - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_click(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_CLICK); - if ( ovc_num_args < 0 ) - ovc_num_args = get_py_method_arg_count((char*)S_ON_VIEW_CLICK); - if ( ovc_num_args == 6 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CLICK, - "iiiiO", - event->x, event->y, event->state, event->button, rpos)); - } - else if ( ovc_num_args == 5 ) - { - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CLICK, - "iiii", - event->x, event->y, event->state, event->button)); - } - else - { - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CLICK, - "iii", - event->x, event->y, event->state)); - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_dblclick(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_DBLCLICK); - if ( ovdc_num_args < 0 ) - ovdc_num_args = get_py_method_arg_count((char*)S_ON_VIEW_DBLCLICK); - if ( ovdc_num_args == 5 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_DBLCLICK, - "iiiO", - event->x, event->y, event->state, rpos)); - } - else - { - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_DBLCLICK, - "iii", - event->x, event->y, event->state)); - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_curpos() -{ - CHK_EVT(GRBASE_HAVE_VIEW_CURPOS); - pycall_res_t result( - PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_CURPOS, - NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_close() -{ - CHK_EVT(GRBASE_HAVE_CLOSE); - pycall_res_t result(PyObject_CallMethod(self.o, (char *)S_ON_CLOSE, NULL)); -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_switched(tcc_renderer_type_t rt) -{ - CHK_EVT(GRBASE_HAVE_VIEW_SWITCHED); - pycall_res_t result(PyObject_CallMethod(self.o, (char *)S_ON_VIEW_SWITCHED, "i", int(rt))); -} - -//------------------------------------------------------------------------- -static ref_t build_current_graph_item_tuple(int *out_icode, const view_mouse_event_t *event) -{ - const selection_item_t *item = event->location.item; - ref_t tuple; - if ( (event->rtype == TCCRT_GRAPH || event->rtype == TCCRT_PROXIMITY) - && item != NULL ) - { - if ( item->is_node ) - { - *out_icode = 1; - tuple = newref_t(Py_BuildValue("(i)", item->node)); - } - else - { - *out_icode = 2; - tuple = newref_t(Py_BuildValue("(ii)", item->elp.e.src, item->elp.e.dst)); - } - } - else - { - *out_icode = 0; - tuple = newref_t(Py_BuildValue("()")); - } - return tuple; -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_mouse_over(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_MOUSE_OVER); - if ( ovmo_num_args < 0 ) - ovmo_num_args = get_py_method_arg_count((char*)S_ON_VIEW_MOUSE_OVER); - if ( event->rtype != TCCRT_GRAPH && event->rtype != TCCRT_PROXIMITY ) - return; - - int icode; - ref_t tuple = build_current_graph_item_tuple(&icode, event); - if ( ovmo_num_args == 7 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result(PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_MOUSE_OVER, - "iiiiOO", - event->x, event->y, event->state, icode, tuple.o, rpos)); - } - else - { - pycall_res_t result(PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_MOUSE_OVER, - "iiiiO", - event->x, event->y, event->state, icode, tuple.o)); - } -} - -//------------------------------------------------------------------------- -void py_customidamemo_t::on_view_mouse_moved(const view_mouse_event_t *event) -{ - CHK_EVT(GRBASE_HAVE_VIEW_MOUSE_MOVED); - if ( ovmm_num_args < 0 ) - ovmm_num_args = get_py_method_arg_count((char*)S_ON_VIEW_MOUSE_MOVED); - - int icode; - ref_t tuple = build_current_graph_item_tuple(&icode, event); - if ( ovmm_num_args == 7 ) - { - PyObject *rpos = build_renderer_pos_swig_proxy(event); - pycall_res_t result(PyObject_CallMethod( - self.o, - (char *)S_ON_VIEW_MOUSE_MOVED, - "iiiiOO", - event->x, event->y, event->state, icode, tuple.o, rpos)); - } -} - - -#undef CHK_EVT - //------------------------------------------------------------------------- // //------------------------------------------------------------------------- @@ -2476,6 +2111,7 @@ DEF_REG_UNREG_REFCOUNTED(array_type_data_t); DEF_REG_UNREG_REFCOUNTED(func_type_data_t); DEF_REG_UNREG_REFCOUNTED(udt_type_data_t); + //------------------------------------------------------------------------- // //--------------------------------------------------------------------------- @@ -2511,4 +2147,89 @@ static void clear_python_timer_instances(void) } } +//------------------------------------------------------------------------- +ref_t ida_export try_create_swig_wrapper(ref_t mod, const char *clsname, void *cobj) +{ + qstring wname; + wname.sprnt("%s__from_ptrval__", clsname); + ref_t res; + ref_t py_cls_wrapper_inst(PyW_TryGetAttrString(mod.o, wname.c_str())); + if ( py_cls_wrapper_inst != NULL ) + { + uninterruptible_op_t op; + res = newref_t(PyObject_CallFunction(py_cls_wrapper_inst.o, "(K)", uint64(cobj))); + } + return res; +} + +//------------------------------------------------------------------------- +typedef qvector modules_callbacks_t; +static modules_callbacks_t modules_callbacks; +void register_module_lifecycle_callbacks( + const module_callbacks_t &cbs) +{ + modules_callbacks.push_back(cbs); +} + +//------------------------------------------------------------------------- +// hooks +//------------------------------------------------------------------------- +#ifdef TESTABLE_BUILD +struct hook_data_t +{ + hook_type_t type; + hook_cb_t *cb; + void *ud; +}; +DECLARE_TYPE_AS_MOVABLE(hook_data_t); +typedef qvector 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) +{ + 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; + } +#endif // TESTABLE_BUILD + return ok; +} + +//------------------------------------------------------------------------- +bool ida_export idapython_unhook_from_notification_point( + hook_type_t hook_type, + hook_cb_t *cb, + void *user_data) +{ + bool ok = unhook_from_notification_point(hook_type, cb, user_data); +#ifdef TESTABLE_BUILD + if ( ok ) + { + bool found = false; + for ( size_t i = 0, n = hook_data_vec.size(); i < n; ++i ) + { + const hook_data_t &hd = hook_data_vec[i]; + if ( hd.type == hook_type && hd.cb == cb && hd.ud == user_data ) + { + hook_data_vec.erase(hook_data_vec.begin() + i); + found = true; + break; + } + } + QASSERT(30510, found); + } +#endif // TESTABLE_BUILD + return ok; +} + #undef DEF_REG_UNREG_REFCOUNTED diff --git a/pywraps.hpp b/pywraps.hpp index afe7760..0d0ee40 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -4,22 +4,27 @@ #include //------------------------------------------------------------------------ -// Types -#ifndef PYUL_DEFINED - #define PYUL_DEFINED - #ifdef __EA64__ - typedef unsigned PY_LONG_LONG pyul_t; - typedef PY_LONG_LONG pyl_t; - #else - typedef unsigned long pyul_t; - typedef long pyl_t; - #endif -#endif +// The following are to be used whenever Py_BuildValue-style +// format specifiers are needed. +#define PY_BV_EA "K" // Convert a C unsigned long long to a Python long integer object. +#define PY_BV_SZ "n" // Convert a C Py_ssize_t to a Python integer or long integer. +#define PY_BV_UVAL PY_BV_EA +#define PY_BV_ASIZE PY_BV_EA +#define PY_BV_SEL PY_BV_EA +#define PY_BV_SVAL "L" // Convert a C long long to a Python long integer object +typedef unsigned PY_LONG_LONG bvea_t; +typedef Py_ssize_t bvsz_t; +typedef bvea_t bvuval_t; +typedef bvea_t bvasize_t; +typedef bvea_t bvsel_t; +typedef PY_LONG_LONG bvsval_t; + +//------------------------------------------------------------------------- // a few forward decls class insn_t; class op_t; -struct switch_info_ex_t; +struct switch_info_t; // "A pointer can be explicitly converted to any integral type large // enough to hold it. The mapping function is implementation-defined." @@ -49,19 +54,12 @@ struct switch_info_ex_t; #define exported #endif -#ifdef __EA64__ - #define PY_FMT64 "K" - #define PY_SFMT64 "L" -#else - #define PY_FMT64 "k" - #define PY_SFMT64 "l" -#endif - //------------------------------------------------------------------------ #define S_IDA_IDAAPI_MODNAME "ida_idaapi" #define S_IDA_NALT_MODNAME "ida_nalt" #define S_IDA_UA_MODNAME "ida_ua" #define S_IDA_KERNWIN_MODNAME "ida_kernwin" +#define S_IDA_MOVES_MODNAME "ida_moves" #define S_IDC_MODNAME "idc" #define S_IDAAPI_EXECSCRIPT "IDAPython_ExecScript" #define S_IDAAPI_COMPLETION "IDAPython_Completion" @@ -73,7 +71,7 @@ struct switch_info_ex_t; //------------------------------------------------------------------------ // String constants used static const char S_PYINVOKE0[] = "_py_invoke0"; -static const char S_PY_SWIEX_CLSNAME[] = "switch_info_ex_t"; +static const char S_PY_SWIEX_CLSNAME[] = "switch_info_t"; static const char S_PY_OP_T_CLSNAME[] = "op_t"; static const char S_PROPS[] = "props"; static const char S_NAME[] = "name"; @@ -108,11 +106,9 @@ static const char S_ON_INSERT_LINE[] = "OnInsertLine"; static const char S_ON_GET_LINE[] = "OnGetLine"; static const char S_ON_DELETE_LINE[] = "OnDeleteLine"; static const char S_ON_REFRESH[] = "OnRefresh"; -static const char S_ON_REFRESHED[] = "OnRefreshed"; static const char S_ON_EXECUTE_LINE[] = "OnExecuteLine"; static const char S_ON_SELECT_LINE[] = "OnSelectLine"; static const char S_ON_SELECTION_CHANGE[] = "OnSelectionChange"; -static const char S_ON_COMMAND[] = "OnCommand"; static const char S_ON_GET_ICON[] = "OnGetIcon"; static const char S_ON_GET_LINE_ATTR[] = "OnGetLineAttr"; static const char S_ON_GET_SIZE[] = "OnGetSize"; @@ -123,19 +119,12 @@ static const char S_ON_SELECT[] = "OnSelect"; static const char S_ON_CREATING_GROUP[] = "OnCreatingGroup"; static const char S_ON_DELETING_GROUP[] = "OnDeletingGroup"; static const char S_ON_GROUP_VISIBILITY[] = "OnGroupVisibility"; +static const char S_ON_INIT[] = "OnInit"; static const char S_M_EDGES[] = "_edges"; static const char S_M_NODES[] = "_nodes"; static const char S_M_THIS[] = "_this"; static const char S_M_TITLE[] = "_title"; static const char S_CLINK_NAME[] = "__clink__"; -static const char S_ON_VIEW_ACTIVATED[] = "OnViewActivated"; -static const char S_ON_VIEW_DEACTIVATED[] = "OnViewDeactivated"; -static const char S_ON_VIEW_KEYDOWN[] = "OnViewKeydown"; -static const char S_ON_VIEW_CLICK[] = "OnViewClick"; -static const char S_ON_VIEW_DBLCLICK[] = "OnViewDblclick"; -static const char S_ON_VIEW_CURPOS[] = "OnViewCurpos"; -static const char S_ON_VIEW_SWITCHED[] = "OnViewSwitched"; -static const char S_ON_VIEW_MOUSE_OVER[] = "OnViewMouseOver"; static const char S_ON_VIEW_MOUSE_MOVED[] = "OnViewMouseMoved"; static const char S_MAIN[] = "__main__"; @@ -198,7 +187,7 @@ idaman uint32 ida_export_data debug; #define IDA_DEBUG_PLUGIN 0x00000020 THREAD_SAFE AS_PRINTF(1, 2) inline int msg(const char *format, ...); #endif // __KERNWIN_HPP -#define GIL_CHKCONDFAIL (((debug & IDA_DEBUG_PLUGIN) == IDA_DEBUG_PLUGIN) \ +#define GIL_CHKCONDFAIL (((debug & IDA_DEBUG_PLUGIN) != 0) \ && PyGILState_GetThisThreadState() != _PyThreadState_Current) #define PYW_GIL_CHECK_LOCKED_SCOPE() \ @@ -233,7 +222,7 @@ 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_ex_t *switch_info_ex_t_get_clink(PyObject *self) { return (switch_info_ex_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 @@ -379,9 +368,9 @@ exported bool ida_export PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_v // Returns a qstring from a Python attribute string exported bool ida_export PyW_GetStringAttr( - PyObject *py_obj, - const char *attr_name, - qstring *str); + PyObject *py_obj, + const char *attr_name, + qstring *str); // Converts a Python number to an uint64 and indicates whether the number was a long number exported bool ida_export PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL); @@ -412,14 +401,25 @@ exported error_t ida_export PyW_CreateIdcException(idc_value_t *res, const char // // Conversion functions // +#define PYWCVTF_AS_TUPLE 0x1 +#define PYWCVTF_INT64_AS_UNSIGNED_PYLONG 0x2 // don't wrap int64 into 'PyIdc_cvt_int64__' objects, but make them 'long' instead + +// Converts from IDC to Python exported bool ida_export pyw_convert_idc_args( const idc_value_t args[], int nargs, ref_vec_t &pargs, - bool as_tupple, - char *errbuf = NULL, - size_t errbufsize = 0); + uint32 flags, + qstring *errbuf = NULL); +// Converts from IDC to Python +// We support converting VT_REF IDC variable types +exported int ida_export idcvar_to_pyvar( + const idc_value_t &idc_var, + ref_t *py_var, + uint32 flags=0); + +//------------------------------------------------------------------------- // Converts Python variable to IDC variable // gvar_sn is used in case the Python object was a created from a call to idcvar_to_pyvar and the IDC object was a VT_REF exported int ida_export pyvar_to_idcvar( @@ -427,23 +427,18 @@ exported int ida_export pyvar_to_idcvar( idc_value_t *idc_var, int *gvar_sn = NULL); -// Converts from IDC to Python -// We support converting VT_REF IDC variable types -exported int ida_export idcvar_to_pyvar( - const idc_value_t &idc_var, - ref_t *py_var); - +//------------------------------------------------------------------------- // Walks a Python list or Sequence and calls the callback exported Py_ssize_t ida_export pyvar_walk_list( PyObject *py_list, - int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud) = NULL, + int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud)=NULL, void *ud = NULL); -// Converts an intvec_t to a Python list object -exported ref_t ida_export PyW_IntVecToPyList(const intvec_t &intvec); +// Converts a sizevec_t to a Python list object +exported ref_t ida_export PyW_SizeVecToPyList(const sizevec_t &vec); -// Converts an Python list to an intvec -exported bool ida_export PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec); +// Converts an Python list to an sizevec +exported bool ida_export PyW_PyListToSizeVec(PyObject *py_list, sizevec_t &vec); // Converts an Python list to an eavec exported bool ida_export PyW_PyListToEaVec(PyObject *py_list, eavec_t &eavec); @@ -456,7 +451,7 @@ exported bool ida_export PyWStringOrNone_Check(PyObject *tp); //------------------------------------------------------------------------- #include -exported PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &areas); +exported PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &ranges); //------------------------------------------------------------------------- exported void ida_export PyW_register_compiled_form(PyObject *py_form); @@ -479,7 +474,8 @@ class pywraps_notify_when_t typedef qvector notify_when_args_vec_t; notify_when_args_vec_t delayed_notify_when_list; - static int idaapi idp_callback(void *ud, int event_id, va_list va); + 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); @@ -498,7 +494,7 @@ exported bool ida_export add_notify_when(int when, PyObject *py_callable); // void free_compiled_form_instances(void); -//#define PYGDBG_ENABLED +// #define PYGDBG_ENABLED #ifdef PYGDBG_ENABLED #define PYGLOG(...) msg(__VA_ARGS__) #else @@ -528,6 +524,8 @@ private: pycall_res_t(); // No. }; +#include + //------------------------------------------------------------------------- // CustomIDAMemo wrappers //-------------------------------------------------------------------------i @@ -535,10 +533,9 @@ class lookup_info_t; class py_customidamemo_t; struct lookup_entry_t { - lookup_entry_t() : form(NULL), view(NULL), py_view(NULL) {} + lookup_entry_t() : view(NULL), py_view(NULL) {} - TForm *form; - TCustomControl *view; + TWidget *view; py_customidamemo_t *py_view; }; DECLARE_TYPE_AS_MOVABLE(lookup_entry_t); @@ -549,17 +546,17 @@ typedef qvector lookup_entries_t; #define PY_LINFO_PARAMS_new_entry (py_customidamemo_t *py_view) #define PY_LINFO_TRANSM_new_entry (this, py_view) -#define PY_LINFO_HLPPRM_commit (lookup_info_t *_this, lookup_entry_t &e, TForm *form, TCustomControl *view) -#define PY_LINFO_PARAMS_commit (lookup_entry_t &e, TForm *form, TCustomControl *view) -#define PY_LINFO_TRANSM_commit (this, e, form, view) +#define PY_LINFO_HLPPRM_commit (lookup_info_t *_this, lookup_entry_t &e, TWidget *view) +#define PY_LINFO_PARAMS_commit (lookup_entry_t &e, TWidget *view) +#define PY_LINFO_TRANSM_commit (this, e, view) -#define PY_LINFO_HLPPRM_find_by_form (const lookup_info_t *_this, TCustomControl **out_view, py_customidamemo_t **out_py_view, const TForm *form) -#define PY_LINFO_PARAMS_find_by_form (TCustomControl **out_view, py_customidamemo_t **out_py_view, const TForm *form) const -#define PY_LINFO_TRANSM_find_by_form (this, out_view, out_py_view, form) +#define PY_LINFO_HLPPRM_find_by_view (const lookup_info_t *_this, py_customidamemo_t **out_py_view, const TWidget *view) +#define PY_LINFO_PARAMS_find_by_view (py_customidamemo_t **out_py_view, const TWidget *view) const +#define PY_LINFO_TRANSM_find_by_view (this, out_py_view, view) -#define PY_LINFO_HLPPRM_find_by_py_view (const lookup_info_t *_this, TForm **out_form, TCustomControl **out_view, const py_customidamemo_t *py_view) -#define PY_LINFO_PARAMS_find_by_py_view (TForm **out_form, TCustomControl **out_view, const py_customidamemo_t *py_view) const -#define PY_LINFO_TRANSM_find_by_py_view (this, out_form, out_view, py_view) +#define PY_LINFO_HLPPRM_find_by_py_view (const lookup_info_t *_this, TWidget **out_view, const py_customidamemo_t *py_view) +#define PY_LINFO_PARAMS_find_by_py_view (TWidget **out_view, const py_customidamemo_t *py_view) const +#define PY_LINFO_TRANSM_find_by_py_view (this, out_view, py_view) #define PY_LINFO_HLPPRM_del_by_py_view (lookup_info_t *_this, const py_customidamemo_t *py_view) #define PY_LINFO_PARAMS_del_by_py_view (const py_customidamemo_t *py_view) @@ -571,7 +568,7 @@ typedef qvector lookup_entries_t; #define DECL_LINFO_HELPERS(decl) \ DECL_LINFO_HELPER(decl, lookup_entry_t&, new_entry, PY_LINFO_HLPPRM_new_entry); \ DECL_LINFO_HELPER(decl, void, commit, PY_LINFO_HLPPRM_commit); \ - DECL_LINFO_HELPER(decl, bool, find_by_form, PY_LINFO_HLPPRM_find_by_form); \ + DECL_LINFO_HELPER(decl, bool, find_by_view, PY_LINFO_HLPPRM_find_by_view);\ DECL_LINFO_HELPER(decl, bool, find_by_py_view, PY_LINFO_HLPPRM_find_by_py_view);\ DECL_LINFO_HELPER(decl, bool, del_by_py_view, PY_LINFO_HLPPRM_del_by_py_view); @@ -589,13 +586,11 @@ public: PY_LINFO_TRAMPOLINE(lookup_entry_t&, new_entry, PY_LINFO_PARAMS_new_entry, PY_LINFO_TRANSM_new_entry); PY_LINFO_TRAMPOLINE(void, commit, PY_LINFO_PARAMS_commit, PY_LINFO_TRANSM_commit); - PY_LINFO_TRAMPOLINE(bool, find_by_form, PY_LINFO_PARAMS_find_by_form, PY_LINFO_TRANSM_find_by_form); + PY_LINFO_TRAMPOLINE(bool, find_by_view, PY_LINFO_PARAMS_find_by_view, PY_LINFO_TRANSM_find_by_view); PY_LINFO_TRAMPOLINE(bool, find_by_py_view, PY_LINFO_PARAMS_find_by_py_view, PY_LINFO_TRANSM_find_by_py_view); PY_LINFO_TRAMPOLINE(bool, del_by_py_view, PY_LINFO_PARAMS_del_by_py_view, PY_LINFO_TRANSM_del_by_py_view); #undef PY_LINFO_TRAMPOLINE - bool find_by_view(TForm **out_form, py_customidamemo_t **out_py_view, const TCustomControl *view) const; - private: lookup_entries_t entries; }; @@ -666,20 +661,14 @@ struct pycim_callbacks_ids_t : public qvector #define PY_CIM_PARAMS_collect_class_callbacks_ids (pycim_callbacks_ids_t *out) #define PY_CIM_TRANSM_collect_class_callbacks_ids (this, out) -#define PY_CIM_HLPPRM_install_custom_viewer_handlers (py_customidamemo_t *_this) -#define PY_CIM_PARAMS_install_custom_viewer_handlers () -#define PY_CIM_TRANSM_install_custom_viewer_handlers (this) - -#define PY_CIM_HLPPRM_bind (py_customidamemo_t *_this, PyObject *self, TCustomControl *view) -#define PY_CIM_PARAMS_bind (PyObject *in_self, TCustomControl *in_view) +#define PY_CIM_HLPPRM_bind (py_customidamemo_t *_this, PyObject *self, TWidget *view) +#define PY_CIM_PARAMS_bind (PyObject *in_self, TWidget *in_view) #define PY_CIM_TRANSM_bind (this, in_self, in_view) #define PY_CIM_HLPPRM_unbind (py_customidamemo_t *_this, bool clear_view) #define PY_CIM_PARAMS_unbind (bool clear_view) #define PY_CIM_TRANSM_unbind (this, clear_view) -#define PY_CIM_HLPPRM_ensure_view_callbacks_installed () - #define DECL_CIM_HELPER(decl, RType, MName, MParams) \ decl RType ida_export py_customidamemo_t_##MName MParams @@ -696,10 +685,8 @@ struct pycim_callbacks_ids_t : public qvector \ DECL_CIM_HELPER(decl, bool, collect_pyobject_callbacks, PY_CIM_HLPPRM_collect_pyobject_callbacks); \ DECL_CIM_HELPER(decl, void, collect_class_callbacks_ids, PY_CIM_HLPPRM_collect_class_callbacks_ids); \ - DECL_CIM_HELPER(decl, void, install_custom_viewer_handlers, PY_CIM_HLPPRM_install_custom_viewer_handlers); \ DECL_CIM_HELPER(decl, bool, bind, PY_CIM_HLPPRM_bind); \ DECL_CIM_HELPER(decl, void, unbind, PY_CIM_HLPPRM_unbind); \ - DECL_CIM_HELPER(decl, void, ensure_view_callbacks_installed, PY_CIM_HLPPRM_ensure_view_callbacks_installed) DECL_CIM_HELPERS(idaman); @@ -714,45 +701,21 @@ class py_customidamemo_t uint32 *out_flags, ref_t py_nodeinfo); + // can use up to 16 bits; not more! (GRCODE_HAVE_* uses the rest) enum { - GRBASE_HAVE_VIEW_ACTIVATED = 0x001, - GRBASE_HAVE_VIEW_DEACTIVATED = 0x002, - GRBASE_HAVE_KEYDOWN = 0x004, - GRBASE_HAVE_POPUP = 0x008, - GRBASE_HAVE_VIEW_CLICK = 0x010, - GRBASE_HAVE_VIEW_DBLCLICK = 0x020, - GRBASE_HAVE_VIEW_CURPOS = 0x040, - GRBASE_HAVE_CLOSE = 0x080, - GRBASE_HAVE_VIEW_SWITCHED = 0x100, - GRBASE_HAVE_VIEW_MOUSE_OVER = 0x200, - GRBASE_HAVE_VIEW_MOUSE_MOVED = 0x400, + GRBASE_HAVE_VIEW_MOUSE_MOVED = 0x0001, }; int cb_flags; - // number of arguments for: - int ovc_num_args; // OnViewClick implementation - int ovdc_num_args; // OnViewDblclick implementation - int ovmo_num_args; // OnViewMouseOver implementation - int ovmm_num_args; // OnViewMouseMoved implementation // View events - void on_view_activated(); - void on_view_deactivated(); - void on_view_keydown(int key, int state); - void on_view_popup(); - void on_view_click(const view_mouse_event_t *event); - void on_view_dblclick(const view_mouse_event_t *event); - void on_view_curpos(); - void on_view_close(); - void on_view_switched(tcc_renderer_type_t rt); - void on_view_mouse_over(const view_mouse_event_t *event); void on_view_mouse_moved(const view_mouse_event_t *event); int get_py_method_arg_count(char *method_name); // View events that are bound with 'set_custom_viewer_handler()'. static void idaapi s_on_view_mouse_moved( - TCustomControl *cv, + TWidget *cv, int shift, view_mouse_event_t *e, void *ud); @@ -761,29 +724,23 @@ class py_customidamemo_t protected: ref_t self; - TCustomControl *view; + TWidget *view; pycim_callbacks_ids_t cbids; PY_CIM_TRAMPOLINE(bool, collect_pyobject_callbacks, PY_CIM_PARAMS_collect_pyobject_callbacks, PY_CIM_TRANSM_collect_pyobject_callbacks); PY_CIM_TRAMPOLINE(virtual void, collect_class_callbacks_ids, PY_CIM_PARAMS_collect_class_callbacks_ids, PY_CIM_TRANSM_collect_class_callbacks_ids); - PY_CIM_TRAMPOLINE(void, install_custom_viewer_handlers, PY_CIM_PARAMS_install_custom_viewer_handlers, PY_CIM_TRANSM_install_custom_viewer_handlers); PY_CIM_TRAMPOLINE(bool, bind, PY_CIM_PARAMS_bind, PY_CIM_TRANSM_bind); PY_CIM_TRAMPOLINE(void, unbind, PY_CIM_PARAMS_unbind, PY_CIM_TRANSM_unbind); - friend TForm *pycim_get_tform(PyObject *self); - friend TCustomControl *pycim_get_tcustom_control(PyObject *self); + friend TWidget *pycim_get_widget(PyObject *self); public: py_customidamemo_t() - : self(newref_t(NULL)), + : cb_flags(0), + self(newref_t(NULL)), view(NULL) { PYGLOG("%p: py_customidamemo_t()\n", this); - py_customidamemo_t_ensure_view_callbacks_installed(); - ovc_num_args = -1; - ovdc_num_args = -1; - ovmo_num_args = -1; - ovmm_num_args = -1; } virtual ~py_customidamemo_t() { @@ -850,4 +807,55 @@ struct py_timer_ctx_t exported py_timer_ctx_t *ida_export python_timer_new(PyObject *py_callback); exported void ida_export python_timer_del(py_timer_ctx_t *t); +//------------------------------------------------------------------------- +exported ref_t ida_export try_create_swig_wrapper(ref_t mod, const char *clsname, void *cobj); + +//------------------------------------------------------------------------- +// Useful for small operations that must not be interrupted: e.g., when +// wrapping an insn_t into a SWiG proxy object, or when destroying +// such an instance from the kernel. Use 'uninterruptible_op_t' if you can. +exported void ida_export set_interruptible_state(bool interruptible); +struct uninterruptible_op_t +{ + uninterruptible_op_t() { set_interruptible_state(false); } + ~uninterruptible_op_t() { set_interruptible_state(true); } +}; + +// //------------------------------------------------------------------------- +// class py_custom_data_type_t; +// class py_custom_data_format_t; +// typedef void py_custom_data_type_t_unregisterer_t(py_custom_data_type_t *inst); +// typedef void py_custom_data_format_t_unregisterer_t(py_custom_data_format_t *inst); +// exported void ida_export register_py_custom_data_type_and_format_unregisterer( +// py_custom_data_type_t_unregisterer_t cdt_unregisterer, +// py_custom_data_format_t_unregisterer_t cdf_unregisterer); +// exported void ida_export register_py_custom_data_type_instance(py_custom_data_type_t *inst); +// exported void ida_export register_py_custom_data_format_instance(py_custom_data_format_t *inst); +// exported void ida_export unregister_py_custom_data_type_instance(py_custom_data_type_t *inst); +// exported void ida_export unregister_py_custom_data_format_instance(py_custom_data_format_t *inst); +// exported py_custom_data_type_t *py_custom_data_type_cast(data_type_t *inst); +// exported py_custom_data_format_t *py_custom_data_format_cast(data_format_t *inst); + +exported bool ida_export idapython_hook_to_notification_point( + hook_type_t hook_type, + hook_cb_t *cb, + void *user_data); +exported bool ida_export idapython_unhook_from_notification_point( + hook_type_t hook_type, + hook_cb_t *cb, + void *user_data); +#define hook_to_notification_point USE_IDAPYTHON_HOOK_TO_NOTIFICATION_POINT +#define unhook_from_notification_point USE_IDAPYTHON_UNHOOK_FROM_NOTIFICATION_POINT + +//------------------------------------------------------------------------- +struct module_callbacks_t +{ + module_callbacks_t() { memset(this, 0, sizeof(*this)); } + void (*closebase) (void); + void (*term) (void); +}; +DECLARE_TYPE_AS_MOVABLE(module_callbacks_t); +exported void register_module_lifecycle_callbacks( + const module_callbacks_t &cbs); + #endif // __PYWRAPS_HPP__ diff --git a/pywraps/driver.cpp b/pywraps/driver.cpp deleted file mode 100644 index 05412f3..0000000 --- a/pywraps/driver.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//-------------------------------------------------------------------------- -// IDA includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//-------------------------------------------------------------------------- -// PyWraps -#include -#include "pywraps.hpp" -#include "swig_stub.h" -#include "py_cvt.hpp" -#include "py_idaapi.hpp" -#include "py_graph.hpp" -#include "py_typeinf.hpp" -#include "py_bytes.hpp" -#include "py_linput.hpp" -#include "py_qfile.hpp" -#include "py_ua.hpp" -#include "py_custdata.hpp" -#include "py_notifywhen.hpp" -#include "py_dbg.hpp" -#include "py_choose2.hpp" -#include "py_plgform.hpp" -#include "py_cli.hpp" -#include "py_custview.hpp" -#include "py_lines.hpp" -#include "py_nalt.hpp" -#include "py_loader.hpp" -#include "py_idp.hpp" -#include "py_kernwin.hpp" -#include "py_askusingform.hpp" -#include "py_expr.hpp" - -//-------------------------------------------------------------------------- -qvector all_methods; -void driver_add_methods(PyMethodDef *methods) -{ - for ( ; methods->ml_name != NULL; ++methods ) - all_methods.push_back(*methods); -} - -//-------------------------------------------------------------------------- -// Define a class and declare an instance so it gets executed on startup -// It will add the desired methods to the all_methods global variable -#define DRIVER_INIT_METHODS(name) \ - class init_##name##_driver_t \ - { \ - public: \ - init_##name##_driver_t() \ - { \ - driver_add_methods(py_methods_##name##); \ - } \ - } init_##name##_driver; - -//-------------------------------------------------------------------------- -// PyWraps test drivers -//#include "driver_kernwin.cpp" -//#include "driver_chooser.cpp" -#include "driver_expr.cpp" -//#include "driver_custview.cpp" -//#include "driver_notifywhen.cpp" -//#include "driver_custdata.cpp" -//#include "driver_graph.cpp" -//#include "driver_diskio.cpp" -//#include "driver_bytes.cpp" -//#include "driver_dbg.cpp" -//#include "driver_nalt.cpp" -//#include "driver_cli.cpp" - -//-------------------------------------------------------------------------- -//#define DRIVER_FIX - -#ifdef DRIVER_FIX - #define PLUGIN_FLAGS PLUGIN_FIX -#else - #define PLUGIN_FLAGS 0 -#endif - -//-------------------------------------------------------------------------- -void setup_pywraps() -{ - static bool installed = false; - if ( installed ) - { - msg("pywraps already installed\n"); - return; - } - static const PyMethodDef null_method = {0}; - all_methods.push_back(null_method); - Py_InitModule("pywraps", all_methods.begin()); - init_pywraps(); - msg("pywraps installed!\n"); - installed = true; -} - -//-------------------------------------------------------------------------- -void idaapi run(int /*arg*/) -{ - setup_pywraps(); -#ifdef DRIVER_RUN - driver_run(0); -#endif -} - -//-------------------------------------------------------------------------- -// -// Initialize. -// -int idaapi init(void) -{ -#ifndef DRIVER_FIX - setup_pywraps(); -#endif -#ifdef DRIVER_INIT - return driver_init(); -#else - return PLUGIN_KEEP; -#endif -} - -//-------------------------------------------------------------------------- -void idaapi term(void) -{ -#ifdef DRIVER_TERM - driver_term(); -#endif -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_FLAGS, // plugin flags - init, // initialize - - term, // terminate. this pointer may be NULL. - - run, // invoke plugin - - // long comment about the plugin - "PyWraps plugin", - - // it could appear in the status line - // or as a hint - "", // multiline help about the plugin - - "pywraps", // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/pywraps/driver_bytes.cpp b/pywraps/driver_bytes.cpp deleted file mode 100644 index cf9446b..0000000 --- a/pywraps/driver_bytes.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "py_bytes.hpp" - -//-------------------------------------------------------------------------- -static PyObject *ex_nextthat(PyObject *self, PyObject *args) -{ - PyObject *callback; - pyul_t addr, bound; - if ( !PyArg_ParseTuple(args, PY_FMT64 PY_FMT64 "O", &addr, &bound, &callback) ) - return NULL; - return Py_BuildValue("i", py_nextthat(pyul_t(addr), pyul_t(bound), callback)); -} - -//-------------------------------------------------------------------------- -static PyMethodDef py_methods_bytes[] = -{ - { "nextthat", ex_nextthat, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } -}; -DRIVER_INIT_METHODS(bytes); \ No newline at end of file diff --git a/pywraps/driver_chooser.cpp b/pywraps/driver_chooser.cpp deleted file mode 100644 index f3775dc..0000000 --- a/pywraps/driver_chooser.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "py_choose2.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_find(PyObject *self, PyObject *args) -{ - char *title; - if ( !PyArg_ParseTuple(args, "s", &title) ) - return NULL; - else - return choose2_find(title); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_create(PyObject *self, PyObject *args) -{ - PyObject *obj; - int embedded; - if ( !PyArg_ParseTuple(args, "Oi", &obj, &embedded) ) - return NULL; - else - return PyInt_FromLong(choose2_create(obj, embedded == 1 ? true : false)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_activate(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - choose2_activate(obj); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_close(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - choose2_close(obj); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_refresh(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - choose2_refresh(obj); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_add_command(PyObject *self, PyObject *args) -{ - PyObject *obj; - char *caption; - int flags, menu_index, icon; - if ( !PyArg_ParseTuple(args, "Osiii", &obj, &caption, &flags, &menu_index, &icon) ) - return NULL; - else - return PyInt_FromLong(choose2_add_command(obj, caption, flags, menu_index, icon)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_get_test_embedded(PyObject *self, PyObject *args) -{ - return PyLong_FromSize_t(choose2_get_test_embedded()); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_get_embedded(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - else - return choose2_get_embedded(obj); -} - -//------------------------------------------------------------------------- -static PyObject *ex_choose2_get_embedded_selection(PyObject *self, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - else - return choose2_get_embedded_selection(obj); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_chooser[] = -{ - { "py_choose2_find", ex_choose2_find, METH_VARARGS, "" }, - { "py_choose2_create", ex_choose2_create, METH_VARARGS, "" }, - { "py_choose2_close", ex_choose2_close, METH_VARARGS, "" }, - { "py_choose2_activate", ex_choose2_activate, METH_VARARGS, "" }, - { "py_choose2_refresh", ex_choose2_refresh, METH_VARARGS, "" }, - { "py_choose2_add_command", ex_choose2_add_command, METH_VARARGS, "" }, - { "py_choose2_get_test_embedded", ex_choose2_get_test_embedded, METH_VARARGS, "" }, - { "py_choose2_get_embedded", ex_choose2_get_embedded, METH_VARARGS, "" }, - { "py_choose2_get_embedded_selection", ex_choose2_get_embedded_selection, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } // End of methods -}; -DRIVER_INIT_METHODS(chooser); diff --git a/pywraps/driver_cli.cpp b/pywraps/driver_cli.cpp deleted file mode 100644 index 208c81d..0000000 --- a/pywraps/driver_cli.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "py_custview.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_install_command_interpreter(PyObject *self, PyObject *args) -{ - PyObject *py_obj; - if ( !PyArg_ParseTuple(args, "O", &py_obj) ) - return NULL; - return PyInt_FromLong(py_install_command_interpreter(py_obj)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_remove_command_interpreter(PyObject *self, PyObject *args) -{ - int cli_idx; - if ( !PyArg_ParseTuple(args, "i", &cli_idx) ) - return NULL; - py_remove_command_interpreter(cli_idx); - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_cli[] = -{ - { "install_command_interpreter", ex_install_command_interpreter, METH_VARARGS, "" }, - { "remove_command_interpreter", ex_remove_command_interpreter, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } -}; -DRIVER_INIT_METHODS(cli); \ No newline at end of file diff --git a/pywraps/driver_custview.cpp b/pywraps/driver_custview.cpp deleted file mode 100644 index fec3d8c..0000000 --- a/pywraps/driver_custview.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include "py_custview.hpp" - -//-------------------------------------------------------------------------- -class my_custviewer: public customviewer_t -{ -private: - cvdata_simpleline_t data; - size_t id_n; - virtual bool on_popup_menu(size_t menu_id) - { - if ( menu_id == id_n ) - msg("popup menu N chosen!\n"); - return true; - } - virtual bool on_click(int shift) - { - msg("onclick; shift=%d\n", shift); - return true; - } - virtual void on_close() - { - id_n = 0; - msg("closed...\n"); - } - virtual bool on_keydown(int key, int shift) - { - switch ( key ) - { - case 'N': - warning("The hotkey 'N' has been pressed"); - return true; - case 'I': - { - int x, y; - place_t *pl = get_place(false, &x, &y); - if ( pl == NULL ) - return false; - msg("x=%d y=%d\n", x, y); - simpleline_t sl = *data.get_line(pl); - sl.bgcolor = bgcolor_t(~uint32(sl.bgcolor)); - data.set_line(data.to_lineno(pl), sl); - refresh_current(); - return true; - } - case 'A': - { - char buf[100]; - qsnprintf(buf, sizeof(buf), "This is line %d\n", data.count()); - data.add_line(buf); - msg("Added one more line...\n"); - return true; - } - case 'S': - { - twinpos_t p1, p2; - ::readsel2(_cv, &p1, &p2); - size_t y1 = data.to_lineno(p1.at); - size_t y2 = data.to_lineno(p2.at); - int x1 = p1.x; - int x2 = p2.x; - msg("(x1=%d y1=%d) (x2=%d y2=%d)", x1, y1, x2, y2); - return true; - } - case 'X': - data.set_minmax(); - return true; - case 'R': - refresh(); - msg("refreshing!\n"); - return true; - case IK_ESCAPE: - close(); - return true; - } - return false; - } - virtual void on_curpos_changed() - { - qstring word; - if ( get_current_word(false, word) ) - msg("Current word is: %s\n", word.c_str()); - } - virtual bool on_hint(place_t *place, int *important_lines, qstring &hint) - { - simpleline_t *line = data.get_line(place); - if ( line == NULL ) - return false; - *important_lines = 1; - hint = line->line; - return true; - } - -public: - void init_sample_lines() - { - strvec_t &lines = data.get_lines(); - static struct - { - const char *text; - bgcolor_t color; - } const sample_lines[] = - { - { "This is a sample text", 0xFFFFFF }, - { "It will be displayed in the custom view", 0xFFC0C0 }, - { COLSTR("This line will be colored as erroneous", SCOLOR_ERROR), 0xC0FFC0 }, - { COLSTR("Every", SCOLOR_AUTOCMT) " " - COLSTR("word", SCOLOR_DNAME) " " - COLSTR("can", SCOLOR_IMPNAME) " " - COLSTR("be", SCOLOR_NUMBER) " " - COLSTR("colored!", SCOLOR_EXTRA), 0xC0C0FF }, - { " No limit on the number of lines.", 0xC0FFFF }, - }; - for ( int i=0; i < qnumber(sample_lines); i++ ) - { - lines.push_back(simpleline_t("")); // add empty line - lines.push_back(simpleline_t(sample_lines[i].text)); - lines.back().bgcolor = sample_lines[i].color; - } - } - my_custviewer() - { - id_n = 0; - init_sample_lines(); - data.set_minmax(); - } - bool init(const char *title) - { - if ( id_n != 0 ) - return true; - if ( !create(title, HAVE_HINT | HAVE_CLICK | HAVE_KEYDOWN | HAVE_CURPOS, &data) ) - return false; - id_n = add_popup_menu("Do this", "N"); - return true; - } -}; - -my_custviewer *g_cv; - -//------------------------------------------------------------------------- -static PyObject *ex_pyscv_init(PyObject *self, PyObject *args) -{ - const char *title; - PyObject *py_link; - if ( !PyArg_ParseTuple(args, "Os", &py_link, &title) ) - return NULL; - return pyscv_init(py_link, title); -} - -static PyObject *ex_pyscv_add_line(PyObject *self, PyObject *args) -{ - PyObject *py_this, *py_sl; - if ( !PyArg_ParseTuple(args, "OO", &py_this, &py_sl) ) - return NULL; - return Py_BuildValue("i", pyscv_add_line(py_this, py_sl)); -} - -static PyObject *ex_pyscv_delete(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return Py_BuildValue("i", pyscv_delete(py_this)); -} - -static PyObject *ex_pyscv_show(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return Py_BuildValue("i", pyscv_show(py_this)); -} - -static PyObject *ex_pyscv_refresh(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return Py_BuildValue("i", pyscv_refresh(py_this)); -} - -static PyObject *ex_pyscv_close(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - pyscv_close(py_this); - Py_RETURN_NONE; -} - -static PyObject *ex_pyscv_clear_popup_menu(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - pyscv_clear_popup_menu(py_this); - Py_RETURN_NONE; -} - -static PyObject *ex_pyscv_del_line(PyObject *self, PyObject *args) -{ - PyObject *py_this; - size_t nline; - if ( !PyArg_ParseTuple(args, "O" PY_FMT64, &py_this, &nline) ) - return NULL; - return Py_BuildValue("i", pyscv_del_line(py_this, nline)); -} - -static PyObject *ex_pyscv_get_pos(PyObject *self, PyObject *args) -{ - PyObject *py_this; - int mouse; - if ( !PyArg_ParseTuple(args, "Oi", &py_this, &mouse) ) - return NULL; - return pyscv_get_pos(py_this, mouse == 0 ? false : true); -} - -static PyObject *ex_pyscv_refresh_current(PyObject *self, PyObject *args) -{ - PyObject *py_this; - int mouse; - if ( !PyArg_ParseTuple(args, "Oi", &py_this, &mouse) ) - return NULL; - return Py_BuildValue("i", pyscv_refresh_current(py_this)); -} - -static PyObject *ex_pyscv_get_current_line(PyObject *self, PyObject *args) -{ - PyObject *py_this; - int mouse, notags; - if ( !PyArg_ParseTuple(args, "Oii", &py_this, &mouse, ¬ags) ) - return NULL; - return pyscv_get_current_line(py_this, mouse == 0 ? false : true, notags == 0 ? false : true); -} - -static PyObject *ex_pyscv_is_focused(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return Py_BuildValue("i", pyscv_is_focused(py_this)); -} - -static PyObject *ex_pyscv_add_popup_menu(PyObject *self, PyObject *args) -{ - PyObject *py_this; - const char *title, *hotkey; - if ( !PyArg_ParseTuple(args, "Oss", &py_this, &title, &hotkey) ) - return NULL; - return Py_BuildValue("i", pyscv_add_popup_menu(py_this, title, hotkey)); -} - -static PyObject *ex_pyscv_get_line(PyObject *self, PyObject *args) -{ - PyObject *py_this; - size_t nline; - if ( !PyArg_ParseTuple(args, "O" PY_FMT64, &py_this, &nline) ) - return NULL; - return pyscv_get_line(py_this, nline); -} - -static PyObject *ex_pyscv_jumpto(PyObject *self, PyObject *args) -{ - PyObject *py_this; - int x, y; - size_t lineno; - if ( !PyArg_ParseTuple(args, "O" PY_FMT64 "ii", &py_this, &lineno, &x, &y) ) - return NULL; - return Py_BuildValue("i", pyscv_jumpto(py_this, lineno, x, y)); -} - -static PyObject *ex_pyscv_edit_line(PyObject *self, PyObject *args) -{ - PyObject *py_this, *py_sl; - size_t lineno; - if ( !PyArg_ParseTuple(args, "O" PY_FMT64 "O", &py_this, &lineno, &py_sl) ) - return NULL; - return Py_BuildValue("i", pyscv_edit_line(py_this, lineno, py_sl)); -} - -static PyObject *ex_pyscv_insert_line(PyObject *self, PyObject *args) -{ - PyObject *py_this, *py_sl; - size_t lineno; - if ( !PyArg_ParseTuple(args, "O" PY_FMT64 "O", &py_this, &lineno, &py_sl) ) - return NULL; - return Py_BuildValue("i", pyscv_insert_line(py_this, lineno, py_sl)); -} - -static PyObject *ex_pyscv_patch_line(PyObject *self, PyObject *args) -{ - PyObject *py_this; - size_t lineno, offs; - int value; - if ( !PyArg_ParseTuple(args, "O" PY_FMT64 PY_FMT64 "i", &py_this, &lineno, &offs, &value) ) - return NULL; - return Py_BuildValue("i", pyscv_patch_line(py_this, lineno, offs, value)); -} - -static PyObject *ex_pyscv_count(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return Py_BuildValue(PY_FMT64, pyscv_count(py_this)); -} - -static PyObject *ex_pyscv_get_selection(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return pyscv_get_selection(py_this); -} - -static PyObject *ex_pyscv_get_current_word(PyObject *self, PyObject *args) -{ - PyObject *py_this; - int mouse; - if ( !PyArg_ParseTuple(args, "Oi", &py_this, &mouse) ) - return NULL; - return pyscv_get_current_word(py_this, mouse != 0); -} - -static PyObject *ex_pyscv_clear_lines(PyObject *self, PyObject *args) -{ - PyObject *py_this; - if ( !PyArg_ParseTuple(args, "O", &py_this) ) - return NULL; - return pyscv_clear_lines(py_this); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_custview[] = -{ - { "pyscv_init", ex_pyscv_init, METH_VARARGS, "" }, - { "pyscv_close", ex_pyscv_close, METH_VARARGS, "" }, - { "pyscv_add_line", ex_pyscv_add_line, METH_VARARGS, "" }, - { "pyscv_delete", ex_pyscv_delete, METH_VARARGS, "" }, - { "pyscv_refresh", ex_pyscv_refresh, METH_VARARGS, "" }, - { "pyscv_clear_lines", ex_pyscv_clear_lines, METH_VARARGS, "" }, - { "pyscv_show", ex_pyscv_show, METH_VARARGS, "" }, - { "pyscv_clear_popup_menu", ex_pyscv_clear_popup_menu, METH_VARARGS, "" }, - { "pyscv_del_line", ex_pyscv_del_line, METH_VARARGS, "" }, - { "pyscv_get_pos", ex_pyscv_get_pos, METH_VARARGS, "" }, - { "pyscv_refresh_current", ex_pyscv_refresh_current, METH_VARARGS, "" }, - { "pyscv_get_current_line", ex_pyscv_get_current_line, METH_VARARGS, "" }, - { "pyscv_is_focused", ex_pyscv_is_focused, METH_VARARGS, "" }, - { "pyscv_add_popup_menu", ex_pyscv_add_popup_menu, METH_VARARGS, "" }, - { "pyscv_get_line", ex_pyscv_get_line, METH_VARARGS, "" }, - { "pyscv_jumpto", ex_pyscv_jumpto, METH_VARARGS, "" }, - { "pyscv_edit_line", ex_pyscv_edit_line, METH_VARARGS, "" }, - { "pyscv_insert_line", ex_pyscv_insert_line, METH_VARARGS, "" }, - { "pyscv_count", ex_pyscv_count, METH_VARARGS, "" }, - { "pyscv_patch_line", ex_pyscv_patch_line, METH_VARARGS, "" }, - { "pyscv_get_selection", ex_pyscv_get_selection, METH_VARARGS, "" }, - { "pyscv_get_current_word", ex_pyscv_get_current_word, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } /* Sentinel */ -}; -DRIVER_INIT_METHODS(custview); - -#define DRIVER_RUN -void driver_run(int) -{ - if ( !g_cv->init("My sample viewer!") ) - { - msg("Failed to create cv\n!"); - return; - } - g_cv->show(); -} - -#define DRIVER_INIT -int driver_init() -{ - g_cv = new my_custviewer(); - return PLUGIN_KEEP; -} - -#define DRIVER_TERM -void driver_term() -{ - g_cv->close(); - delete g_cv; -} diff --git a/pywraps/driver_dbg.cpp b/pywraps/driver_dbg.cpp deleted file mode 100644 index f2ff86e..0000000 --- a/pywraps/driver_dbg.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "py_dbg.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_getthreadsregbase(PyObject * /*self*/, PyObject *args) -{ - PyObject *py_tid, *py_sreg_value; - if ( !PyArg_ParseTuple(args, "OO", &py_tid, &py_sreg_value) ) - return NULL; - return dbg_get_thread_sreg_base(py_tid, py_sreg_value); -} - -//------------------------------------------------------------------------- -static PyObject *ex_readmemory(PyObject * /*self*/, PyObject *args) -{ - PyObject *py_ea, *py_size; - if ( !PyArg_ParseTuple(args, "OO", &py_ea, &py_size) ) - return NULL; - return dbg_read_memory(py_ea, py_size); -} - -//------------------------------------------------------------------------- -static PyObject *ex_writememory(PyObject * /*self*/, PyObject *args) -{ - PyObject *py_ea, *py_buf; - if ( !PyArg_ParseTuple(args, "OO", &py_ea, &py_buf) ) - return NULL; - return dbg_write_memory(py_ea, py_buf); -} - -//------------------------------------------------------------------------- -static PyObject *ex_getmeminfo(PyObject * /*self*/, PyObject *args) -{ - return dbg_get_memory_info(); -} - -//------------------------------------------------------------------------- -static PyObject *ex_getregs(PyObject *self, PyObject *args) -{ - return dbg_get_registers(); -} - -//------------------------------------------------------------------------- -static PyObject *ex_appcall(PyObject * /*self*/, PyObject *args) -{ - PyObject *app_args, *type, *fields; - int func_ea, tid; - if ( !PyArg_ParseTuple(args, "iiOOO", &func_ea, &tid, &type, &fields, &app_args) ) - return NULL; - return py_appcall(func_ea, tid, type, fields, app_args); -} - -//------------------------------------------------------------------------- -static PyObject *ex_pytoidc( - PyObject *self, - PyObject *args) -{ - if ( !PyArg_ParseTuple(args, "O", &self) ) - return NULL; - idc_value_t v; - int sn = 0; - borref_t self_ref(self); - if ( pyvar_to_idcvar(self_ref, &v, &sn) < CIP_OK ) - Py_RETURN_NONE; - Py_RETURN_TRUE; -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_dbg[] = -{ - { "getregs", ex_getregs, METH_VARARGS, "" }, - { "getmeminfo", ex_getmeminfo, METH_VARARGS, "" }, - { "readmemory", ex_readmemory, METH_VARARGS, "" }, - { "writememory", ex_writememory, METH_VARARGS, "" }, - { "getthreadsregbase", ex_getthreadsregbase, METH_VARARGS, "" }, - { "appcall", ex_appcall, METH_VARARGS, "" }, - { "pytoidc", ex_pytoidc, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } /* Sentinel */ -}; -DRIVER_INIT_METHODS(dbg); diff --git a/pywraps/driver_diskio.cpp b/pywraps/driver_diskio.cpp deleted file mode 100644 index 8f99dda..0000000 --- a/pywraps/driver_diskio.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "py_diskio.hpp" - -static PyObject *ex_enumfiles(PyObject * /*self*/, PyObject *args) -{ - PyObject *path, *fname, *callback; - if ( !PyArg_ParseTuple(args, "OOO", &path, &fname, &callback) ) - return NULL; - return py_enumerate_files(path, fname, callback); -} - -// -//static PyObject *ex_linput_close(PyObject * /*self*/, PyObject *args) -//{ -// PyObject *obj; -// if ( !PyArg_ParseTuple(args, "O", &obj) ) -// return NULL; -// pyl_close(obj); -// Py_RETURN_NONE; -//} -// -//static PyObject *ex_linput_open(PyObject *self, PyObject *args) -//{ -// PyObject *obj, *py_filename, *py_remote; -// if ( !PyArg_ParseTuple(args, "OOO", &obj, &py_filename, &py_remote) ) -// return NULL; -// return pyl_open(obj, py_filename, py_remote); -//} -// -//static PyObject *ex_linput_read(PyObject *self, PyObject *args) -//{ -// PyObject *obj, *py_size; -// if ( !PyArg_ParseTuple(args, "OO", &obj, &py_size) ) -// return NULL; -// return pyl_read(obj, py_size); -//} - -static PyMethodDef py_methods_diskio[] = -{ - { "enumfiles", ex_enumfiles, METH_VARARGS, "" }, - //{ "tell", ex_linput_tell, METH_VARARGS, "" }, - //{ "open", ex_linput_open, METH_VARARGS, "" }, - //{ "size", ex_linput_tell, METH_VARARGS, "" }, - //{ "read", ex_linput_read, METH_VARARGS, "" }, - //{ "close", ex_linput_close, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } /* Sentinel */ -}; -DRIVER_INIT_METHODS(diskio); \ No newline at end of file diff --git a/pywraps/driver_expr.cpp b/pywraps/driver_expr.cpp deleted file mode 100644 index c636adb..0000000 --- a/pywraps/driver_expr.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "py_expr.hpp" - -#pragma warning(push) -#pragma warning(disable: 4244) - -//--------------------------------------------------------------------------- -static PyObject *ex_pyw_register_idc_func(PyObject *self, PyObject *args) -{ - char *name, *arg; - PyObject *py_fp; - if ( !PyArg_ParseTuple(args, "ssO", &name, &arg, &py_fp) ) - return NULL; - else - return PyLong_FromUnsignedLongLong(pyw_register_idc_func(name, arg, py_fp)); -} - -//--------------------------------------------------------------------------- -static PyObject *ex_pyw_unregister_idc_func(PyObject *self, PyObject *args) -{ - unsigned PY_LONG_LONG ctxptr; - if ( !PyArg_ParseTuple(args, "K", &ctxptr) ) - return NULL; - return PyLong_FromLong(pyw_unregister_idc_func(ctxptr)); -} - -static PyObject *ex_py_set_idc_func_ex(PyObject *self, PyObject *pyargs) -{ - const char *name; - unsigned PY_LONG_LONG fp_ptr; - const char *args; - int flags; - if ( !PyArg_ParseTuple(pyargs, "sKsi", &name, &fp_ptr, &args, &flags) ) - return NULL; - else - return PyLong_FromLong(py_set_idc_func_ex(name, fp_ptr, args, flags)); -} - -//--------------------------------------------------------------------------- -static PyObject *ex_py_get_call_idc_func(PyObject *self, PyObject *args) -{ - return PyLong_FromUnsignedLongLong(py_get_call_idc_func()); -} - -//------------------------------------------------------------------------- -#pragma warning(pop) - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_expr[] = -{ - { "pyw_register_idc_func", ex_pyw_register_idc_func, METH_VARARGS, "" }, - { "pyw_unregister_idc_func", ex_pyw_unregister_idc_func, METH_VARARGS, "" }, - { "py_get_call_idc_func", ex_py_get_call_idc_func, METH_VARARGS, "" }, - { "py_set_idc_func_ex", ex_py_set_idc_func_ex, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } // End of methods -}; -DRIVER_INIT_METHODS(expr); diff --git a/pywraps/driver_graph.cpp b/pywraps/driver_graph.cpp deleted file mode 100644 index 6216c78..0000000 --- a/pywraps/driver_graph.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "py_graph.hpp" - -//-------------------------------------------------------------------------- -//py_choose2_t *last_c2 = NULL; -static PyObject *ex_graph_show(PyObject * /*self*/, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - - py_graph_t *ret = py_graph_t::Show(obj); - return PyBool_FromLong(ret == NULL ? 0 : 1); -} - -//-------------------------------------------------------------------------- -static PyObject *ex_graph_refresh(PyObject * /*self*/, PyObject *args) -{ - PyObject *obj; - if ( !PyArg_ParseTuple(args, "O", &obj) ) - return NULL; - py_graph_t::Refresh(obj); - Py_RETURN_NONE; -} - -//-------------------------------------------------------------------------- -static PyObject *ex_graph_addcmd(PyObject *self, PyObject *args) -{ - PyObject *obj; - const char *title, *hotkey; - if ( !PyArg_ParseTuple(args, "Oss", &obj, &title, &hotkey) ) - return NULL; - Py_ssize_t r = py_graph_t::AddCommand(obj, title, hotkey); - return Py_BuildValue("n", r); -} - -//-------------------------------------------------------------------------- -static PyMethodDef py_methods_graph[] = -{ - { "show", ex_graph_show, METH_VARARGS, "" }, - { "refresh", ex_graph_refresh, METH_VARARGS, "" }, - { "addcmd", ex_graph_addcmd, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } /* Sentinel */ -}; -DRIVER_INIT_METHODS(graph); \ No newline at end of file diff --git a/pywraps/driver_kernwin.cpp b/pywraps/driver_kernwin.cpp deleted file mode 100644 index 1c28e45..0000000 --- a/pywraps/driver_kernwin.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "py_kernwin.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_add_menu_item(PyObject *self, PyObject *args) -{ - const char *menupath, *name, *hotkey; - PyObject *pyfunc, *pyargs; - int flags; - if ( !PyArg_ParseTuple(args, "sssiOO", &menupath, &name, &hotkey, &flags, &pyfunc, &pyargs) ) - return NULL; - return py_add_menu_item(menupath, name, hotkey, flags, pyfunc, pyargs); -} - -//------------------------------------------------------------------------- -static PyObject *ex_del_menu_item(PyObject *self, PyObject *args) -{ - if ( !PyArg_ParseTuple(args, "O", &self) ) - return NULL; - if ( py_del_menu_item(self) ) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -//------------------------------------------------------------------------- -static PyObject *ex_execute_sync(PyObject *self, PyObject *args) -{ - PyObject *pycall; - int reqf; - if ( !PyArg_ParseTuple(args, "Oi", &pycall, &reqf) ) - return NULL; - return PyInt_FromLong(py_execute_sync(pycall, reqf)); -} - -//------------------------------------------------------------------------- -static PyObject *ex_add_hotkey(PyObject *self, PyObject *args) -{ - PyObject *pyfunc; - const char *hotkey; - if ( !PyArg_ParseTuple(args, "sO", &hotkey, &pyfunc) ) - return NULL; - else - return py_add_hotkey(hotkey, pyfunc); -} - -//------------------------------------------------------------------------- -static PyObject *ex_del_hotkey(PyObject *self, PyObject *args) -{ - PyObject *pyctx; - if ( !PyArg_ParseTuple(args, "O", &pyctx) ) - return NULL; - else - return PyInt_FromLong(py_del_hotkey(pyctx) ? 1 : 0); -} - -//------------------------------------------------------------------------- -static PyObject *ex_execute_ui_request(PyObject *self, PyObject *args) -{ - PyObject *py_list; - if ( !PyArg_ParseTuple(args, "O", &py_list) ) - return NULL; - else - return PyBool_FromLong(py_execute_ui_requests(py_list) ? 1 : 0); -} - - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_kernwin[] = -{ - { "py_del_menu_item", ex_del_menu_item, METH_VARARGS, "" }, - { "py_add_menu_item", ex_add_menu_item, METH_VARARGS, "" }, - { "py_execute_sync", ex_execute_sync, METH_VARARGS, "" }, - { "py_add_hotkey", ex_add_hotkey, METH_VARARGS, "" }, - { "py_del_hotkey", ex_del_hotkey, METH_VARARGS, "" }, - { "py_execute_ui_request", ex_execute_ui_request, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } /* Sentinel */ -}; -DRIVER_INIT_METHODS(kernwin); \ No newline at end of file diff --git a/pywraps/driver_nalt.cpp b/pywraps/driver_nalt.cpp deleted file mode 100644 index 395d18b..0000000 --- a/pywraps/driver_nalt.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "py_nalt.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_get_switch_info_ex(PyObject *self, PyObject *args) -{ - pyul_t ea; - if ( !PyArg_ParseTuple(args, PY_FMT64, &ea) ) - return NULL; - return py_get_switch_info_ex(ea_t(ea)); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_nalt[] = -{ - { "get_switch_info_ex", ex_get_switch_info_ex, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } -}; -DRIVER_INIT_METHODS(nalt); diff --git a/pywraps/driver_notifywhen.cpp b/pywraps/driver_notifywhen.cpp deleted file mode 100644 index 662fe77..0000000 --- a/pywraps/driver_notifywhen.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "py_notifywhen.hpp" - -//------------------------------------------------------------------------- -static PyObject *ex_notify_when(PyObject *self, PyObject *args) -{ - int when; - PyObject *py_callable; - if ( !PyArg_ParseTuple(args, "IO", &when, &py_callable) ) - return NULL; - return Py_BuildValue("i", notify_when(when, py_callable)); -} - -//------------------------------------------------------------------------- -static PyMethodDef py_methods_nw[] = -{ - { "notify_when", ex_notify_when, METH_VARARGS, "" }, - { NULL, NULL, 0, NULL } /* Sentinel */ -}; -DRIVER_INIT_METHODS(nw); - -#define DRIVER_INIT -int driver_init() -{ - bool ok = pywraps_nw_init(); - if ( !ok ) - return PLUGIN_SKIP; - pywraps_nw_notify(NW_INITIDA_SLOT); - return PLUGIN_KEEP; -} - -#define DRIVER_TERM -void driver_term() -{ - pywraps_nw_notify(NW_TERMIDA_SLOT); - pywraps_nw_term(); -} diff --git a/pywraps/py_area.hpp b/pywraps/py_area.hpp deleted file mode 100644 index 85c5a4b..0000000 --- a/pywraps/py_area.hpp +++ /dev/null @@ -1,11 +0,0 @@ - -// -enum areacb_type_t -{ - AREACB_TYPE_UNKNOWN, - AREACB_TYPE_FUNC, - AREACB_TYPE_SEGMENT, - AREACB_TYPE_HIDDEN_AREA, - AREACB_TYPE_SRAREA, -}; -// diff --git a/pywraps/py_auto.py b/pywraps/py_auto.py new file mode 100644 index 0000000..5996d14 --- /dev/null +++ b/pywraps/py_auto.py @@ -0,0 +1,14 @@ + +# +analyze_area = plan_and_wait +autoCancel = auto_cancel +autoIsOk = auto_is_ok +autoMark = auto_mark +autoUnmark = auto_unmark +autoWait = auto_wait + +noUsed = plan_ea +setStat = set_ida_state +showAddr = show_addr +showAuto = show_auto +# diff --git a/pywraps/py_bytes.hpp b/pywraps/py_bytes.hpp index 13d7d98..bffa52b 100644 --- a/pywraps/py_bytes.hpp +++ b/pywraps/py_bytes.hpp @@ -19,29 +19,92 @@ static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next) if ( !PyCallable_Check(py_callable) ) return BADADDR; else - return (next ? nextthat : prevthat)(ea, bound, py_testf_cb, py_callable); + return (next ? next_that : prev_that)(ea, bound, py_testf_cb, py_callable); } //--------------------------------------------------------------------------- static int idaapi py_visit_patched_bytes_cb( - ea_t ea, - int32 fpos, - uint32 o, - uint32 v, - void *ud) + ea_t ea, + qoff64_t fpos, + uint32 o, + uint32 v, + void *ud) { PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_result( PyObject_CallFunction( (PyObject *)ud, - PY_FMT64 "iII", - pyul_t(ea), + PY_BV_EA "LII", + bvea_t(ea), fpos, o, v)); PyW_ShowCbErr("visit_patched_bytes"); return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0; } + +//------------------------------------------------------------------------- +static void ida_bytes_term(void) {} + +//------------------------------------------------------------------------- +static void clear_custom_data_types_and_formats(); +static void ida_bytes_closebase(void) +{ + clear_custom_data_types_and_formats(); +} + +//------------------------------------------------------------------------- +static bool py_do_get_bytes( + PyObject **out_py_bytes, + PyObject **out_py_mask, + ea_t ea, + unsigned int size, + int gmb_flags) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + bool has_mask = out_py_mask != NULL; + do + { + if ( size <= 0 ) + break; + + // Allocate memory via Python + newref_t py_bytes(PyString_FromStringAndSize(NULL, Py_ssize_t(size))); + if ( py_bytes == NULL ) + break; + + bytevec_t mask; + if ( has_mask ) + mask.resize((size + 7) / 8, 0); + + // Read bytes + int code = get_bytes(PyString_AsString(py_bytes.o), + size, + ea, + gmb_flags, + has_mask ? mask.begin() : NULL); + if ( code < 0 ) + break; + + // note: specify size, as '0' bytes would otherwise cut the mask short + if ( has_mask ) + { + newref_t py_mask(PyString_FromStringAndSize( + (const char *) mask.begin(), + mask.size())); + if ( py_mask == NULL ) + break; + py_mask.incref(); + *out_py_mask = py_mask.o; + } + + py_bytes.incref(); + *out_py_bytes = py_bytes.o; + return true; + } while ( false ); + return false; +} + // //------------------------------------------------------------------------ @@ -78,7 +141,7 @@ static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable) //------------------------------------------------------------------------ /* # -def nextthat(ea, maxea, callable): +def next_that(ea, maxea, callable): """ Find next address with a flag satisfying the function 'testf'. Start searching from address 'ea'+1 and inspect bytes up to 'maxea'. @@ -91,13 +154,13 @@ def nextthat(ea, maxea, callable): pass # */ -static ea_t py_nextthat(ea_t ea, ea_t maxea, PyObject *callable) +static ea_t py_next_that(ea_t ea, ea_t maxea, PyObject *callable) { return py_npthat(ea, maxea, callable, true); } //--------------------------------------------------------------------------- -static ea_t py_prevthat(ea_t ea, ea_t minea, PyObject *callable) +static ea_t py_prev_that(ea_t ea, ea_t minea, PyObject *callable) { return py_npthat(ea, minea, callable, false); } @@ -105,106 +168,57 @@ static ea_t py_prevthat(ea_t ea, ea_t minea, PyObject *callable) //------------------------------------------------------------------------ /* # -def get_many_bytes(ea, size): +def get_bytes(ea, size): """ - Get the specified number of bytes of the program into the buffer. + Get the specified number of bytes of the program. @param ea: program address @param size: number of bytes to return - @return: None or the string buffer + @return: the bytes (as a str), or None in case of failure """ pass # */ -static PyObject *py_get_many_bytes(ea_t ea, unsigned int size) +static PyObject *py_get_bytes(ea_t ea, unsigned int size, int gmb_flags=GMB_READALL) { - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - if ( size <= 0 ) - break; - - // Allocate memory via Python - newref_t py_buf(PyString_FromStringAndSize(NULL, Py_ssize_t(size))); - if ( py_buf == NULL ) - break; - - // Read bytes - if ( !get_many_bytes(ea, PyString_AsString(py_buf.o), size) ) - Py_RETURN_NONE; - - py_buf.incref(); - return py_buf.o; - } while ( false ); - Py_RETURN_NONE; + PyObject *py_bytes = NULL; + if ( py_do_get_bytes(&py_bytes, NULL, ea, size, gmb_flags) ) + return py_bytes; + else + Py_RETURN_NONE; } //--------------------------------------------------------------------------- /* # -def get_many_bytes_ex(ea, size, mask): +def get_bytes_and_mask(ea, size, mask): """ - Get the specified number of bytes of the program into the buffer. + Get the specified number of bytes of the program, and a bitmask + specifying what bytes are defined and what bytes are not. @param ea: program address @param size: number of bytes to return - @return: None or (string buffer, string mask) + @return: a tuple (bytes, mask), or None in case of failure. + Both 'bytes' and 'mask' are 'str' instances. """ pass # */ -static PyObject *py_get_many_bytes_ex(ea_t ea, unsigned int size) +static PyObject *py_get_bytes_and_mask(ea_t ea, unsigned int size, int gmb_flags=GMB_READALL) { - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - if ( size <= 0 ) - break; - - // Allocate memory via Python - newref_t py_buf(PyString_FromStringAndSize(NULL, Py_ssize_t(size))); - if ( py_buf == NULL ) - break; - - bytevec_t mask; - mask.resize((size + 7) / 8, 0); - - // Read bytes - int code = get_many_bytes_ex( - ea, - PyString_AsString(py_buf.o), - size, - (void *) mask.begin()); - if ( code < 0 ) - Py_RETURN_NONE; - - // note: specify size, as '0' bytes would otherwise cut the mask short - newref_t py_mask( - PyString_FromStringAndSize( - (const char *) mask.begin(), - mask.size())); - if ( py_mask == NULL ) - break; - - py_buf.incref(); - py_mask.incref(); - return Py_BuildValue("(OO)", py_buf.o, py_mask.o); - } while ( false ); - Py_RETURN_NONE; + PyObject *py_bytes = NULL; + PyObject *py_mask = NULL; + if ( py_do_get_bytes(&py_bytes, &py_mask, ea, size, gmb_flags) ) + return Py_BuildValue("(OO)", py_bytes, py_mask); + else + Py_RETURN_NONE; } //--------------------------------------------------------------------------- /* # -# Conversion options for get_ascii_contents2(): -ACFOPT_ASCII = 0x00000000 # convert Unicode strings to ASCII -ACFOPT_UTF16 = 0x00000001 # return UTF-16 (aka wide-char) array for Unicode strings - # ignored for non-Unicode strings -ACFOPT_UTF8 = 0x00000002 # convert Unicode strings to UTF-8 - # ignored for non-Unicode strings -ACFOPT_CONVMASK = 0x0000000F -ACFOPT_ESCAPE = 0x00000010 # for ACFOPT_ASCII, convert non-printable - # characters to C escapes (\n, \xNN, \uNNNN) +# Conversion options for get_strlit_contents(): +STRCONV_ESCAPE = 0x00000001 # convert non-printable characters to C escapes (\n, \xNN, \uNNNN) -def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII): +def get_strlit_contents(ea, len, type, flags = 0): """ Get bytes contents at location, possibly converted. It works even if the string has not been created in the database yet. @@ -219,60 +233,52 @@ def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII): @param len: length of the string in bytes (including terminating 0) @param type: type of the string. Represents both the character encoding, and the 'type' of string at the given location. - @param flags: combination of ACFOPT_..., to perform output conversion. + @param flags: combination of STRCONV_..., to perform output conversion. @return: a bytes-filled str object. """ pass # */ -static PyObject *py_get_ascii_contents2( - ea_t ea, - size_t len, - int32 type, - int flags = ACFOPT_ASCII) +static PyObject *py_get_strlit_contents( + ea_t ea, + size_t len, + int32 type, + int flags = 0) { - char *buf = (char *)qalloc(len+1); - if ( buf == NULL ) - return NULL; + qstring buf; - size_t used_size; - if ( !get_ascii_contents2(ea, len, type, buf, len+1, &used_size, flags) ) - { - qfree(buf); + if ( get_strlit_contents(&buf, ea, len, type, NULL, flags) < 0 ) Py_RETURN_NONE; - } - if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' ) - used_size--; + if ( type == STRTYPE_C && buf.length() > 0 && buf.last() == '\0' ) + buf.remove_last(); PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t py_buf(PyString_FromStringAndSize((const char *)buf, used_size)); - qfree(buf); + newref_t py_buf(PyString_FromStringAndSize(buf.begin(), buf.length())); py_buf.incref(); return py_buf.o; } -//--------------------------------------------------------------------------- -/* -# -def get_ascii_contents(ea, len, type): - """ - Get contents of ascii string - This function returns the displayed part of the string - It works even if the string has not been created in the database yet. - @param ea: linear address of the string - @param len: length of the string in bytes (including terminating 0) - @param type: type of the string - @return: string contents (not including terminating 0) or None - """ - pass -# -*/ -static PyObject *py_get_ascii_contents( - ea_t ea, - size_t len, - int32 type) +//------------------------------------------------------------------------- +static ea_t py_bin_search( + ea_t start_ea, + ea_t end_ea, + const uchar *image, + size_t len, + const uchar *mask, + int step, + int flags) { - return py_get_ascii_contents2(ea, len, type); + return bin_search(start_ea, end_ea, image, mask, len, step, flags); } + +//------------------------------------------------------------------------- +static PyObject *py_print_strlit_type(int32 strtype, int flags=0) +{ + qstring s, t; + if ( !print_strlit_type(&s, strtype, &t, flags) ) + Py_RETURN_NONE; + return Py_BuildValue("(ss)", s.c_str(), t.c_str()); +} + // #endif diff --git a/pywraps/py_bytes.py b/pywraps/py_bytes.py index 50516db..4c82e61 100644 --- a/pywraps/py_bytes.py +++ b/pywraps/py_bytes.py @@ -1,8 +1,234 @@ # -def doExtra(ea): - setFlags(ea, get_flags_novalue(ea) | FF_LINE) - -def noExtra(ea): - setFlags(ea, get_flags_novalue(ea) & ~(FF_LINE)) # + + +# +ACFOPT_ASCII=0 +ACFOPT_CONVMASK=0 +ACFOPT_ESCAPE=STRCONV_ESCAPE +ACFOPT_UTF16=0 +ACFOPT_UTF8=0 +DOUNK_DELNAMES=DELIT_DELNAMES +DOUNK_EXPAND=DELIT_EXPAND +DOUNK_NOTRUNC=DELIT_NOTRUNC +DOUNK_SIMPLE=DELIT_SIMPLE +FF_ASCI=FF_STRLIT +FF_DWRD=FF_DWORD +FF_OWRD=FF_OWORD +FF_QWRD=FF_QWORD +FF_STRU=FF_STRUCT +FF_TBYT=FF_TBYTE +FF_VAR=0 +FF_YWRD=FF_YWORD +FF_ZWRD=FF_ZWORD +GFE_NOVALUE=0 +add_hidden_area=add_hidden_range +asciflag=strlit_flag +delValue=del_value +del_hidden_area=del_hidden_range +do16bit=create_16bit_data +do32bit=create_32bit_data +doAlign=create_align +doByte=create_byte +doCustomData=create_custdata +doDouble=create_double +doDwrd=create_dword +doExtra=ida_idaapi._BC695.false_p +doFloat=create_float +doImmd=set_immd +doOwrd=create_oword +doPackReal=create_packed_real +doQwrd=create_qword +doStruct=create_struct +doTbyt=create_tbyte +doWord=create_word +doYwrd=create_yword +doZwrd=create_zword +do_data_ex=create_data +do_unknown=del_items +@bc695redef +def do_unknown_range(ea, size, flags): + return del_items(ea, flags, size) # swap 2 last args +dwrdflag=dword_flag +f_hasRef=f_has_xref +f_isASCII=f_is_strlit +f_isAlign=f_is_align +f_isByte=f_is_byte +f_isCode=f_is_code +f_isCustom=f_is_custom +f_isData=f_is_data +f_isDouble=f_is_double +f_isDwrd=f_is_dword +f_isFloat=f_is_float +f_isHead=f_is_head +f_isNotTail=f_is_not_tail +f_isOwrd=f_is_oword +f_isPackReal=f_is_pack_real +f_isQwrd=f_is_qword +f_isStruct=f_is_struct +f_isTail=f_is_tail +f_isTbyt=f_is_tbyte +f_isWord=f_is_word +f_isYwrd=f_is_yword +getDefaultRadix=get_default_radix +getFlags=get_full_flags +get_long=get_dword +get_full_byte=get_wide_byte +get_full_word=get_wide_word +get_full_long=get_wide_dword +get_original_long=get_original_dword +put_long=put_dword +patch_long=patch_dword +add_long=add_dword +getRadix=get_radix +get_ascii_contents=get_strlit_contents +get_ascii_contents2=get_strlit_contents +get_flags_novalue=get_flags +get_hidden_area=get_hidden_range +get_hidden_area_num=get_hidden_range_num +get_hidden_area_qty=get_hidden_range_qty +@bc695redef +def get_many_bytes(ea, size): + return get_bytes(ea, size) +@bc695redef +def get_many_bytes_ex(ea, size): + return get_bytes_and_mask(ea, size) +get_max_ascii_length=get_max_strlit_length +get_next_hidden_area=get_next_hidden_range +get_prev_hidden_area=get_prev_hidden_range +get_zero_areas=get_zero_ranges +getn_hidden_area=getn_hidden_range +hasExtra=has_extra_cmts +hasRef=has_xref +hasValue=has_value +hidden_area_t=hidden_range_t +isASCII=is_strlit +isAlign=is_align +isByte=is_byte +isChar=is_char +isChar0=is_char0 +isChar1=is_char1 +isCode=is_code +isCustFmt=is_custfmt +isCustFmt0=is_custfmt0 +isCustFmt1=is_custfmt1 +isCustom=is_custom +isData=is_data +isDefArg=is_defarg +isDefArg0=is_defarg0 +isDefArg1=is_defarg1 +isDouble=is_double +isDwrd=is_dword +isEnabled=is_mapped +isEnum=is_enum +isEnum0=is_enum0 +isEnum1=is_enum1 +isFloat=is_float +isFloat0=is_float0 +isFloat1=is_float1 +isFlow=is_flow +isFltnum=is_fltnum +isFop=is_forced_operand +isFunc=is_func +isHead=is_head +isImmd=has_immd +isLoaded=is_loaded +isNotTail=is_not_tail +isNum=is_numop +isNum0=is_numop0 +isNum1=is_numop1 +isOff=is_off +isOff0=is_off0 +isOff1=is_off1 +isOwrd=is_oword +isPackReal=is_pack_real +isQwrd=is_qword +isSeg=is_seg +isSeg0=is_seg0 +isSeg1=is_seg1 +isStkvar=is_stkvar +isStkvar0=is_stkvar0 +isStkvar1=is_stkvar1 +isStroff=is_stroff +isStroff0=is_stroff0 +isStroff1=is_stroff1 +isStruct=is_struct +isTail=is_tail +isTbyt=is_tbyte +isUnknown=is_unknown +isVoid=is_suspop +isWord=is_word +isYwrd=is_yword +isZwrd=is_zword +make_ascii_string=create_strlit +noExtra=ida_idaapi._BC695.false_p +noType=clr_op_type +owrdflag=oword_flag +patch_many_bytes=patch_bytes +print_ascii_string_type=print_strlit_type +put_many_bytes=put_bytes +qwrdflag=qword_flag +tbytflag=tbyte_flag +update_hidden_area=update_hidden_range +ywrdflag=yword_flag +zwrdflag=zword_flag +def get_opinfo(*args): + import ida_nalt + if isinstance(args[3], ida_nalt.opinfo_t): # 6.95: ea, n, flags, buf + ea, n, flags, buf = args + else: # 7.00: buf, ea, n, flags + buf, ea, n, flags = args + return _ida_bytes.get_opinfo(buf, ea, n, flags) +@bc695redef +def doASCI(ea, length): + import ida_netnode + return create_data(ea, FF_STRLIT, length, ida_netnode.BADNODE) +FF_3BYTE=FF_BYTE +chunksize=chunk_size +chunkstart=chunk_start +do3byte=ida_idaapi._BC695.false_p +f_is3byte=ida_idaapi._BC695.false_p +freechunk=free_chunk +get_3byte=ida_idaapi._BC695.false_p +is3byte=ida_idaapi._BC695.false_p +nextaddr=next_addr +nextchunk=next_chunk +nextthat=next_that +prevaddr=prev_addr +prevchunk=prev_chunk +prevthat=prev_that +tribyteflag=byte_flag +alignflag=align_flag +binflag=bin_flag +byteflag=byte_flag +charflag=char_flag +codeflag=code_flag +custflag=cust_flag +custfmtflag=custfmt_flag +decflag=dec_flag +doubleflag=double_flag +enumflag=enum_flag +floatflag=float_flag +fltflag=flt_flag +hexflag=hex_flag +numflag=num_flag +octflag=oct_flag +offflag=off_flag +packrealflag=packreal_flag +segflag=seg_flag +stkvarflag=stkvar_flag +stroffflag=stroff_flag +struflag=stru_flag +wordflag=word_flag +invalidate_visea_cache=ida_idaapi._BC695.false_p +@bc695redef +def op_stroff(*args): + insn, n, path, path_len, delta = args + import ida_ua + if not isinstance(insn, ida_ua.insn_t): + tmp = ida_ua.insn_t() + ida_ua.decode_insn(tmp, insn) + insn = tmp + return _ida_bytes.op_stroff(insn, n, path, path_len, delta) +# diff --git a/pywraps/py_bytes_custdata.hpp b/pywraps/py_bytes_custdata.hpp index 369bd9e..4f0b703 100644 --- a/pywraps/py_bytes_custdata.hpp +++ b/pywraps/py_bytes_custdata.hpp @@ -2,29 +2,33 @@ #define __PY_IDA_BYTES_CUSTDATA__ // -class py_custom_data_type_t + +//------------------------------------------------------------------------- +class py_custom_data_type_t; +static qvector py_custom_data_types; + +//------------------------------------------------------------------------- +class py_custom_data_type_t : public data_type_t { - data_type_t dt; qstring dt_name, dt_menu_name, dt_hotkey, dt_asm_keyword; int dtid; // The data format id - PyObject *py_self; // Associated Python object + PyObject *py_self; // may create data? NULL means always may static bool idaapi s_may_create_at( - void *ud, // user-defined data - ea_t ea, // address of the future item - size_t nbytes) // size of the future item + void *ud, // user-defined data + ea_t ea, // address of the future item + size_t nbytes) // size of the future item { py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; - PYW_GIL_GET; newref_t py_result( PyObject_CallMethod( _this->py_self, (char *)S_MAY_CREATE_AT, - PY_FMT64 PY_FMT64, - pyul_t(ea), - pyul_t(nbytes))); + PY_BV_EA PY_BV_SZ, + bvea_t(ea), + bvsz_t(nbytes))); PyW_ShowCbErr(S_MAY_CREATE_AT); return py_result != NULL && PyObject_IsTrue(py_result.o); @@ -32,11 +36,11 @@ class py_custom_data_type_t // !=NULL means variable size datatype static asize_t idaapi s_calc_item_size( - // This function is used to determine - // size of the (possible) item at 'ea' - void *ud, // user-defined data - ea_t ea, // address of the item - asize_t maxsize) // maximal size of the item + // This function is used to determine + // size of the (possible) item at 'ea' + void *ud, // user-defined data + ea_t ea, // address of the item + asize_t maxsize) // maximal size of the item { PYW_GIL_GET; // Returns: 0-no such item can be created/displayed @@ -46,9 +50,9 @@ class py_custom_data_type_t PyObject_CallMethod( _this->py_self, (char *)S_CALC_ITEM_SIZE, - PY_FMT64 PY_FMT64, - pyul_t(ea), - pyul_t(maxsize))); + PY_BV_EA PY_BV_ASIZE, + bvea_t(ea), + bvasize_t(maxsize))); if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL ) return 0; @@ -59,132 +63,127 @@ class py_custom_data_type_t } public: - const char *get_name() const - { - return dt_name.c_str(); - } - - py_custom_data_type_t() + py_custom_data_type_t( + PyObject *py_dt, + const char *name, + asize_t value_size, + const char *menu_name, + const char *hotkey, + const char *asm_keyword, + int props) { + memset(this, 0, sizeof(data_type_t)); + cbsize = sizeof(data_type_t); + dt_name = name; + dt_menu_name = menu_name; + dt_hotkey = hotkey; + dt_asm_keyword = asm_keyword; + this->name = dt_name.begin(); + this->menu_name = dt_menu_name.begin(); + this->hotkey = dt_hotkey.begin(); + this->asm_keyword = dt_asm_keyword.begin(); + this->value_size = value_size; + this->props = props; dtid = -1; - py_self = NULL; + py_custom_data_types.add_unique(this); + py_self = py_dt; } - int register_dt(PyObject *py_obj) + ~py_custom_data_type_t() + { + do_unregister(); + py_custom_data_types.del(this); + } + + int get_dtid() const { return dtid; } + + int do_register() { PYW_GIL_CHECK_LOCKED_SCOPE(); // Already registered? if ( dtid >= 0 ) - return dtid; + return -1; - memset(&dt, 0, sizeof(dt)); - dt.cbsize = sizeof(dt); - dt.ud = this; + ud = this; - do - { - ref_t py_attr; + ref_t py_attr; - // name - if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) ) - break; + // may_create_at + py_attr = PyW_TryGetAttrString(py_self, S_MAY_CREATE_AT); + if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) + may_create_at = s_may_create_at; - dt.name = dt_name.c_str(); + // calc_item_size + py_attr = PyW_TryGetAttrString(py_self, S_CALC_ITEM_SIZE); + if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) + calc_item_size = s_calc_item_size; - // menu_name (optional) - if ( PyW_GetStringAttr(py_obj, S_MENU_NAME, &dt_menu_name) ) - dt.menu_name = dt_menu_name.c_str(); - - // asm_keyword (optional) - if ( PyW_GetStringAttr(py_obj, S_ASM_KEYWORD, &dt_asm_keyword) ) - dt.asm_keyword = dt_asm_keyword.c_str(); - - // hotkey (optional) - if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &dt_hotkey) ) - dt.hotkey = dt_hotkey.c_str(); - - // value_size - py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - dt.value_size = PyInt_AsLong(py_attr.o); - py_attr = ref_t(); - - // props - py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - dt.props = PyInt_AsLong(py_attr.o); - py_attr = ref_t(); - - // may_create_at - py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - dt.may_create_at = s_may_create_at; - py_attr = ref_t(); - - // calc_item_size - py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - dt.calc_item_size = s_calc_item_size; - py_attr = ref_t(); - - // Now try to register - dtid = register_custom_data_type(&dt); - if ( dtid < 0 ) - break; - - // Hold reference to the PyObject - Py_INCREF(py_obj); - py_self = py_obj; - - py_attr = newref_t(PyInt_FromLong(dtid)); - PyObject_SetAttrString(py_obj, S_ID, py_attr.o); - } while ( false ); + // Now try to register + dtid = register_custom_data_type(this); + if ( dtid >= 0 ) + Py_INCREF(py_self); return dtid; } - bool unregister_dt() + bool do_unregister() { PYW_GIL_CHECK_LOCKED_SCOPE(); - - if ( dtid < 0 ) - return true; - - if ( !unregister_custom_data_type(dtid) ) - return false; - - // Release reference of Python object - Py_XDECREF(py_self); - py_self = NULL; - dtid = -1; - return true; - } - - ~py_custom_data_type_t() - { - unregister_dt(); + bool ok = unregister_custom_data_type(dtid); + if ( ok ) + { + // when this is called at IDAPython-shutdown-time, this will cause the + // dtor to be called, which in turn will call this 'do_unregister' a + // second time, but this is no problem since the dtid has already been + // unregistered and thus we won't end up in this Py_XDECREF block. + Py_XDECREF(py_self); + dtid = -1; + } + return ok; } }; -typedef std::map py_custom_data_type_map_t; -static py_custom_data_type_map_t py_dt_map; -//------------------------------------------------------------------------ -class py_custom_data_format_t +//------------------------------------------------------------------------- +py_custom_data_type_t *py_custom_data_type_cast(data_type_t *inst) +{ + // The following code seems to not work with gcc. Compiler bug? Not sure, but no time ATM + // py_custom_data_type_t *py_inst = (py_custom_data_type_t *) inst; + // py_custom_data_types.has(py_inst) ? py_inst : NULL; + if ( py_custom_data_types.has((py_custom_data_type_t *) inst) ) + return (py_custom_data_type_t *) inst; + else + return 0; +} + +//------------------------------------------------------------------------- +static int py_custom_data_type_t_get_id(data_type_t *_dt) +{ + py_custom_data_type_t *dt = py_custom_data_type_cast(_dt); + return dt != NULL ? dt->get_dtid() : -1; +} + +//------------------------------------------------------------------------- +// data_format_t +//------------------------------------------------------------------------- +class py_custom_data_format_t; +static qvector py_custom_data_formats; + +//------------------------------------------------------------------------- +class py_custom_data_format_t : public data_format_t { private: - data_format_t df; int dfid; PyObject *py_self; qstring df_name, df_menu_name, df_hotkey; - static bool idaapi s_print( // convert to colored string - void *ud, // user-defined data - qstring *out, // output buffer. may be NULL - const void *value, // value to print. may not be NULL - asize_t size, // size of value in bytes - ea_t current_ea, // current address (BADADDR if unknown) - int operand_num, // current operand number - int dtid) // custom data type id + static bool idaapi s_print( // convert to colored string + void *ud, // user-defined data + qstring *out, // output buffer. may be NULL + const void *value, // value to print. may not be NULL + asize_t size, // size of value in bytes + ea_t current_ea, // current address (BADADDR if unknown) + int operand_num, // current operand number + int dtid) // custom data type id { PYW_GIL_GET; @@ -199,9 +198,9 @@ private: newref_t py_result(PyObject_CallMethod( _this->py_self, (char *)S_PRINTF, - "O" PY_FMT64 "ii", + "O" PY_BV_EA "ii", py_value.o, - pyul_t(current_ea), + bvea_t(current_ea), operand_num, dtid)); @@ -224,13 +223,13 @@ private: return ok; } - static bool idaapi s_scan( // convert from uncolored string - void *ud, // user-defined data - bytevec_t *value, // output buffer. may be NULL - const char *input, // input string. may not be NULL - ea_t current_ea, // current address (BADADDR if unknown) - int operand_num, // current operand number (-1 if unknown) - qstring *errstr) // buffer for error message + static bool idaapi s_scan( // convert from uncolored string + void *ud, // user-defined data + bytevec_t *value, // output buffer. may be NULL + const char *input, // input string. may not be NULL + ea_t current_ea, // current address (BADADDR if unknown) + int operand_num, // current operand number (-1 if unknown) + qstring *errstr) // buffer for error message { PYW_GIL_GET; @@ -239,9 +238,9 @@ private: PyObject_CallMethod( _this->py_self, (char *)S_SCAN, - "s" PY_FMT64, + "s" PY_BV_EA "i", input, - pyul_t(current_ea), + bvea_t(current_ea), operand_num)); // Error while calling the function? @@ -292,10 +291,10 @@ private: return ok; } - static void idaapi s_analyze( // analyze custom data format occurrence - void *ud, // user-defined data - ea_t current_ea, // current address (BADADDR if unknown) - int operand_num) // current operand number + static void idaapi s_analyze( // analyze custom data format occurrence + void *ud, // user-defined data + ea_t current_ea, // current address (BADADDR if unknown) + int operand_num) // current operand number // this callback can be used to create // xrefs from the current item. // this callback may be missing. @@ -307,190 +306,117 @@ private: PyObject_CallMethod( _this->py_self, (char *)S_ANALYZE, - PY_FMT64 "i", - pyul_t(current_ea), + PY_BV_EA "i", + bvea_t(current_ea), operand_num)); PyW_ShowCbErr(S_ANALYZE); } public: - py_custom_data_format_t() + py_custom_data_format_t( + PyObject *py_df, + const char *name, + asize_t value_size, + const char *menu_name, + int props, + const char *hotkey, + int32 text_width) { + memset(this, 0, sizeof(data_format_t)); + cbsize = sizeof(data_format_t); + df_name = name; + df_menu_name = menu_name; + df_hotkey = hotkey; + this->name = df_name.begin(); + this->menu_name = df_menu_name.begin(); + this->hotkey = df_hotkey.begin(); + this->value_size = value_size; + this->props = props; + this->text_width = text_width; dfid = -1; - py_self = NULL; - } - - const char *get_name() const - { - return df_name.c_str(); - } - - int register_df(int dtid, PyObject *py_obj) - { - // Already registered? - if ( dfid >= 0 ) - return dfid; - - memset(&df, 0, sizeof(df)); - df.cbsize = sizeof(df); - df.ud = this; - - PYW_GIL_CHECK_LOCKED_SCOPE(); - do - { - ref_t py_attr; - - // name - if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) ) - break; - df.name = df_name.c_str(); - - // menu_name (optional) - if ( PyW_GetStringAttr(py_obj, S_MENU_NAME, &df_menu_name) ) - df.menu_name = df_menu_name.c_str(); - - // props - py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - df.props = PyInt_AsLong(py_attr.o); - - // hotkey - if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) ) - df.hotkey = df_hotkey.c_str(); - - // value_size - py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - df.value_size = PyInt_AsLong(py_attr.o); - - // text_width - py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH); - if ( py_attr != NULL && PyInt_Check(py_attr.o) ) - df.text_width = PyInt_AsLong(py_attr.o); - - // print cb - py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - df.print = s_print; - - // scan cb - py_attr = PyW_TryGetAttrString(py_obj, S_SCAN); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - df.scan = s_scan; - - // analyze cb - py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE); - if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) - df.analyze = s_analyze; - - // Now try to register - dfid = register_custom_data_format(dtid, &df); - if ( dfid < 0 ) - break; - - // Hold reference to the PyObject - Py_INCREF(py_obj); - py_self = py_obj; - - // Update the format ID - py_attr = newref_t(PyInt_FromLong(dfid)); - PyObject_SetAttrString(py_obj, S_ID, py_attr.o); - } while ( false ); - return dfid; - } - - bool unregister_df(int dtid) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Never registered? - if ( dfid < 0 ) - return true; - - if ( !unregister_custom_data_format(dtid, dfid) ) - return false; - - // Release reference of Python object - Py_XDECREF(py_self); - py_self = NULL; - dfid = -1; - return true; + py_custom_data_formats.add_unique(this); + py_self = py_df; } ~py_custom_data_format_t() { + do_unregister(); + py_custom_data_formats.del(this); } -}; -//------------------------------------------------------------------------ -// Helper class to bind pairs to py_custom_data_format_t -class py_custom_data_format_list_t -{ - struct py_custom_data_format_entry_t + int get_dfid() const { return dfid; } + + int do_register() { - int dtid; - int dfid; - py_custom_data_format_t *df; - }; - typedef qvector ENTRY; - ENTRY entries; -public: - typedef ENTRY::iterator POS; - void add(int dtid, int dfid, py_custom_data_format_t *df) - { - py_custom_data_format_entry_t &e = entries.push_back(); - e.dtid = dtid; - e.dfid = dfid; - e.df = df; + // Already registered? + if ( dfid >= 0 ) + return -1; + + ud = this; + + PYW_GIL_CHECK_LOCKED_SCOPE(); + ref_t py_attr; + + // print cb + py_attr = PyW_TryGetAttrString(py_self, S_PRINTF); + if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) + print = s_print; + + // scan cb + py_attr = PyW_TryGetAttrString(py_self, S_SCAN); + if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) + scan = s_scan; + + // analyze cb + py_attr = PyW_TryGetAttrString(py_self, S_ANALYZE); + if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) + analyze = s_analyze; + + // Now try to register + dfid = register_custom_data_format(this); + if ( dfid >= 0 ) + Py_INCREF(py_self); + return dfid; } - py_custom_data_format_t *find(int dtid, int dfid, POS *loc = NULL) + + bool do_unregister() { - for ( POS it=entries.begin(), it_end = entries.end(); it != it_end; ++it ) + PYW_GIL_CHECK_LOCKED_SCOPE(); + bool ok = unregister_custom_data_format(dfid); + if ( ok ) { - if ( it->dfid == dfid && it->dtid == dtid ) - { - if ( loc != NULL ) - *loc = it; - return it->df; - } + // see comment in py_custom_data_type_t::do_unregister() + Py_XDECREF(py_self); + dfid = -1; } - return NULL; - } - void erase(POS &pos) - { - entries.erase(pos); + return ok; } }; -static py_custom_data_format_list_t py_df_list; -//------------------------------------------------------------------------ -static PyObject *py_data_type_to_py_dict(const data_type_t *dt) +//------------------------------------------------------------------------- +py_custom_data_format_t *py_custom_data_format_cast(data_format_t *inst) { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - return Py_BuildValue("{s:" PY_FMT64 ",s:i,s:i,s:s,s:s,s:s,s:s}", - S_VALUE_SIZE, pyul_t(dt->value_size), - S_PROPS, dt->props, - S_CBSIZE, dt->cbsize, - S_NAME, dt->name == NULL ? "" : dt->name, - S_MENU_NAME, dt->menu_name == NULL ? "" : dt->menu_name, - S_HOTKEY, dt->hotkey == NULL ? "" : dt->hotkey, - S_ASM_KEYWORD, dt->asm_keyword == NULL ? "" : dt->asm_keyword); + if ( py_custom_data_formats.has((py_custom_data_format_t *) inst) ) + return (py_custom_data_format_t *) inst; + else + return 0; } -//------------------------------------------------------------------------ -static PyObject *py_data_format_to_py_dict(const data_format_t *df) +//------------------------------------------------------------------------- +static int py_custom_data_format_t_get_id(data_format_t *_df) { - PYW_GIL_CHECK_LOCKED_SCOPE(); + py_custom_data_format_t *df = py_custom_data_format_cast(_df); + return df != NULL ? df->get_dfid() : -1; +} - return Py_BuildValue("{s:i,s:i,s:i,s:" PY_FMT64 ",s:s,s:s,s:s}", - S_PROPS, df->props, - S_CBSIZE, df->cbsize, - S_TEXT_WIDTH, df->text_width, - S_VALUE_SIZE, pyul_t(df->value_size), - S_NAME, df->name == NULL ? "" : df->name, - S_MENU_NAME, df->menu_name == NULL ? "" : df->menu_name, - S_HOTKEY, df->hotkey == NULL ? "" : df->hotkey); +//------------------------------------------------------------------------- +static void clear_custom_data_types_and_formats() +{ + PYW_GIL_GET; + for ( size_t n = py_custom_data_types.size(); n > 0; --n ) + py_custom_data_types[n-1]->do_unregister(); + for ( size_t n = py_custom_data_formats.size(); n > 0; --n ) + py_custom_data_formats[n-1]->do_unregister(); } // @@ -511,19 +437,18 @@ def register_custom_data_type(dt): pass # */ -// Given a py.data_format_t object, this function will register a datatype +// Given a py_data_type_t object, this function will register a datatype static int py_register_custom_data_type(PyObject *py_dt) { - py_custom_data_type_t *inst = new py_custom_data_type_t(); - int r = inst->register_dt(py_dt); - if ( r < 0 ) - { - delete inst; - return r; - } - // Insert the instance to the map - py_dt_map[r] = inst; - return r; + ref_t py_attr = PyW_TryGetAttrString(py_dt, "this"); + if ( py_attr == NULL ) + return -1; + + py_custom_data_type_t *inst = NULL; + int cvt = SWIG_ConvertPtr(py_attr.o, (void **) &inst, SWIGTYPE_p_data_type_t, 0); + if ( !SWIG_IsOK(cvt) || py_custom_data_type_cast(inst) == NULL ) + return -1; + return inst->do_register(); } //------------------------------------------------------------------------ @@ -540,38 +465,25 @@ def unregister_custom_data_type(dtid): */ static bool py_unregister_custom_data_type(int dtid) { - py_custom_data_type_map_t::iterator it = py_dt_map.find(dtid); - - // Maybe the user is trying to unregister a C api dt? - if ( it == py_dt_map.end() ) - return unregister_custom_data_type(dtid); - - py_custom_data_type_t *inst = it->second; - bool ok = inst->unregister_dt(); - - // Perhaps it was automatically unregistered because the idb was close? - if ( !ok ) - { - // Is this type still registered with IDA? - // If not found then mark the context for deletion - ok = find_custom_data_type(inst->get_name()) < 0; - } + const data_type_t *_dt = get_custom_data_type(dtid); + if ( _dt == NULL ) + return false; + py_custom_data_type_t *dt = py_custom_data_type_cast((data_type_t *) _dt); + bool ok = dt != NULL; if ( ok ) - { - py_dt_map.erase(it); - delete inst; - } + ok = dt->do_unregister(); + else + ok = unregister_custom_data_type(dtid); // C API dt return ok; } //------------------------------------------------------------------------ /* # -def register_custom_data_format(dtid, df): +def register_custom_data_format(df): """ Registers a custom data format with a given data type. - @param dtid: data type id @param df: an instance of data_format_t @return: < 0 if failed to register @@ -580,102 +492,47 @@ def register_custom_data_format(dtid, df): pass # */ -static int py_register_custom_data_format(int dtid, PyObject *py_df) +static int py_register_custom_data_format(PyObject *py_df) { - py_custom_data_format_t *inst = new py_custom_data_format_t(); - int r = inst->register_df(dtid, py_df); - if ( r < 0 ) - { - delete inst; - return r; - } - // Insert the instance - py_df_list.add(dtid, r, inst); - return r; + ref_t py_attr = PyW_TryGetAttrString(py_df, "this"); + if ( py_attr == NULL ) + return -1; + + py_custom_data_format_t *inst = NULL; + int cvt = SWIG_ConvertPtr(py_attr.o, (void **) &inst, SWIGTYPE_p_data_format_t, 0); + if ( !SWIG_IsOK(cvt) || py_custom_data_format_cast(inst) == NULL ) + return -1; + + return inst->do_register(); } //------------------------------------------------------------------------ /* # -def unregister_custom_data_format(dtid, dfid): +def unregister_custom_data_format(dfid): """ Unregisters a custom data format - @param dtid: data type id @param dfid: data format id @return: Boolean """ pass # */ -static bool py_unregister_custom_data_format(int dtid, int dfid) +static bool py_unregister_custom_data_format(int dfid) { - py_custom_data_format_list_t::POS pos; - py_custom_data_format_t *inst = py_df_list.find(dtid, dfid, &pos); - // Maybe the user is trying to unregister a C api data format? - if ( inst == NULL ) - return unregister_custom_data_format(dtid, dfid); - - bool ok = inst->unregister_df(dtid); - - // Perhaps it was automatically unregistered because the type was unregistered? - if ( !ok ) - { - // Is this format still registered with IDA? - // If not, mark the context for deletion - ok = find_custom_data_format(inst->get_name()) < 0; - } + const data_format_t *_df = get_custom_data_format(dfid); + if ( _df == NULL ) + return false; + py_custom_data_format_t *df = py_custom_data_format_cast((data_format_t *) _df); + bool ok = df != NULL; if ( ok ) - { - py_df_list.erase(pos); - delete inst; - } + ok = df->do_unregister(); + else + ok = unregister_custom_data_format(dfid); // C API df return ok; } -//------------------------------------------------------------------------ -/* -# -def get_custom_data_format(dtid, dfid): - """ - Returns a dictionary populated with the data format values or None on failure. - @param dtid: data type id - @param dfid: data format id - """ - pass -# -*/ -// Get definition of a registered custom data format and returns a dictionary -static PyObject *py_get_custom_data_format(int dtid, int fid) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - const data_format_t *df = get_custom_data_format(dtid, fid); - if ( df == NULL ) - Py_RETURN_NONE; - return py_data_format_to_py_dict(df); -} - -//------------------------------------------------------------------------ -/* -# -def get_custom_data_type(dtid): - """ - Returns a dictionary populated with the data type values or None on failure. - @param dtid: data type id - """ - pass -# -*/ -// Get definition of a registered custom data format and returns a dictionary -static PyObject *py_get_custom_data_type(int dtid) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - const data_type_t *dt = get_custom_data_type(dtid); - if ( dt == NULL ) - Py_RETURN_NONE; - return py_data_type_to_py_dict(dt); -} - // #endif // __PY_IDA_BYTES_CUSTDATA__ diff --git a/pywraps/py_bytes_custdata.py b/pywraps/py_bytes_custdata.py index 6595424..d142205 100644 --- a/pywraps/py_bytes_custdata.py +++ b/pywraps/py_bytes_custdata.py @@ -1,143 +1,6 @@ # ----------------------------------------------------------------------- # DTP_NODUP = 0x0001 -class data_type_t(object): - """ - Custom data type definition. All data types should inherit from this class. - """ - - def __init__(self, name, value_size = 0, menu_name = None, hotkey = None, asm_keyword = None, props = 0): - """Please refer to bytes.hpp / data_type_t in the SDK""" - self.name = name - self.props = props - self.menu_name = menu_name - self.hotkey = hotkey - self.asm_keyword = asm_keyword - self.value_size = value_size - - self.id = -1 # Will be initialized after registration - """Contains the data type id after the data type is registered""" - - def register(self): - """Registers the data type and returns the type id or < 0 on failure""" - return _ida_bytes.register_custom_data_type(self) - - def unregister(self): - """Unregisters the data type and returns True on success""" - # Not registered? - if self.id < 0: - return True - - # Try to unregister - r = _ida_bytes.unregister_custom_data_type(self.id) - - # Clear the ID - if r: - self.id = -1 - return r -# -# def may_create_at(self, ea, nbytes): -# """ -# (optional) If this callback is not defined then this means always may create data type at the given ea. -# @param ea: address of the future item -# @param nbytes: size of the future item -# @return: Boolean -# """ -# -# return False -# -# def calc_item_size(self, ea, maxsize): -# """ -# (optional) If this callback is defined it means variable size datatype -# This function is used to determine size of the (possible) item at 'ea' -# @param ea: address of the item -# @param maxsize: maximal size of the item -# @return: integer -# Returns: 0-no such item can be created/displayed -# this callback is required only for varsize datatypes -# """ -# return 0 -# -# ----------------------------------------------------------------------- -# Uncomment the corresponding callbacks in the inherited class -class data_format_t(object): - """Information about a data format""" - def __init__(self, name, value_size = 0, menu_name = None, props = 0, hotkey = None, text_width = 0): - """Custom data format definition. - @param name: Format name, must be unique - @param menu_name: Visible format name to use in menus - @param props: properties (currently 0) - @param hotkey: Hotkey for the corresponding menu item - @param value_size: size of the value in bytes. 0 means any size is ok - @text_width: Usual width of the text representation - """ - self.name = name - self.menu_name = menu_name - self.props = props - self.hotkey = hotkey - self.value_size = value_size - self.text_width = text_width - - self.id = -1 # Will be initialized after registration - """contains the format id after the format gets registered""" - - def register(self, dtid): - """Registers the data format with the given data type id and returns the type id or < 0 on failure""" - return _ida_bytes.register_custom_data_format(dtid, self) - - def unregister(self, dtid): - """Unregisters the data format with the given data type id""" - - # Not registered? - if self.id < 0: - return True - - # Unregister - r = _ida_bytes.unregister_custom_data_format(dtid, self.id) - - # Clear the ID - if r: - self.id = -1 - return r -# -# def printf(self, value, current_ea, operand_num, dtid): -# """ -# Convert a value buffer to colored string. -# -# @param value: The value to be printed -# @param current_ea: The ea of the value -# @param operand_num: The affected operand -# @param dtid: custom data type id (0-standard built-in data type) -# @return: a colored string representing the passed 'value' or None on failure -# """ -# return None -# -# def scan(self, input, current_ea, operand_num): -# """ -# Convert from uncolored string 'input' to byte value -# -# @param input: input string -# @param current_ea: current address (BADADDR if unknown) -# @param operand_num: current operand number (-1 if unknown) -# -# @return: tuple (Boolean, string) -# - (False, ErrorMessage) if conversion fails -# - (True, Value buffer) if conversion succeeds -# """ -# return (False, "Not implemented") -# -# def analyze(self, current_ea, operand_num): -# """ -# (optional) Analyze custom data format occurrence. -# It can be used to create xrefs from the current item. -# -# @param current_ea: current address (BADADDR if unknown) -# @param operand_num: current operand number -# @return: None -# """ -# -# pass -# # ----------------------------------------------------------------------- def __walk_types_and_formats(formats, type_action, format_action, installing): broken = False @@ -182,17 +45,27 @@ def register_data_types_and_formats(formats): ] The first two tuples describe data types and their associated formats. The last two tuples describe two data formats to be used with built-in data types. + The data format may be attached to several data types. The id of the + data format is stored in the first data_format_t object. For example: + assert many_formats[1][1] != -1 + assert many_formats[2][0] != -1 + assert many_formats[3][0] == -1 """ def __reg_format(df, dtid): - df.register(dtid) + dfid = register_custom_data_format(df); + if dfid == -1: + dfid = find_custom_data_format(df.name); + if dfid == -1: + return False + attach_custom_data_format(dtid, dfid) if dtid == 0: - print "Registered format '%s' with built-in types, ID=%d" % (df.name, df.id) + print "Registered format '%s' with built-in types, ID=%d" % (df.name, dfid) else: - print " Registered format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid) - return df.id != -1 + print " Registered format '%s', ID=%d (dtid=%d)" % (df.name, dfid, dtid) + return True def __reg_type(dt): - dt.register() + register_custom_data_type(dt) print "Registered type '%s', ID=%d" % (dt.name, dt.id) return dt.id != -1 ok = __walk_types_and_formats(formats, __reg_type, __reg_format, True) @@ -205,15 +78,93 @@ def unregister_data_types_and_formats(formats): """ def __unreg_format(df, dtid): print "%snregistering format '%s'" % ("U" if dtid == 0 else " u", df.name) - df.unregister(dtid) + unregister_custom_data_format(df.id) return True def __unreg_type(dt): print "Unregistering type '%s', ID=%d" % (dt.name, dt.id) - dt.unregister() + unregister_custom_data_type(dt.id) return True ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format, False) return 1 if ok else -1 +#-------------------------------------------------------------------------- +# +# +# +#class data_type_t(object): +# """ +# The following optional callback methods can be implemented +# in a data_type_t subclass +# """ +# +# def may_create_at(ea, nbytes): +# """May create data? +# No such callback means: always succeed (i.e., no restriction where +# such a data type can be created.) +# @param ea: candidate address for the data item +# @param nbytes: candidate size for the data item +# @return: True/False +# """ +# return True +# +# def calc_item_size(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`. +# (thus, this callback is required only for varsize datatypes.) +# @param ea: address of the item +# @param maxsize: maximum size of the item +# @return: 0 - no such item can be created/displayed +# """ +# return 0 +# +# +#class data_format_t(object): +# """ +# The following callback methods can be implemented +# in a data_format_t subclass +# """ +# +# def printf(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) +# @param operand_num: current operand number +# @param dtid: custom data type id +# @return: string representing data +# """ +# return None +# +# def scan(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., +# an MMX register.) +# @param input: input string +# @param current_ea: current address (BADADDR if unknown) +# @param operand_num: current operand number (-1 if unknown) +# @return: tuple(bool, string) +# (True, output value) or +# (False, error message) +# """ +# return (False, "Not implemented") +# +# def analyze(current_ea, operand_num): +# """Analyze custom data format occurrence. +# This callback is called in 2 cases: +# - after emulating an instruction (after a call of +# 'ev_emu_insn') if its operand is marked as "custom data +# representation" +# - when emulating data (this is done using a call of +# 'ev_out_data' with analyze_only == true). This is the right +# place to create cross references from the current item. +# @param current_ea: current address (BADADDR if unknown) +# @param operand_num: current operand number +# """ +# pass +# +# +# # # ----------------------------------------------------------------------- diff --git a/pywraps/py_dbg.hpp b/pywraps/py_dbg.hpp index 7aaa64b..bd58f13 100644 --- a/pywraps/py_dbg.hpp +++ b/pywraps/py_dbg.hpp @@ -12,16 +12,16 @@ def get_manual_regions(): """ Returns the manual memory regions - @return: list(startEA, endEA, name, sclass, sbase, bitness, perm) + @return: list(start_ea, end_ea, name, sclass, sbase, bitness, perm) """ pass # */ static PyObject *py_get_manual_regions() { - meminfo_vec_t areas; - get_manual_regions(&areas); - return meminfo_vec_t_to_py(areas); + meminfo_vec_t ranges; + get_manual_regions(&ranges); + return meminfo_vec_t_to_py(ranges); } //------------------------------------------------------------------------- @@ -61,20 +61,20 @@ static PyObject *refresh_debugger_memory() dbg->stopped_at_debug_event(true); // Invalidate the cache - isEnabled(0); + is_mapped(0); PYW_GIL_CHECK_LOCKED_SCOPE(); Py_RETURN_NONE; } -int idaapi DBG_Callback(void *ud, int notification_code, va_list va); +ssize_t idaapi DBG_Callback(void *ud, int notification_code, va_list va); class DBG_Hooks { public: virtual ~DBG_Hooks() { unhook(); } - bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); } - bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); } + bool hook() { return idapython_hook_to_notification_point(HT_DBG, DBG_Callback, this); } + bool unhook() { return idapython_unhook_from_notification_point(HT_DBG, DBG_Callback, this); } static int store_int(int rc, const debug_event_t *, int *warn) { @@ -91,7 +91,7 @@ public: // hookgenDBG:methods }; -int idaapi DBG_Callback(void *ud, int notification_code, va_list va) +ssize_t idaapi DBG_Callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; @@ -168,7 +168,7 @@ static ea_t py_internal_get_sreg_base(thid_t tid, int sreg_value) { PYW_GIL_CHECK_LOCKED_SCOPE(); ea_t answer; - return internal_get_sreg_base(tid, sreg_value, &answer) < 1 + return internal_get_sreg_base(&answer, tid, sreg_value) < 1 ? BADADDR : answer; } diff --git a/pywraps/py_dbg.py b/pywraps/py_dbg.py index 4cacdaf..87b22ef 100644 --- a/pywraps/py_dbg.py +++ b/pywraps/py_dbg.py @@ -1,8 +1,48 @@ - # +import ida_idd + +def get_tev_reg_val(tev, reg): + rv = ida_idd.regval_t() + if get_insn_tev_reg_val(tev, reg, rv): + if rv.rvtype == ida_idd.RVT_INT: + return rv.ival + +def get_tev_reg_mem_qty(tev): + ti = tev_info_t() + if get_tev_info(tev, ti): + mis = memreg_infos_t() + if get_insn_tev_reg_mem(tev, mis): + return mis.size() + def get_tev_reg_mem(tev, idx): mis = memreg_infos_t() if get_insn_tev_reg_mem(tev, mis): if idx < mis.size(): return mis[idx].bytes + +def get_tev_reg_mem_ea(tev, idx): + ti = tev_info_t() + if get_tev_info(tev, ti): + mis = memreg_infos_t() + if get_insn_tev_reg_mem(tev, mis): + if idx >= 0 and idx < mis.size(): + return mis[idx].ea # + +# +import ida_idd +@bc695redef +def get_process_info(n, pi): + pis = ida_idd.procinfo_vec_t() + cnt = get_processes(pis) + if n >= cnt: + return ida_idd.NO_PROCESS + pi.name = pis[n].name + pi.pid = pis[n].pid + return pi.pid + +@bc695redef +def get_process_qty(): + pis = ida_idd.procinfo_vec_t() + return get_processes(pis) +# diff --git a/pywraps/py_diskio.hpp b/pywraps/py_diskio.hpp index 8c7b937..4db535f 100644 --- a/pywraps/py_diskio.hpp +++ b/pywraps/py_diskio.hpp @@ -17,6 +17,16 @@ int idaapi py_enumerate_files_cb(const char *file, void *ud) NULL)); return (py_ret == NULL || !PyNumber_Check(py_ret.o)) ? 1 /* stop enum on failure */ : PyInt_AsLong(py_ret.o); } + +//------------------------------------------------------------------------- +struct bytearray_linput_data_t +{ + linput_t *li; + qstring *bytes; +}; +DECLARE_TYPE_AS_MOVABLE(bytearray_linput_data_t); +typedef qvector bytearray_linput_data_vec_t; +static bytearray_linput_data_vec_t bytearray_linput_data_vec; // // @@ -59,6 +69,42 @@ PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback } while ( false ); Py_RETURN_NONE; } + +//------------------------------------------------------------------------- +linput_t *py_create_bytearray_linput(const qstring &s) +{ + qstring *bytes = new qstring(s); + linput_t *li = create_bytearray_linput((const uchar *) bytes->c_str(), bytes->length()); + if ( li != NULL ) + { + bytearray_linput_data_t &ld = bytearray_linput_data_vec.push_back(); + ld.bytes = bytes; + ld.li = li; + } + else + { + delete bytes; + } + return li; +} + +//------------------------------------------------------------------------- +void py_close_linput(linput_t *li) +{ + bytearray_linput_data_vec_t::iterator it = bytearray_linput_data_vec.begin(); + bytearray_linput_data_vec_t::iterator end = bytearray_linput_data_vec.end(); + for ( ; it != end; ++it ) + { + if ( it->li == li ) + { + delete it->bytes; + bytearray_linput_data_vec.erase(it); + break; + } + } + close_linput(li); +} + // #endif diff --git a/pywraps/py_diskio.py b/pywraps/py_diskio.py index 9434cb7..44c7034 100644 --- a/pywraps/py_diskio.py +++ b/pywraps/py_diskio.py @@ -1,5 +1,4 @@ -# -def enumerate_system_files(subdir, fname, callback): - """Similar to enumerate_files() however it searches inside IDA directory or its subdirectories""" - return enumerate_files(idadir(subdir), fname, callback) -# +# +create_generic_linput64=create_generic_linput +generic_linput64_t=generic_linput_t +# diff --git a/pywraps/py_enum.py b/pywraps/py_enum.py new file mode 100644 index 0000000..11661b3 --- /dev/null +++ b/pywraps/py_enum.py @@ -0,0 +1,37 @@ +# +CONST_ERROR_ENUM=ENUM_MEMBER_ERROR_NAME +CONST_ERROR_ILLV=ENUM_MEMBER_ERROR_VALUE +CONST_ERROR_MASK=ENUM_MEMBER_ERROR_ENUM +CONST_ERROR_NAME=ENUM_MEMBER_ERROR_MASK +CONST_ERROR_VALUE=ENUM_MEMBER_ERROR_ILLV +add_const=add_enum_member +del_const=del_enum_member +get_const=get_enum_member +get_const_bmask=get_enum_member_bmask +get_const_by_name=get_enum_member_by_name +get_const_cmt=get_enum_member_cmt +get_const_enum=get_enum_member_enum +get_const_name=get_enum_member_name +get_const_serial=get_enum_member_serial +get_const_value=get_enum_member_value +get_first_const=get_first_enum_member +get_first_serial_const=get_first_serial_enum_member +get_last_const=get_last_enum_member +get_last_serial_const=get_last_serial_enum_member +get_next_const=get_next_enum_member +get_next_serial_const=get_next_serial_enum_member +get_prev_const=get_prev_enum_member +get_prev_serial_const=get_prev_serial_enum_member +set_const_cmt=set_enum_member_cmt +set_const_name=set_enum_member_name +def get_next_serial_enum_member(*args): + serial, cid = args[0], args[1] + if serial > 0xFF: + serial, cid = cid, serial + return _ida_enum.get_next_serial_enum_member(serial, cid) +def get_prev_serial_enum_member(*args): + serial, cid = args[0], args[1] + if serial > 0xFF: + serial, cid = cid, serial + return _ida_enum.get_prev_serial_enum_member(serial, cid) +# diff --git a/pywraps/py_expr.hpp b/pywraps/py_expr.hpp index e6bdcaa..c313ab6 100644 --- a/pywraps/py_expr.hpp +++ b/pywraps/py_expr.hpp @@ -4,50 +4,51 @@ // struct py_idcfunc_ctx_t { - PyObject *py_func; + ref_t py_func; qstring name; int nargs; - py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs) + py_idcfunc_ctx_t(PyObject *_py_func, const char *name, int nargs) + : py_func(borref_t(_py_func)), + name(name), + nargs(nargs) { PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_INCREF(py_func); } ~py_idcfunc_ctx_t() { PYW_GIL_CHECK_LOCKED_SCOPE(); - Py_DECREF(py_func); } }; //--------------------------------------------------------------------------- static error_t py_call_idc_func( - void *_ctx, - idc_value_t *argv, - idc_value_t *r) + void *_ctx, + idc_value_t *argv, + idc_value_t *r) { + PYW_GIL_GET; + // Convert IDC arguments to Python list py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx; - int cvt; - char errbuf[MAXSTR]; - PYW_GIL_CHECK_LOCKED_SCOPE(); ref_vec_t pargs; - if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, true, errbuf, sizeof(errbuf)) ) + qstring errbuf; + if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, PYWCVTF_AS_TUPLE, &errbuf) ) { // Error during conversion? Create an IDC exception - return PyW_CreateIdcException(r, errbuf); + return PyW_CreateIdcException(r, errbuf.c_str()); } // Call the Python function - newref_t py_result(PyObject_CallObject( - ctx->py_func, - pargs.empty() ? NULL : pargs[0].o)); + newref_t py_result = PyObject_CallObject( + ctx->py_func.o, + pargs.empty() ? NULL : pargs[0].o); + int cvt; error_t err; - qstring qerrbuf; - if ( PyW_GetError(&qerrbuf) ) + if ( PyW_GetError(&errbuf) ) { - err = PyW_CreateIdcException(r, qerrbuf.c_str()); + err = PyW_CreateIdcException(r, errbuf.c_str()); } else { @@ -78,9 +79,9 @@ static size_t py_get_call_idc_func() // - capture the python callable // - return a C context as a numeric value static size_t pyw_register_idc_func( - const char *name, - const char *args, - PyObject *py_fp) + const char *name, + const char *args, + PyObject *py_fp) { return (size_t)new py_idcfunc_ctx_t(py_fp, name, strlen(args)); } @@ -92,7 +93,7 @@ static bool pyw_unregister_idc_func(size_t ctxptr) { // Unregister the function py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)ctxptr; - bool ok = set_idc_func_ex(ctx->name.c_str(), NULL, NULL, 0); + bool ok = del_idc_func(ctx->name.c_str()); // Delete the context delete ctx; @@ -100,53 +101,69 @@ static bool pyw_unregister_idc_func(size_t ctxptr) return ok; } -//--------------------------------------------------------------------------- -static bool py_set_idc_func_ex( - const char *name, - size_t fp_ptr, - const char *args, - int flags) +//------------------------------------------------------------------------- +typedef qvector idc_values_t; + +//------------------------------------------------------------------------- +static bool pyw_convert_defvals(idc_values_t *out, PyObject *py_seq) { - return set_idc_func_ex(name, (idc_func_t *)fp_ptr, args, flags); + if ( !PySequence_Check(py_seq) ) + return false; + for ( Py_ssize_t i = 0, n = PySequence_Size(py_seq); i < n; ++i ) + { + newref_t py_var(PySequence_GetItem(py_seq, i)); + idc_value_t &idc_var = out->push_back(); + if ( pyvar_to_idcvar(py_var, &idc_var, NULL) != CIP_OK ) + return false; + } + return true; } //--------------------------------------------------------------------------- -// Compile* functions return false when error so the return +static bool py_add_idc_func( + const char *name, + size_t fp_ptr, + const char *args, + const idc_values_t &defvals, + int flags) +{ + ext_idcfunc_t desc = { name, (idc_func_t *)fp_ptr, args, defvals.begin(), defvals.size(), flags }; + return add_idc_func(desc); +} + +//--------------------------------------------------------------------------- +// compile_idc_* functions return false when error so the return // value must be negated for the error string to be returned -bool CompileEx_wrap( - const char *file, - bool del_macros, - char *errbuf, size_t errbufsize) +bool py_compile_idc_file( + const char *file, + qstring *errbuf) { - return !CompileEx(file, del_macros, errbuf, errbufsize); + return !compile_idc_file(file, errbuf); } -bool Compile_wrap(const char *file, char *errbuf, size_t errbufsize) +bool py_compile_idc_text( + const char *line, + qstring *errbuf) { - return !Compile(file, errbuf, errbufsize); + return !compile_idc_text(line, errbuf); } -bool calcexpr_wrap( - ea_t where, - const char *line, - idc_value_t *rv, - char *errbuf, size_t errbufsize) +bool py_eval_expr( + idc_value_t *rv, + ea_t where, + const char *line, + qstring *errbuf) { - return !calcexpr(where, line, rv, errbuf, errbufsize); + return !eval_expr(rv, where, line, errbuf); } -bool calc_idc_expr_wrap( - ea_t where, - const char *line, - idc_value_t *rv, - char *errbuf, size_t errbufsize) +bool py_eval_idc_expr( + idc_value_t *rv, + ea_t where, + const char *line, + qstring *errbuf) { - return !calc_idc_expr(where, line, rv, errbuf, errbufsize); -} - -bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize) -{ - return !CompileLineEx(line, errbuf, errbufsize); + return !eval_idc_expr(rv, where, line, errbuf); } // diff --git a/pywraps/py_expr.py b/pywraps/py_expr.py index c5838bb..f59f78e 100644 --- a/pywraps/py_expr.py +++ b/pywraps/py_expr.py @@ -5,20 +5,19 @@ try: import ctypes # Callback for IDC func callback (On Windows, we use stdcall) # typedef error_t idaapi idc_func_t(idc_value_t *argv,idc_value_t *r); - _IDCFUNC_CB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) + try: + _IDCFUNC_CB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) + except: + _IDCFUNC_CB_T = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) # A trampoline function that is called from idcfunc_t that will # call the Python callback with the argv and r properly serialized to python - call_idc_func__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_expr.py_get_call_idc_func()) + call_idc_func__ = ctypes.CFUNCTYPE(ctypes.c_long, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)(_ida_expr.py_get_call_idc_func()) except: def call_idc_func__(*args): warning("IDC extensions need ctypes library in order to work") return 0 - try: - _IDCFUNC_CB_T = CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) - except: - _IDCFUNC_CB_T = None - + _IDCFUNC_CB_T = None # -------------------------------------------------------------------------- EXTFUN_BASE = 0x0001 @@ -37,7 +36,7 @@ class _IdcFunction(object): self.ctxptr = ctxptr # Take a reference to the ctypes callback # (note: this will create a circular reference) - self.cb = _IDCFUNC_CB_T(self) + self.cb = _IDCFUNC_CB_T(self) fp_ptr = property(lambda self: ctypes.cast(self.cb, ctypes.c_void_p).value) @@ -50,48 +49,65 @@ class _IdcFunction(object): # retrieved by using the internal pyw_register_idc_func() __IDC_FUNC_CTXS = {} -# -------------------------------------------------------------------------- -def set_idc_func_ex(name, fp=None, args=(), flags=0): +def del_idc_func(name): """ - Extends the IDC language by exposing a new IDC function that is backed up by a Python function - This function also unregisters the IDC function if 'fp' was passed as None + Unregisters the specified IDC function - @param name: IDC function name to expose - @param fp: Python callable that will receive the arguments and return a tuple. - If this argument is None then the IDC function is unregistered - @param args: Arguments. A tuple of idaapi.VT_XXX constants - @param flags: IDC function flags. A combination of EXTFUN_XXX constants + @param name: IDC function name to unregister - @return: Boolean. + @return: Boolean """ global __IDC_FUNC_CTXS # Get the context f = __IDC_FUNC_CTXS.get(name, None) - # Unregistering? - if fp is None: - # Not registered? - if f is None: - return False + if f is None: + return False # Not registered - # Break circular reference - del f.cb + # Break circular reference + del f.cb - # Delete the name from the dictionary - del __IDC_FUNC_CTXS[name] + # Delete the name from the dictionary + del __IDC_FUNC_CTXS[name] - # Delete the context and unregister the function - return _ida_expr.pyw_unregister_idc_func(f.ctxptr) + # Delete the context and unregister the function + return _ida_expr.pyw_unregister_idc_func(f.ctxptr) + +# -------------------------------------------------------------------------- +def add_idc_func(name, fp, args, defvals=None, flags=0): + """ + Extends the IDC language by exposing a new IDC function that is backed up by a Python function + + @param name: IDC function name to expose + @param fp: Python callable that will receive the arguments and return a tuple. + @param args: Arguments. A tuple of idaapi.VT_XXX constants + @param flags: IDC function flags. A combination of EXTFUN_XXX constants + + @return: Boolean + """ + global __IDC_FUNC_CTXS + + # Get the context + f = __IDC_FUNC_CTXS.get(name, None) # Registering a function that is already registered? if f is not None: # Unregister it first - set_idc_func_ex(name, None) + del_idc_func(name) # Convert the tupple argument info to a string args = "".join([chr(x) for x in args]) + # make sure we don't have an obvious discrepancy between + # the number of args, and the provided default values + if len(defvals) > len(args): + return False + + vdefvals = idc_values_t() + if not _ida_expr.pyw_convert_defvals(vdefvals, defvals): + return False + # Create a context ctxptr = _ida_expr.pyw_register_idc_func(name, args, fp) if ctxptr == 0: @@ -104,10 +120,55 @@ def set_idc_func_ex(name, fp=None, args=(), flags=0): __IDC_FUNC_CTXS[name] = f # Register IDC function with a callback - return _ida_expr.py_set_idc_func_ex( + return _ida_expr.py_add_idc_func( name, f.fp_ptr, args, + vdefvals, flags) # + +# +Compile=compile_idc_file +CompileEx=compile_idc_file +CompileLine=compile_idc_text +VT_STR2=VT_STR +VarCopy=copy_idcv +VarDelAttr=del_idcv_attr +VarDeref=deref_idcv +VarFirstAttr=first_idcv_attr +@bc695redef +def VarGetAttr(obj, attr, res, may_use_getattr=False): + return get_idcv_attr(res, obj, attr, may_use_getattr) +VarGetClassName=get_idcv_class_name +VarGetSlice=get_idcv_slice +VarInt64=idcv_int64 +VarLastAttr=last_idcv_attr +VarMove=move_idcv +VarNextAttr=next_idcv_attr +VarObject=idcv_object +VarPrevAttr=prev_idcv_attr +VarPrint=print_idcv +VarRef=create_idcv_ref +VarSetAttr=set_idcv_attr +VarSetSlice=set_idcv_slice +VarString2=idcv_string +VarSwap=swap_idcvs +@bc695redef +def calc_idc_expr(where, expr, res): + return eval_idc_expr(res, where, expr) +@bc695redef +def calcexpr(where, expr, res): + return eval_expr(res, where, expr) +@bc695redef +def dosysfile(complain_if_no_file, fname): + return exec_system_script(fname, complain_if_no_file) +@bc695redef +def execute(line): + return eval_idc_snippet(None, line) +py_set_idc_func_ex=py_add_idc_func +@bc695redef +def set_idc_func_ex(name, fp=None, args=(), flags=0): + return add_idc_func(name, fp, args, (), flags) +# diff --git a/pywraps/py_fixup.py b/pywraps/py_fixup.py new file mode 100644 index 0000000..b862b0c --- /dev/null +++ b/pywraps/py_fixup.py @@ -0,0 +1,6 @@ + +# +FIXUP_CREATED=FIXUPF_CREATED +FIXUP_EXTDEF=FIXUPF_EXTDEF +FIXUP_REL=FIXUPF_REL +# diff --git a/pywraps/py_fpro.hpp b/pywraps/py_fpro.hpp index 7eed9f1..1f26367 100644 --- a/pywraps/py_fpro.hpp +++ b/pywraps/py_fpro.hpp @@ -207,7 +207,7 @@ public: } //-------------------------------------------------------------------------- - int seek(int32 offset, int whence = SEEK_SET) + int seek(int64 offset, int whence = SEEK_SET) { int rc; Py_BEGIN_ALLOW_THREADS; @@ -217,9 +217,9 @@ public: } //-------------------------------------------------------------------------- - int32 tell() + int64 tell() { - int32 rc; + int64 rc; Py_BEGIN_ALLOW_THREADS; rc = qftell(fp); Py_END_ALLOW_THREADS; @@ -348,10 +348,10 @@ public: } //-------------------------------------------------------------------------- - int32 size() + int64 size() { PYW_GIL_CHECK_LOCKED_SCOPE(); - int32 r; + qoff64_t r; Py_BEGIN_ALLOW_THREADS; int pos = qfseek(fp, 0, SEEK_END); r = qftell(fp); diff --git a/pywraps/py_frame.hpp b/pywraps/py_frame.hpp index ba3ad67..acc3bab 100644 --- a/pywraps/py_frame.hpp +++ b/pywraps/py_frame.hpp @@ -1,27 +1,4 @@ // -//------------------------------------------------------------------------- -/* -header: frame.hpp -# -def add_stkvar3(op, v, flags): - """ - Automatically add stack variable if doesn't exist - Processor modules should use ua_stkvar2() - @param op: reference to instruction operand - @param v: immediate value in the operand (usually op.addr) - @param flags: combination of STKVAR_... constants - @return: Boolean - """ - pass -# -*/ -bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - uint64 v; - return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true; -} //------------------------------------------------------------------------- /* @@ -39,21 +16,16 @@ def get_stkvar(op, v): pass # */ -PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v) +PyObject *py_get_stkvar(const insn_t &insn, const op_t &op, sval_t v) { PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - uint64 v; - if ( op == NULL || !PyW_GetNumber(py_v, &v) ) - Py_RETURN_NONE; - sval_t actval; - member_t *member = get_stkvar(*op, sval_t(v), &actval); + member_t *member = get_stkvar(&actval, insn, op, v); if ( member == NULL ) Py_RETURN_NONE; - return Py_BuildValue("(O" PY_SFMT64 ")", + return Py_BuildValue("(O" PY_BV_SVAL ")", SWIG_NewPointerObj(SWIG_as_voidptr(member), SWIGTYPE_p_member_t, 0), - pyl_t(actval)); + bvsval_t(actval)); } // diff --git a/pywraps/py_frame.py b/pywraps/py_frame.py new file mode 100644 index 0000000..5081506 --- /dev/null +++ b/pywraps/py_frame.py @@ -0,0 +1,21 @@ + +# +add_auto_stkpnt2=add_auto_stkpnt +# in fact, we cannot simulate add_stkvar[23] here, because we simply +# don't have the insn_t object -- and no way of retrieving it, either, +# since cmd is gone +def get_stkvar(*args): + if len(args) == 2: + import ida_ua + insn, op, v = ida_ua.cmd, args[0], args[1] + else: + insn, op, v = args + return _ida_frame.get_stkvar(insn, op, v) +def get_frame_part(*args): + import ida_funcs + if isinstance(args[0], ida_funcs.func_t): # 6.95: pfn, part, range + rnge, pfn, part = args[2], args[0], args[1] + else: # 7.00: range, pfn, part + rnge, pfn, part = args + return _ida_frame.get_frame_part(rnge, pfn, part) +# diff --git a/pywraps/py_funcs.hpp b/pywraps/py_funcs.hpp index 4075db0..7601645 100644 --- a/pywraps/py_funcs.hpp +++ b/pywraps/py_funcs.hpp @@ -42,13 +42,13 @@ def get_idasgn_desc(n): */ static PyObject *py_get_idasgn_desc(int n) { - char signame[MAXSTR]; - char optlibs[MAXSTR]; + qstring signame; + qstring optlibs; - if ( get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)) < 0 ) + if ( get_idasgn_desc(&signame, &optlibs, n) < 0 ) Py_RETURN_NONE; else - return Py_BuildValue("(ss)", signame, optlibs); + return Py_BuildValue("(ss)", signame.c_str(), optlibs.c_str()); } //----------------------------------------------------------------------- @@ -67,42 +67,14 @@ def get_idasgn_desc_with_matches(n): */ static PyObject *py_get_idasgn_desc_with_matches(int n) { - char signame[MAXSTR]; - char optlibs[MAXSTR]; + qstring signame; + qstring optlibs; - int32 matches = get_idasgn_desc(n, signame, sizeof(signame), optlibs, sizeof(optlibs)); + int32 matches = get_idasgn_desc(&signame, &optlibs, n); if ( matches < 0 ) Py_RETURN_NONE; else - return Py_BuildValue("(ssi)", signame, optlibs, matches); -} - -//----------------------------------------------------------------------- -/* -# -def get_func_cmt(fn, repeatable): - """ - Retrieve function comment - @param fn: function instance - @param repeatable: retrieve repeatable or non-repeatable comments - @return: None on failure or the comment - """ - pass -# -*/ -static PyObject *py_get_func_cmt(func_t *fn, bool repeatable) -{ - char *s = get_func_cmt(fn, repeatable); - if ( s == NULL ) - { - Py_RETURN_NONE; - } - else - { - PyObject *py_s = PyString_FromString(s); - qfree(s); - return py_s; - } + return Py_BuildValue("(ssi)", signame.c_str(), optlibs.c_str(), matches); } // diff --git a/pywraps/py_funcs.py b/pywraps/py_funcs.py new file mode 100644 index 0000000..8dbc3d7 --- /dev/null +++ b/pywraps/py_funcs.py @@ -0,0 +1,25 @@ +# +# + +# +FUNC_STATIC=FUNC_STATICDEF +add_regarg2=add_regarg +clear_func_struct=lambda *args: True +@bc695redef +def del_func_cmt(pfn, rpt): + set_func_cmt(pfn, "", rpt) +func_parent_iterator_set2=func_parent_iterator_set +func_setend=set_func_end +func_setstart=set_func_start +func_tail_iterator_set2=func_tail_iterator_set +@bc695redef +def get_func_limits(pfn, limits): + import ida_range + rs = ida_range.rangeset_t() + if get_func_ranges(rs, pfn) == ida_idaapi.BADADDR: + return False + limits.start_ea = rs.begin().start_ea + limits.end_ea = rs.begin().end_ea + return True +get_func_name2=get_func_name +# diff --git a/pywraps/py_gdl.py b/pywraps/py_gdl.py index f503ef9..090c768 100644 --- a/pywraps/py_gdl.py +++ b/pywraps/py_gdl.py @@ -10,11 +10,11 @@ class BasicBlock(object): self.id = id """Basic block ID""" - self.startEA = bb.startEA - """startEA of basic block""" + self.start_ea = bb.start_ea + """start_ea of basic block""" - self.endEA = bb.endEA - """endEA of basic block""" + self.end_ea = bb.end_ea + """end_ea of basic block""" self.type = self._fc._q.calc_block_type(self.id) """Block type (check fc_block_type_t enum)""" @@ -37,6 +37,13 @@ class BasicBlock(object): for i in xrange(0, q.nsucc(self.id)): yield self._fc[q.succ(self.id, i)] + try: + if _BC695: + startEA = property(lambda self: self.start_ea, lambda self, ea: setattr(self, "start_ea", ea)) + endEA = property(lambda self: self.end_ea, lambda self, ea: setattr(self, "end_ea", ea)) + except: + pass # BC695 not defined at compile-time + # ----------------------------------------------------------------------- class FlowChart(object): """ diff --git a/pywraps/py_graph.hpp b/pywraps/py_graph.hpp index 43d3b9b..b2583af 100644 --- a/pywraps/py_graph.hpp +++ b/pywraps/py_graph.hpp @@ -18,10 +18,9 @@ private: GRCODE_HAVE_GOTFOCUS = 0x00080000, GRCODE_HAVE_LOSTFOCUS = 0x00100000, GRCODE_HAVE_CHANGED_CURRENT = 0x00200000, - GRCODE_HAVE_COMMAND = 0x00400000, - GRCODE_HAVE_CREATING_GROUP = 0x00800000, - GRCODE_HAVE_DELETING_GROUP = 0x01000000, - GRCODE_HAVE_GROUP_VISIBILITY = 0x02000000, + GRCODE_HAVE_CREATING_GROUP = 0x00400000, + GRCODE_HAVE_DELETING_GROUP = 0x00800000, + GRCODE_HAVE_GROUP_VISIBILITY = 0x01000000, }; struct nodetext_cache_t { @@ -48,84 +47,29 @@ private: } }; - class cmdid_map_t: public std::map - { - private: - Py_ssize_t uid; - public: - - cmdid_map_t() - { - // We start by one and keep zero for error id - uid = 1; - } - - void add(py_graph_t *pyg) - { - (*this)[uid] = pyg; - ++uid; - } - - const Py_ssize_t id() const - { - return uid; - } - - void clear(py_graph_t *pyg) - { - iterator e = end(); - for ( iterator it=begin(); it != end(); ) - { - if ( it->second == pyg ) - { - iterator temp = it++; - erase(temp); - } - else - ++it; - } - } - - py_graph_t *get(Py_ssize_t id) - { - iterator it = find(id); - return it == end() ? NULL : it->second; - } - }; - - static cmdid_map_t cmdid_pyg; - bool refresh_needed; nodetext_cache_map_t node_cache; // instance callback - int gr_callback(int code, va_list va); + ssize_t gr_callback(int code, va_list va); // static callback - static int idaapi s_callback(void *obj, int code, va_list va) - { - QASSERT(30453, pycim_lookup_info.find_by_py_view(NULL, NULL, (py_graph_t *) obj)); - PYW_GIL_GET; - return ((py_graph_t *)obj)->gr_callback(code, va); - } - - static bool idaapi s_menucb(void *ud) - { - PYW_GIL_GET; - Py_ssize_t id = (Py_ssize_t)ud; - py_graph_t *_this = cmdid_pyg.get(id); - if ( _this != NULL ) - _this->on_command(id); - - return true; - } - - void on_command(Py_ssize_t id) - { - // Check return value to OnRefresh() call - PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t ret(PyObject_CallMethod(self.o, (char *)S_ON_COMMAND, "n", id)); - PyW_ShowCbErr(S_ON_COMMAND); + static ssize_t idaapi s_callback(void *obj, int code, va_list va) +{ + // don't perform sanity check for 'grcode_destroyed', since if we called + // Close() on this object, it'll have been marked for later deletion in the + // UI, and thus when we end up here, the view has already been destroyed. + bool found = pycim_lookup_info.find_by_py_view(NULL, (py_graph_t *) obj); + QASSERT(30453, found || code == grcode_destroyed); + if ( found ) + { + PYW_GIL_GET; + return ((py_graph_t *)obj)->gr_callback(code, va); + } + else + { + return 0; + } } // Refresh user-defined graph node number and edges @@ -287,9 +231,9 @@ private: void show() { - TForm *form; - if ( pycim_lookup_info.find_by_py_view(&form, NULL, this) ) - open_tform(form, FORM_TAB|FORM_MENU|FORM_QWIDGET); + TWidget *view; + if ( pycim_lookup_info.find_by_py_view(&view, this) ) + display_widget(view, WOPN_TAB|WOPN_MENU); } void jump_to_node(int nid) @@ -325,10 +269,8 @@ private: if ( !collect_pyobject_callbacks(self) ) return -1; - // Create form - HWND hwnd = NULL; - TForm *form = create_tform(title, &hwnd); - if ( hwnd != NULL ) // Created new tform + TWidget *widget = find_widget(title); + if ( widget == NULL ) // create new widget { lookup_entry_t &e = pycim_lookup_info.new_entry(this); // get a unique graph id @@ -338,14 +280,14 @@ private: id.create(grnode); // pre-bind 'self', so that 'on_user_refresh()' can complete this->self = borref_t(self); - graph_viewer_t *pview = create_graph_viewer(form, id, s_callback, this, 0); + graph_viewer_t *pview = create_graph_viewer(title, id, s_callback, this, 0); this->self = ref_t(); - open_tform(form, FORM_TAB | FORM_MENU | FORM_QWIDGET); + display_widget(pview, WOPN_TAB | WOPN_MENU); + newref_t ret(PyObject_CallMethod(self, "hook", NULL)); if ( pview != NULL ) viewer_fit_window(pview); bind(self, pview); - install_custom_viewer_handlers(); - pycim_lookup_info.commit(e, form, view); + pycim_lookup_info.commit(e, view); } else { @@ -356,18 +298,6 @@ private: return 0; } - Py_ssize_t add_command(const char *title, const char *hotkey) - { - if ( !has_callback(GRCODE_HAVE_COMMAND) || view == NULL ) - return 0; - Py_ssize_t cmd_id = cmdid_pyg.id(); - bool ok = viewer_add_menu_item(view, title, s_menucb, (void *)cmd_id, hotkey, 0); - if ( !ok ) - return 0; - cmdid_pyg.add(this); - return cmd_id; - } - public: py_graph_t() { @@ -375,40 +305,27 @@ public: refresh_needed = true; } - virtual ~py_graph_t() - { - // Remove all associated commands from the list - cmdid_pyg.clear(this); - } - static void SelectNode(PyObject *self, int nid) { if ( nid < 0 ) return; py_graph_t *_this = view_extract_this(self); - if ( _this == NULL || !pycim_lookup_info.find_by_py_view(NULL, NULL, _this) ) + if ( _this == NULL || !pycim_lookup_info.find_by_py_view(NULL, _this) ) return; _this->jump_to_node(nid); } - static Py_ssize_t AddCommand(PyObject *self, const char *title, const char *hotkey) + static py_graph_t *Close(PyObject *self) { + TWidget *view; py_graph_t *_this = view_extract_this(self); - if ( _this == NULL || !pycim_lookup_info.find_by_py_view(NULL, NULL, _this) ) - return 0; - - return _this->add_command(title, hotkey); - } - - static void Close(PyObject *self) - { - TForm *form; - py_graph_t *_this = view_extract_this(self); - if ( _this == NULL || !pycim_lookup_info.find_by_py_view(&form, NULL, _this) ) - return; - close_tform(form, FORM_CLOSE_LATER); + if ( _this == NULL || !pycim_lookup_info.find_by_py_view(&view, _this) ) + return NULL; + newref_t ret(PyObject_CallMethod(self, "unhook", NULL)); + close_widget(view, WCLS_CLOSE_LATER); + return _this; } static py_graph_t *Show(PyObject *self) @@ -426,10 +343,9 @@ public: // Form already created? try to get associated py_graph instance // so that we reuse it - graph_viewer_t *found_view; - TForm *form = find_tform(title.c_str()); - if ( form != NULL ) - pycim_lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_graph, form); + TWidget *existing = find_widget(title.c_str()); + if ( existing != NULL ) + pycim_lookup_info.find_by_view((py_customidamemo_t**) &py_graph, existing); if ( py_graph == NULL ) { @@ -466,7 +382,6 @@ void py_graph_t::collect_class_callbacks_ids(pycim_callbacks_ids_t *out) out->add(S_ON_HINT, GRCODE_HAVE_USER_HINT); out->add(S_ON_CLICK, GRCODE_HAVE_CLICKED); out->add(S_ON_DBL_CLICK, GRCODE_HAVE_DBL_CLICKED); - out->add(S_ON_COMMAND, GRCODE_HAVE_COMMAND); out->add(S_ON_SELECT, GRCODE_HAVE_CHANGED_CURRENT); out->add(S_ON_ACTIVATE, GRCODE_HAVE_GOTFOCUS); out->add(S_ON_DEACTIVATE, GRCODE_HAVE_LOSTFOCUS); @@ -613,7 +528,7 @@ int py_graph_t::on_user_hint(mutable_graph_t *, int mousenode, int /*mouseedge_s //------------------------------------------------------------------------- -int py_graph_t::gr_callback(int code, va_list va) +ssize_t py_graph_t::gr_callback(int code, va_list va) { int ret; switch ( code ) @@ -763,8 +678,6 @@ int py_graph_t::gr_callback(int code, va_list va) } //------------------------------------------------------------------------- -py_graph_t::cmdid_map_t py_graph_t::cmdid_pyg; - bool pyg_show(PyObject *self) { return py_graph_t::Show(self) != NULL; @@ -772,13 +685,9 @@ bool pyg_show(PyObject *self) void pyg_close(PyObject *self) { - py_graph_t::Close(self); -} - -PyObject *pyg_add_command(PyObject *self, const char *title, const char *hotkey) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return Py_BuildValue("n", py_graph_t::AddCommand(self, title, hotkey)); + py_graph_t *pyg = py_graph_t::Close(self); + if ( pyg != NULL ) + delete pyg; } void pyg_select_node(PyObject *self, int nid) @@ -791,7 +700,6 @@ void pyg_select_node(PyObject *self, int nid) // void pyg_close(PyObject *self); -PyObject *pyg_add_command(PyObject *self, const char *title, const char *hotkey); void pyg_select_node(PyObject *self, int nid); bool pyg_show(PyObject *self); // diff --git a/pywraps/py_graph.py b/pywraps/py_graph.py index d05d58b..add5856 100644 --- a/pywraps/py_graph.py +++ b/pywraps/py_graph.py @@ -1,6 +1,25 @@ # import ida_idaapi -class GraphViewer(ida_idaapi.CustomIDAMemo): +import ida_kernwin +try: + if _BC695: + from ida_kernwin import BC695_control_cmd +except: + pass # BC695 not defined at compile-time + +class GraphViewer(ida_kernwin.CustomIDAMemo): + class UI_Hooks_Trampoline(ida_kernwin.UI_Hooks): + def __init__(self, v): + ida_kernwin.UI_Hooks.__init__(self) + self.hook() + import weakref + self.v = weakref.ref(v) + + def populating_widget_popup(self, form, popup_handle): + my_form = self.v().GetWidget() + if form == my_form: + self.v().OnPopup(my_form, popup_handle) + """This class wraps the user graphing facility provided by the graph.hpp file""" def __init__(self, title, close_open = False): """ @@ -14,6 +33,8 @@ class GraphViewer(ida_idaapi.CustomIDAMemo): self._nodes = [] self._edges = [] self._close_open = close_open + ida_kernwin.CustomIDAMemo.__init__(self) + self.ui_hooks_trampoline = self.UI_Hooks_Trampoline(self) def AddNode(self, obj): """Creates a node associated with the given object and returns the node id""" @@ -30,6 +51,8 @@ class GraphViewer(ida_idaapi.CustomIDAMemo): self._nodes = [] self._edges = [] + def OnPopup(self, form, popup_handle): + pass def __iter__(self): return (self._nodes[index] for index in xrange(0, len(self._nodes))) @@ -61,23 +84,15 @@ class GraphViewer(ida_idaapi.CustomIDAMemo): """ if self._close_open: import ida_kernwin - frm = ida_kernwin.find_tform(self._title) + frm = ida_kernwin.find_widget(self._title) if frm: - ida_kernwin.close_tform(frm, 0) + ida_kernwin.close_widget(frm, 0) return _ida_graph.pyg_show(self) def Select(self, node_id): """Selects a node on the graph""" _ida_graph.pyg_select_node(self, node_id) - def AddCommand(self, title, hotkey): - """ - Deprecated: Use - - register_action() - - attach_action_to_popup() - """ - return _ida_graph.pyg_add_command(self, title, hotkey) - def OnRefresh(self): """ Event called when the graph is refreshed or first created. @@ -90,6 +105,25 @@ class GraphViewer(ida_idaapi.CustomIDAMemo): self.Clear() return True + + def AddCommand(self, title, hotkey): + return BC695_control_cmd.add_to_control( + self, + title, + ida_kernwin.CHOOSER_POPUP_MENU, # KLUDGE + -1, # menu index + -1, # icon + None, # emb + hotkey, + is_chooser=False) + + def OnPopup(self, widget, popup_handle): + BC695_control_cmd.populate_popup(self, widget, popup_handle) + + def OnCommand(self, cmd_id): + return 0 + + # # def OnGetText(self, node_id): # """ @@ -153,11 +187,13 @@ class GraphViewer(ida_idaapi.CustomIDAMemo): # """ # print "dblclicked on", self[node_id] # return True -# -# def OnCommand(self, cmd_id): -# """ -# Deprecated -# """ -# pass # # + +# +clr_node_info2=clr_node_info +del_node_info2=del_node_info +get_node_info2=get_node_info +set_node_info2=set_node_info +GraphViewer.GetTForm = GraphViewer.GetWidget +# diff --git a/pywraps/py_hexrays.hpp b/pywraps/py_hexrays.hpp index 719c018..1e3d577 100644 --- a/pywraps/py_hexrays.hpp +++ b/pywraps/py_hexrays.hpp @@ -1,9 +1,38 @@ //------------------------------------------------------------------------- // #ifdef WITH_HEXRAYS -hexdsp_t *hexdsp = NULL; +static void *idaapi init_time_dummy_hexdsp(int code, ...) +{ + switch ( code ) + { + case hx_cexpr_t_cleanup: + case hx_cinsn_t_cleanup: + { +#ifdef _DEBUG + va_list va; + va_start(va, code); + citem_t *item = va_arg(va, citem_t*); + // catch leaks + if ( code == hx_cexpr_t_cleanup ) + QASSERT(30497, ((cexpr_t *)item)->op == cot_empty && ((cexpr_t *)item)->n == NULL); + else + QASSERT(30498, ((cinsn_t *)item)->op == cit_empty && ((cinsn_t *)item)->cblock == NULL); + va_end(va); +#endif + } + break; + default: + warning("Hex-Rays Decompiler got called from Python without being loaded"); + break; + } + return NULL; +} + +hexdsp_t *hexdsp = init_time_dummy_hexdsp; #endif // WITH_HEXRAYS +#define MODULE_NAME "Hex-Rays Decompiler" // Copied from vd/hexrays.cpp + //------------------------------------------------------------------------- qstring_printer_t *new_qstring_printer_t(const cfunc_t *f, bool tags) { @@ -18,7 +47,7 @@ void delete_qstring_printer_t(qstring_printer_t *qs) } //--------------------------------------------------------------------- -static int hexrays_python_call(ref_t fct, ref_t args) +static ref_t hexrays_python_call(ref_t fct, ref_t args) { PYW_GIL_GET; @@ -26,9 +55,17 @@ static int hexrays_python_call(ref_t fct, ref_t args) if ( PyErr_Occurred() ) { PyErr_Print(); - return 0; + 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; @@ -44,7 +81,7 @@ static bool idaapi __python_custom_viewer_popup_item_callback(void *ud) int ret; borref_t fct((PyObject *)ud); newref_t nil(NULL); - ret = hexrays_python_call(fct, nil); + ret = hexrays_python_intcall(fct, nil); return ret ? true : false; } @@ -66,7 +103,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ ctree_maturity_t arg1 = va_argi(va, ctree_maturity_t); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 )); newref_t args(Py_BuildValue("(iOi)", event, arg0obj.o, arg1)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_interr: @@ -75,7 +112,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ { int arg0 = va_argi(va, int); newref_t args(Py_BuildValue("(ii)", event, arg0)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; @@ -90,7 +127,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 )); newref_t arg1obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg1), SWIGTYPE_p_vc_printer_t, 0 )); newref_t args(Py_BuildValue("(iOO)", event, arg0obj.o, arg1obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; @@ -102,7 +139,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ cfunc_t *arg0 = va_arg(va, cfunc_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_cfunc_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; @@ -114,7 +151,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_switch_pseudocode: @@ -126,7 +163,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_refresh_pseudocode: @@ -137,7 +174,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_close_pseudocode: @@ -147,7 +184,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_keyboard: @@ -162,7 +199,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ int arg2 = va_argi(va, int); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iOii)", event, arg0obj.o, arg1, arg2)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_right_click: @@ -172,7 +209,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_double_click: @@ -185,7 +222,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ int arg1 = va_argi(va, int); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iOi)", event, arg0obj.o, arg1)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_curpos: @@ -196,7 +233,7 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_create_hint: @@ -213,7 +250,28 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = 0; + ref_t resultobj = hexrays_python_call(fct, args); + if ( PyTuple_Check(resultobj.o) && PyTuple_Size(resultobj.o) == 3 ) + { + borref_t i0 = PyTuple_GetItem(resultobj.o, 0); + borref_t i1 = PyTuple_GetItem(resultobj.o, 1); + borref_t i2 = PyTuple_GetItem(resultobj.o, 2); + if ( PyInt_Check(i0.o) && PyString_Check(i1.o) && PyInt_Check(i2.o) ) + { + qstring *result_hint = va_arg(va, qstring *); + char *buf; + Py_ssize_t bufsize; + if ( PyString_AsStringAndSize(i1.o, &buf, &bufsize) > -1 ) + { + ret = PyInt_AsLong(i0.o); + qstring tmp(buf, bufsize); + result_hint->swap(tmp); + int *implines = va_arg(va, int *); + *implines = PyInt_AsLong(i2.o); + } + } + } } break; case hxe_text_ready: @@ -226,23 +284,23 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ vdui_t *arg0 = va_arg(va, vdui_t *); newref_t arg0obj(SWIG_NewPointerObj(SWIG_as_voidptr(arg0), SWIGTYPE_p_vdui_t, 0 )); newref_t args(Py_BuildValue("(iO)", event, arg0obj.o)); - ret = hexrays_python_call(fct, args); + ret = hexrays_python_intcall(fct, args); } break; case hxe_populating_popup: ///< Populating popup menu. We can add menu items now. - ///< TForm *form + ///< TWidget *widget ///< TPopupMenu *popup_handle ///< vdui_t *vu { - TForm *form = va_arg(va, TForm *); + TWidget *widget = va_arg(va, TWidget *); TPopupMenu *pp = va_arg(va, TPopupMenu*); vdui_t *vdui = va_arg(va, vdui_t *); - newref_t py_form(SWIG_NewPointerObj(SWIG_as_voidptr(form), SWIGTYPE_p_Forms__TForm, 0)); - newref_t py_popup(SWIG_NewPointerObj(SWIG_as_voidptr(pp), SWIGTYPE_p_Menus__TPopupMenu, 0)); + newref_t py_widget(SWIG_NewPointerObj(SWIG_as_voidptr(widget), SWIGTYPE_p_TWidget, 0)); + newref_t py_popup(SWIG_NewPointerObj(SWIG_as_voidptr(pp), SWIGTYPE_p_TPopupMenu, 0)); newref_t py_vdui(SWIG_NewPointerObj(SWIG_as_voidptr(vdui), SWIGTYPE_p_vdui_t, 0 )); - newref_t py_args(Py_BuildValue("(iOOO)", event, py_form.o, py_popup.o, py_vdui.o)); - ret = hexrays_python_call(fct, py_args); + newref_t py_args(Py_BuildValue("(iOOO)", event, py_widget.o, py_popup.o, py_vdui.o)); + ret = hexrays_python_intcall(fct, py_args); } break; default: @@ -255,40 +313,88 @@ static int idaapi __hexrays_python_callback(void *ud, hexrays_event_t event, va_ } //------------------------------------------------------------------------- -// A set of cfuncptr_t objects that were created from IDAPython. -// This is necessary in order to delete those objects before the hexrays -// plugin is unloaded. Otherwise, IDAPython will still delete them, but -// the plugin's 'hexdsp' dispatcher function will point to dlclose()'d -// code. -static qvector python_cfuncptrs; -void hexrays_clear_python_cfuncptr_t_references(void) -{ - for ( size_t i = 0, n = python_cfuncptrs.size(); i < n; ++i ) - python_cfuncptrs[i]->reset(); - // NOTE: Don't clear() the array of pointers. All the python-exposed - // cfuncptr_t instances will be deleted through the python - // shutdown/ref-decrementing process anyway, and the entries will be - // properly pulled out of the vector when that happens. -} - +// Clearable objects //------------------------------------------------------------------------- -void hexrays_register_python_cfuncptr_t_instance(cfuncptr_t *fp) +// A set of objects that were created from IDAPython. This is necessary in +// order to delete those objects before the hexrays plugin is unloaded. +// Otherwise, IDAPython will still delete them, but the plugin's 'hexdsp' +// dispatcher function will point to dlclose()'d code. +enum hx_clearable_type_t { - QASSERT(30457, !python_cfuncptrs.has(fp)); - python_cfuncptrs.push_back(fp); -} + hxclr_unknown = 0, + hxclr_cfuncptr, + hxclr_cinsn, + hxclr_cexpr, + hxclr_cblock, +}; +struct hx_clearable_t +{ + void *ptr; + hx_clearable_type_t type; +}; +DECLARE_TYPE_AS_MOVABLE(hx_clearable_t); -//------------------------------------------------------------------------- -void hexrays_deregister_python_cfuncptr_t_instance(cfuncptr_t *fp) +typedef qvector hx_clearables_t; +static hx_clearables_t python_clearables; +void hexrays_clear_python_clearable_references(void) { - qvector::iterator found = python_cfuncptrs.find(fp); - if ( found != python_cfuncptrs.end() ) + for ( size_t i = 0, n = python_clearables.size(); i < n; ++i ) { - fp->reset(); - python_cfuncptrs.erase(found); + const hx_clearable_t &hxc = python_clearables[i]; + /*msg("### cleaning up %p\n", hxc.ptr);*/ + switch ( hxc.type ) + { + case hxclr_cfuncptr: + ((cfuncptr_t*)hxc.ptr)->reset(); + break; + case hxclr_cinsn: + ((cinsn_t *)hxc.ptr)->cleanup(); + break; + case hxclr_cexpr: + ((cexpr_t *)hxc.ptr)->cleanup(); + break; + case hxclr_cblock: + ((cblock_t *)hxc.ptr)->clear(); + break; + default: INTERR(30499); + } } } +//------------------------------------------------------------------------- +void hexrays_register_python_clearable_instance( + void *ptr, + hx_clearable_type_t type) +{ + for ( size_t i = 0, n = python_clearables.size(); i < n; ++i ) + if ( python_clearables[i].ptr == ptr ) + return; + hx_clearable_t &hxc = python_clearables.push_back(); + hxc.ptr = ptr; + hxc.type = type; + /*msg("### registered %p\n", hxc.ptr);*/ +} + +//------------------------------------------------------------------------- +// Note: drop ownership, but don't cleanup! The cleanup will be done by +// the SWiG destructor wrapper if this object's still owned by the Python +// runtime, or it will be done by the C tree itself later. +void hexrays_deregister_python_clearable_instance(void *ptr) +{ + for ( size_t i = 0, n = python_clearables.size(); i < n; ++i ) + { + const hx_clearable_t &hxc = python_clearables[i]; + if ( hxc.ptr == ptr ) + { + python_clearables.erase(python_clearables.begin() + i); + /*msg("### de-registered %p\n", hxc.ptr);*/ + break; + } + } +} + +//------------------------------------------------------------------------- +// //------------------------------------------------------------------------- cfuncptr_t _decompile(func_t *pfn, hexrays_failure_t *hf) { @@ -311,7 +417,7 @@ static bool is_hexrays_plugin(const plugin_info_t *pinfo) if ( pinfo != NULL && pinfo->entry != NULL ) { const plugin_t *p = pinfo->entry; - if ( streq(p->wanted_name, "Hex-Rays Decompiler") ) + if ( streq(p->wanted_name, MODULE_NAME) ) is_hx = true; } return is_hx; @@ -326,59 +432,82 @@ static void try_init() } //------------------------------------------------------------------------- -static int idaapi on_ui_notification(void *, int code, va_list va) +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. + switch ( code ) + { + case hx_cexpr_t_cleanup: break; + case hx_cinsn_t_cleanup: break; + default: break; + }*/ + return NULL; +} + +//------------------------------------------------------------------------- +inline bool hexdsp_inited() +{ + return hexdsp != NULL + && hexdsp != init_time_dummy_hexdsp + && hexdsp != exit_time_dummy_hexdsp; +} + +//------------------------------------------------------------------------- +static ssize_t idaapi ida_hexrays_ui_notification(void *, int code, va_list va) { switch ( code ) { case ui_plugin_loaded: - if ( hexdsp == NULL && is_hexrays_plugin(va_arg(va, plugin_info_t *)) ) - try_init(); + if ( !hexdsp_inited() ) + { + const plugin_info_t *pi = va_arg(va, plugin_info_t *); + if ( is_hexrays_plugin(pi) ) + try_init(); + } break; case ui_plugin_unloading: + if ( hexdsp != NULL && hexdsp != init_time_dummy_hexdsp ) { - if ( hexdsp != NULL ) + // Hex-Rays will close. Make sure all the refcounted cfunc_t objects + // are cleared right away. + const plugin_info_t *pi = va_arg(va, plugin_info_t *); + if ( is_hexrays_plugin(pi) ) { - // Hex-Rays will close. Make sure all the refcounted cfunc_t objects - // are cleared right away. - if ( is_hexrays_plugin(va_arg(va, plugin_info_t *)) ) - { - hexrays_clear_python_cfuncptr_t_references(); - hexdsp = NULL; - } + QASSERT(30500, hexdsp != exit_time_dummy_hexdsp); + hexrays_clear_python_clearable_references(); + hexdsp = exit_time_dummy_hexdsp; } } break; + case ui_term: + hexdsp = init_time_dummy_hexdsp; + break; } return 0; } + +//------------------------------------------------------------------------- +static void ida_hexrays_term(void) +{ + idapython_unhook_from_notification_point( + HT_UI, ida_hexrays_ui_notification, NULL); +} + +//------------------------------------------------------------------------- +static void ida_hexrays_closebase(void) {} // // //--------------------------------------------------------------------- -extern hexdsp_t *hexdsp; bool py_init_hexrays_plugin(int flags=0) { // Only initialize one time - if ( hexdsp == NULL ) - return init_hexrays_plugin(flags); - else - return true; + return hexdsp_inited() || init_hexrays_plugin(flags); } -//--------------------------------------------------------------------- -void py_add_custom_viewer_popup_item( - TCustomControl *custom_viewer, - const char *title, - const char *hotkey, - PyObject *custom_viewer_popup_item_callback) -{ - PYW_GIL_GET; - Py_INCREF(custom_viewer_popup_item_callback); - add_custom_viewer_popup_item(custom_viewer, title, hotkey, __python_custom_viewer_popup_item_callback, custom_viewer_popup_item_callback); -}; - //--------------------------------------------------------------------- bool py_install_hexrays_callback(PyObject *hx_cblist_callback) { @@ -420,20 +549,29 @@ bool py_decompile_many(const char *outfile, PyObject *funcaddrs, int flags) //------------------------------------------------------------------------- // Some examples will want to use action_handler_t's whose update() method -// calls get_tform_vdui() to figure out whether the action should be enabled -// for the current form. Unfortunately, if hexrays is first unloaded before +// calls get_widget_vdui() to figure out whether the action should be enabled +// for the current widget. Unfortunately, if hexrays is first unloaded before // the widget cleanup is performed (e.g., while loading another IDB), // the action would crash. Ideally we should wrap all toplevel calls // with such wrappers, but it doesn't seem to be really necessary at the // moment: only corner-cases will reveal this issue (reported by // the idapython_hr-decompile test.) -vdui_t *py_get_tform_vdui(TForm *f) +vdui_t *py_get_widget_vdui(TWidget *f) { - return hexdsp != NULL ? get_tform_vdui(f) : NULL; + return hexdsp_inited() ? get_widget_vdui(f) : NULL; +} + +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) +{ + return boundaries_insert(map, key, val); } // // -try_init(); -hook_to_notification_point(HT_UI, on_ui_notification, NULL); +idapython_hook_to_notification_point(HT_UI, ida_hexrays_ui_notification, NULL); // diff --git a/pywraps/py_hexrays.py b/pywraps/py_hexrays.py index 3f32205..895cb17 100644 --- a/pywraps/py_hexrays.py +++ b/pywraps/py_hexrays.py @@ -258,6 +258,10 @@ lvar_t.is_mapdst_var = property(lvar_t.is_mapdst_var) # dictify all dict-like types +def _map___iter__(self): + """ Iterate over dictionary keys. """ + return self.iterkeys() + def _map___getitem__(self, key): """ Returns the value associated with the provided key. """ if not isinstance(key, self.keytype): @@ -389,6 +393,7 @@ def _map_as_dict(maptype, name, keytype, valuetype): maptype.erase = lambda self, *args: self.__erase(self, *args) maptype.clear = lambda self, *args: self.__clear(self, *args) maptype.size = lambda self, *args: self.__size(self, *args) + maptype.__iter__ = _map___iter__ maptype.__getitem__ = _map___getitem__ maptype.__setitem__ = _map___setitem__ maptype.__delitem__ = _map___delitem__ @@ -414,6 +419,66 @@ _map_as_dict(user_iflags_t, 'user_iflags', citem_locator_t, (int, long)) import ida_pro _map_as_dict(user_unions_t, 'user_unions', (int, long), ida_pro.intvec_t) _map_as_dict(eamap_t, 'eamap', long, cinsnptrvec_t) -#_map_as_dict(boundaries_t, 'boundaries', cinsn_t, areaset_t) +import ida_range +_map_as_dict(boundaries_t, 'boundaries', cinsn_t, ida_range.rangeset_t) + +# +# Object ownership +# +def _call_with_transferrable_ownership(fun, *args): + e = args[0] + was_owned = e.thisown + res = fun(e, *args[1:]) + # ATM, 'res' doesn't own the resulting cexpr_t. + # In case 'fun' + # - created a new object: we want to own that one in case 'e' was owned + # - didn't create a new object: we will remove & re-gain ownership on + # the same underlying cexpr_t. No biggie. + if res and was_owned: + e._maybe_disown_and_deregister() + res._own_and_register() + return res + +def lnot(e): + return _call_with_transferrable_ownership(_ll_lnot, e) + +def make_ref(e): + return _call_with_transferrable_ownership(_ll_make_ref, e) + +def dereference(e, ptrsize, is_float=False): + return _call_with_transferrable_ownership(_ll_dereference, e, ptrsize, is_float) + +def call_helper(rettype, args, *rest): + res = _ll_call_helper(rettype, args, *rest) + if res: + res._own_and_register() + if type(args) == carglist_t: + args.thisown = False + return res + +def new_block(): + res = _ll_new_block() + if res: + res._own_and_register() + return res + +def make_num(*args): + res = _ll_make_num(*args) + if res: + res._own_and_register() + return res + +def create_helper(*args): + res = _ll_create_helper(*args) + if res: + res._own_and_register() + return res # + +# +get_tform_vdui=get_widget_vdui +hx_get_tform_vdui=hx_get_widget_vdui +HEXRAYS_API_MAGIC1=(HEXRAYS_API_MAGIC>>32) +HEXRAYS_API_MAGIC2=(HEXRAYS_API_MAGIC&0xFFFFFFFFL) +# diff --git a/pywraps/py_ida.py b/pywraps/py_ida.py new file mode 100644 index 0000000..e7efbaf --- /dev/null +++ b/pywraps/py_ida.py @@ -0,0 +1,47 @@ + +# +AF2_ANORET=AF_ANORET +AF2_CHKUNI=AF_CHKUNI +AF2_DATOFF=AF_DATOFF +AF2_DOCODE=AF_DOCODE +AF2_DODATA=AF_DODATA +AF2_FTAIL=AF_FTAIL +AF2_HFLIRT=AF_HFLIRT +AF2_JUMPTBL=AF_JUMPTBL +AF2_MEMFUNC=AF_MEMFUNC +AF2_PURDAT=AF_PURDAT +AF2_REGARG=AF_REGARG +AF2_SIGCMT=AF_SIGCMT +AF2_SIGMLT=AF_SIGMLT +AF2_STKARG=AF_STKARG +AF2_TRFUNC=AF_TRFUNC +AF2_VERSP=AF_VERSP +AF_ASCII=AF_STRLIT +ASCF_AUTO=STRF_AUTO +ASCF_COMMENT=STRF_COMMENT +ASCF_GEN=STRF_GEN +ASCF_SAVECASE=STRF_SAVECASE +ASCF_SERIAL=STRF_SERIAL +ASCF_UNICODE=STRF_UNICODE +INFFL_LZERO=OFLG_LZERO +ansi2idb=ida_idaapi._BC695.identity +idb2scr=ida_idaapi._BC695.identity +scr2idb=ida_idaapi._BC695.identity +showAllComments=show_all_comments +showComments=show_comments +showRepeatables=show_repeatables +toEA=to_ea + +def __wrap_hooks_callback(klass, new_name, old_name, do_call): + bkp_name = "__real_%s" % new_name + def __wrapper(self, *args): + rc = getattr(self, bkp_name)(*args) + cb = getattr(self, old_name, None) + if cb: + rc = do_call(cb, *args) + return rc + + setattr(klass, bkp_name, getattr(klass, new_name)) + setattr(klass, new_name, __wrapper) + +# diff --git a/pywraps/py_idaapi.hpp b/pywraps/py_idaapi.hpp index 6ac3971..253d860 100644 --- a/pywraps/py_idaapi.hpp +++ b/pywraps/py_idaapi.hpp @@ -95,23 +95,20 @@ PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject } //------------------------------------------------------------------------- -TForm *pycim_get_tform(PyObject *self) +TWidget *pycim_get_widget(PyObject *self) { CHK_THIS_OR_NULL(); - TForm *form = NULL; - if ( !pycim_lookup_info.find_by_py_view(&form, NULL, _this) ) + TWidget *widget = NULL; + if ( !pycim_lookup_info.find_by_py_view(&widget, _this) ) return NULL; - return form; + return widget; } //------------------------------------------------------------------------- -TCustomControl *pycim_get_tcustom_control(PyObject *self) +void pycim_view_close(PyObject *self) { - CHK_THIS_OR_NULL(); - TCustomControl *tcc = NULL; - if ( !pycim_lookup_info.find_by_py_view(NULL, &tcc, _this) ) - return NULL; - return tcc; + CHK_THIS(); + delete _this; } #undef CHK_THIS_OR_NONE @@ -141,7 +138,7 @@ static PyObject *py_parse_command_line(const char *cmdline) PYW_GIL_CHECK_LOCKED_SCOPE(); qstrvec_t args; - if ( parse_command_line3(cmdline, &args, NULL, LP_PATH_WITH_ARGS) == 0 ) + if ( parse_command_line(&args, NULL, cmdline, LP_PATH_WITH_ARGS) == 0 ) Py_RETURN_NONE; return qstrvec2pylist(args); } @@ -253,8 +250,8 @@ void pygc_set_current_renderer_type(PyObject *self, PyObject *py_rt); PyObject *pygc_create_groups(PyObject *self, PyObject *groups_infos); PyObject *pygc_delete_groups(PyObject *self, PyObject *groups, PyObject *new_current); PyObject *pygc_set_groups_visibility(PyObject *self, PyObject *groups, PyObject *expand, PyObject *new_current); -TForm *pycim_get_tform(PyObject *self); -TCustomControl *pycim_get_tcustom_control(PyObject *self); +TWidget *pycim_get_widget(PyObject *self); +void pycim_view_close(PyObject *self); // #endif diff --git a/pywraps/py_idaapi.py b/pywraps/py_idaapi.py index b3f1e04..c84a454 100644 --- a/pywraps/py_idaapi.py +++ b/pywraps/py_idaapi.py @@ -178,6 +178,14 @@ class object_t(object): """Allow access to object attributes by index (like dictionaries)""" return getattr(self, idx) +# ----------------------------------------------------------------------- +def _qvector_front(self): + return self.at(0) + +# ----------------------------------------------------------------------- +def _qvector_back(self): + return self.at((self.size() - 1) if self.size() else 0) + # ----------------------------------------------------------------------- def _bounded_getitem_iterator(self): """Helper function, to be set as __iter__ method for qvector-, or array-based classes.""" @@ -276,7 +284,7 @@ def as_unicode(s): """Convenience function to convert a string into appropriate unicode format""" # use UTF16 big/little endian, depending on the environment? import _ida_ida - return unicode(s).encode("UTF-16" + ("BE" if _ida_ida.cvar.inf.mf else "LE")) + return unicode(s).encode("UTF-16" + ("BE" if _ida_ida.cvar.inf.is_be() else "LE")) # ----------------------------------------------------------------------- def as_uint32(v): @@ -340,6 +348,19 @@ def struct_unpack(buffer, signed = False, offs = 0): # Unpack return struct.unpack_from(__struct_unpack_table[n][signed], buffer, offs)[0] +# ------------------------------------------------------------ +try: + "".decode("UTF-8").encode("mbcs") + has_mbcs = True +except: + has_mbcs = False + +def _utf8_native(utf8): + if has_mbcs: + uni = utf8.decode("UTF-8") + return uni.encode("mbcs") + else: + return utf8 # ------------------------------------------------------------ def IDAPython_ExecSystem(cmd): @@ -347,6 +368,7 @@ def IDAPython_ExecSystem(cmd): Executes a command with popen(). """ try: + cmd = _utf8_native(cmd) f = os.popen(cmd, "r") s = ''.join(f.readlines()) f.close() @@ -374,6 +396,7 @@ def IDAPython_ExecScript(script, g, print_error=True): This function is used by the low-level plugin code. """ + script = _utf8_native(script) scriptpath = os.path.dirname(script) if len(scriptpath) and scriptpath not in sys.path: sys.path.append(scriptpath) @@ -404,6 +427,7 @@ def IDAPython_LoadProcMod(script, g, print_error=True): """ Load processor module. """ + script = _utf8_native(script) pname = g['__name__'] if g and g.has_key("__name__") else '__main__' parent = sys.modules[pname] @@ -444,6 +468,7 @@ def IDAPython_UnLoadProcMod(script, g, print_error=True): """ Unload processor module. """ + script = _utf8_native(script) pname = g['__name__'] if g and g.has_key("__name__") else '__main__' parent = sys.modules[pname] @@ -551,127 +576,38 @@ NW_TERMIDA = 0x0008 NW_REMOVE = 0x0010 """Use this flag with other flags to uninstall a notifywhen callback""" -# ----------------------------------------------------------------------- -# CustomIDAMemo -# ----------------------------------------------------------------------- -class CustomIDAMemo(object): - def Refresh(self): - """ - Refreshes the graph. This causes the OnRefresh() to be called - """ - ida_idaapi.pygc_refresh(self) - def GetCurrentRendererType(self): - return ida_idaapi.pygc_get_current_renderer_type(self) +# 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 +# to abort(). +# We do not want that to happen in IDA, and simply having a sys.excepthook +# that is different from sys.__excepthook__ is enough for PyQt5 to return +# to the previous behavior +def __install_excepthook(): + real_hook = sys.excepthook + sys.excepthook = lambda *args: real_hook(*args) +__install_excepthook() - def SetCurrentRendererType(self, rtype): - """ - Set the current view's renderer. - @param rtype: The renderer type. Should be one of the idaapi.TCCRT_* values. - """ - ida_idaapi.pygc_set_current_renderer_type(self, rtype) +# ----------------------------------- helpers for bw-compat w/ 6.95 API +class __BC695: + def __init__(self): + self.FIXME = "FIXME @arnaud" - def SetNodeInfo(self, node_index, node_info, flags): - """ - Set the properties for the given node. + def false_p(self, *args): + return False - Example usage (set second nodes's bg color to red): - inst = ... - p = idaapi.node_info_t() - p.bg_color = 0x00ff0000 - inst.SetNodeInfo(1, p, idaapi.NIF_BG_COLOR) + def identity(self, arg): + return arg - @param node_index: The node index. - @param node_info: An idaapi.node_info_t instance. - @param flags: An OR'ed value of NIF_* values. - """ - ida_idaapi.pygc_set_node_info(self, node_index, node_info, flags) - - def SetNodesInfos(self, values): - """ - Set the properties for the given nodes. - - Example usage (set first three nodes's bg color to purple): - inst = ... - p = idaapi.node_info_t() - p.bg_color = 0x00ff00ff - inst.SetNodesInfos({0 : p, 1 : p, 2 : p}) - - @param values: A dictionary of 'int -> node_info_t' objects. - """ - ida_idaapi.pygc_set_nodes_infos(self, values) - - def GetNodeInfo(self, node): - """ - Get the properties for the given node. - - @param node: The index of the node. - @return: A tuple (bg_color, frame_color, ea, text), or None. - """ - return ida_idaapi.pygc_get_node_info(self, node) - - def DelNodesInfos(self, *nodes): - """ - Delete the properties for the given node(s). - - @param nodes: A list of node IDs - """ - return ida_idaapi.pygc_del_nodes_infos(self, nodes) - - def CreateGroups(self, groups_infos): - """ - Send a request to modify the graph by creating a - (set of) group(s), and perform an animation. - - Each object in the 'groups_infos' list must be of the format: - { - "nodes" : [, , , ...] # The list of nodes to group - "text" : # The synthetic text for that group - } - - @param groups_infos: A list of objects that describe those groups. - @return: A [, , ...] list of group nodes, or None (failure). - """ - return ida_idaapi.pygc_create_groups(self, groups_infos) - - def DeleteGroups(self, groups, new_current = -1): - """ - Send a request to delete the specified groups in the graph, - and perform an animation. - - @param groups: A list of group node numbers. - @param new_current: A node to focus on after the groups have been deleted - @return: True on success, False otherwise. - """ - return ida_idaapi.pygc_delete_groups(self, groups, new_current) - - def SetGroupsVisibility(self, groups, expand, new_current = -1): - """ - Send a request to expand/collapse the specified groups in the graph, - and perform an animation. - - @param groups: A list of group node numbers. - @param expand: True to expand the group, False otherwise. - @param new_current: A node to focus on after the groups have been expanded/collapsed. - @return: True on success, False otherwise. - """ - return ida_idaapi.pygc_set_groups_visibility(self, groups, expand, new_current) - - def GetTForm(self): - """ - Return the TForm hosting this view. - - @return: The TForm that hosts this view, or None. - """ - return ida_idaapi.pycim_get_tform(self) - - def GetTCustomControl(self): - """ - Return the TCustomControl underlying this view. - - @return: The TCustomControl underlying this view, or None. - """ - return ida_idaapi.pycim_get_tcustom_control(self) + def dummy(self, *args): + pass +_BC695 = __BC695() # + +# +pycim_get_tcustom_control=pycim_get_widget +pycim_get_tform=pycim_get_widget +# diff --git a/pywraps/py_idaapi_loader_input.hpp b/pywraps/py_idaapi_loader_input.hpp index de0e5b0..e1615e1 100644 --- a/pywraps/py_idaapi_loader_input.hpp +++ b/pywraps/py_idaapi_loader_input.hpp @@ -35,7 +35,7 @@ class loader_input_t(pyidc_opaque_object_t): """Create a linput for process memory (By internally calling idaapi.create_memory_linput()) This linput will use dbg->read_memory() to read data @param start: starting address of the input - @param size: size of the memory area to represent as linput + @param size: size of the memory range to represent as linput if unknown, may be passed as 0 """ pass @@ -251,9 +251,9 @@ public: } //-------------------------------------------------------------------------- - int32 seek(int32 pos, int whence = SEEK_SET) + int64 seek(int64 pos, int whence = SEEK_SET) { - int32 r; + int64 r; PYW_GIL_GET; Py_BEGIN_ALLOW_THREADS; r = qlseek(li, pos, whence); @@ -262,9 +262,9 @@ public: } //-------------------------------------------------------------------------- - int32 tell() + int64 tell() { - int32 r; + int64 r; PYW_GIL_GET; Py_BEGIN_ALLOW_THREADS; r = qltell(li); @@ -273,7 +273,7 @@ public: } //-------------------------------------------------------------------------- - PyObject *getz(size_t sz, int32 fpos = -1) + PyObject *getz(size_t sz, int64 fpos = -1) { PYW_GIL_CHECK_LOCKED_SCOPE(); do @@ -305,10 +305,7 @@ public: ok = qlgets(buf, len, li) != NULL; Py_END_ALLOW_THREADS; if ( !ok ) - { - free(buf); - break; - } + buf[0] = '\0'; PyObject *ret = PyString_FromString(buf); free(buf); return ret; @@ -330,10 +327,7 @@ public: r = qlread(li, buf, size); Py_END_ALLOW_THREADS; if ( r == -1 ) - { - free(buf); - break; - } + r = 0; PyObject *ret = PyString_FromStringAndSize(buf, r); free(buf); return ret; @@ -361,10 +355,7 @@ public: r = lreadbytes(li, buf, size, big_endian); Py_END_ALLOW_THREADS; if ( r == -1 ) - { - free(buf); - break; - } + r = 0; PyObject *ret = PyString_FromStringAndSize(buf, r); free(buf); return ret; @@ -373,7 +364,7 @@ public: } //-------------------------------------------------------------------------- - int file2base(int32 pos, ea_t ea1, ea_t ea2, int patchable) + int file2base(int64 pos, ea_t ea1, ea_t ea2, int patchable) { int rc; Py_BEGIN_ALLOW_THREADS; @@ -383,9 +374,9 @@ public: } //-------------------------------------------------------------------------- - int32 size() + int64 size() { - int32 rc; + int64 rc; Py_BEGIN_ALLOW_THREADS; rc = qlsize(li); Py_END_ALLOW_THREADS; diff --git a/pywraps/py_idc.hpp b/pywraps/py_idc.hpp new file mode 100644 index 0000000..a7b5dab --- /dev/null +++ b/pywraps/py_idc.hpp @@ -0,0 +1,46 @@ + +// +//------------------------------------------------------------------------- +inline void mark_position( + ea_t ea, + int lnnum, + short x, + short y, + int32 slot, + const char *comment) +{ + idaplace_t ip(ea, lnnum); + renderer_info_t ri; + ri.rtype = TCCRT_FLAT; + ri.pos.cx = x; + ri.pos.cy = y; + lochist_entry_t loc(&ip, ri); + bookmarks_t::mark(loc, slot, NULL, comment, NULL); +} + +//------------------------------------------------------------------------- +inline ea_t get_marked_pos(int32 slot) +{ + idaplace_t ip(inf.min_ea, 0); + renderer_info_t ri; + lochist_entry_t loc(&ip, ri); + uint32 uslot = uint32(slot); + return bookmarks_t::get(&loc, NULL, &uslot, NULL) + ? loc.place()->toea() + : BADADDR; +} + +//------------------------------------------------------------------------- +inline PyObject *get_mark_comment(int32 slot) +{ + qstring desc; + idaplace_t ip(inf.min_ea, 0); + renderer_info_t ri; + lochist_entry_t loc(&ip, ri); + if ( bookmarks_t::get_desc(&desc, loc, slot, NULL) ) + return PyString_FromString(desc.c_str()); + else + Py_RETURN_NONE; +} +// + diff --git a/pywraps/py_idd.hpp b/pywraps/py_idd.hpp index 0443002..f426871 100644 --- a/pywraps/py_idd.hpp +++ b/pywraps/py_idd.hpp @@ -11,11 +11,11 @@ static bool dbg_can_query() //------------------------------------------------------------------------- PyObject *py_appcall( - ea_t func_ea, - thid_t tid, - PyObject *py_type, - PyObject *py_fields, - PyObject *arg_list) + ea_t func_ea, + thid_t tid, + PyObject *py_type, + PyObject *py_fields, + PyObject *arg_list) { PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -24,6 +24,10 @@ PyObject *py_appcall( const char *type = py_type == Py_None ? NULL : PyString_AS_STRING(py_type); const char *fields = py_fields == Py_None ? NULL : PyString_AS_STRING(py_fields); + tinfo_t tif; + tinfo_t *ptif = NULL; + if ( tif.deserialize(NULL, (const type_t **)&type, (const p_list **)&fields) ) + ptif = &tif; // Convert Python arguments into IDC values qvector idc_args; @@ -70,21 +74,19 @@ PyObject *py_appcall( qstring s; for ( Py_ssize_t i=0; i < nargs; i++ ) { - VarPrint(&s, &idc_args[i]); + print_idcv(&s, idc_args[i]); msg("%d]\n%s\n-----------\n", int(i), s.c_str()); s.qclear(); } } // Do Appcall - ret = appcall( - func_ea, - tid, - (type_t *)type, - (p_list *)fields, - idc_args.size(), - idc_args.begin(), - &idc_result); + ret = dbg_appcall(&idc_result, + func_ea, + tid, + ptif, + idc_args.begin(), + idc_args.size()); Py_END_ALLOW_THREADS; @@ -102,9 +104,7 @@ PyObject *py_appcall( // An error in the Appcall? (or an exception but AppCallOptions/DEBEV is not set) else { - char err_str[MAXSTR]; - qstrerror(ret, err_str, sizeof(err_str)); - PyErr_SetString(PyExc_Exception, err_str); + PyErr_SetString(PyExc_Exception, qstrerror(ret)); return NULL; } } @@ -116,7 +116,7 @@ PyObject *py_appcall( qstring s; for ( Py_ssize_t i=0; i < nargs; i++ ) { - VarPrint(&s, &idc_args[i]); + print_idcv(&s, idc_args[i]); msg("%d]\n%s\n-----------\n", int(i), s.c_str()); s.qclear(); } @@ -147,7 +147,7 @@ PyObject *py_appcall( msg("return var:\n" "-----------\n"); qstring s; - VarPrint(&s, &idc_result); + print_idcv(&s, idc_result); msg("%s\n-----------\n", s.c_str()); } py_result.incref(); @@ -166,7 +166,7 @@ def dbg_get_registers(): Basically, it returns an array of structure similar to to idd.hpp / register_info_t @return: None if no debugger is loaded - tuple(name, flags, class, dtyp, bit_strings, default_bit_strings_mask) + tuple(name, flags, class, dtype, bit_strings, default_bit_strings_mask) The bit_strings can be a tuple of strings or None (if the register does not have bit_strings) """ pass @@ -190,7 +190,7 @@ static PyObject *dbg_get_registers() // (Make sure it does not use custom formats because bit_string would be the format name) if ( ri.bit_strings != NULL && (ri.flags & REGISTER_CUSTFMT) == 0 ) { - int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4; + int nbits = (int)b2a_width((int)get_dtype_size(ri.dtype), 0) * 4; py_bits = PyList_New(nbits); for ( int i=0; i < nbits; i++ ) { @@ -204,13 +204,13 @@ static PyObject *dbg_get_registers() py_bits = Py_None; } - // name, flags, class, dtyp, bit_strings, default_bit_strings_mask + // name, flags, class, dtype, bit_strings, default_bit_strings_mask PyList_SetItem(py_list, i, Py_BuildValue("(sIIINI)", ri.name, ri.flags, (unsigned int)ri.register_class, - (unsigned int)ri.dtyp, + (unsigned int)ri.dtype, py_bits, (unsigned int)ri.default_bit_strings_mask)); } @@ -241,10 +241,10 @@ static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_va ea_t answer; thid_t tid = PyInt_AsLong(py_tid); int sreg_value = PyInt_AsLong(py_sreg_value); - if ( internal_get_sreg_base(tid, sreg_value, &answer) != 1 ) + if ( internal_get_sreg_base(&answer, tid, sreg_value) != 1 ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, pyul_t(answer)); + return Py_BuildValue(PY_BV_EA, bvea_t(answer)); } //------------------------------------------------------------------------- @@ -343,7 +343,7 @@ def dbg_get_memory_info(): This function returns the memory configuration of a debugged process. @return: None if no debugger is active - tuple(startEA, endEA, name, sclass, sbase, bitness, perm) + tuple(start_ea, end_ea, name, sclass, sbase, bitness, perm) """ pass # @@ -356,14 +356,14 @@ static PyObject *dbg_get_memory_info() Py_RETURN_NONE; // Invalidate memory - meminfo_vec_t areas; + meminfo_vec_t ranges; Py_BEGIN_ALLOW_THREADS; invalidate_dbgmem_config(); invalidate_dbgmem_contents(BADADDR, BADADDR); - get_dbg_memory_info(&areas); + get_dbg_memory_info(&ranges); Py_END_ALLOW_THREADS; - return meminfo_vec_t_to_py(areas); + return meminfo_vec_t_to_py(ranges); } //------------------------------------------------------------------------- @@ -384,11 +384,11 @@ def dbg_can_query(): */ static bool dbg_can_query(); PyObject *py_appcall( - ea_t func_ea, - thid_t tid, - PyObject *py_type, - PyObject *py_fields, - PyObject *arg_list); + ea_t func_ea, + thid_t tid, + PyObject *py_type, + PyObject *py_fields, + PyObject *arg_list); char get_event_module_name(const debug_event_t *ev, char *buf, size_t bufsize) { diff --git a/pywraps/py_idd.py b/pywraps/py_idd.py index f672a5f..45ca764 100644 --- a/pywraps/py_idd.py +++ b/pywraps/py_idd.py @@ -155,7 +155,7 @@ class Appcall_callable__(object): def __get_size(self): if self.__type == None: return -1 - r = _ida_typeinf.calc_type_size(_ida_typeinf.cvar.idati, self.__type) + r = _ida_typeinf.calc_type_size(None, self.__type) if not r: return -1 return r @@ -188,9 +188,9 @@ class Appcall_callable__(object): src = self.ea if type(src) == types.StringType: - return _ida_typeinf.unpack_object_from_bv(_ida_typeinf.cvar.idati, self.type, self.fields, src, flags) + return _ida_typeinf.unpack_object_from_bv(None, self.type, self.fields, src, flags) else: - return _ida_typeinf.unpack_object_from_idb(_ida_typeinf.cvar.idati, self.type, self.fields, src, flags) + return _ida_typeinf.unpack_object_from_idb(None, self.type, self.fields, src, flags) def store(self, obj, dest_ea=None, base_ea=0, flags=0): """ @@ -207,14 +207,14 @@ class Appcall_callable__(object): # no ea passed? thus pack to a string if dest_ea is None: return _ida_typeinf.pack_object_to_bv(obj, - _ida_typeinf.cvar.idati, + None, self.type, self.fields, base_ea, flags) else: return _ida_typeinf.pack_object_to_idb(obj, - _ida_typeinf.cvar.idati, + None, self.type, self.fields, dest_ea, @@ -277,7 +277,7 @@ class Appcall__(object): else: ea = name_or_ea # could not resolve name or invalid address? - if ea == _ida_idaapi.BADADDR or not _ida_bytes.isEnabled(ea): + if ea == _ida_idaapi.BADADDR or not _ida_bytes.is_mapped(ea): raise ValueError, "Undefined function " + name_or_ea return ea @@ -299,7 +299,7 @@ class Appcall__(object): if flags is None: flags = 1 | 2 | 4 # PT_SIL | PT_NDC | PT_TYP - result = _ida_typeinf.idc_parse_decl(_ida_typeinf.cvar.idati, prototype, flags) + result = _ida_typeinf.idc_parse_decl(None, prototype, flags) if result is None: raise ValueError, "Could not parse type: " + prototype @@ -389,7 +389,7 @@ class Appcall__(object): @return: Appcall object or raises ValueError exception """ # parse the type - result = _ida_typeinf.idc_parse_decl(_ida_typeinf.cvar.idati, typestr, 1 | 2 | 4) # PT_SIL | PT_NDC | PT_TYP + 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 # Return the callable method with type info @@ -414,3 +414,7 @@ class Appcall__(object): Appcall = Appcall__() # + +# +PROCESS_NO_THREAD=NO_THREAD +# diff --git a/pywraps/py_idp.hpp b/pywraps/py_idp.hpp index a71a88d..3e6a1ae 100644 --- a/pywraps/py_idp.hpp +++ b/pywraps/py_idp.hpp @@ -25,22 +25,16 @@ def AssembleLine(ea, cs, ip, use32, line): # */ static PyObject *AssembleLine( - ea_t ea, - ea_t cs, - ea_t ip, - bool use32, - const char *line) + ea_t ea, + ea_t cs, + ea_t ip, + bool use32, + const char *line) { - int inslen; char buf[MAXSTR]; - bool ok = false; - if ( ph.notify != NULL - && (inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0 ) - { - ok = true; - } + int inslen = ph.assemble((uchar *)buf, ea, cs, ip, use32, line); PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) + if ( inslen > 0 ) return PyString_FromStringAndSize(buf, inslen); else Py_RETURN_NONE; @@ -63,25 +57,21 @@ def assemble(ea, cs, ip, use32, line): # */ bool assemble( - ea_t ea, - ea_t cs, - ea_t ip, - bool use32, - const char *line) + ea_t ea, + ea_t cs, + ea_t ip, + bool use32, + const char *line) { - int inslen; char buf[MAXSTR]; PYW_GIL_CHECK_LOCKED_SCOPE(); bool rc = false; Py_BEGIN_ALLOW_THREADS; - if ( ph.notify != NULL ) + int inslen = ph.assemble((uchar *)buf, ea, cs, ip, use32, line); + if ( inslen > 0 ) { - inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf); - if ( inslen > 0 ) - { - patch_many_bytes(ea, buf, inslen); - rc = true; - } + patch_bytes(ea, buf, inslen); + rc = true; } Py_END_ALLOW_THREADS; return rc; @@ -165,31 +155,31 @@ static size_t ph_get_dnbits() //------------------------------------------------------------------------- /* # -def ph_get_regFirstSreg(): +def ph_get_reg_first_sreg(): """ - Returns the 'ph.regFirstSreg' + Returns the 'ph.reg_first_sreg' """ pass # */ -static size_t ph_get_regFirstSreg() +static size_t ph_get_reg_first_sreg() { - return ph.regFirstSreg; + return ph.reg_first_sreg; } //------------------------------------------------------------------------- /* # -def ph_get_regLastSreg(): +def ph_get_reg_last_sreg(): """ - Returns the 'ph.regLastSreg' + Returns the 'ph.reg_last_sreg' """ pass # */ -static size_t ph_get_regLastSreg() +static size_t ph_get_reg_last_sreg() { - return ph.regLastSreg; + return ph.reg_last_sreg; } //------------------------------------------------------------------------- @@ -210,46 +200,31 @@ static size_t ph_get_segreg_size() //------------------------------------------------------------------------- /* # -def ph_get_regCodeSreg(): +def ph_get_reg_code_sreg(): """ - Returns the 'ph.regCodeSreg' + Returns the 'ph.reg_code_sreg' """ pass # */ -static size_t ph_get_regCodeSreg() +static size_t ph_get_reg_code_sreg() { - return ph.regCodeSreg; + return ph.reg_code_sreg; } //------------------------------------------------------------------------- /* # -def ph_get_regDataSreg(): +def ph_get_reg_data_sreg(): """ - Returns the 'ph.regDataSreg' + Returns the 'ph.reg_data_sreg' """ pass # */ -static size_t ph_get_regDataSreg() +static size_t ph_get_reg_data_sreg() { - return ph.regDataSreg; -} - -//------------------------------------------------------------------------- -/* -# -def ph_get_high_fixup_bits(): - """ - Returns the 'ph.high_fixup_bits' - """ - pass -# -*/ -static size_t ph_get_high_fixup_bits() -{ - return ph.high_fixup_bits; + return ph.reg_data_sreg; } //------------------------------------------------------------------------- @@ -351,16 +326,16 @@ static PyObject *ph_get_regnames() { Py_ssize_t i = 0; PYW_GIL_CHECK_LOCKED_SCOPE(); - PyObject *py_result = PyList_New(ph.regsNum); - for ( Py_ssize_t i=0; i < ph.regsNum; i++ ) - PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i])); + PyObject *py_result = PyList_New(ph.regs_num); + for ( Py_ssize_t i=0; i < ph.regs_num; i++ ) + PyList_SetItem(py_result, i, PyString_FromString(ph.reg_names[i])); return py_result; } //--------------------------------------------------------------------------- static const regval_t *idaapi _py_getreg( - const char *name, - const regval_t *regvals); + const char *name, + const regval_t *regvals); /* # @@ -378,8 +353,8 @@ def ph_get_operand_info(): # */ static PyObject *ph_get_operand_info( - ea_t ea, - int n) + ea_t ea, + int n) { PYW_GIL_CHECK_LOCKED_SCOPE(); bool ok = false; @@ -399,13 +374,13 @@ static PyObject *ph_get_operand_info( break; // Call the processor module - if ( ph.notify(ph.get_operand_info, + if ( ph.notify(ph.ev_get_idd_opinfo, + &opinf, ea, n, tid, _py_getreg, - regvalues.begin(), - &opinf) > 0 ) + regvalues.begin()) == 0 ) { break; } @@ -414,9 +389,9 @@ static PyObject *ph_get_operand_info( Py_END_ALLOW_THREADS; if ( ok ) - return Py_BuildValue("(i" PY_FMT64 "Kii)", + return Py_BuildValue("(i" PY_BV_EA "Kii)", opinf.modified, - opinf.ea, + bvea_t(opinf.ea), opinf.value.ival, opinf.debregidx, opinf.value_size); @@ -445,65 +420,65 @@ class IDP_Hooks(object): pass - def custom_ana(self): + def ev_ana_insn(self, insn): """ - Analyzes and decodes an instruction at idaapi.cmd.ea - - cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE - - cmd.size must be set to the instruction length + Analyzes and decodes an instruction at insn.ea + - insn.itype must be set >= idaapi.CUSTOM_CMD_ITYPE + - insn.size must be set to the instruction length @return: Boolean - False if the instruction is not recognized - - True if the instruction was decoded. idaapi.cmd should be filled in that case. + - True if the instruction was decoded. 'insn' should be filled in that case. """ pass - def custom_out(self): + def ev_out_insn(self, ctx): """ - Outputs the instruction defined in idaapi.cmd + Outputs the instruction defined in 'ctx.insn' @return: Boolean (whether this instruction can be outputted or not) """ pass - def custom_emu(self): + def ev_emu_insn(self, insn): """ Emulate instruction, create cross-references, plan to analyze subsequent instructions, modify flags etc. Upon entrance to this function - all information about the instruction is in 'cmd' structure. + all information about the instruction is in 'insn' structure. @return: Boolean (whether this instruction has been emulated or not) """ pass - def custom_outop(self, op): + def ev_out_operand(self, ctx, op): """ Notification to generate operand text. If False was returned, then the standard operand output function will be called. - The output buffer is inited with init_output_buffer() - and this notification may use out_...() functions to form the operand text + this notification may use out_...() functions to form the operand text @return: Boolean (whether the operand has been outputted or not) """ pass - def custom_mnem(self): + def ev_gen_mnem(self, ctx): """ - Prints the mnemonic of the instruction defined in idaapi.cmd + Notification to generate instruction mnemonics. @return: - - None: No mnemonic. IDA will use the default mnemonic value if present - - String: The desired mnemonic string + - None: No custom mnemonics. IDA will generate a mnemonic name + - 1: Generated the instruction mnemonics """ pass - def is_sane_insn(self, no_crefs): + def ev_is_sane_insn(self, insn, no_crefs): """ is the instruction sane for the current file type? + @param insn: the instruction @param no_crefs: - 1: the instruction has no code refs to it. ida just tries to convert unexplored bytes @@ -512,14 +487,15 @@ class IDP_Hooks(object): - 0: the instruction is created because of some coderef, user request or another weighty reason. - @return: 1-ok, <=0-no, the instruction isn't likely to appear in the program + @return: >=0-ok, <0-no, the instruction isn't likely to appear in the program """ pass - def may_be_func(self, no_crefs): + def ev_may_be_func(self, insn, state): """ Can a function start here? + @param insn: the instruction @param state: autoanalysis phase 0: creating functions 1: creating chunks @@ -529,21 +505,7 @@ class IDP_Hooks(object): pass - def closebase(self): - """ - The database will be closed now - """ - pass - - - def savebase(self): - """ - The database is being saved. Processor module should - """ - pass - - - def rename(self, ea, new_name): + def ev_rename(self, ea, new_name): """ The kernel is going to rename a byte. @@ -551,121 +513,46 @@ class IDP_Hooks(object): @param new_name: The new name @return: - - If returns value <=0, then the kernel should + - If returns value <0, then the kernel should not rename it. See also the 'renamed' event """ pass - def renamed(self, ea, new_name, local_name): - """ - The kernel has renamed a byte - - @param ea: Address - @param new_name: The new name - @param local_name: Is local name - - @return: Ignored - """ - pass - - - def undefine(self, ea): + def ev_undefine(self, ea): """ An item in the database (insn or data) is being deleted @param ea: Address @return: - - returns: >0-ok, <=0-the kernel should stop - - if the return value is positive: - bit0 - ignored - bit1 - do not delete srareas at the item end + - 1 - do not delete srranges at the item end + - 0 - srranges can be deleted """ pass - def make_code(self, ea, size): - """ - An instruction is being created - @param ea: Address - @param size: Instruction size - @return: 1-ok, <=0-the kernel should stop - """ - pass - - - def make_code(self, ea, size): - """ - An instruction is being created - @param ea: Address - @param size: Instruction size - @return: 1-ok, <=0-the kernel should stop - """ - pass - - - def make_data(self, ea, flags, tid, len): - """ - A data item is being created - @param ea: Address - @param tid: type id - @param flags: item flags - @param len: data item size - @return: 1-ok, <=0-the kernel should stop - """ - pass - - - def load_idasgn(self, short_sig_name): - """ - FLIRT signature have been loaded for normal processing - (not for recognition of startup sequences) - @param short_sig_name: signature name - @return: Ignored - """ - pass - - - def add_func(self, func): - """ - The kernel has added a function - @param func: the func_t instance - @return: Ignored - """ - pass - - - def del_func(self, func): - """ - The kernel is about to delete a function - @param func: the func_t instance - @return: 1-ok,<=0-do not delete - """ - pass - - - def is_call_insn(self, ea, func_name): + def ev_is_call_insn(self, insn): """ Is the instruction a "call"? - @param ea: instruction address - @return: 1-unknown, 0-no, 2-yes + @param insn: instruction + @return: 0-unknown, 1-yes, -1-no """ pass - def is_ret_insn(self, ea, func_name): + def ev_is_ret_insn(self, insn, strict): """ Is the instruction a "return"? - @param ea: instruction address + @param insn: instruction @param strict: - True: report only ret instructions False: include instructions like "leave" which begins the function epilog - @return: 1-unknown, 0-no, 2-yes + @return: 0-unknown, 1-yes, -1-no """ pass - def assemble(self, ea, cs, ip, use32, line): + def ev_assemble(self, ea, cs, ip, use32, line): """ Assembles an instruction @@ -689,37 +576,28 @@ class IDP_Hooks(object): // Necessary forward declarations; idp.hpp itself doesn't need them. struct mblock_t; struct proc_def; -struct set_elf_reloc_t; struct libfunc_t; -int idaapi IDP_Callback(void *ud, int notification_code, va_list va); +ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va); class IDP_Hooks { - friend int idaapi IDP_Callback(void *ud, int notification_code, va_list va); - static int bool_to_cmdsize(bool in) { return in ? (1 + cmd.size) : 0; } - static int bool_to_2or0(bool in) { return in ? 2 : 0; } + friend ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va); + static int bool_to_insn_t_size(bool in, const insn_t *insn) { return in ? insn->size : 0; } + static int bool_to_1or0(bool in) { return in ? 1 : 0; } static int cm_t_to_int(cm_t cm) { return int(cm); } - static bool _handle_string_output(PyObject *o, char *buf, size_t bufsize) - { - bool is_str = o != NULL && PyString_Check(o); - if ( is_str && buf != NULL ) - qstrncpy(buf, PyString_AS_STRING(o), bufsize); - Py_XDECREF(o); - return is_str; - } static bool _handle_qstring_output(PyObject *o, qstring *buf) { bool is_str = o != NULL && PyString_Check(o); if ( is_str && buf != NULL ) - buf->append(PyString_AS_STRING(o)); + *buf = PyString_AS_STRING(o); Py_XDECREF(o); return is_str; } - static int handle_custom_mnem_output(PyObject *o, char *buf, size_t bufsize) + static int handle_custom_mnem_output(PyObject *o, qstring *out, const insn_t *) { - return _handle_string_output(o, buf, bufsize) ? 2 : 0; + return _handle_qstring_output(o, out) && !out->empty() ? 1 : 0; } - static int handle_assemble_output(PyObject *o, ea_t /*ea*/, ea_t /*cs*/, ea_t /*ip*/, bool /*use32*/, const char */*line*/, uchar *bin) + static int handle_assemble_output(PyObject *o, uchar *bin, ea_t /*ea*/, ea_t /*cs*/, ea_t /*ip*/, bool /*use32*/, const char */*line*/) { int rc = 0; if ( o != NULL && PyString_Check(o) ) @@ -737,16 +615,13 @@ class IDP_Hooks Py_XDECREF(o); return rc; } - static int handle_get_reg_name_output(PyObject *o, int /*reg*/, size_t /*width*/, char *buf, size_t bufsize, int /*reghi*/) + static int handle_get_reg_name_output(PyObject *o, qstring *buf, int /*reg*/, size_t /*width*/, int /*reghi*/) { - int rc = 0; - if ( _handle_string_output(o, buf, bufsize) ) - rc = qstrlen(buf) + 2; - return rc; + return _handle_qstring_output(o, buf) ? buf->length() : 0; } - static int handle_decorate_name3_output(PyObject *o, qstring *outbuf, const char * /*name*/, bool /*mangle*/, int /*cc*/) + static int handle_decorate_name3_output(PyObject *o, qstring *outbuf, const char * /*name*/, bool /*mangle*/, int /*cc*/, const tinfo_t * /*type*/) { - return _handle_qstring_output(o, outbuf) ? 2 : 0; + return _handle_qstring_output(o, outbuf) ? 1 : 0; } static int handle_delay_slot_insn_output(PyObject *o, ea_t *pea, bool *pbexec, bool *pfexec) { @@ -766,11 +641,58 @@ class IDP_Hooks *pbexec = py_bexec.o == Py_True; if ( pfexec != NULL ) *pfexec = py_fexec.o == Py_True; - return 2; + return 1; } } return -1; } + static int handle_use_regarg_type_output(PyObject *o, int *idx, ea_t, const funcargvec_t *) + { + int rc = 0; + if ( PySequence_Check(o) && PySequence_Size(o) == 2 ) + { + newref_t py_rc(PySequence_GetItem(o, 0)); + newref_t py_idx(PySequence_GetItem(o, 1)); + if ( PyInt_Check(py_rc.o) && PyInt_Check(py_idx.o) ) + { + rc = PyInt_AsLong(py_rc.o); + *idx = PyInt_AsLong(py_idx.o); + } + } + return rc; + } + static int handle_demangle_name_output( + PyObject *o, + int32 *out_res, + qstring *out, + const char *name, + uint32 disable_mask, + demreq_type_t demreq) + { + int rc = 0; + if ( PySequence_Check(o) && PySequence_Size(o) == 3 ) + { + newref_t py_rc(PySequence_GetItem(o, 0)); + newref_t py_out(PySequence_GetItem(o, 1)); + newref_t py_out_res(PySequence_GetItem(o, 2)); + char *s; + Py_ssize_t len = 0; + if ( PyInt_Check(py_rc.o) + && PyInt_Check(py_out_res.o) + && PyString_Check(py_out.o) + && PyString_AsStringAndSize(py_out.o, &s, &len) != -1 ) + { + rc = PyInt_AsLong(py_rc.o); + *out_res = PyInt_AsLong(py_out_res.o); + if ( out != NULL ) + { + out->qclear(); + out->append(s, len); + } + } + } + return rc; + } public: virtual ~IDP_Hooks() @@ -780,12 +702,12 @@ public: bool hook() { - return hook_to_notification_point(HT_IDP, IDP_Callback, this); + return idapython_hook_to_notification_point(HT_IDP, IDP_Callback, this); } bool unhook() { - return unhook_from_notification_point(HT_IDP, IDP_Callback, this); + return idapython_unhook_from_notification_point(HT_IDP, IDP_Callback, this); } // hookgenIDP:methods }; @@ -794,7 +716,7 @@ public: //------------------------------------------------------------------------- // //------------------------------------------------------------------------- -int idaapi IDP_Callback(void *ud, int notification_code, va_list va) +ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; @@ -819,8 +741,8 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va) //------------------------------------------------------------------------- static const regval_t *idaapi _py_getreg( - const char *name, - const regval_t *regvals) + const char *name, + const regval_t *regvals) { for ( int i=dbg->registers_size - 1; i >= 0; i-- ) { diff --git a/pywraps/py_idp.py b/pywraps/py_idp.py index 0c3ea17..a473ccd 100644 --- a/pywraps/py_idp.py +++ b/pywraps/py_idp.py @@ -7,7 +7,7 @@ # ---------------------------------------------------------------------- # processor_t related constants -CUSTOM_CMD_ITYPE = 0x8000 +CUSTOM_INSN_ITYPE = 0x8000 REG_SPOIL = 0x80000000 REAL_ERROR_FORMAT = -1 # not supported format for current .idp @@ -109,7 +109,6 @@ PR_ALIGN = 0x000800 # All data items should be aligned properly PR_TYPEINFO = 0x001000 # the processor module supports # type information callbacks # ALL OF THEM SHOULD BE IMPLEMENTED! - # (the ones >= decorate_name) PR_USE64 = 0x002000 # supports 64-bit addressing? PR_SGROTHER = 0x004000 # the segment registers don't contain # the segment selectors, something else @@ -122,13 +121,11 @@ PR_BINMEM = 0x010000 # the processor module provides correct PR_SEGTRANS = 0x020000 # the processor module supports # the segment translation feature # (it means it calculates the code - # addresses using the codeSeg() function) + # addresses using the map_code_ea() function) PR_CHK_XREF = 0x040000 # don't allow near xrefs between segments # with different bases PR_NO_SEGMOVE = 0x080000 # the processor module doesn't support move_segm() # (i.e. the user can't move segments) -PR_FULL_HIFXP = 0x100000 # REF_VHIGH operand value contains full operand - # not only the high bits. Meaningful if ph.high_fixup_bits PR_USE_ARG_TYPES = 0x200000 # use ph.use_arg_types callback PR_SCALE_STKVARS = 0x400000 # use ph.get_stkvar_scale callback PR_DELAYED = 0x800000 # has delayed jumps and calls @@ -187,8 +184,7 @@ import ida_ua class processor_t(ida_idaapi.pyidc_opaque_object_t): """Base class for all processor module scripts""" def __init__(self): - # Take a reference to 'cmd' - self.cmd = ida_ua.cmd + pass def get_idpdesc(self): """ @@ -202,9 +198,9 @@ class processor_t(ida_idaapi.pyidc_opaque_object_t): """Use this utility function to retrieve the 'uFlag' global variable""" return ida_ua.cvar.uFlag - def get_auxpref(self): - """This function returns cmd.auxpref value""" - return self.cmd.auxpref + def get_auxpref(self, insn): + """This function returns insn.auxpref value""" + return insn.auxpref # ---------------------------------------------------------------------- @@ -213,15 +209,14 @@ class __ph(object): cnbits = property(lambda self: ph_get_cnbits()) dnbits = property(lambda self: ph_get_dnbits()) flag = property(lambda self: ph_get_flag()) - high_fixup_bits = property(lambda self: ph_get_high_fixup_bits()) icode_return = property(lambda self: ph_get_icode_return()) instruc = property(lambda self: ph_get_instruc()) instruc_end = property(lambda self: ph_get_instruc_end()) instruc_start = property(lambda self: ph_get_instruc_start()) - regCodeSreg = property(lambda self: ph_get_regCodeSreg()) - regDataSreg = property(lambda self: ph_get_regDataSreg()) - regFirstSreg = property(lambda self: ph_get_regFirstSreg()) - regLastSreg = property(lambda self: ph_get_regLastSreg()) + reg_code_sreg = property(lambda self: ph_get_reg_code_sreg()) + reg_data_sreg = property(lambda self: ph_get_reg_data_sreg()) + reg_first_sreg = property(lambda self: ph_get_reg_first_sreg()) + reg_last_sreg = property(lambda self: ph_get_reg_last_sreg()) regnames = property(lambda self: ph_get_regnames()) segreg_size = property(lambda self: ph_get_segreg_size()) tbyte_size = property(lambda self: ph_get_tbyte_size()) @@ -230,3 +225,65 @@ class __ph(object): ph = __ph() # + +# +AS_NOTAB=0 +CUSTOM_CMD_ITYPE=CUSTOM_INSN_ITYPE +InstrIsSet=has_insn_feature +NEXTEAS_ANSWER_SIZE=0 +PR_FULL_HIFXP=0 +SETPROC_ALL=SETPROC_LOADER_NON_FATAL +SETPROC_COMPAT=SETPROC_IDB +SETPROC_FATAL=SETPROC_LOADER +area_cmt_changed=range_cmt_changed +changed_stkpnts=stkpnts_changed +changed_struc=struc_align_changed +changing_area_cmt=changing_range_cmt +changing_struc=changing_struc_align +func_tail_removed=func_tail_deleted +get_reg_info2=get_reg_info +ph_get_regCodeSreg=ph_get_reg_code_sreg +ph_get_regDataSreg=ph_get_reg_data_sreg +ph_get_regFirstSreg=ph_get_reg_first_sreg +ph_get_regLastSreg=ph_get_reg_last_sreg +removing_func_tail=deleting_func_tail +segm_attrs_changed=segm_attrs_updated +str2regf=str2reg +def __wrap_insn_func(name): + def __wrapper(*args): + arg0 = args[0] + import ida_ua + if not isinstance(arg0, ida_ua.insn_t): + tmp = ida_ua.insn_t() + if not ida_ua.decode_insn(tmp, arg0): + return False + arg0 = tmp + return getattr(_ida_idp, name)(arg0, *args[1:]) + globals()[name] = __wrapper +__wrap_insn_func("is_call_insn") +__wrap_insn_func("is_ret_insn") +__wrap_insn_func("is_indirect_jump_insn") +__wrap_insn_func("is_basic_block_end") +def parse_reg_name(*args): + if isinstance(args[1], reg_info_t): # 6.95: regname, reg_info_t + regname, ri = args + else: # 7.00: reg_info_t, regname + ri, regname = args + return _ida_idp.parse_reg_name(ri, regname) + +def __call_IDP_Hooks_auto_queue_empty(cb, qtype): + old_rc = cb(qtype) + if old_rc == 0: # 6.95's queue not empty anymore + rc = -1 # 7.0's queue not empty anymore + else: + rc = old_rc + return rc + +import ida_ida +ida_ida.__wrap_hooks_callback( + IDP_Hooks, + "ev_auto_queue_empty", + "auto_queue_empty", + __call_IDP_Hooks_auto_queue_empty) + +# diff --git a/pywraps/py_idp_idbhooks.hpp b/pywraps/py_idp_idbhooks.hpp index 5f40831..8ef143b 100644 --- a/pywraps/py_idp_idbhooks.hpp +++ b/pywraps/py_idp_idbhooks.hpp @@ -4,7 +4,7 @@ //--------------------------------------------------------------------------- // IDB hooks //--------------------------------------------------------------------------- -int idaapi IDB_Callback(void *ud, int notification_code, va_list va); +ssize_t idaapi IDB_Callback(void *ud, int notification_code, va_list va); class IDB_Hooks { public: @@ -12,11 +12,11 @@ public: bool hook() { - return hook_to_notification_point(HT_IDB, IDB_Callback, this); + return idapython_hook_to_notification_point(HT_IDB, IDB_Callback, this); } bool unhook() { - return unhook_from_notification_point(HT_IDB, IDB_Callback, this); + return idapython_unhook_from_notification_point(HT_IDB, IDB_Callback, this); } // hookgenIDB:methods @@ -26,7 +26,7 @@ public: // //--------------------------------------------------------------------------- -int idaapi IDB_Callback(void *ud, int notification_code, va_list va) +ssize_t idaapi IDB_Callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; diff --git a/pywraps/py_kernwin.hpp b/pywraps/py_kernwin.hpp index ba66780..dc662a3 100644 --- a/pywraps/py_kernwin.hpp +++ b/pywraps/py_kernwin.hpp @@ -6,15 +6,7 @@ // //------------------------------------------------------------------------ -//--------------------------------------------------------------------------- -// Context structure used by add|del_menu_item() -struct py_add_del_menu_item_ctx -{ - qstring menupath; - PyObject *cb_data; -}; - -//--------------------------------------------------------------------------- +//------------------------------------------------------------------------- // Context structure used by add|del_idc_hotkey() struct py_idchotkey_ctx_t { @@ -147,25 +139,25 @@ static PyObject *py_choose_idasgn() //------------------------------------------------------------------------ /* # -def get_highlighted_identifier(flags = 0): +def get_highlight(): """ - Returns the currently highlighted identifier + Returns the currently highlighted identifier and flags - @param flags: reserved (pass 0) - @return: None or the highlighted identifier + @return: a tuple (text, flags), or None if nothing + is highlighted or in case of error. """ pass # */ -static PyObject *py_get_highlighted_identifier(int flags = 0) +static PyObject *py_get_highlight(TWidget *v) { - char buf[MAXSTR]; - bool ok = get_highlighted_identifier(buf, sizeof(buf), flags); + qstring buf; + uint32 flags; + bool ok = get_highlight(&buf, v, &flags); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !ok ) Py_RETURN_NONE; - else - return PyString_FromString(buf); + return Py_BuildValue("(sk)", buf.c_str(), flags); } //------------------------------------------------------------------------ @@ -200,7 +192,7 @@ def free_custom_icon(icon_id): //------------------------------------------------------------------------- /* # -def readsel2(view, p0, p1): +def read_selection(view, p0, p1): """ Read the user selection, and store its information in p0 (from) and p1 (to). @@ -210,7 +202,7 @@ def readsel2(view, p0, p1): >>> p0 = idaapi.twinpos_t() p1 = idaapi.twinpos_t() view = idaapi.get_current_viewer() - idaapi.readsel2(view, p0, p1) + idaapi.read_selection(view, p0, p1) At that point, p0 and p1 hold information for the selection. @@ -236,41 +228,6 @@ def readsel2(view, p0, p1): # */ -//------------------------------------------------------------------------ -/* -# -def umsg(text): - """ - Prints text into IDA's Output window - - @param text: text to print - Can be Unicode, or string in UTF-8 encoding - @return: number of bytes printed - """ - pass -# -*/ -static PyObject *py_umsg(PyObject *o) -{ - PyObject *utf8 = NULL; - if ( PyUnicode_Check(o) ) - { - utf8 = PyUnicode_AsUTF8String(o); - o = utf8; - } - else if ( !PyString_Check(o) ) - { - PyErr_SetString(PyExc_TypeError, "A unicode or UTF-8 string expected"); - return NULL; - } - int rc; - Py_BEGIN_ALLOW_THREADS; - rc = umsg("%s", PyString_AsString(o)); - Py_END_ALLOW_THREADS; - Py_XDECREF(utf8); - return PyInt_FromLong(rc); -} - //------------------------------------------------------------------------ /* # @@ -287,17 +244,25 @@ def msg(text): */ static PyObject *py_msg(PyObject *o) { + const char *utf8 = NULL; + ref_t py_utf8; if ( PyUnicode_Check(o) ) - return py_umsg(o); - - if ( !PyString_Check(o) ) + { + py_utf8 = newref_t(PyUnicode_AsUTF8String(o)); + utf8 = PyString_AsString(py_utf8.o); + } + else if ( PyString_Check(o) ) + { + utf8 = PyString_AsString(o); + } + else { PyErr_SetString(PyExc_TypeError, "A string expected"); return NULL; } int rc; Py_BEGIN_ALLOW_THREADS; - rc = msg("%s", PyString_AsString(o)); + rc = msg("%s", utf8); Py_END_ALLOW_THREADS; return PyInt_FromLong(rc); } @@ -305,11 +270,11 @@ static PyObject *py_msg(PyObject *o) //------------------------------------------------------------------------ /* # -def asktext(max_text, defval, prompt): +def ask_text(defval, prompt): """ Asks for a long text - @param max_text: Maximum text length + @param max_size: Maximum text length, 0 for unlimited @param defval: The default value @param prompt: The prompt value @return: None or the entered string @@ -317,27 +282,54 @@ def asktext(max_text, defval, prompt): pass # */ -PyObject *py_asktext(int max_text, const char *defval, const char *prompt) +PyObject *py_ask_text(size_t max_size, const char *defval, const char *prompt) { PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( max_text <= 0 ) - Py_RETURN_NONE; - char *buf = new char[max_text]; - if ( buf == NULL ) - Py_RETURN_NONE; + qstring qbuf; PyObject *py_ret; - if ( asktext(size_t(max_text), buf, defval, "%s", prompt) != NULL ) + if ( ask_text(&qbuf, max_size, defval, "%s", prompt) ) { - py_ret = PyString_FromString(buf); + py_ret = PyString_FromStringAndSize(qbuf.begin(), qbuf.length()); + } + else + { + py_ret = Py_None; + Py_INCREF(py_ret); + } + return py_ret; +} + +//------------------------------------------------------------------------ +/* +# +def ask_str(defval, hist, prompt): + """ + Asks for a long text + + @param hist: history id + @param defval: The default value + @param prompt: The prompt value + @return: None or the entered string + """ + pass +# +*/ +PyObject *py_ask_str(qstring *defval, int hist, const char *prompt) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + PyObject *py_ret; + if ( ask_str(defval, hist, "%s", prompt) ) + { + py_ret = PyString_FromStringAndSize(defval->begin(), defval->length()); } else { py_ret = Py_None; Py_INCREF(py_ret); } - delete [] buf; return py_ret; } @@ -356,30 +348,10 @@ def str2ea(addr): ea_t py_str2ea(const char *str, ea_t screenEA = BADADDR) { ea_t ea; - bool ok = str2ea(str, &ea, screenEA); + bool ok = str2ea(&ea, str, screenEA); return ok ? ea : BADADDR; } -//------------------------------------------------------------------------ -/* -# -def str2user(str): - """ - Insert C-style escape characters to string - - @return: new string with escape characters inserted - """ - pass -# -*/ -PyObject *py_str2user(const char *str) -{ - qstring qstr(str); - qstring retstr; - qstr2user(&retstr, qstr); - return PyString_FromString(retstr.c_str()); -} - //------------------------------------------------------------------------ /* # @@ -398,32 +370,6 @@ static bool py_process_ui_action(const char *name, int flags = 0) return process_ui_action(name, flags, NULL); } -//------------------------------------------------------------------------ -/* -# -def del_menu_item(menu_ctx): - """Deprecated. Use detach_menu_item()/unregister_action() instead.""" - pass -# -*/ -static bool py_del_menu_item(PyObject *py_ctx) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_ctx) ) - return false; - - py_add_del_menu_item_ctx *ctx = (py_add_del_menu_item_ctx *)PyCObject_AsVoidPtr(py_ctx); - - bool ok = del_menu_item(ctx->menupath.c_str()); - if ( ok ) - { - Py_DECREF(ctx->cb_data); - delete ctx; - } - - return ok; -} - //------------------------------------------------------------------------ /* # @@ -508,8 +454,8 @@ PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc) idc_gvarname.c_str()); // Compile the IDC condition - char errbuf[MAXSTR]; - if ( !CompileLineEx(idc_func.c_str(), errbuf, sizeof(errbuf)) ) + qstring errbuf; + if ( !compile_idc_text(idc_func.c_str(), &errbuf) ) break; // Create new context @@ -573,9 +519,9 @@ static void idaapi py_ss_restore_callback(const char *err_msg, void *userdata) PyErr_Print(); } static PyObject *py_restore_database_snapshot( - const snapshot_t *ss, - PyObject *pyfunc_or_none, - PyObject *pytuple_or_none) + const snapshot_t *ss, + PyObject *pyfunc_or_none, + PyObject *pytuple_or_none) { PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -607,76 +553,6 @@ static PyObject *py_restore_database_snapshot( return PyBool_FromLong(b); } -//------------------------------------------------------------------------ -/* -# -def add_menu_item(menupath, name, hotkey, flags, callback, args): - """Deprecated. Use register_action()/attach_menu_item() instead.""" - pass -# -*/ -bool idaapi py_menu_item_callback(void *userdata); -static PyObject *py_add_menu_item( - const char *menupath, - const char *name, - const char *hotkey, - int flags, - PyObject *pyfunc, - PyObject *args) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - bool no_args; - - // No slash in the menu path? - const char *p = strrchr(menupath, '/'); - if ( p == NULL ) - Py_RETURN_NONE; - - if ( args == Py_None ) - { - no_args = true; - args = PyTuple_New(0); - if ( args == NULL ) - return NULL; - } - else if ( !PyTuple_Check(args) ) - { - PyErr_SetString(PyExc_TypeError, "args must be a tuple or None"); - return NULL; - } - else - { - no_args = false; - } - - // Form a tuple holding the function to be called and its arguments - PyObject *cb_data = Py_BuildValue("(OO)", pyfunc, args); - - // If we created an empty tuple, then we must free it - if ( no_args ) - Py_DECREF(args); - - // Add the menu item - bool b = add_menu_item(menupath, name, hotkey, flags, py_menu_item_callback, (void *)cb_data); - - if ( !b ) - { - Py_XDECREF(cb_data); - Py_RETURN_NONE; - } - // Create a context (for the delete_menu_item()) - py_add_del_menu_item_ctx *ctx = new py_add_del_menu_item_ctx(); - - // Form the complete menu path - ctx->menupath.append(menupath, p - menupath + 1); - ctx->menupath.append(name); - // Save callback data - ctx->cb_data = cb_data; - - // Return context to user - return PyCObject_FromVoidPtr(ctx, NULL); -} - //------------------------------------------------------------------------ /* # @@ -711,7 +587,7 @@ def execute_sync(callable, reqf): If the current thread not the main thread, then the call is queued and executed afterwards. - @param callable: A python callable object + @param callable: A python callable object, must return an integer value @param reqf: one of MFF_ flags @return: -1 or the return value of the callable """ @@ -895,7 +771,7 @@ def is_idaq(): //--------------------------------------------------------------------------- // UI hooks //--------------------------------------------------------------------------- -int idaapi UI_Callback(void *ud, int notification_code, va_list va); +ssize_t idaapi UI_Callback(void *ud, int notification_code, va_list va); /* # class UI_Hooks(object): @@ -914,19 +790,19 @@ class UI_Hooks(object): """ pass - def preprocess(self, name): + def preprocess_action(self, name): """ - IDA ui is about to handle a user command + IDA ui is about to handle a user action - @param name: ui command name + @param name: ui action name (these names can be looked up in ida[tg]ui.cfg) - @return: 0-ok, nonzero - a plugin has handled the command + @return: 0-ok, nonzero - a plugin has handled the action """ pass - def postprocess(self): + def postprocess_action(self): """ - An ida ui command has been handled + An ida ui action has been handled @return: Ignored """ @@ -974,23 +850,23 @@ class UI_Hooks(object): """ pass - def populating_tform_popup(self, form, popup): + def populating_widget_popup(self, widget, popup): """ - The UI is populating the TForm's popup menu. + The UI is populating the TWidget's popup menu. Now is a good time to call idaapi.attach_action_to_popup() - @param form: The form + @param widget: The widget @param popup: The popup menu. @return: Ignored """ pass - def finish_populating_tform_popup(self, form, popup): + def finish_populating_widget_popup(self, widget, popup): """ - The UI is about to be done populating the TForm's popup menu. + The UI is about to be done populating the TWidget's popup menu. Now is a good time to call idaapi.attach_action_to_popup() - @param form: The form + @param widget: The widget @param popup: The popup menu. @return: Ignored """ @@ -1019,29 +895,29 @@ public: bool hook() { - return hook_to_notification_point(HT_UI, UI_Callback, this); + return idapython_hook_to_notification_point(HT_UI, UI_Callback, this); } bool unhook() { - return unhook_from_notification_point(HT_UI, UI_Callback, this); + return idapython_unhook_from_notification_point(HT_UI, UI_Callback, this); } - static int handle_get_ea_hint_output(PyObject *o, ea_t, char *buf, size_t bufsize) + static int handle_get_ea_hint_output(PyObject *o, qstring *buf, ea_t) { int rc = 0; char *_buf; Py_ssize_t _len; if ( o != NULL && PyString_Check(o) && PyString_AsStringAndSize(o, &_buf, &_len) != -1 ) { - qstrncpy(buf, _buf, qmin(_len, bufsize)); + buf->append(_buf, _len); rc = 1; } Py_XDECREF(o); return rc; } - static int handle_hint_output(PyObject *o, int *important_lines, qstring *hint) + static int handle_hint_output(PyObject *o, qstring *hint, int *important_lines) { int rc = 0; if ( o != NULL && PyTuple_Check(o) && PyTuple_Size(o) == 2 ) @@ -1070,14 +946,14 @@ public: return rc; } - static int handle_hint_output(PyObject *o, ea_t, int, int *important_lines, qstring *hint) + static int handle_hint_output(PyObject *o, qstring *hint, ea_t, int, int *important_lines) { - return handle_hint_output(o, important_lines, hint); + return handle_hint_output(o, hint, important_lines); } - static int handle_hint_output(PyObject *o, TCustomControl *, place_t *, int *important_lines, qstring *hint) + static int handle_hint_output(PyObject *o, qstring *hint, TWidget *, place_t *, int *important_lines) { - return handle_hint_output(o, important_lines, hint); + return handle_hint_output(o, hint, important_lines); } // hookgenUI:methods @@ -1086,12 +962,10 @@ public: //------------------------------------------------------------------------- bool py_register_action(action_desc_t *desc) { + desc->flags |= ADF_OWN_HANDLER; bool ok = register_action(*desc); if ( ok ) { - // Success. We are managing this handler from now on, - // and must prevent it from being destroyed. - py_action_handlers[desc->name] = desc->handler; // Let's set this to NULL, so when the wrapping Python action_desc_t // instance is deleted, it doesn't try to delete the handler (See // kernwin.i's action_desc_t::~action_desc_t()). @@ -1100,20 +974,6 @@ bool py_register_action(action_desc_t *desc) return ok; } -//------------------------------------------------------------------------- -bool py_unregister_action(const char *name) -{ - bool ok = unregister_action(name); - if ( ok ) - { - py_action_handler_t *handler = - (py_action_handler_t *) py_action_handlers[name]; - delete handler; - py_action_handlers.erase(name); - } - return ok; -} - //------------------------------------------------------------------------- PyObject *py_get_registered_actions() { @@ -1124,15 +984,42 @@ PyObject *py_get_registered_actions() } //------------------------------------------------------------------------- +/* +# +def py_attach_dynamic_action_to_popup( + widget, + popup_handle, + desc, + popuppath = None, + flags = 0) + """ + Create & insert an action into the widget's popup menu + (::ui_attach_dynamic_action_to_popup). + Note: The action description in the 'desc' parameter is modified by + this call so you should prepare a new description for each call. + For example: + desc = idaapi.action_desc_t(None, 'Dynamic popup action', Handler()) + idaapi.attach_dynamic_action_to_popup(form, popup, desc) + + @param widget: target widget + @param popup_handle: target popup + @param desc: action description of type action_desc_t + @param popuppath: can be None + @param flags: a combination of SETMENU_ constants + @return: success + """ + pass +# +*/ bool py_attach_dynamic_action_to_popup( - TForm *form, + TWidget *widget, TPopupMenu *popup_handle, action_desc_t *desc, const char *popuppath = NULL, int flags = 0) { bool ok = attach_dynamic_action_to_popup( - form, popup_handle, *desc, popuppath, flags); + widget, popup_handle, *desc, popuppath, flags); if ( ok ) // Set the handler to null, so the desc won't destroy // it, as it noticed ownership was taken by IDA. @@ -1166,51 +1053,19 @@ DECLARE_TYPE_AS_MOVABLE(disasm_line_t); typedef qvector disasm_text_t; //------------------------------------------------------------------------- -void py_gen_disasm_text(ea_t ea1, ea_t ea2, disasm_text_t &text, bool truncate_lines) +void py_gen_disasm_text(disasm_text_t &text, ea_t ea1, ea_t ea2, bool truncate_lines) { text_t _text; - gen_disasm_text(ea1, ea2, _text, truncate_lines); + gen_disasm_text(_text, ea1, ea2, truncate_lines); for ( size_t i = 0, n = _text.size(); i < n; ++i ) { - const twinline_t &tl = _text[i]; + twinline_t &tl = _text[i]; disasm_line_t &dl = text.push_back(); dl.at = tl.at; // Transfer ownership - dl.line.inject(tl.line); // Transfer ownership + dl.line.swap(tl.line); // Transfer ownership } } -//------------------------------------------------------------------------- -// Although 'TCustomControl*' and 'TForm*' instances can both be used -// for attach_action_to_popup() at a binary-level, IDAPython SWIG bindings -// require that a 'TForm *' wrapper be passed to wrap_attach_action_to_popup(). -// Thus, we provide another attach_action_to_popup() version, that -// accepts a 'TCustomControl' as first argument. -// -// Since user-created GraphViewer are created like so: -// +-------- PluginForm ----------+ -// |+----- TCustomControl -------+| -// || || -// || || -// || || -// || || -// || || -// |+----------------------------+| -// +------------------------------+ -// The user cannot use GetTForm(), and use that to attach -// an action to, because that'll attach the action to the PluginForm -// instance. -// Instead, the user must use GetTCustomControl(), and call -// this function below with it. -bool attach_action_to_popup( - TCustomControl *tcc, - TPopupMenu *popup_handle, - const char *name, - const char *popuppath = NULL, - int flags = 0) -{ - return attach_action_to_popup((TForm*) tcc, popup_handle, name, popuppath, flags); -} - //------------------------------------------------------------------------- /* # @@ -1311,7 +1166,7 @@ uint32 py_call_nav_colorizer( //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- -int idaapi UI_Callback(void *ud, int notification_code, va_list va) +ssize_t idaapi UI_Callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; diff --git a/pywraps/py_kernwin.py b/pywraps/py_kernwin.py index 7fa5876..d426796 100644 --- a/pywraps/py_kernwin.py +++ b/pywraps/py_kernwin.py @@ -35,8 +35,8 @@ def load_custom_icon(file_name=None, data=None, format=None): return 0 # ---------------------------------------------------------------------- -def asklong(defval, format): - res, val = _ida_kernwin._asklong(defval, format) +def ask_long(defval, format): + res, val = _ida_kernwin._ask_long(defval, format) if res == 1: return val @@ -44,8 +44,8 @@ def asklong(defval, format): return None # ---------------------------------------------------------------------- -def askaddr(defval, format): - res, ea = _ida_kernwin._askaddr(defval, format) +def ask_addr(defval, format): + res, ea = _ida_kernwin._ask_addr(defval, format) if res == 1: return ea @@ -53,23 +53,431 @@ def askaddr(defval, format): return None # ---------------------------------------------------------------------- -def askseg(defval, format): - res, sel = _ida_kernwin._askseg(defval, format) +def ask_seg(defval, format): + res, sel = _ida_kernwin._ask_seg(defval, format) if res == 1: return sel else: return None +# ---------------------------------------------------------------------- +def ask_ident(defval, format): + return ask_str(defval, HIST_IDENT, format) + # ---------------------------------------------------------------------- class action_handler_t(object): def __init__(self): pass def activate(self, ctx): - return 0 + return 0 def update(self, ctx): pass +# ---------------------------------------------------------------------- +# bw-compat/deprecated. You shouldn't rely on this in new code +from ida_pro import str2user + # + +# +AST_DISABLE_FOR_FORM=AST_DISABLE_FOR_WIDGET +AST_ENABLE_FOR_FORM=AST_ENABLE_FOR_WIDGET +CB_CLOSE_IDB=CB_INVISIBLE +chtype_generic2=chtype_generic +chtype_segreg=chtype_srcp +close_tform=close_widget +find_tform=find_widget +get_current_tform=get_current_widget +get_highlighted_identifier=get_highlight +get_tform_title=get_widget_title +get_tform_type=get_widget_type +is_chooser_tform=is_chooser_widget +open_tform=display_widget +pyscv_get_tcustom_control=pyscv_get_widget +pyscv_get_tform=pyscv_get_widget +__read_selection70 = read_selection +def read_selection(*args): + if len(args) == 0: + # bw-compat + t0, t1, view = twinpos_t(), twinpos_t(), get_current_viewer() + sel = __read_selection70(view, t0, t1) + import ida_idaapi + a0, a1 = ida_idaapi.BADADDR, ida_idaapi.BADADDR + if sel: + a0, a1 = t0.place(view).toea(), t1.place(view).toea() + return sel, a0, a1 + else: + return __read_selection70(*args) + +readsel2=read_selection +switchto_tform=activate_widget +umsg=msg + +import ida_ida +def __wrap_uihooks_callback(name, do_call): + return ida_ida.__wrap_hooks_callback(UI_Hooks, name, name.replace("widget", "tform"), do_call) + + +__wrap_uihooks_callback("widget_visible", lambda cb, *args: cb(args[0], args[0])) +__wrap_uihooks_callback("widget_invisible", lambda cb, *args: cb(args[0], args[0])) +__wrap_uihooks_callback("populating_widget_popup", lambda cb, *args: cb(*args)) +__wrap_uihooks_callback("finish_populating_widget_popup", lambda cb, *args: cb(*args)) +__wrap_uihooks_callback("current_widget_changed", lambda cb, *args: cb(*args)) + +AskUsingForm=ask_form +HIST_ADDR=0 +HIST_NUM=0 +KERNEL_VERSION_MAGIC1=0 +KERNEL_VERSION_MAGIC2=0 +OpenForm=open_form +_askaddr=_ida_kernwin._ask_addr +_asklong=_ida_kernwin._ask_long +_askseg=_ida_kernwin._ask_seg +askaddr=ask_addr +askbuttons_c=ask_buttons +askfile_c=ask_file +@bc695redef +def askfile2_c(forsave, defdir, filters, fmt): + if filters: + fmt = "FILTER %s\n%s" % (filters, fmt) + return ask_file(forsave, defdir, fmt) +askident=ask_ident +asklong=ask_long +@bc695redef +def askqstr(defval, fmt): + return ask_str(defval, 0, fmt) +askseg=ask_seg +@bc695redef +def askstr(hist, defval, fmt): + return ask_str(defval, hist, fmt) +asktext=ask_text +askyn_c=ask_yn +choose2_activate=choose_activate +choose2_close=choose_close +choose2_create=choose_create +choose2_find=choose_find +choose2_get_embedded=choose_get_embedded +choose2_get_embedded_selection=choose_get_embedded_selection +choose2_refresh=choose_refresh +clearBreak=clr_cancelled +py_get_AskUsingForm=py_get_ask_form +py_get_OpenForm=py_get_open_form +setBreak=set_cancelled +wasBreak=user_cancelled +refresh_lists=refresh_choosers + +#-------------------------------------------------------------------------- +class BC695_control_cmd: + def __init__(self, cmd_id, caption, flags, menu_index, icon, emb, shortcut, is_chooser): + self.cmd_id = cmd_id + self.caption = caption + self.flags = flags + self.menu_index = menu_index + self.icon = icon + self.emb = emb + self.shortcut = shortcut + self.is_chooser = is_chooser + + @staticmethod + def add_to_control(control, caption, flags, menu_index, icon, emb, shortcut, is_chooser): + if getattr(control, "commands", None) is None: + setattr(control, "commands", []) + found = filter(lambda x: x.caption == caption, control.commands) + if len(found) == 1: + cmd_id = found[0].cmd_id + else: + cmd_id = len(control.commands) + cmd = BC695_control_cmd(cmd_id, caption, flags, menu_index, icon, emb, shortcut, is_chooser) + control.commands.append(cmd) + return cmd_id + + @staticmethod + def populate_popup(control, widget, popup): + cmds = getattr(control, "commands", []) + for cmd in cmds: + if (cmd.flags & CHOOSER_POPUP_MENU) != 0: + desc = action_desc_t(None, cmd.caption, BC695_control_cmd_ah_t(control, cmd), cmd.shortcut, None, cmd.icon) + attach_dynamic_action_to_popup(widget, popup, desc) + +class BC695_control_cmd_ah_t(action_handler_t): + def __init__(self, control, cmd): + action_handler_t.__init__(self) + self.control = control + self.cmd = cmd + + def activate(self, ctx): + if self.cmd.is_chooser: + idx = ctx.chooser_selection[0] + self.control.OnCommand(idx, self.cmd.cmd_id) + else: + self.control.OnCommand(self.cmd.cmd_id) + + def update(self, ctx): + return AST_ENABLE_ALWAYS + + +class Choose2(object): + """v.6.95 compatible chooser wrapper class.""" + + CH_MODAL = 0x01 + CH_MULTI = 0x04 + CH_MULTI_EDIT = 0x08 + """ + The OnEditLine() callback will be called for all + selected items using the START_SEL/END_SEL + protocol. + This bit implies #CH_MULTI. + """ + CH_NOBTNS = 0x10 + CH_ATTRS = 0x20 + CH_NOIDB = 0x40 + CH_BUILTIN_SHIFT = 19 + CH_BUILTIN_MASK = 0x1F << CH_BUILTIN_SHIFT + + # column flags (are specified in the widths array) + CHCOL_PLAIN = 0x00000000 + CHCOL_PATH = 0x00010000 + CHCOL_HEX = 0x00020000 + CHCOL_DEC = 0x00030000 + CHCOL_FORMAT = 0x00070000 + + # special values of the chooser index + NO_SELECTION = -1 + """there is no selected item""" + START_SEL = -2 + """before calling the first selected item""" + END_SEL = -3 + """after calling the last selected item""" + + + # the v.7.0 chooser object implementing the v.6.95 chooser + class ChooseWrapper(Choose): + + def __init__(self, v695_chooser): + self.link = v695_chooser + # check what non-base callbacks we have + forbidden_cb = 0 + for cb in [("OnInsertLine", Choose.CHOOSE_HAVE_INS ), + ("OnDeleteLine", Choose.CHOOSE_HAVE_DEL ), + ("OnEditLine", Choose.CHOOSE_HAVE_EDIT ), + ("OnSelectLine", Choose.CHOOSE_HAVE_ENTER ), + ("OnRefresh", Choose.CHOOSE_HAVE_REFRESH), + ("OnSelectionChange", Choose.CHOOSE_HAVE_SELECT)]: + if not hasattr(self.link, cb[0]) or \ + not callable(getattr(self.link, cb[0])): + forbidden_cb |= cb[1] + Choose.__init__( + self, self.link.title, self.link.cols, + forbidden_cb = forbidden_cb) + + # redirect base callbacks to the v.6.95 chooser + def __getattr__(self, attr): + if attr in ["OnGetSize", + "OnGetLine", + "OnGetIcon", + "OnGetLineAttr", + "OnClose"]: + return getattr(self.link, attr) + return getattr(self.link, attr) + + def Show(self, modal = False): + # set `flags` and `deflt` + self.flags = self.link.flags + if self.link.deflt == -1: + self.deflt = 0 + else: + self.deflt = self.link.deflt - 1 + self.flags |= Choose.CH_FORCE_DEFAULT + if (self.flags & Choose.CH_MULTI) != 0: + self.deflt = [self.deflt] + # copy simple attributes from v.6.95 + for attr in ["title", "cols", "popup_names", "icon", + "x1", "y1", "x2", "y2", + "embedded", "width", "height"]: + if hasattr(self.link, attr): + setattr(self, attr, getattr(self.link, attr)) + else: + delattr(self, attr) + return Choose.Show(self, modal) + + def OnInsertLine(self, n): + # assert: hasattr(self.link, "OnInsertLine") + self.link.OnInsertLine() + # we preserve the selection + return (Choose.ALL_CHANGED, n) + if (self.link.flags & Choose2.CH_MULTI) == 0: + return (Choose.ALL_CHANGED, n) + else: + return [Choose.ALL_CHANGED] + n + + def OnDeleteLine(self, n): + # assert: hasattr(self.link, "OnDeleteLine") + res = None + if (self.link.flags & Choose2.CH_MULTI) == 0: + res = self.link.OnDeleteLine(n) + else: + # assert: n is iterable and n + # call the callback multiple times + self.link.OnDeleteLine(Choose2.START_SEL) + res = None + for idx in n: + new_idx = self.link.OnDeleteLine(idx) + if res == None: + res = new_idx + self.link.OnDeleteLine(Choose2.END_SEL) + return [Choose.ALL_CHANGED] + self.adjust_last_item(res) + + def OnEditLine(self, n): + # assert: hasattr(self.link, "OnEditLine") + if (self.link.flags & Choose2.CH_MULTI) == 0: + self.link.OnEditLine(n) + return (Choose.ALL_CHANGED, n) # preserve the selection + # assert: n is iterable and n + if (self.link.flags & Choose2.CH_MULTI_EDIT) == 0: + self.link.OnEditLine(n[0]) + return [Choose.ALL_CHANGED] + n # preserve the selection + # call the callback multiple times + self.link.OnEditLine(Choose2.START_SEL) + for idx in n: + self.link.OnEditLine(idx) + self.link.OnEditLine(Choose2.END_SEL) + return [Choose.ALL_CHANGED] + n # preserve the selection + + def OnSelectLine(self, n): + # assert: hasattr(self.link, "OnSelectLine") + if (self.link.flags & Choose2.CH_MULTI) == 0: + self.link.OnSelectLine(n) + return (Choose.ALL_CHANGED, n) + # assert: n is iterable and n + idx = n.pop(0) + self.link.OnSelectLine(idx) + # preserve all but the first item + return [Choose.ALL_CHANGED] + n + + def OnRefresh(self, n): + # assert: hasattr(self.link, "OnRefresh") + if (self.link.flags & Choose2.CH_MULTI) != 0: + # ignore all but the first item + n = n[0] if n else Choose.NO_SELECTION + res = self.link.OnRefresh(n) + return (Choose.ALL_CHANGED, res) + + def OnSelectionChange(self, n): + # assert: hasattr(self.link, "OnSelectionChange") + if (self.link.flags & Choose2.CH_MULTI) == 0: + n = [n] if n != Choose.NO_SELECTION else [] + self.link.OnSelectionChange(n) + + def OnPopup(self, widget, popup_handle): + BC695_control_cmd.populate_popup( + self.link, + widget, + popup_handle) + + + def __init__(self, title, cols, flags=0, popup_names=None, + icon=-1, x1=-1, y1=-1, x2=-1, y2=-1, deflt=-1, + embedded=False, width=None, height=None): + """ + Constructs a chooser window. + @param title: The chooser title + @param cols: a list of colums; each list item is a list of two items + example: [ ["Address", 10 | Choose2.CHCOL_HEX], + ["Name", 30 | Choose2.CHCOL_PLAIN] ] + @param flags: One of CH_XXXX constants + @param deflt: Default starting item (1-based). + 0 means that no item is selected, + -1 means that the first item selected for a new window and + that the selection is not updated for an existing window + @param popup_names: list of new captions to replace this list + ["Insert", "Delete", "Edit", "Refresh"] + @param icon: Icon index (the icon should exist in ida resources or + an index to a custom loaded icon) + @param x1, y1, x2, y2: The default location (for txt-version) + @param embedded: Create as embedded chooser + @param width: Embedded chooser width + @param height: Embedded chooser height + """ + # remember attributes + self.title = title + self.flags = flags + self.cols = cols + self.deflt = deflt + self.popup_names = popup_names + self.icon = icon + self.x1 = x1 + self.y1 = y1 + self.x2 = x2 + self.y2 = y2 + self.embedded = embedded + self.width = width + self.height = height + # construct the v.7.0 chooser object + self.chobj = Choose2.ChooseWrapper(self) + + + # redirect methods to the v.7.0 chooser + def __getattr__(self, attr): + if attr not in ["GetEmbSelection", + "Activate", + "Refresh", + "Close", + "GetWidget"]: + raise AttributeError(attr) + return getattr(self.chobj, attr) + + def Embedded(self): + """ + Creates an embedded chooser (as opposed to Show()) + @return: Returns 1 on success + """ + return 1 if self.chobj.Embedded() == 0 else 0 + + + def Show(self, modal=False): + """ + Activates or creates a chooser window + @param modal: Display as modal dialog + @return: For modal choosers it will return the selected item index (0-based) + or -1 in the case of error, + For non-modal choosers it will return 0 + or -1 if the chooser was already open and is active now + """ + ret = self.chobj.Show(modal) + return -1 if ret < 0 else ret + + + def AddCommand(self, + caption, + flags = _ida_kernwin.CHOOSER_POPUP_MENU, + menu_index = -1, + icon = -1, + emb=None, + shortcut=None): + # Use the 'emb' as a sentinel. It will be passed the correct value + # from the EmbeddedChooserControl + if self.embedded and ((emb is None) or (emb != 2002)): + raise RuntimeError("Please add a command through " + "EmbeddedChooserControl.AddCommand()") + return BC695_control_cmd.add_to_control( + self, caption, flags, menu_index, icon, emb, None, + is_chooser=True) + + # callbacks + # def OnGetSize(self): + # def OnGetLine(self, n): + # def OnGetIcon(self, n): + # def OnGetLineAttr(self, n): + # def OnInsertLine(self): + # def OnDeleteLine(self, n): + # def OnEditLine(self, n): + # def OnSelectLine(self, n): + # def OnRefresh(self, n): + # def OnSelectionChange(self, sel_list): + # def OnClose(self): + # def OnCommand(self, n, cmd_id): +# + diff --git a/pywraps/py_kernwin_askusingform.hpp b/pywraps/py_kernwin_askform.hpp similarity index 81% rename from pywraps/py_kernwin_askusingform.hpp rename to pywraps/py_kernwin_askform.hpp index 76262e1..6bbacbd 100644 --- a/pywraps/py_kernwin_askusingform.hpp +++ b/pywraps/py_kernwin_askform.hpp @@ -1,11 +1,11 @@ -#ifndef __PY_KERNWIN_ASKUSINGFORM__ -#define __PY_KERNWIN_ASKUSINGFORM__ +#ifndef __PY_KERNWIN_ASKFORM__ +#define __PY_KERNWIN_ASKFORM__ -// -// +// +// //--------------------------------------------------------------------------- -// +// #define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa; //--------------------------------------------------------------------------- @@ -49,8 +49,8 @@ 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) + PyObject *self, + unsigned int flags) { textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); return ti == NULL ? 0 : ti->flags; @@ -58,8 +58,8 @@ static unsigned int textctrl_info_t_get_flags( //------------------------------------------------------------------------- static bool textctrl_info_t_set_tabsize( - PyObject *self, - unsigned int tabsize) + PyObject *self, + unsigned int tabsize) { textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); if ( ti == NULL ) @@ -70,8 +70,8 @@ static bool textctrl_info_t_set_tabsize( //------------------------------------------------------------------------- static unsigned int textctrl_info_t_get_tabsize( - PyObject *self, - unsigned int tabsize) + PyObject *self, + unsigned int tabsize) { textctrl_info_t *ti = (textctrl_info_t *)pyobj_get_clink(self); return ti == NULL ? 0 : ti->tabsize; @@ -93,12 +93,12 @@ static bool formchgcbfa_show_field(size_t p_fa, int fid, bool show) //--------------------------------------------------------------------------- static bool formchgcbfa_move_field( - size_t p_fa, - int fid, - int x, - int y, - int w, - int h) + size_t p_fa, + int fid, + int x, + int y, + int w, + int h) { DECLARE_FORM_ACTIONS; return fa->move_field(fid, x, y, w, h); @@ -134,10 +134,10 @@ static void formchgcbfa_close(size_t p_fa, int close_normally) //--------------------------------------------------------------------------- static PyObject *formchgcbfa_get_field_value( - size_t p_fa, - int fid, - int ft, - size_t sz) + size_t p_fa, + int fid, + int ft, + size_t sz) { DECLARE_FORM_ACTIONS; PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -190,7 +190,7 @@ static PyObject *formchgcbfa_get_field_value( case 1: { char val[MAXSTR]; - if ( fa->get_ascii_value(fid, val, sizeof(val)) ) + if ( fa->get_string_value(fid, val, sizeof(val)) ) return PyString_FromString(val); break; } @@ -199,20 +199,16 @@ static PyObject *formchgcbfa_get_field_value( { qstring val; val.resize(sz + 1); - if ( fa->get_ascii_value(fid, val.begin(), val.size()) ) + if ( fa->get_string_value(fid, val.begin(), val.size()) ) return PyString_FromString(val.begin()); break; } case 5: { - intvec_t intvec; - // Returned as 1-base - if ( fa->get_chooser_value(fid, &intvec) ) + sizevec_t selection; + if ( fa->get_chooser_value(fid, &selection) ) { - // Make 0-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it ) - (*it)--; - ref_t l(PyW_IntVecToPyList(intvec)); + ref_t l(PyW_SizeVecToPyList(selection)); l.incref(); return l.o; } @@ -233,7 +229,7 @@ static PyObject *formchgcbfa_get_field_value( case 'S': // sel_t { if ( fa->get_segment_value(fid, &u.sel) ) - return Py_BuildValue(PY_FMT64, u.sel); + return Py_BuildValue(PY_BV_SEL, bvsel_t(u.sel)); break; } // sval_t @@ -244,7 +240,7 @@ static PyObject *formchgcbfa_get_field_value( case 'H': { if ( fa->get_signed_value(fid, &u.sval) ) - return Py_BuildValue(PY_SFMT64, u.sval); + return Py_BuildValue(PY_BV_SVAL, bvsval_t(u.sval)); break; } case 'L': // uint64 @@ -258,13 +254,13 @@ static PyObject *formchgcbfa_get_field_value( case 'M': // uval_t { if ( fa->get_unsigned_value(fid, &u.uval) ) - return Py_BuildValue(PY_FMT64, u.uval); + return Py_BuildValue(PY_BV_UVAL, bvuval_t(u.uval)); break; } case '$': // ea_t { if ( fa->get_ea_value(fid, &u.uval) ) - return Py_BuildValue(PY_FMT64, u.uval); + return Py_BuildValue(PY_BV_UVAL, bvuval_t(u.uval)); break; } } @@ -276,10 +272,10 @@ static PyObject *formchgcbfa_get_field_value( //--------------------------------------------------------------------------- static bool formchgcbfa_set_field_value( - size_t p_fa, - int fid, - int ft, - PyObject *py_val) + size_t p_fa, + int fid, + int ft, + PyObject *py_val) { DECLARE_FORM_ACTIONS; PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -324,20 +320,14 @@ static bool formchgcbfa_set_field_value( // strings case 3: case 1: - return fa->set_ascii_value(fid, PyString_AsString(py_val)); + return fa->set_string_value(fid, PyString_AsString(py_val)); // intvec_t case 5: { - intvec_t intvec; - // Passed as 0-based - if ( !PyW_PyListToIntVec(py_val, intvec) ) + sizevec_t selection; + if ( !PyW_PyListToSizeVec(py_val, selection) ) break; - - // Make 1-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it ) - (*it)++; - - return fa->set_chooser_value(fid, &intvec); + return fa->set_chooser_value(fid, &selection); } // Numeric case 6: @@ -352,20 +342,20 @@ static bool formchgcbfa_set_field_value( #undef DECLARE_FORM_ACTIONS -static size_t py_get_AskUsingForm() +static size_t py_get_ask_form() { // Return a pointer to the function. Note that, although - // the C implementation of AskUsingForm_cv will do some + // the C implementation of vask_form will do some // Qt/txt widgets generation, the Python's ctypes - // implementation through which the call well go will first + // implementation through which the call will go will first // unblock other threads. No need to do it ourselves. - return (size_t)AskUsingForm_c; + return (size_t)ask_form; } -static size_t py_get_OpenForm() +static size_t py_get_open_form() { // See comments above. - return (size_t)OpenForm_c; + return (size_t)open_form; } static void py_register_compiled_form(PyObject *py_form) @@ -377,8 +367,8 @@ static void py_unregister_compiled_form(PyObject *py_form) { PyW_unregister_compiled_form(py_form); } -// +// -#endif // __PY_KERNWIN_ASKUSINGFORM__ +#endif // __PY_KERNWIN_ASKFORM__ diff --git a/pywraps/py_kernwin_askusingform.py b/pywraps/py_kernwin_askform.py old mode 100755 new mode 100644 similarity index 92% rename from pywraps/py_kernwin_askusingform.py rename to pywraps/py_kernwin_askform.py index 7f935da..3f1eb89 --- a/pywraps/py_kernwin_askusingform.py +++ b/pywraps/py_kernwin_askform.py @@ -1,5 +1,5 @@ # -------------------------------------------------------------------------- -# +# import ida_idaapi, _ida_idaapi import ida_pro @@ -11,23 +11,23 @@ import ida_pro #HELP / ENDHELP try: import types - from ctypes import * + import ctypes # On Windows, we use stdcall # Callback for buttons - # typedef void (idaapi *formcb_t)(TView *fields[], int code); + # typedef int (idaapi *buttoncb_t)(int button_code, form_actions_t &fa); - _FORMCB_T = WINFUNCTYPE(None, c_void_p, c_int) + _BUTTONCB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_void_p) # Callback for form change # typedef int (idaapi *formchgcb_t)(int field_id, form_actions_t &fa); - _FORMCHGCB_T = WINFUNCTYPE(c_int, c_int, c_void_p) + _FORMCHGCB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_void_p) except: try: - _FORMCB_T = CFUNCTYPE(None, c_void_p, c_int) - _FORMCHGCB_T = CFUNCTYPE(c_int, c_int, c_void_p) + _BUTTONCB_T = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_void_p) + _FORMCHGCB_T = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_void_p) except: - _FORMCHGCB_T = _FORMCB_T = None + _BUTTONCB_T = _FORMCHGCB_T = None # ----------------------------------------------------------------------- @@ -147,7 +147,7 @@ class Form(object): FT_FORMCHG = '%/' """Form change callback - formchgcb_t""" FT_ECHOOSER = 'E' - """Embedded chooser - idaapi.Choose2""" + """Embedded chooser - idaapi.Choose""" FT_MULTI_LINE_TEXT = 't' """Multi text control - textctrl_info_t""" FT_DROPDOWN_LIST = 'b' @@ -166,19 +166,19 @@ class Form(object): Factory method returning a ctype class corresponding to the field type string """ if tp in (Form.FT_SEG, Form.FT_HEX, Form.FT_RAWHEX, Form.FT_ADDR): - return c_ulonglong if i64 else c_ulong + return ctypes.c_ulonglong if i64 else ctypes.c_ulong elif tp in (Form.FT_SHEX, Form.FT_DEC, Form.FT_OCT, Form.FT_BIN, Form.FT_CHAR): - return c_longlong if i64 else c_long + return ctypes.c_longlong if i64 else ctypes.c_long elif tp == Form.FT_UINT64: - return c_ulonglong + return ctypes.c_ulonglong elif tp == Form.FT_INT64: - return c_longlong + return ctypes.c_longlong elif tp == Form.FT_COLOR: - return c_ulong + return ctypes.c_ulong elif tp == Form._FT_USHORT: - return c_ushort + return ctypes.c_ushort elif tp in (Form.FT_FORMCHG, Form.FT_ECHOOSER): - return c_void_p + return ctypes.c_void_p else: return None @@ -197,7 +197,7 @@ class Form(object): if cls is None: raise TypeError("Invalid numeric field type: %s" % tp) # Get a pointer type to the ctype type - self.arg = pointer(cls(value)) + self.arg = ctypes.pointer(cls(value)) def __set_value(self, v): self.arg.contents.value = v @@ -213,9 +213,9 @@ class Form(object): raise SyntaxError("The string size must be passed") if value is None: - self.arg = create_string_buffer(size) + self.arg = ctypes.create_string_buffer(size) else: - self.arg = create_string_buffer(value, size) + self.arg = ctypes.create_string_buffer(value, size) self.size = size def __set_value(self, v): @@ -240,6 +240,7 @@ class Form(object): self.form = None """Reference to the parent form. It is filled by Form.Add()""" + self.form_hasattr = False def get_tag(self): """ @@ -251,7 +252,7 @@ class Form(object): def get_arg(self): """ Control returns the parameter to be pushed on the stack - (Of AskUsingForm()) + (Of ask_form()) """ return self.arg @@ -301,7 +302,7 @@ class Form(object): tp = Form.FT_ASCII Form.LabelControl.__init__(self, tp) self.size = sz - self.arg = create_string_buffer(value, sz) + self.arg = ctypes.create_string_buffer(value, sz) class NumericLabel(LabelControl, NumericArgument): @@ -597,7 +598,16 @@ class Form(object): code, swidth, hlp) - self.arg = _FORMCB_T(lambda view, code, h=handler: h(code)) + self.handler = handler + self.arg = _BUTTONCB_T(self.helper_cb) + + def helper_cb(self, button_code, p_fa): + # Remember the pointer to the forms_action in the parent form + self.form.p_fa = p_fa + + # Call user's handler + r = self.handler(button_code) + return 0 if r is None else r def is_input_field(self): return False @@ -667,23 +677,23 @@ class Form(object): """ # !! Make sure a chooser instance is passed !! - if chooser is None or not isinstance(chooser, Choose2): + if chooser is None or not isinstance(chooser, Choose): raise ValueError("Invalid chooser passed.") - # Create an embedded chooser structure from the Choose2 instance - if chooser.Embedded() != 1: + # Create an embedded chooser structure from the Choose instance + if chooser.Embedded() != 0: raise ValueError("Failed to create embedded chooser instance.") # Construct input control Form.InputControl.__init__(self, Form.FT_ECHOOSER, "", swidth) # Get a pointer to the chooser_info_t and the selection vector - # (These two parameters are the needed arguments for the AskUsingForm()) - emb, sel = _ida_kernwin.choose2_get_embedded(chooser) + # (These two parameters are the needed arguments for the ask_form()) + emb, sel = _ida_kernwin.choose_get_embedded(chooser) # Get a pointer to a c_void_p constructed from an address - p_embedded = pointer(c_void_p.from_address(emb)) - p_sel = pointer(c_void_p.from_address(sel)) + p_embedded = ctypes.pointer(ctypes.c_void_p.from_address(emb)) + p_sel = ctypes.pointer(ctypes.c_void_p.from_address(sel)) # - Create the embedded chooser info on control creation # - Do not free the embeded chooser because after we get the args @@ -702,25 +712,6 @@ class Form(object): """Returns the embedded chooser instance""" - def AddCommand(self, - caption, - flags = _ida_kernwin.CHOOSER_POPUP_MENU, - menu_index = -1, - icon = -1): - """ - Adds a new embedded chooser command - Save the returned value and later use it in the OnCommand handler - - @return: Returns a negative value on failure or the command index - """ - if not self.form.title: - raise ValueError("Form title is not set!") - - # Encode all information for the AddCommand() in the 'caption' parameter - caption = "%s:%d:%s" % (self.form.title, self.id, caption) - return self.chooser.AddCommand(caption, flags=flags, menu_index=menu_index, icon=icon, emb=2002) - - def free(self): """ Frees the embedded chooser data @@ -764,8 +755,8 @@ class Form(object): if readonly: # Create a C integer and remember it - self.__selval = c_int(selval) - val_addr = addressof(self.__selval) + self.__selval = ctypes.c_int(selval) + val_addr = ctypes.addressof(self.__selval) else: # Create an strvec with one qstring self.__selval = ida_pro._qstrvec_t([selval]) @@ -778,8 +769,8 @@ class Form(object): # or # #2: a qstring to hold the dropdown text control value self.arg = ( - pointer(c_void_p.from_address(self.clink_ptr)), - pointer(c_void_p.from_address(val_addr)) + ctypes.pointer(ctypes.c_void_p.from_address(self.clink_ptr)), + ctypes.pointer(ctypes.c_void_p.from_address(val_addr)) ) @@ -832,7 +823,7 @@ class Form(object): textctrl_info_t.__init__(self, text=text, flags=flags, tabsize=tabsize) # Get the argument as a pointer from the embedded ti - self.arg = pointer(c_void_p.from_address(self.clink_ptr)) + self.arg = ctypes.pointer(ctypes.c_void_p.from_address(self.clink_ptr)) def free(self): @@ -845,7 +836,7 @@ class Form(object): def __init__(self, form, controls): """ Contruct a Form class. - This class wraps around AskUsingForm() or OpenForm() and provides an easier / alternative syntax for describing forms. + This class wraps around ask_form() or open_form() and provides an easier / alternative syntax for describing forms. The form control names are wrapped inside the opening and closing curly braces and the control themselves are defined and instantiated via various form controls (subclasses of Form). @@ -867,7 +858,7 @@ class Form(object): self.openform_flags = 0 """ - If non-modal, these flags will be passed to OpenForm. + If non-modal, these flags will be passed to open_form. This is an OR'ed combination of the PluginForm.FORM_* values. """ @@ -879,8 +870,11 @@ class Form(object): """ # Free all the controls - for ctrl in self.__controls.values(): - ctrl.free() + for name, ctrl in self.__controls.items(): + if ctrl.parent_hasattr: + delattr(self, name) + ctrl.parent_hasattr = False + ctrl.free() # Reset the controls # (Note that we are not removing the form control attributes, no need) @@ -919,6 +913,7 @@ class Form(object): # Create attribute with control name if mkattr: setattr(self, name, ctrl) + ctrl.parent_hasattr = True # Remember the control self.__controls[name] = ctrl @@ -994,7 +989,7 @@ class Form(object): """ Low level function. Compiles (parses the form syntax and adds the control) the form string and - returns the argument list to be passed the argument list to AskUsingForm(). + returns the argument list to be passed the argument list to ask_form(). The form controls are wrapped inside curly braces: {ControlName}. @@ -1003,7 +998,7 @@ class Form(object): (note that, technically, the index is not the same as the ID; that's because STARTITEM uses raw, 0-based indexes rather than control IDs to determine the focused widget.) - @param form: Compiles the form and returns the arguments needed to be passed to AskUsingForm() + @param form: Compiles the form and returns the arguments needed to be passed to ask_form() """ # First argument is the form string args = [None] @@ -1184,7 +1179,7 @@ class Form(object): if not self.modal: raise SyntaxError("Form is not modal. Open() should be instead") - return AskUsingForm(*self.__args) + return ask_form(*self.__args) def Open(self): @@ -1195,7 +1190,7 @@ class Form(object): if self.modal: raise SyntaxError("Form is modal. Execute() should be instead") - OpenForm(*self.__args) + open_form(*self.__args) def EnableField(self, ctrl, enable): @@ -1334,38 +1329,38 @@ class Form(object): raise NotImplementedError, "Not yet implemented" # -------------------------------------------------------------------------- -# Instantiate AskUsingForm function pointer +# Instantiate ask_form function pointer try: import ctypes # Setup the numeric argument size Form.NumericArgument.DefI64 = _ida_idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL - AskUsingForm__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_AskUsingForm()) - OpenForm__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_OpenForm()) + ask_form__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_ask_form()) + open_form__ = ctypes.CFUNCTYPE(ctypes.c_long)(_ida_kernwin.py_get_open_form()) except: - def AskUsingForm__(*args): - warning("AskUsingForm() needs ctypes library in order to work") + def ask_form__(*args): + warning("ask_form() needs ctypes library in order to work") return 0 - def OpenForm__(*args): - warning("OpenForm() needs ctypes library in order to work") + def open_form__(*args): + warning("open_form() needs ctypes library in order to work") -def AskUsingForm(*args): +def ask_form(*args): """ - Calls AskUsingForm() + Calls ask_form() @param: Compiled Arguments obtain through the Form.Compile() function @return: 1 = ok, 0 = cancel """ old = _ida_idaapi.set_script_timeout(0) - r = AskUsingForm__(*args) + r = ask_form__(*args) _ida_idaapi.set_script_timeout(old) return r -def OpenForm(*args): +def open_form(*args): """ - Calls OpenForm() + Calls open_form() @param: Compiled Arguments obtain through the Form.Compile() function """ old = _ida_idaapi.set_script_timeout(0) - r = OpenForm__(*args) + r = open_form__(*args) _ida_idaapi.set_script_timeout(old) -# +# diff --git a/pywraps/py_kernwin_choose.hpp b/pywraps/py_kernwin_choose.hpp index bbce7a0..d4416ec 100644 --- a/pywraps/py_kernwin_choose.hpp +++ b/pywraps/py_kernwin_choose.hpp @@ -1,78 +1,858 @@ #ifndef __PY_KERNWIN_CHOOSE__ #define __PY_KERNWIN_CHOOSE__ -//--------------------------------------------------------------------------- -// -//--------------------------------------------------------------------------- -uint32 idaapi choose_sizer(void *self) +// + +//------------------------------------------------------------------------ +// Helper functions +class py_choose_t; +typedef std::map py2c_choose_map_t; +static py2c_choose_map_t choosers; + +py_choose_t *choose_find_instance(PyObject *self) { - PYW_GIL_GET; - newref_t pyres(PyObject_CallMethod((PyObject *)self, "sizer", "")); - return PyInt_AsLong(pyres.o); + py2c_choose_map_t::iterator it = choosers.find(self); + return it == choosers.end() ? NULL : it->second; } -//--------------------------------------------------------------------------- -char *idaapi choose_getl(void *self, uint32 n, char *buf) +void choose_add_instance(PyObject *self, py_choose_t *pych) { - PYW_GIL_GET; - newref_t pyres( - PyObject_CallMethod( - (PyObject *)self, - "getl", - "l", - n)); - - const char *res; - if ( pyres == NULL || (res = PyString_AsString(pyres.o)) == NULL ) - qstrncpy(buf, "", MAXSTR); - else - qstrncpy(buf, res, MAXSTR); - return buf; + choosers[self] = pych; } -//--------------------------------------------------------------------------- -void idaapi choose_enter(void *self, uint32 n) +void choose_del_instance(PyObject *self) { - PYW_GIL_GET; - newref_t res(PyObject_CallMethod((PyObject *)self, "enter", "l", n)); + py2c_choose_map_t::iterator it = choosers.find(self); + if ( it != choosers.end() ) + choosers.erase(it); } -//--------------------------------------------------------------------------- -uint32 choose_choose( - PyObject *self, - int flags, - int x0,int y0, - int x1,int y1, - int width, - int deflt, - int icon) +// set `prm` to the integer value of the `name` attribute +template +static void py_get_int(PyObject *self, T *prm, const char *name) +{ + ref_t attr(PyW_TryGetAttrString(self, name)); + if ( attr != NULL && attr.o != Py_None ) + *prm = T(PyInt_AsLong(attr.o)); +} + +//------------------------------------------------------------------------ +// Python's chooser class +class py_choose_t +{ +public: + // Python object link + PyObject *self; + + // the chooser object will be created in the create() method + chooser_base_t *chobj; + + enum + { + CHOOSE_HAVE_INIT = 0x0001, + CHOOSE_HAVE_GETICON = 0x0002, + CHOOSE_HAVE_GETATTR = 0x0004, + CHOOSE_HAVE_INS = 0x0008, + CHOOSE_HAVE_DEL = 0x0010, + CHOOSE_HAVE_EDIT = 0x0020, + CHOOSE_HAVE_ENTER = 0x0040, + CHOOSE_HAVE_REFRESH = 0x0080, + CHOOSE_HAVE_SELECT = 0x0100, + CHOOSE_HAVE_ONCLOSE = 0x0200, + CHOOSE_IS_EMBEDDED = 0x0400, + }; + + // Callback flags (to tell which callback exists and which not) + // One of CHOOSE_xxxx + uint32 cb_flags; + + sizevec_t embedded_sel; + + // Chooser title + qstring title; + + // Column widths + intvec_t widths; + + // Chooser headers + qstrvec_t header_strings; + qvector header; + +public: + py_choose_t(PyObject *self_) : self(self_), chobj(NULL), cb_flags(0) + { + PYW_GIL_GET; + choose_add_instance(self, this); + + // Increase object reference + Py_INCREF(self); + } + + // if the chooser object was created it will delete linked Python's + // chooser. + // if it was not created (e.g. because of the lack of a mandatory + // callback) it will be deleted in choose_close(). + ~py_choose_t() + { + PYW_GIL_GET; + // Remove from list + choose_del_instance(self); + + Py_XDECREF(self); + } + + // common callbacks + bool idaapi init() + { + if ( (cb_flags & CHOOSE_HAVE_INIT) == 0 ) + return chobj->chooser_base_t::init(); + PYW_GIL_GET; + pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_INIT, NULL)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chobj->chooser_base_t::init(); + return bool(PyInt_AsLong(pyres.result.o)); + } + + size_t idaapi get_count() const + { + PYW_GIL_GET; + pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return 0; + + return size_t(PyInt_AsLong(pyres.result.o)); + } + + void idaapi get_row( + qstrvec_t *cols, + int *icon_, + chooser_item_attrs_t *attrs, + size_t n) const + { + PYW_GIL_GET; + + // Call Python + PYW_GIL_CHECK_LOCKED_SCOPE(); + pycall_res_t list( + PyObject_CallMethod( + self, (char *)S_ON_GET_LINE, + "i", int(n))); + if ( list.result != NULL ) + { + // Go over the List returned by Python and convert to C strings + for ( int i = chobj->columns - 1; i >= 0; --i ) + { + borref_t item(PyList_GetItem(list.result.o, Py_ssize_t(i))); + if ( item == NULL ) + continue; + + const char *str = PyString_AsString(item.o); + if ( str != NULL ) + (*cols)[i] = str; + } + } + + *icon_ = chobj->icon; + if ( (cb_flags & CHOOSE_HAVE_GETICON) != 0 ) + { + pycall_res_t pyres( + PyObject_CallMethod( + self, (char *)S_ON_GET_ICON, + "i", int(n))); + if ( pyres.result != NULL ) + *icon_ = PyInt_AsLong(pyres.result.o); + } + + if ( (cb_flags & CHOOSE_HAVE_GETATTR) != 0 ) + { + pycall_res_t pyres( + PyObject_CallMethod( + self, (char *)S_ON_GET_LINE_ATTR, + "i", int(n))); + if ( pyres.result != NULL && PyList_Check(pyres.result.o) ) + { + PyObject *item; + if ( (item = PyList_GetItem(pyres.result.o, 0)) != NULL ) + attrs->color = PyInt_AsLong(item); + if ( (item = PyList_GetItem(pyres.result.o, 1)) != NULL ) + attrs->flags = PyInt_AsLong(item); + } + } + } + + void idaapi closed() + { + if ( (cb_flags & CHOOSE_HAVE_ONCLOSE) == 0 ) + { + chobj->chooser_base_t::closed(); + return; + } + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL)); + // delete UI hook + PyObject_DelAttrString(self, "ui_hooks_trampoline"); + } + +public: + static py_choose_t *find_chooser(const char *title) + { + return static_cast(::get_chooser_obj(title)); + } + + void close() + { + // will trigger closed() + close_chooser(chobj->title); + } + + bool activate() + { + TWidget *widget = get_widget(); + if ( widget == NULL ) + return false; + + activate_widget(widget, true); + return true; + } + + TWidget *get_widget() + { + return find_widget(chobj->title); + } + + // Create a chooser. + // If it doesn't detect the "embedded" attribute, then the chooser window + // is created and displayed. + // See ::choose() for the returned values. + // \retval NO_ATTR some mandatory attribute is missing + int create(); + + inline PyObject *get_self() + { + return self; + } + + void do_refresh() + { + refresh_chooser(chobj->title); + } + + chooser_base_t *get_chobj() const + { + return chobj; + } + + const sizevec_t *get_sel_vec() const + { + return &embedded_sel; + } + + bool is_valid() const + { + return chobj != NULL; + } + + bool is_embedded() const + { + return (cb_flags & CHOOSE_IS_EMBEDDED) != 0; + } +}; + +//------------------------------------------------------------------------ +// link from the chooser object to the Python's chooser +struct py_chooser_link_t +{ + py_choose_t *link; // link to Python's chooser + py_chooser_link_t(py_choose_t *pych) : link(pych) {} + ~py_chooser_link_t() { delete link; } +}; + +//------------------------------------------------------------------------ +// we do not use virtual subclasses so we use #define for common code +#define DEFINE_COMMON_CALLBACKS \ + virtual void *get_chooser_obj() ida_override { return link; } \ + virtual bool idaapi init() ida_override { return link->init(); } \ + virtual size_t idaapi get_count() const ida_override \ + { \ + return link->get_count(); \ + } \ + virtual void idaapi get_row( \ + qstrvec_t *cols, \ + int *icon_, \ + chooser_item_attrs_t *attrs, \ + size_t n) const ida_override \ + { \ + link->get_row(cols, icon_, attrs, n); \ + } \ + virtual void idaapi closed() ida_override { link->closed(); } + +//------------------------------------------------------------------------ +// chooser class without multi-selection +class py_chooser_single_t + : public py_chooser_link_t, + public chooser_t +{ +public: + py_chooser_single_t( + py_choose_t *pych, + uint32 flags_ = 0, + int columns_ = 0, + const int *widths_ = NULL, + const char *const *header_ = NULL, + const char *title_ = NULL) + : py_chooser_link_t(pych), + chooser_t(flags_, columns_, widths_, header_, title_) {} + + DEFINE_COMMON_CALLBACKS + + virtual cbret_t idaapi ins(ssize_t n) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_INS) == 0 ) + return chooser_t::ins(n); + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_INSERT_LINE, + "i", int(n))); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_t::ins(n); + return py_as_cbret(pyres.result.o); + } + + virtual cbret_t idaapi del(size_t n) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_DEL) == 0 ) + return chooser_t::del(n); + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_DELETE_LINE, + "i", int(n))); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_t::del(n); + return py_as_cbret(pyres.result.o); + } + + virtual cbret_t idaapi edit(size_t n) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_EDIT) == 0 ) + return chooser_t::edit(n); + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_EDIT_LINE, + "i", int(n))); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_t::edit(n); + return py_as_cbret(pyres.result.o); + } + + virtual cbret_t idaapi enter(size_t n) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_ENTER) == 0 ) + return chooser_t::enter(n); + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_SELECT_LINE, + "i", int(n))); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_t::enter(n); + return py_as_cbret(pyres.result.o); + } + + virtual cbret_t idaapi refresh(ssize_t n) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_REFRESH) == 0 ) + return chooser_t::refresh(n); + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_REFRESH, + "i", int(n))); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_t::refresh(n); + return py_as_cbret(pyres.result.o); + } + + virtual void idaapi select(ssize_t n) const ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_SELECT) == 0 ) + { + chooser_t::select(n); + return; + } + PYW_GIL_GET; + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_SELECTION_CHANGE, + "i", int(n))); + } + +protected: + // [ changed, idx ] + static cbret_t py_as_cbret(PyObject *py_ret) + { + cbret_t ret; + if ( PySequence_Check(py_ret) ) + { + { + newref_t item(PySequence_GetItem(py_ret, 0)); + if ( item.o != NULL && PyInt_Check(item.o) ) + ret.changed = cbres_t(PyInt_AsLong(item.o)); + } + if ( ret.changed != NOTHING_CHANGED ) + { + newref_t item(PySequence_GetItem(py_ret, 1)); + if ( item.o != NULL && PyInt_Check(item.o) ) + ret.idx = ssize_t(PyInt_AsSsize_t(item.o)); + } + } + return ret; + } +}; + +//------------------------------------------------------------------------ +// chooser class with multi-selection +class py_chooser_multi_t + : public py_chooser_link_t, + public chooser_multi_t +{ +public: + py_chooser_multi_t( + py_choose_t *pych, + uint32 flags_ = 0, + int columns_ = 0, + const int *widths_ = NULL, + const char *const *header_ = NULL, + const char *title_ = NULL) + : py_chooser_link_t(pych), + chooser_multi_t(flags_, columns_, widths_, header_, title_) {} + + DEFINE_COMMON_CALLBACKS + + virtual cbres_t idaapi ins(sizevec_t *sel) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_INS) == 0 ) + return chooser_multi_t::ins(sel); + PYW_GIL_GET; + ref_t py_list(PyW_SizeVecToPyList(*sel)); + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_INSERT_LINE, + "O", py_list.o)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_multi_t::ins(sel); + return py_as_cbres_sel(sel, pyres.result.o); + } + + virtual cbres_t idaapi del(sizevec_t *sel) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_DEL) == 0 ) + return chooser_multi_t::del(sel); + PYW_GIL_GET; + ref_t py_list(PyW_SizeVecToPyList(*sel)); + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_DELETE_LINE, + "O", py_list.o)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_multi_t::del(sel); + return py_as_cbres_sel(sel, pyres.result.o); + } + + virtual cbres_t idaapi edit(sizevec_t *sel) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_EDIT) == 0 ) + return chooser_multi_t::edit(sel); + PYW_GIL_GET; + ref_t py_list(PyW_SizeVecToPyList(*sel)); + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_EDIT_LINE, + "O", py_list.o)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_multi_t::edit(sel); + return py_as_cbres_sel(sel, pyres.result.o); + } + + virtual cbres_t idaapi enter(sizevec_t *sel) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_ENTER) == 0 ) + return chooser_multi_t::enter(sel); + PYW_GIL_GET; + ref_t py_list(PyW_SizeVecToPyList(*sel)); + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_SELECT_LINE, + "O", py_list.o)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_multi_t::enter(sel); + return py_as_cbres_sel(sel, pyres.result.o); + } + + virtual cbres_t idaapi refresh(sizevec_t *sel) ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_REFRESH) == 0 ) + return chooser_multi_t::refresh(sel); + PYW_GIL_GET; + ref_t py_list(PyW_SizeVecToPyList(*sel)); + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_REFRESH, + "O", py_list.o)); + if ( pyres.result == NULL || pyres.result.o == Py_None ) + return chooser_multi_t::refresh(sel); + return py_as_cbres_sel(sel, pyres.result.o); + } + + virtual void idaapi select(const sizevec_t &sel) const ida_override + { + if ( (link->cb_flags & py_choose_t::CHOOSE_HAVE_SELECT) == 0 ) + { + chooser_multi_t::select(sel); + return; + } + PYW_GIL_GET; + ref_t py_list(PyW_SizeVecToPyList(sel)); + pycall_res_t pyres( + PyObject_CallMethod( + link->self, (char *)S_ON_SELECTION_CHANGE, + "O", py_list.o)); + } + +protected: + // [ changed, idx, ... ] + static cbres_t py_as_cbres_sel(sizevec_t *sel, PyObject *py_ret) + { + // this is an easy but not an optimal way of converting + if ( !PySequence_Check(py_ret) + || !PyW_PyListToSizeVec(py_ret, *sel) + || sel->empty() ) + { + sel->clear(); + return NOTHING_CHANGED; + } + cbres_t res = cbres_t(sel->front()); + sel->erase(sel->begin()); + return res; + } +}; + +//------------------------------------------------------------------------ +int py_choose_t::create() { PYW_GIL_CHECK_LOCKED_SCOPE(); - newref_t pytitle(PyObject_GetAttrString(self, "title")); - const char *title = pytitle != NULL ? PyString_AsString(pytitle.o) : "Choose"; - int r = choose( - flags, - x0, y0, - x1, y1, - (void*) self, - width, - choose_sizer, - choose_getl, - title, - icon, - deflt, - NULL, /* del */ - NULL, /* inst */ - NULL, /* update */ - NULL, /* edit */ - choose_enter, - NULL, /* destroy */ - NULL, /* popup_names */ - NULL);/* get_icon */ + // Get flags + uint32 flags; + ref_t flags_attr(PyW_TryGetAttrString(self, S_FLAGS)); + if ( flags_attr == NULL ) + return chooser_base_t::NO_ATTR; + if ( PyInt_Check(flags_attr.o) ) + flags = uint32(PyInt_AsLong(flags_attr.o)); + // instruct TChooser destructor to delete this chooser when window + // closes + flags &= ~CH_KEEP; - return r; + // Get the title + if ( !PyW_GetStringAttr(self, S_TITLE, &title) ) + return chooser_base_t::NO_ATTR; + + // Get columns + ref_t cols_attr(PyW_TryGetAttrString(self, "cols")); + if ( cols_attr == NULL ) + return chooser_base_t::NO_ATTR; + + // Get col count + int columns = int(PyList_Size(cols_attr.o)); + if ( columns < 1 ) + return chooser_base_t::NO_ATTR; + + // Get columns caption and widthes + header_strings.resize(columns); + header.resize(columns); + widths.resize(columns); + for ( int i = 0; i < columns; ++i ) + { + // get list item: [name, width] + borref_t list(PyList_GetItem(cols_attr.o, i)); + borref_t v(PyList_GetItem(list.o, 0)); + + // Extract string + const char *str = v == NULL ? "" : PyString_AsString(v.o); + header_strings[i] = str; + header[i] = header_strings[i].c_str(); + + // Extract width + int width; + borref_t v2(PyList_GetItem(list.o, 1)); + // No width? Guess width from column title + if ( v2 == NULL ) + width = strlen(str); + else + width = PyInt_AsLong(v2.o); + widths[i] = width; + } + + // Check what callbacks we have + static const struct + { + const char *name; + unsigned int have; // 0 = mandatory callback + int chooser_t_flags; + } callbacks[] = + { + { S_ON_INIT, CHOOSE_HAVE_INIT, 0 }, + { S_ON_GET_SIZE, 0 }, + { S_ON_GET_LINE, 0 }, + { S_ON_GET_ICON, CHOOSE_HAVE_GETICON, 0 }, + { S_ON_GET_LINE_ATTR, CHOOSE_HAVE_GETATTR, 0 }, + { S_ON_INSERT_LINE, CHOOSE_HAVE_INS, CH_CAN_INS }, + { S_ON_DELETE_LINE, CHOOSE_HAVE_DEL, CH_CAN_DEL }, + { S_ON_EDIT_LINE, CHOOSE_HAVE_EDIT, CH_CAN_EDIT }, + { S_ON_SELECT_LINE, CHOOSE_HAVE_ENTER, 0 }, + { S_ON_REFRESH, CHOOSE_HAVE_REFRESH, CH_CAN_REFRESH }, + { S_ON_SELECTION_CHANGE, CHOOSE_HAVE_SELECT, 0 }, + { S_ON_CLOSE, CHOOSE_HAVE_ONCLOSE, 0 }, + }; + // we can forbid some callbacks explicitly + uint32 forbidden_cb = 0; + ref_t forbidden_cb_attr(PyW_TryGetAttrString(self, "forbidden_cb")); + if ( forbidden_cb_attr != NULL && PyInt_Check(forbidden_cb_attr.o) ) + forbidden_cb = uint32(PyInt_AsLong(forbidden_cb_attr.o)); + cb_flags = 0; + for ( int i = 0; i < qnumber(callbacks); ++i ) + { + ref_t cb_attr(PyW_TryGetAttrString(self, callbacks[i].name)); + bool have_cb = cb_attr != NULL && PyCallable_Check(cb_attr.o); + if ( have_cb && (forbidden_cb & callbacks[i].have) == 0 ) + { + cb_flags |= callbacks[i].have; + flags |= callbacks[i].chooser_t_flags; + } + else + { + // Mandatory field? + if ( callbacks[i].have == 0 ) + return chooser_base_t::NO_ATTR; + } + } + + // create chooser object + if ( (flags & CH_MULTI) == 0 ) + { + chobj = new py_chooser_single_t( + this, + flags, + columns, widths.begin(), header.begin(), + title.c_str()); + } + else + { + chobj = new py_chooser_multi_t( + this, + flags, + columns, widths.begin(), header.begin(), + title.c_str()); + } + + // Get *x1,y1,x2,y2 + py_get_int(self, &chobj->x0, "x1"); + py_get_int(self, &chobj->y0, "y1"); + py_get_int(self, &chobj->x1, "x2"); + py_get_int(self, &chobj->y1, "y2"); + + // Get *icon + py_get_int(self, &chobj->icon, "icon"); + + // Get *popup names + // An array of 4 strings: ("Insert", "Delete", "Edit", "Refresh") + ref_t pn_attr(PyW_TryGetAttrString(self, S_POPUP_NAMES)); + if ( pn_attr != NULL && PyList_Check(pn_attr.o) ) + { + int npopups = int(PyList_Size(pn_attr.o)); + if ( npopups > chooser_base_t::NSTDPOPUPS ) + npopups = chooser_base_t::NSTDPOPUPS; + for ( int i = 0; i < npopups; ++i ) + { + const char *str = PyString_AsString(PyList_GetItem(pn_attr.o, i)); + chobj->popup_names[i] = str; + } + } + + // Check if *embedded + ref_t emb_attr(PyW_TryGetAttrString(self, S_EMBEDDED)); + if ( emb_attr != NULL && PyObject_IsTrue(emb_attr.o) == 1 ) + { + cb_flags |= CHOOSE_IS_EMBEDDED; + py_get_int(self, &chobj->width, "width"); + py_get_int(self, &chobj->height, "height"); + return 0; // success + } + + // run + ssize_t res; + if ( !chobj->is_multi() ) + { + // Get *deflt + ssize_t deflt = 0; + py_get_int(self, &deflt, "deflt"); + res = ((chooser_t *)chobj)->choose(deflt); + } + else + { + // Get *deflt + sizevec_t deflt; + ref_t deflt_attr(PyW_TryGetAttrString(self, "deflt")); + if ( deflt_attr != NULL + && PyList_Check(deflt_attr.o) + && !PyW_PyListToSizeVec(deflt_attr.o, deflt) ) + { + deflt.clear(); + } + res = ((chooser_multi_t *)chobj)->choose(deflt); + } + // assert: `this` is deleted in the case of the modal chooser + + return res; } + +//------------------------------------------------------------------------ +int choose_create(PyObject *self) +{ + py_choose_t *pych; + + pych = choose_find_instance(self); + if ( pych != NULL && pych->is_valid() ) + { + if ( !pych->is_embedded() ) + pych->activate(); + return chooser_base_t::ALREADY_EXISTS; + } + + if ( pych == NULL ) + pych = new py_choose_t(self); + // assert: returned value != chooser_base_t::ALREADY_EXISTS + return pych->create(); +} + +//------------------------------------------------------------------------ +void choose_close(PyObject *self) +{ + py_choose_t *pych = choose_find_instance(self); + if ( pych == NULL ) + return; + + if ( !pych->is_valid() ) + { + // the chooser object is not created + // so we delete Python's chooser ourself + delete pych; + return; + } + + // embedded chooser is deleted by form + if ( pych->is_embedded() ) + return; + + // modal chooser is closed and deleted in py_choose_t::create() + // assert: !pych->is_modal() + + // close the non-modal chooser, + // in turn this will lead to the deletion of the object + pych->close(); +} + +//------------------------------------------------------------------------ +void choose_refresh(PyObject *self) +{ + py_choose_t *pych = choose_find_instance(self); + if ( pych != NULL && pych->is_valid() ) + pych->do_refresh(); +} + +//------------------------------------------------------------------------ +void choose_activate(PyObject *self) +{ + py_choose_t *pych = choose_find_instance(self); + if ( pych != NULL && pych->is_valid() ) + pych->activate(); +} + +//------------------------------------------------------------------------ +PyObject *choose_get_embedded_selection(PyObject *self) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + py_choose_t *pych = choose_find_instance(self); + if ( pych == NULL || !pych->is_valid() || !pych->is_embedded() ) + Py_RETURN_NONE; + + ref_t ret(PyW_SizeVecToPyList(*pych->get_sel_vec())); + ret.incref(); + return ret.o; +} + +//------------------------------------------------------------------------ +// Return the C instances as 64bit numbers +PyObject *choose_get_embedded(PyObject *self) +{ + PYW_GIL_CHECK_LOCKED_SCOPE(); + + py_choose_t *pych = choose_find_instance(self); + if ( pych == NULL || !pych->is_valid() || !pych->is_embedded() ) + Py_RETURN_NONE; + + return Py_BuildValue( + "(KK)", + PTR2U64(pych->get_chobj()), + PTR2U64(pych->get_sel_vec())); +} + +//------------------------------------------------------------------------ +PyObject *choose_find(const char *title) +{ + py_choose_t *pych = py_choose_t::find_chooser(title); + if ( pych == NULL || !pych->is_valid() ) + Py_RETURN_NONE; + PyObject *self = pych->get_self(); + Py_INCREF(self); + return self; +} +// + +//--------------------------------------------------------------------------- +// +PyObject *choose_find(const char *title); +void choose_refresh(PyObject *self); +void choose_close(PyObject *self); +int choose_create(PyObject *self); +void choose_activate(PyObject *self); +PyObject *choose_get_embedded(PyObject *self); +PyObject *choose_get_embedded_selection(PyObject *self); + +PyObject *py_get_chooser_data(const char *chooser_caption, int n) +{ + qstrvec_t data; + if ( !get_chooser_data(&data, chooser_caption, n) ) + Py_RETURN_NONE; + PyObject *py_list = PyList_New(data.size()); + for ( size_t i = 0; i < data.size(); ++i ) + PyList_SetItem(py_list, i, PyString_FromString(data[i].c_str())); + return py_list; +} + +//------------------------------------------------------------------------- +TWidget *choose_get_widget(PyObject *self) +{ + py_choose_t *pych = choose_find_instance(self); + if ( pych == NULL || !pych->is_valid() ) + return NULL; + return pych->get_widget(); +} + // #endif // __PY_KERNWIN_CHOOSE__ diff --git a/pywraps/py_kernwin_choose.py b/pywraps/py_kernwin_choose.py index 5923fcd..2c0d969 100644 --- a/pywraps/py_kernwin_choose.py +++ b/pywraps/py_kernwin_choose.py @@ -1,70 +1,242 @@ - +#-------------------------------------------------------------------------- # -import _ida_idaapi - class Choose(object): - """ - Choose - class for choose() with callbacks - """ - def __init__(self, list, title, flags=0, deflt=1, icon=37): - self.list = list - self.title = title - - self.flags = flags - self.x0 = -1 - self.x1 = -1 - self.y0 = -1 - self.y1 = -1 - - self.width = -1 - self.deflt = deflt - self.icon = icon - - # HACK: Add a circular reference for non-modal choosers. This prevents the GC - # from collecting the class object the callbacks need. Unfortunately this means - # that the class will never be collected, unless refhack is set to None explicitly. - if (flags & Choose2.CH_MODAL) == 0: - self.refhack = self - - - def sizer(self): """ - Callback: sizer - returns the length of the list + Chooser wrapper class. + + Some constants are defined in this class. + Please refer to kernwin.hpp for more information. """ - return len(self.list) + CH_MODAL = 0x01 + """Modal chooser""" - def getl(self, n): + CH_MULTI = 0x04 """ - Callback: getl - get one item from the list + Allow multi selection. + Refer the description of the OnInsertLine(), OnDeleteLine(), + OnEditLine(), OnSelectLine(), OnRefresh(), OnSelectionChange() to + see a difference between single and multi selection callbacks. """ - if n == 0: - return self.title - if n <= self.sizer(): - return str(self.list[n-1]) - else: - return "" + CH_NOBTNS = 0x10 - def enter(self, n): - print "enter(%d) called" % n + CH_ATTRS = 0x20 + CH_NOIDB = 0x40 + """use the chooser even without an open database, same as x0=-2""" - def choose(self): + CH_FORCE_DEFAULT = 0x80 """ - choose - Display the choose dialogue + If a non-modal chooser was already open, change selection to the given + default one """ - old = _ida_idaapi.set_script_timeout(0) - n = _ida_kernwin.choose_choose( - self, - self.flags, - self.x0, - self.y0, - self.x1, - self.y1, - self.width, - self.deflt, - self.icon) - _ida_idaapi.set_script_timeout(old) - return n + + CH_QFLT = 0x1000 + """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_CAN_INS = 0x000100 + """allow to insert new items""" + CH_CAN_DEL = 0x000200 + """allow to delete existing item(s)""" + CH_CAN_EDIT = 0x000400 + """allow to edit existing item(s)""" + CH_CAN_REFRESH = 0x000800 + """allow to refresh chooser""" + + CH_BUILTIN_SHIFT = 19 + CH_BUILTIN_MASK = 0x1F << CH_BUILTIN_SHIFT + + # column flags (are specified in the widths array) + CHCOL_PLAIN = 0x00000000 + CHCOL_PATH = 0x00010000 + CHCOL_HEX = 0x00020000 + CHCOL_DEC = 0x00030000 + CHCOL_FORMAT = 0x00070000 + + # special values of the chooser index + NO_SELECTION = -1 + """there is no selected item""" + EMPTY_CHOOSER = -4 + """the chooser is initialized""" + ALREADY_EXISTS = -5 + """the non-modal chooser with the same data is already open""" + NO_ATTR = -6 + """some mandatory attribute is missing""" + + # return value of ins(), del(), edit(), enter(), refresh() callbacks + NOTHING_CHANGED = 0 + ALL_CHANGED = 1 + SELECTION_CHANGED = 2 + + # to construct `forbidden_cb` + CHOOSE_HAVE_INIT = 0x0001 + CHOOSE_HAVE_GETICON = 0x0002 + CHOOSE_HAVE_GETATTR = 0x0004 + CHOOSE_HAVE_INS = 0x0008 + CHOOSE_HAVE_DEL = 0x0010 + CHOOSE_HAVE_EDIT = 0x0020 + CHOOSE_HAVE_ENTER = 0x0040 + CHOOSE_HAVE_REFRESH = 0x0080 + CHOOSE_HAVE_SELECT = 0x0100 + CHOOSE_HAVE_ONCLOSE = 0x0200 + + class UI_Hooks_Trampoline(UI_Hooks): + def __init__(self, v): + UI_Hooks.__init__(self) + self.hook() + import weakref + self.v = weakref.ref(v) + + def populating_widget_popup(self, form, popup_handle): + chooser = self.v() + if form == chooser.GetWidget() and \ + hasattr(chooser, "OnPopup") and \ + callable(getattr(chooser, "OnPopup")): + chooser.OnPopup(form, popup_handle) + + def __init__(self, title, cols, flags = 0, popup_names = None, + icon=-1, x1=-1, y1=-1, x2=-1, y2=-1, + deflt = None, + embedded = False, width = None, height = None, + forbidden_cb = 0): + """ + Constructs a chooser window. + @param title: The chooser title + @param cols: a list of colums; each list item is a list of two items + example: [ ["Address", 10 | Choose.CHCOL_HEX], + ["Name", 30 | Choose.CHCOL_PLAIN] ] + @param flags: One of CH_XXXX constants + @param deflt: The index of the default item (0-based) for single + selection choosers or the list of indexes for multi selection + chooser + @param popup_names: List of new captions to replace this list + ["Insert", "Delete", "Edit", "Refresh"] + @param icon: Icon index (the icon should exist in ida resources or + an index to a custom loaded icon) + @param x1, y1, x2, y2: The default location (for txt-version) + @param embedded: Create as embedded chooser + @param width: Embedded chooser width + @param height: Embedded chooser height + @param forbidden_cb: Explicitly forbidden callbacks + """ + self.title = title + self.flags = flags + self.cols = cols + if deflt == None: + deflt = 0 if (flags & Choose.CH_MULTI) == 0 else [0] + self.deflt = deflt + self.popup_names = popup_names + self.icon = icon + self.x1 = x1 + self.y1 = y1 + self.x2 = x2 + self.y2 = y2 + self.embedded = embedded + self.width = width + self.height = height + self.forbidden_cb = forbidden_cb + self.ui_hooks_trampoline = None # set on Show + + + def Embedded(self): + """ + 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) + + + def GetEmbSelection(self): + """ + Returns the selection associated with an embedded chooser + + @return: + - None if chooser is not embedded + - A list with selection indexes (0-based) + """ + return _ida_kernwin.choose_get_embedded_selection(self) + + + def Show(self, modal=False): + """ + Activates or creates a chooser window + @param modal: Display as modal dialog + @return: For all choosers it will return NO_ATTR if some mandatory + attribute is missing. The mandatory attributes are: flags, + title, cols, OnGetSize(), OnGetLine(); + For modal choosers it will return the selected item index (0-based), + or NO_SELECTION if no selection, + or EMPTY_CHOOSER if the OnRefresh() callback returns EMPTY_CHOOSER; + For non-modal choosers it will return 0 + or ALREADY_EXISTS if the chooser was already open and is active now; + """ + if self.embedded: + return Choose.NO_ATTR + # it will be deleted and unhooked in py_choose_t::closed() + self.ui_hooks_trampoline = self.UI_Hooks_Trampoline(self) + if modal: + self.flags |= Choose.CH_MODAL + + # Disable the timeout + old = _ida_idaapi.set_script_timeout(0) + n = _ida_kernwin.choose_create(self) + _ida_idaapi.set_script_timeout(old) + + # Delete the modal chooser instance + self.Close() + + return n + else: + self.flags &= ~Choose.CH_MODAL + return _ida_kernwin.choose_create(self) + + + def Activate(self): + """Activates a visible chooser""" + return _ida_kernwin.choose_activate(self) + + + def Refresh(self): + """Causes the refresh callback to trigger""" + return _ida_kernwin.choose_refresh(self) + + + def Close(self): + """Closes the chooser""" + _ida_kernwin.choose_close(self) + + def GetWidget(self): + """ + Return the TWidget underlying this view. + + @return: The TWidget underlying this view, or None. + """ + return _ida_kernwin.choose_get_widget(self) + + def adjust_last_item(self, n): + """ + Helper for OnDeleteLine() and OnRefresh() callbacks. + They can be finished by the following line: + return [Choose.ALL_CHANGED] + self.adjust_last_item(n) + @param: line number of the remaining select item + @return: list of selected lines numbers (one element or empty) + """ + cnt = self.OnGetSize(); + if cnt == 0: + return [] + # take in account deleting of the last item(s) + if n >= cnt: + n = cnt - 1 + return [n] # diff --git a/pywraps/py_kernwin_choose2.hpp b/pywraps/py_kernwin_choose2.hpp deleted file mode 100644 index 03a5054..0000000 --- a/pywraps/py_kernwin_choose2.hpp +++ /dev/null @@ -1,912 +0,0 @@ -#ifndef __PY_KERNWIN_CHOOSE2__ -#define __PY_KERNWIN_CHOOSE2__ - -// - -//------------------------------------------------------------------------ -// Some defines -#define POPUP_NAMES_COUNT 4 -#define MAX_CHOOSER_MENU_COMMANDS 20 -#define thisobj ((py_choose2_t *) obj) -#define thisdecl py_choose2_t *_this = thisobj -#define MENU_COMMAND_CB(id) \ - static uint32 idaapi s_menu_command_##id(void *obj, uint32 n) \ - { \ - return thisobj->on_command(id, int(n)); \ - } - -//------------------------------------------------------------------------ -// Helper functions -class py_choose2_t; -typedef std::map pychoose2_to_choose2_map_t; -static pychoose2_to_choose2_map_t choosers; - -py_choose2_t *choose2_find_instance(PyObject *self) -{ - pychoose2_to_choose2_map_t::iterator it = choosers.find(self); - return it == choosers.end() ? NULL : it->second; -} - -void choose2_add_instance(PyObject *self, py_choose2_t *c2) -{ - choosers[self] = c2; -} - -void choose2_del_instance(PyObject *self) -{ - pychoose2_to_choose2_map_t::iterator it = choosers.find(self); - if ( it != choosers.end() ) - choosers.erase(it); -} - -//------------------------------------------------------------------------ -class py_choose2_t -{ -private: - enum - { - CHOOSE2_HAVE_DEL = 0x0001, - CHOOSE2_HAVE_INS = 0x0002, - CHOOSE2_HAVE_UPDATE = 0x0004, - CHOOSE2_HAVE_EDIT = 0x0008, - CHOOSE2_HAVE_ENTER = 0x0010, - CHOOSE2_HAVE_GETICON = 0x0020, - CHOOSE2_HAVE_GETATTR = 0x0040, - CHOOSE2_HAVE_COMMAND = 0x0080, - CHOOSE2_HAVE_ONCLOSE = 0x0100, - CHOOSE2_HAVE_SELECT = 0x0200, - CHOOSE2_HAVE_REFRESHED = 0x0400, - }; - // Chooser flags - int flags; - - // Callback flags (to tell which callback exists and which not) - // One of CHOOSE2_HAVE_xxxx - unsigned int cb_flags; - chooser_info_t *embedded; - intvec_t embedded_sel; - - // Menu callback index (in the menu_cbs array) - int menu_cb_idx; - - // Chooser title - qstring title; - - // Column widths - intvec_t widths; - - // Python object link - PyObject *self; - // Chooser columns - qstrvec_t cols; - const char **popup_names; - bool ui_cb_hooked; - - // The number of declarations should follow the MAX_CHOOSER_MENU_COMMANDS value - MENU_COMMAND_CB(0) MENU_COMMAND_CB(1) - MENU_COMMAND_CB(2) MENU_COMMAND_CB(3) - MENU_COMMAND_CB(4) MENU_COMMAND_CB(5) - MENU_COMMAND_CB(6) MENU_COMMAND_CB(7) - MENU_COMMAND_CB(8) MENU_COMMAND_CB(9) - MENU_COMMAND_CB(10) MENU_COMMAND_CB(11) - MENU_COMMAND_CB(12) MENU_COMMAND_CB(13) - MENU_COMMAND_CB(14) MENU_COMMAND_CB(15) - MENU_COMMAND_CB(16) MENU_COMMAND_CB(17) - MENU_COMMAND_CB(18) MENU_COMMAND_CB(19) - static chooser_cb_t *menu_cbs[MAX_CHOOSER_MENU_COMMANDS]; - - //------------------------------------------------------------------------ - // Static methods to dispatch to member functions - //------------------------------------------------------------------------ - static int idaapi ui_cb(void *obj, int notification_code, va_list va) - { - // UI callback to handle chooser items with attributes - if ( notification_code != ui_get_chooser_item_attrs ) - return 0; - - // Pass events that belong to our chooser only - void *chooser_obj = va_arg(va, void *); - if ( obj != chooser_obj ) - return 0; - - // We will treat the demand. - // This hook gets called from the kernel. Ensure we hold the GIL. - PYW_GIL_GET; - int n = int(va_arg(va, uint32)); - chooser_item_attrs_t *attr = va_arg(va, chooser_item_attrs_t *); - thisobj->on_get_line_attr(n, attr); - return 1; - } - - static void idaapi s_select(void *obj, const intvec_t &sel) - { - thisobj->on_select(sel); - } - - static void idaapi s_refreshed(void *obj) - { - thisobj->on_refreshed(); - } - - static uint32 idaapi s_sizer(void *obj) - { - return (uint32)thisobj->on_get_size(); - } - - static void idaapi s_getl(void *obj, uint32 n, char *const *arrptr) - { - thisobj->on_get_line(int(n), arrptr); - } - - static uint32 idaapi s_del(void *obj, uint32 n) - { - return uint32(thisobj->on_delete_line(int(n))); - } - - static void idaapi s_ins(void *obj) - { - thisobj->on_insert_line(); - } - - static uint32 idaapi s_update(void *obj, uint32 n) - { - return uint32(thisobj->on_refresh(int(n))); - } - - static void idaapi s_edit(void *obj, uint32 n) - { - thisobj->on_edit_line(int(n)); - } - - static void idaapi s_enter(void * obj, uint32 n) - { - thisobj->on_enter(int(n)); - } - - static int idaapi s_get_icon(void *obj, uint32 n) - { - return thisobj->on_get_icon(int(n)); - } - - static void idaapi s_destroy(void *obj) - { - thisobj->on_close(); - } - - //------------------------------------------------------------------------ - // Member functions corresponding to each chooser2() callback - //------------------------------------------------------------------------ - void clear_popup_names() - { - if ( popup_names == NULL ) - return; - - for ( int i=0; i < POPUP_NAMES_COUNT; i++ ) - qfree((void *)popup_names[i]); - - delete [] popup_names; - popup_names = NULL; - } - - void install_hooks(bool install) - { - if ( install ) - { - if ( (flags & CH_ATTRS) != 0 ) - { - if ( !hook_to_notification_point(HT_UI, ui_cb, this) ) - flags &= ~CH_ATTRS; - else - ui_cb_hooked = true; - } - } - else - { - if ( (flags & CH_ATTRS) != 0 ) - { - unhook_from_notification_point(HT_UI, ui_cb, this); - ui_cb_hooked = false; - } - } - } - - void on_get_line(int lineno, char *const *line_arr) - { - // Called from s_getl, which itself can be called from the kernel. Ensure GIL - PYW_GIL_GET; - - // Get headers? - if ( lineno == 0 ) - { - // Copy the pre-parsed columns - for ( size_t i=0; i < cols.size(); i++ ) - qstrncpy(line_arr[i], cols[i].c_str(), MAXSTR); - return; - } - - // Clear buffer - int ncols = int(cols.size()); - for ( int i=ncols-1; i >= 0; i-- ) - line_arr[i][0] = '\0'; - - // Call Python - PYW_GIL_CHECK_LOCKED_SCOPE(); - pycall_res_t list(PyObject_CallMethod(self, (char *)S_ON_GET_LINE, "i", lineno - 1)); - if ( list.result == NULL ) - return; - - // Go over the List returned by Python and convert to C strings - for ( int i=ncols-1; i >= 0; i-- ) - { - borref_t item(PyList_GetItem(list.result.o, Py_ssize_t(i))); - if ( item == NULL ) - continue; - - const char *str = PyString_AsString(item.o); - if ( str != NULL ) - qstrncpy(line_arr[i], str, MAXSTR); - } - } - - size_t on_get_size() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_SIZE, NULL)); - if ( pyres.result == NULL ) - return 0; - - return PyInt_AsLong(pyres.result.o); - } - - void on_refreshed() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_REFRESHED, NULL)); - } - - void on_select(const intvec_t &intvec) - { - PYW_GIL_GET; - ref_t py_list(PyW_IntVecToPyList(intvec)); - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_SELECTION_CHANGE, "O", py_list.o)); - } - - void on_close() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_CLOSE, NULL)); - - // Delete this instance if non-modal and not embedded - if ( !is_modal() && get_embedded() == NULL ) - delete this; - } - - int on_delete_line(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_DELETE_LINE, - "i", - IS_CHOOSER_EVENT(lineno) ? lineno : lineno-1)); - return pyres.result == NULL ? 1 : PyInt_AsLong(pyres.result.o); - } - - int on_refresh(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_REFRESH, - "i", - lineno - 1)); - return pyres.result == NULL ? lineno : PyInt_AsLong(pyres.result.o) + 1; - } - - void on_insert_line() - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_INSERT_LINE, NULL)); - } - - void on_enter(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_SELECT_LINE, - "i", - lineno - 1)); - } - - void on_edit_line(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_EDIT_LINE, - "i", - lineno - 1)); - } - - int on_command(int cmd_id, int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_COMMAND, - "ii", - lineno - 1, - cmd_id)); - return pyres.result == NULL ? lineno : PyInt_AsLong(pyres.result.o); - } - - int on_get_icon(int lineno) - { - PYW_GIL_GET; - pycall_res_t pyres( - PyObject_CallMethod( - self, - (char *)S_ON_GET_ICON, - "i", - lineno - 1)); - return pyres.result == NULL ? -1 : PyInt_AsLong(pyres.result.o); - } - - void on_get_line_attr(int lineno, chooser_item_attrs_t *attr) - { - PYW_GIL_GET; - pycall_res_t pyres(PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1)); - if ( pyres.result != NULL ) - { - if ( PyList_Check(pyres.result.o) ) - { - PyObject *item; - if ( (item = PyList_GetItem(pyres.result.o, 0)) != NULL ) - attr->color = PyInt_AsLong(item); - if ( (item = PyList_GetItem(pyres.result.o, 1)) != NULL ) - attr->flags = PyInt_AsLong(item); - } - } - } - - bool split_chooser_caption(qstring *out_title, qstring *out_caption, const char *caption) const - { - if ( get_embedded() != NULL ) - { - // For embedded chooser, the "caption" will be overloaded to encode - // the AskUsingForm's title, caption and embedded chooser id - // Title:EmbeddedChooserID:Caption - - char title_buf[MAXSTR]; - const char *ptitle; - - static const char delimiter[] = ":"; - char temp[MAXSTR]; - qstrncpy(temp, caption, sizeof(temp)); - - char *ctx; - char *p = qstrtok(temp, delimiter, &ctx); - if ( p == NULL ) - return false; - - // Copy the title - char title_str[MAXSTR]; - qstrncpy(title_str, p, sizeof(title_str)); - - // Copy the echooser ID - p = qstrtok(NULL, delimiter, &ctx); - if ( p == NULL ) - return false; - - char id_str[10]; - qstrncpy(id_str, p, sizeof(id_str)); - - // Form the new title of the form: "AskUsingFormTitle:EchooserId" - qsnprintf(title_buf, sizeof(title_buf), "%s:%s", title_str, id_str); - - // Adjust the title - *out_title = title_buf; - - // Adjust the caption - p = qstrtok(NULL, delimiter, &ctx); - *out_caption = caption + (p - temp); - } - else - { - *out_title = title; - *out_caption = caption; - } - return true; - } - - // This must be called at the end of create(), when many dependencies - // have been computed (title, widths, popup_names, [cb_]flags, ...) - void fill_chooser_info( - chooser_info_t *out, - int deflt, - int desired_width, - int desired_height, - int icon) - { - out->obj = this; - out->title = title.c_str(); - out->columns = widths.size(); - out->deflt = deflt; - out->flags = flags; - out->width = desired_width; - out->height = desired_height; - out->icon = icon; - out->popup_names = popup_names; - out->widths = widths.begin(); - out->destroyer = s_destroy; - out->getl = s_getl; - out->sizer = s_sizer; - out->del = (cb_flags & CHOOSE2_HAVE_DEL) != 0 ? s_del : NULL; - out->edit = (cb_flags & CHOOSE2_HAVE_EDIT) != 0 ? s_edit : NULL; - out->enter = (cb_flags & CHOOSE2_HAVE_ENTER) != 0 ? s_enter : NULL; - out->get_icon = (cb_flags & CHOOSE2_HAVE_GETICON) != 0 ? s_get_icon : NULL; - out->ins = (cb_flags & CHOOSE2_HAVE_INS) != 0 ? s_ins : NULL; - out->update = (cb_flags & CHOOSE2_HAVE_UPDATE) != 0 ? s_update : NULL; - out->get_attrs = NULL; - out->initializer = NULL; - // Fill callbacks that are only present in idaq - if ( is_idaq() ) - { - out->select = (cb_flags & CHOOSE2_HAVE_SELECT) != 0 ? s_select : NULL; - out->refresh = (cb_flags & CHOOSE2_HAVE_REFRESHED) != 0 ? s_refreshed : NULL; - } - else - { - out->select = NULL; - out->refresh = NULL; - } - } - -public: - //------------------------------------------------------------------------ - // Public methods - //------------------------------------------------------------------------ - py_choose2_t(): flags(0), cb_flags(0), - embedded(NULL), menu_cb_idx(0), - self(NULL), popup_names(NULL), ui_cb_hooked(false) - { - } - - ~py_choose2_t() - { - // Remove from list - choose2_del_instance(self); - - // Uninstall hooks - install_hooks(false); - - delete embedded; - Py_XDECREF(self); - clear_popup_names(); - } - - static py_choose2_t *find_chooser(const char *title) - { - return (py_choose2_t *) get_chooser_obj(title); - } - - void close() - { - // Will trigger on_close() - close_chooser(title.c_str()); - } - - bool activate() - { - TForm *frm = find_tform(title.c_str()); - if ( frm == NULL ) - return false; - - switchto_tform(frm, true); - return true; - } - - int add_command( - const char *_caption, - int flags=0, - int menu_index=-1, - int icon=-1) - { - if ( menu_cb_idx >= MAX_CHOOSER_MENU_COMMANDS ) - return -1; - - qstring title, caption; - if ( !split_chooser_caption(&title, &caption, _caption) - || !add_chooser_command( - title.c_str(), - caption.c_str(), - menu_cbs[menu_cb_idx], - menu_index, - icon, - flags) ) - return -1; - - return menu_cb_idx++; - } - - // Create a chooser. - // If it detects the "embedded" attribute, then it will create a chooser_info_t structure - // Otherwise the chooser window is created and displayed - int create(PyObject *self) - { - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Get flags - ref_t flags_attr(PyW_TryGetAttrString(self, S_FLAGS)); - if ( flags_attr == NULL ) - return -1; - flags = PyInt_Check(flags_attr.o) != 0 ? PyInt_AsLong(flags_attr.o) : 0; - - // Get the title - if ( !PyW_GetStringAttr(self, S_TITLE, &title) ) - return -1; - - // Get columns - ref_t cols_attr(PyW_TryGetAttrString(self, "cols")); - if ( cols_attr == NULL ) - return -1; - - // Get col count - int ncols = int(PyList_Size(cols_attr.o)); - - // Get cols caption and widthes - cols.qclear(); - for ( int i=0; i < ncols; i++ ) - { - // get list item: [name, width] - borref_t list(PyList_GetItem(cols_attr.o, i)); - borref_t v(PyList_GetItem(list.o, 0)); - - // Extract string - const char *str = v == NULL ? "" : PyString_AsString(v.o); - cols.push_back(str); - - // Extract width - int width; - borref_t v2(PyList_GetItem(list.o, 1)); - // No width? Guess width from column title - if ( v2 == NULL ) - width = strlen(str); - else - width = PyInt_AsLong(v2.o); - widths.push_back(width); - } - - // Get *deflt - int deflt = -1; - ref_t deflt_attr(PyW_TryGetAttrString(self, "deflt")); - if ( deflt_attr != NULL ) - deflt = PyInt_AsLong(deflt_attr.o); - - // Get *icon - int icon = -1; - ref_t icon_attr(PyW_TryGetAttrString(self, "icon")); - if ( icon_attr != NULL ) - icon = PyInt_AsLong(icon_attr.o); - - // Get *x1,y1,x2,y2 - int pts[4]; - static const char *pt_attrs[qnumber(pts)] = { "x1", "y1", "x2", "y2" }; - for ( size_t i=0; i < qnumber(pts); i++ ) - { - ref_t pt_attr(PyW_TryGetAttrString(self, pt_attrs[i])); - if ( pt_attr == NULL ) - pts[i] = -1; - else - pts[i] = PyInt_AsLong(pt_attr.o); - } - - // Check what callbacks we have - static const struct - { - const char *name; - unsigned int have; // 0 = mandatory callback - } callbacks[] = - { - { S_ON_GET_SIZE, 0 }, - { S_ON_GET_LINE, 0 }, - { S_ON_CLOSE, 0 }, - { S_ON_EDIT_LINE, CHOOSE2_HAVE_EDIT }, - { S_ON_INSERT_LINE, CHOOSE2_HAVE_INS }, - { S_ON_DELETE_LINE, CHOOSE2_HAVE_DEL }, - { S_ON_REFRESH, CHOOSE2_HAVE_UPDATE }, // update() - { S_ON_SELECT_LINE, CHOOSE2_HAVE_ENTER }, // enter() - { S_ON_COMMAND, CHOOSE2_HAVE_COMMAND }, - { S_ON_GET_LINE_ATTR, CHOOSE2_HAVE_GETATTR }, - { S_ON_GET_ICON, CHOOSE2_HAVE_GETICON }, - { S_ON_SELECTION_CHANGE, CHOOSE2_HAVE_SELECT }, - { S_ON_REFRESHED, CHOOSE2_HAVE_REFRESHED }, - }; - cb_flags = 0; - for ( int i=0; i < qnumber(callbacks); i++ ) - { - ref_t cb_attr(PyW_TryGetAttrString(self, callbacks[i].name)); - bool have_cb = cb_attr != NULL && PyCallable_Check(cb_attr.o) != 0; - if ( have_cb ) - { - cb_flags |= callbacks[i].have; - } - else - { - // Mandatory field? - if ( callbacks[i].have == 0 ) - return -1; - } - } - - // Get *popup names - // An array of 4 strings: ("Insert", "Delete", "Edit", "Refresh" - ref_t pn_attr(PyW_TryGetAttrString(self, S_POPUP_NAMES)); - if ( (pn_attr != NULL) - && PyList_Check(pn_attr.o) - && PyList_Size(pn_attr.o) == POPUP_NAMES_COUNT ) - { - popup_names = new const char *[POPUP_NAMES_COUNT]; - for ( int i=0; i < POPUP_NAMES_COUNT; i++ ) - { - const char *str = PyString_AsString(PyList_GetItem(pn_attr.o, i)); - popup_names[i] = qstrdup(str); - } - } - - // Adjust flags (if needed) - if ( (cb_flags & CHOOSE2_HAVE_GETATTR) != 0 ) - flags |= CH_ATTRS; - - // Increase object reference - Py_INCREF(self); - this->self = self; - - // Hook to notification point (to handle chooser item attributes) - install_hooks(true); - - // Check if *embedded - ref_t emb_attr(PyW_TryGetAttrString(self, S_EMBEDDED)); - int rc; - if ( emb_attr != NULL && PyObject_IsTrue(emb_attr.o) == 1 ) - { - // Create an embedded chooser structure - embedded = new chooser_info_t(); - fill_chooser_info(embedded, deflt, pts[0], pts[1], icon); - rc = 1; // success - } - else - { - chooser_info_t ci; - fill_chooser_info(&ci, deflt, -1, -1, icon); - rc = choose3(&ci); - clear_popup_names(); - if ( is_modal() ) - --rc; // modal chooser return the index of the selected item - } - return rc; - } - - inline PyObject *get_self() - { - return self; - } - - void refresh() - { - refresh_chooser(title.c_str()); - } - - bool is_modal() - { - return (flags & CH_MODAL) != 0; - } - - intvec_t *get_sel_vec() - { - return &embedded_sel; - } - - chooser_info_t *get_embedded() const - { - return embedded; - } -}; - -//------------------------------------------------------------------------ -// Initialize the callback pointers -#define DECL_MENU_COMMAND_CB(id) s_menu_command_##id -chooser_cb_t *py_choose2_t::menu_cbs[MAX_CHOOSER_MENU_COMMANDS] = -{ - DECL_MENU_COMMAND_CB(0), DECL_MENU_COMMAND_CB(1), - DECL_MENU_COMMAND_CB(2), DECL_MENU_COMMAND_CB(3), - DECL_MENU_COMMAND_CB(4), DECL_MENU_COMMAND_CB(5), - DECL_MENU_COMMAND_CB(6), DECL_MENU_COMMAND_CB(7), - DECL_MENU_COMMAND_CB(8), DECL_MENU_COMMAND_CB(9), - DECL_MENU_COMMAND_CB(10), DECL_MENU_COMMAND_CB(11), - DECL_MENU_COMMAND_CB(12), DECL_MENU_COMMAND_CB(13), - DECL_MENU_COMMAND_CB(14), DECL_MENU_COMMAND_CB(15), - DECL_MENU_COMMAND_CB(16), DECL_MENU_COMMAND_CB(17), - DECL_MENU_COMMAND_CB(18), DECL_MENU_COMMAND_CB(19) -}; -#undef DECL_MENU_COMMAND_CB - -#undef POPUP_NAMES_COUNT -#undef MAX_CHOOSER_MENU_COMMANDS -#undef thisobj -#undef thisdecl -#undef MENU_COMMAND_CB - -//------------------------------------------------------------------------ -int choose2_create(PyObject *self, bool embedded) -{ - py_choose2_t *c2; - - c2 = choose2_find_instance(self); - if ( c2 != NULL ) - { - if ( !embedded ) - c2->activate(); - return 1; - } - - c2 = new py_choose2_t(); - - choose2_add_instance(self, c2); - - int r = c2->create(self); - // Non embedded chooser? Return immediately - if ( !embedded ) - return r; - - // Embedded chooser was not created? - if ( c2->get_embedded() == NULL || r != 1 ) - { - delete c2; - r = 0; - } - return r; -} - -//------------------------------------------------------------------------ -void choose2_close(PyObject *self) -{ - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 == NULL ) - return; - - // Modal or embedded chooser? - if ( c2->get_embedded() != NULL || c2->is_modal() ) - { - // Then simply delete the instance - delete c2; - } - else - { - // Close the chooser. - // In turn this will lead to the deletion of the object - c2->close(); - } -} - -//------------------------------------------------------------------------ -void choose2_refresh(PyObject *self) -{ - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 != NULL ) - c2->refresh(); -} - -//------------------------------------------------------------------------ -void choose2_activate(PyObject *self) -{ - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 != NULL ) - c2->activate(); -} - -//------------------------------------------------------------------------ -PyObject *choose2_get_embedded_selection(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - py_choose2_t *c2 = choose2_find_instance(self); - chooser_info_t *embedded; - - if ( c2 == NULL || (embedded = c2->get_embedded()) == NULL ) - Py_RETURN_NONE; - - // Returned as 1-based - intvec_t &intvec = *c2->get_sel_vec(); - - // Make 0-based - for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it ) - (*it)--; - - ref_t ret(PyW_IntVecToPyList(intvec)); - ret.incref(); - return ret.o; -} - -//------------------------------------------------------------------------ -// Return the C instances as 64bit numbers -PyObject *choose2_get_embedded(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - py_choose2_t *c2 = choose2_find_instance(self); - if ( c2 == NULL ) - Py_RETURN_NONE; - - chooser_info_t *embedded = c2->get_embedded(); - if ( embedded == NULL ) - Py_RETURN_NONE; - - return Py_BuildValue("(KK)", PTR2U64(embedded), PTR2U64(c2->get_sel_vec())); -} - -//------------------------------------------------------------------------ -int choose2_add_command( - PyObject *self, - const char *caption, - int flags=0, - int menu_index=-1, - int icon=-1) -{ - py_choose2_t *c2 = choose2_find_instance(self); - return c2 == NULL ? -2 : c2->add_command(caption, flags, menu_index, icon); -} - -//------------------------------------------------------------------------ -PyObject *choose2_find(const char *title) -{ - py_choose2_t *c2 = py_choose2_t::find_chooser(title); - return c2 == NULL ? NULL : c2->get_self(); -} -// - -//--------------------------------------------------------------------------- -// -PyObject *choose2_find(const char *title); -int choose2_add_command(PyObject *self, const char *caption, int flags, int menu_index, int icon); -void choose2_refresh(PyObject *self); -void choose2_close(PyObject *self); -int choose2_create(PyObject *self, bool embedded); -void choose2_activate(PyObject *self); -PyObject *choose2_get_embedded(PyObject *self); -PyObject *choose2_get_embedded_selection(PyObject *self); - -PyObject *py_get_chooser_data(const char *chooser_caption, uint32 n) -{ - qstrvec_t data; - if ( !get_chooser_data(&data, chooser_caption, n) ) - Py_RETURN_NONE; - PyObject *py_list = PyList_New(data.size()); - for ( size_t i = 0; i < data.size(); ++i ) - PyList_SetItem(py_list, i, PyString_FromString(data[i].c_str())); - return py_list; -} - -// - -//--------------------------------------------------------------------------- -// Testing functions. They belong to PyWraps and won't be copied to IDAPython -//--------------------------------------------------------------------------- - -static void NT_CDECL choose2_test_embedded(chooser_info_t *embedded) -{ - msg("cb=%d -> looks %valid\n", - embedded->cb, - embedded->cb == sizeof(chooser_info_t) ? "" : "in"); -} -static size_t choose2_get_test_embedded() -{ - return (size_t)choose2_test_embedded; -} -#endif // __PY_KERNWIN_CHOOSE2__ diff --git a/pywraps/py_kernwin_choose2.py b/pywraps/py_kernwin_choose2.py deleted file mode 100644 index 4320bdc..0000000 --- a/pywraps/py_kernwin_choose2.py +++ /dev/null @@ -1,237 +0,0 @@ -# ----------------------------------------------------------------------- -# -class Choose2(object): - """ - Choose2 wrapper class. - - Some constants are defined in this class. Please refer to kernwin.hpp for more information. - """ - - CH_MODAL = 0x01 - """Modal chooser""" - - CH_MULTI = 0x02 - """Allow multi selection""" - - CH_MULTI_EDIT = 0x04 - CH_NOBTNS = 0x08 - CH_ATTRS = 0x10 - CH_NOIDB = 0x20 - """use the chooser even without an open database, same as x0=-2""" - CH_UTF8 = 0x40 - """string encoding is utf-8""" - - CH_BUILTIN_MASK = 0xF80000 - - # column flags (are specified in the widths array) - CHCOL_PLAIN = 0x00000000 - CHCOL_PATH = 0x00010000 - CHCOL_HEX = 0x00020000 - CHCOL_DEC = 0x00030000 - CHCOL_FORMAT = 0x00070000 - - - def __init__(self, title, cols, flags=0, popup_names=None, - icon=-1, x1=-1, y1=-1, x2=-1, y2=-1, deflt=-1, - embedded=False, width=None, height=None): - """ - Constructs a chooser window. - @param title: The chooser title - @param cols: a list of colums; each list item is a list of two items - example: [ ["Address", 10 | Choose2.CHCOL_HEX], ["Name", 30 | Choose2.CHCOL_PLAIN] ] - @param flags: One of CH_XXXX constants - @param deflt: Default starting item - @param popup_names: list of new captions to replace this list ["Insert", "Delete", "Edit", "Refresh"] - @param icon: Icon index (the icon should exist in ida resources or an index to a custom loaded icon) - @param x1, y1, x2, y2: The default location - @param embedded: Create as embedded chooser - @param width: Embedded chooser width - @param height: Embedded chooser height - """ - self.title = title - self.flags = flags - self.cols = cols - self.deflt = deflt - self.popup_names = popup_names - self.icon = icon - self.x1 = x1 - self.y1 = y1 - self.x2 = x2 - self.y2 = y2 - self.embedded = embedded - if embedded: - self.x1 = width - self.y1 = height - - - def Embedded(self): - """ - Creates an embedded chooser (as opposed to Show()) - @return: Returns 1 on success - """ - return _ida_kernwin.choose2_create(self, True) - - - def GetEmbSelection(self): - """ - Returns the selection associated with an embedded chooser - - @return: - - None if chooser is not embedded - - A list with selection indices (0-based) - """ - return _ida_kernwin.choose2_get_embedded_selection(self) - - - def Show(self, modal=False): - """ - Activates or creates a chooser window - @param modal: Display as modal dialog - @return: For modal choosers it will return the selected item index (0-based) or -1 if no selection - """ - if modal: - self.flags |= Choose2.CH_MODAL - - # Disable the timeout - old = _ida_idaapi.set_script_timeout(0) - n = _ida_kernwin.choose2_create(self, False) - _ida_idaapi.set_script_timeout(old) - - # Delete the modal chooser instance - self.Close() - - return n - else: - self.flags &= ~Choose2.CH_MODAL - return _ida_kernwin.choose2_create(self, False) - - - def Activate(self): - """Activates a visible chooser""" - return _ida_kernwin.choose2_activate(self) - - - def Refresh(self): - """Causes the refresh callback to trigger""" - return _ida_kernwin.choose2_refresh(self) - - - def Close(self): - """Closes the chooser""" - return _ida_kernwin.choose2_close(self) - - - def AddCommand(self, - caption, - flags = _ida_kernwin.CHOOSER_POPUP_MENU, - menu_index = -1, - icon = -1, - emb=None): - """ - Deprecated: Use - - register_action() - - attach_action_to_menu() - - attach_action_to_popup() - """ - # Use the 'emb' as a sentinel. It will be passed the correct value from the EmbeddedChooserControl - if self.embedded and ((emb is None) or (emb != 2002)): - raise RuntimeError("Please add a command through EmbeddedChooserControl.AddCommand()") - return _ida_kernwin.choose2_add_command(self, caption, flags, menu_index, icon) - - # - # Implement these methods in the subclass: - # -# -# def OnClose(self): -# """ -# Called when the window is being closed. -# This callback is mandatory. -# @return: nothing -# """ -# pass -# -# def OnGetLine(self, n): -# """Called when the chooser window requires lines. -# This callback is mandatory. -# @param n: Line number (0-based) -# @return: The user should return a list with ncols elements. -# example: a list [col1, col2, col3, ...] describing the n-th line -# """ -# return ["col1 val", "col2 val"] -# -# def OnGetSize(self): -# """Returns the element count. -# This callback is mandatory. -# @return: Number of elements -# """ -# return len(self.the_list) -# -# def OnEditLine(self, n): -# """ -# Called when an item is being edited. -# @param n: Line number (0-based) -# @return: Nothing -# """ -# pass -# -# def OnInsertLine(self): -# """ -# Called when 'Insert' is selected either via the hotkey or popup menu. -# @return: Nothing -# """ -# pass -# -# def OnSelectLine(self, n): -# """ -# Called when a line is selected and then Ok or double click was pressed -# @param n: Line number (0-based) -# """ -# pass -# -# def OnSelectionChange(self, sel_list): -# """ -# Called when the selection changes -# @param sel_list: A list of selected item indices -# """ -# pass -# -# def OnDeleteLine(self, n): -# """ -# Called when a line is about to be deleted -# @param n: Line number (0-based) -# """ -# return self.n -# -# def OnRefresh(self, n): -# """ -# Triggered when the 'Refresh' is called from the popup menu item. -# -# @param n: The currently selected line (0-based) at the time of the refresh call -# @return: Return the new selected line -# """ -# return self.n -# -# def OnRefreshed(self): -# """ -# Triggered when a refresh happens (for example due to column sorting) -# """ -# -# def OnCommand(self, n, cmd_id): -# """Return int ; check add_chooser_command()""" -# return 0 -# -# def OnGetIcon(self, n): -# """ -# Return icon number for a given item (or -1 if no icon is avail) -# @param n: Line number (0-based) -# """ -# return -1 -# -# def OnGetLineAttr(self, n): -# """ -# Return list [bgcolor, flags=CHITEM_XXXX] or None; check chooser_item_attrs_t -# @param n: Line number (0-based) -# """ -# return [0x0, CHITEM_BOLD] -# -# diff --git a/pywraps/py_kernwin_custview.hpp b/pywraps/py_kernwin_custview.hpp index 8476978..5170a23 100644 --- a/pywraps/py_kernwin_custview.hpp +++ b/pywraps/py_kernwin_custview.hpp @@ -141,8 +141,7 @@ class customviewer_t { protected: qstring _title; - TForm *_form; - TCustomControl *_cv; + TWidget *_cv; custviewer_data_t *_data; int _features; custom_viewer_handlers_t handlers; @@ -166,27 +165,14 @@ private: cvw_popupctx_t(size_t mid, customviewer_t *v): menu_id(mid), cv(v) {} }; typedef std::map cvw_popupmap_t; - static cvw_popupmap_t _global_popup_map; static size_t _global_popup_id; qstring _curline; - intvec_t _installed_popups; - - static bool idaapi s_popup_menu_cb(void *ud) - { - size_t mid = (size_t)ud; - cvw_popupmap_t::iterator it = _global_popup_map.find(mid); - if ( it == _global_popup_map.end() ) - return false; - - PYW_GIL_GET; - return it->second.cv->on_popup_menu(it->second.menu_id); - } static bool idaapi s_cv_keydown( - TCustomControl * /*cv*/, - int vk_key, - int shift, - void *ud) + TWidget * /*cv*/, + int vk_key, + int shift, + void *ud) { PYW_GIL_GET; customviewer_t *_this = (customviewer_t *)ud; @@ -194,7 +180,7 @@ private: } // The popup menu is being constructed - static void idaapi s_cv_popup(TCustomControl * /*cv*/, void *ud) + static void idaapi s_cv_popup(TWidget * /*cv*/, void *ud) { PYW_GIL_GET; customviewer_t *_this = (customviewer_t *)ud; @@ -202,7 +188,7 @@ private: } // The user clicked - static bool idaapi s_cv_click(TCustomControl * /*cv*/, int shift, void *ud) + static bool idaapi s_cv_click(TWidget * /*cv*/, int shift, void *ud) { PYW_GIL_GET; customviewer_t *_this = (customviewer_t *)ud; @@ -210,7 +196,7 @@ private: } // The user double clicked - static bool idaapi s_cv_dblclick(TCustomControl * /*cv*/, int shift, void *ud) + static bool idaapi s_cv_dblclick(TWidget * /*cv*/, int shift, void *ud) { PYW_GIL_GET; customviewer_t *_this = (customviewer_t *)ud; @@ -218,7 +204,7 @@ private: } // Cursor position has been changed - static void idaapi s_cv_curpos(TCustomControl * /*cv*/, void *ud) + static void idaapi s_cv_curpos(TWidget * /*cv*/, void *ud) { PYW_GIL_GET; customviewer_t *_this = (customviewer_t *)ud; @@ -226,7 +212,7 @@ private: } //-------------------------------------------------------------------------- - static int idaapi s_ui_cb(void *ud, int code, va_list va) + static ssize_t idaapi s_ui_cb(void *ud, int code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; @@ -235,25 +221,25 @@ private: { case ui_get_custom_viewer_hint: { - TCustomControl *viewer = va_arg(va, TCustomControl *); - place_t *place = va_arg(va, place_t *); - int *important_lines = va_arg(va, int *); - qstring &hint = *va_arg(va, qstring *); + 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 ) return 0; else return _this->on_hint(place, important_lines, hint) ? 1 : 0; } - case ui_tform_invisible: + case ui_widget_invisible: { - TForm *form = va_arg(va, TForm *); - if ( _this->_form != form ) + TWidget *widget = va_arg(va, TWidget *); + if ( _this->_cv != widget ) break; } // fallthrough... case ui_term: - unhook_from_notification_point(HT_UI, s_ui_cb, _this); + idapython_unhook_from_notification_point(HT_UI, s_ui_cb, _this); _this->on_close(); _this->on_post_close(); break; @@ -265,13 +251,11 @@ private: void on_post_close() { init_vars(); - clear_popup_menu(); } public: - inline TForm *get_tform() { return _form; } - inline TCustomControl *get_tcustom_control() { return _cv; } + inline TWidget *get_widget() { return _cv; } // // All the overridable callbacks @@ -307,7 +291,6 @@ public: _features = 0; _curline.clear(); _cv = NULL; - _form = NULL; } customviewer_t() @@ -322,8 +305,8 @@ public: //-------------------------------------------------------------------------- void close() { - if ( _form != NULL ) - close_tform(_form, FORM_SAVE | FORM_CLOSE_LATER); + if ( _cv != NULL ) + close_widget(_cv, WCLS_SAVE | WCLS_CLOSE_LATER); } //-------------------------------------------------------------------------- @@ -404,12 +387,8 @@ public: if ( r == NULL || !notags ) return r; - size_t sz = strlen(r); - if ( sz == 0 ) - return r; - - _curline.resize(sz + 5, '\0'); - tag_remove(r, &_curline[0], sz + 1); + _curline = r; + tag_remove(&_curline); return _curline.c_str(); } @@ -425,63 +404,19 @@ public: return ::jumpto(_cv, place, x, y); } - //-------------------------------------------------------------------------- - void clear_popup_menu() - { - if ( _cv != NULL ) - set_custom_viewer_popup_menu(_cv, NULL); - - intvec_t::iterator it, it_end; - for ( it=_installed_popups.begin(), it_end=_installed_popups.end(); - it != it_end; - ++it ) - { - _global_popup_map.erase(*it); - } - _installed_popups.clear(); - } - - //-------------------------------------------------------------------------- - size_t add_popup_menu( - const char *title, - const char *hotkey) - { - size_t menu_id = _global_popup_id + 1; - - // Overlap / already exists? - if ( _cv == NULL // No custviewer? - || menu_id == 0 // Overlap? - || _global_popup_map.find(menu_id) != _global_popup_map.end() ) // Already exists? - { - return 0; - } - add_custom_viewer_popup_item(_cv, title, hotkey, s_popup_menu_cb, (void *)menu_id); - - // Save global association - _global_popup_map[menu_id] = cvw_popupctx_t(menu_id, this); - _global_popup_id = menu_id; - - // Remember what menu IDs are set with this form - _installed_popups.push_back(menu_id); - return menu_id; - } - - //-------------------------------------------------------------------------- bool create(const char *title, int features, custviewer_data_t *data) { // Already created? (in the instance) - if ( _form != NULL ) + if ( _cv != NULL ) return true; // Already created? (in IDA windows list) - HWND hwnd(NULL); - TForm *form = create_tform(title, &hwnd); - if ( hwnd == NULL ) + TWidget *found = find_widget(title); + if ( found != NULL ) return false; _title = title; _data = data; - _form = form; _features = features; // @@ -505,7 +440,6 @@ public: // Create the viewer _cv = create_custom_viewer( title, - (TWinControl *)_form, _data->get_min(), _data->get_max(), _data->get_min(), @@ -514,8 +448,8 @@ public: &handlers, this); - // Hook to UI notifications (for TForm close event) - hook_to_notification_point(HT_UI, s_ui_cb, this); + // Hook to UI notifications (for TWidget close event) + idapython_hook_to_notification_point(HT_UI, s_ui_cb, this); return true; } @@ -524,15 +458,14 @@ public: bool show() { // Closed already? - if ( _form == NULL ) + if ( _cv == NULL ) return false; - open_tform(_form, FORM_TAB|FORM_MENU|FORM_RESTORE|FORM_QWIDGET); + display_widget(_cv, WOPN_TAB|WOPN_MENU|WOPN_RESTORE); return true; } }; -customviewer_t::cvw_popupmap_t customviewer_t::_global_popup_map; size_t customviewer_t::_global_popup_id = 0; //--------------------------------------------------------------------------- class py_simplecustview_t: public customviewer_t @@ -675,8 +608,8 @@ private: PyObject_CallMethod( py_self, (char *)S_ON_HINT, - PY_FMT64, - pyul_t(ln))); + PY_BV_SZ, + bvsz_t(ln))); PyW_ShowCbErr(S_ON_HINT); bool ok = py_result != NULL && PyTuple_Check(py_result.o) && PyTuple_Size(py_result.o) == 2; @@ -698,8 +631,8 @@ private: PyObject_CallMethod( py_self, (char *)S_ON_POPUP_MENU, - PY_FMT64, - pyul_t(menu_id))); + PY_BV_SZ, + bvsz_t(menu_id))); PyW_ShowCbErr(S_ON_POPUP_MENU); return py_result != NULL && PyObject_IsTrue(py_result.o); } @@ -776,7 +709,7 @@ public: PYW_GIL_CHECK_LOCKED_SCOPE(); if ( pl == NULL ) Py_RETURN_NONE; - return Py_BuildValue("(" PY_FMT64 "ii)", pyul_t(data.to_lineno(pl)), x, y); + return Py_BuildValue("(" PY_BV_SZ "ii)", bvsz_t(data.to_lineno(pl)), x, y); } //-------------------------------------------------------------------------- @@ -815,7 +748,7 @@ public: bool init(PyObject *py_link, const char *title) { // Already created? - if ( _form != NULL ) + if ( _cv != NULL ) return true; // Probe callbacks @@ -859,8 +792,7 @@ public: //-------------------------------------------------------------------------- bool show() { - // Form was closed, but object already linked? - if ( _form == NULL && py_last_link != NULL ) + if ( _cv == NULL && py_last_link != NULL ) { // Re-create the view (with same previous parameters) if ( !init(py_last_link, _title.c_str()) ) @@ -876,7 +808,7 @@ public: return false; twinpos_t p1, p2; - if ( !::readsel2(_cv, &p1, &p2) ) + if ( !::read_selection(_cv, &p1, &p2) ) return false; if ( y1 != NULL ) @@ -896,7 +828,9 @@ public: PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !get_selection(&x1, &y1, &x2, &y2) ) Py_RETURN_NONE; - return Py_BuildValue("(" PY_FMT64 PY_FMT64 PY_FMT64 PY_FMT64 ")", pyul_t(x1), pyul_t(y1), pyul_t(x2), pyul_t(y2)); + return Py_BuildValue( + "(" PY_BV_SZ PY_BV_SZ PY_BV_SZ PY_BV_SZ ")", + bvsz_t(x1), bvsz_t(y1), bvsz_t(x2), bvsz_t(y2)); } static py_simplecustview_t *get_this(PyObject *py_this) @@ -984,19 +918,6 @@ bool pyscv_is_focused(PyObject *py_this) return _this->is_focused(); } -void pyscv_clear_popup_menu(PyObject *py_this) -{ - DECL_THIS; - if ( _this != NULL ) - _this->clear_popup_menu(); -} - -size_t pyscv_add_popup_menu(PyObject *py_this, const char *title, const char *hotkey) -{ - DECL_THIS; - return _this == NULL ? 0 : _this->add_popup_menu(title, hotkey); -} - size_t pyscv_count(PyObject *py_this) { DECL_THIS; @@ -1123,17 +1044,10 @@ bool pyscv_edit_line(PyObject *py_this, size_t nline, PyObject *py_sl) } //------------------------------------------------------------------------- -TForm *pyscv_get_tform(PyObject *py_this) +TWidget *pyscv_get_widget(PyObject *py_this) { DECL_THIS; - return _this == NULL ? NULL : _this->get_tform(); -} - -//------------------------------------------------------------------------- -TCustomControl *pyscv_get_tcustom_control(PyObject *py_this) -{ - DECL_THIS; - return _this == NULL ? NULL : _this->get_tcustom_control(); + return _this == NULL ? NULL : _this->get_widget(); } diff --git a/pywraps/py_kernwin_custview.py b/pywraps/py_kernwin_custview.py index 35c18ea..e738a0b 100644 --- a/pywraps/py_kernwin_custview.py +++ b/pywraps/py_kernwin_custview.py @@ -57,7 +57,7 @@ class simplecustviewer_t(object): def GetSelection(self): """ - Returns the selected area or None + Returns the selected range or None @return: - tuple(x1, y1, x2, y2) - None if no selection @@ -142,42 +142,17 @@ class simplecustviewer_t(object): def Jump(self, lineno, x=0, y=0): return _ida_kernwin.pyscv_jumpto(self.__this, lineno, x, y) - def AddPopupMenu(self, title, hotkey=""): - """ - Adds a popup menu item, and get its ID (for use in the OnPopupMenu() handler) - @param title: The name of the menu item - @param hotkey: Hotkey of the item or just empty - @return: Returns the id of the registered popup menu item - """ - return _ida_kernwin.pyscv_add_popup_menu(self.__this, title, hotkey) - - def ClearPopupMenu(self): - """ - Clears all previously installed popup menu items. - Use this function if you're generating menu items on the fly (in the OnPopup() callback), - and before adding new items - """ - _ida_kernwin.pyscv_clear_popup_menu(self.__this) - def IsFocused(self): """Returns True if the current view is the focused view""" return _ida_kernwin.pyscv_is_focused(self.__this) - def GetTForm(self): + def GetWidget(self): """ - Return the TForm hosting this view. + Return the TWidget underlying this view. - @return: The TForm that hosts this view, or None. + @return: The TWidget underlying this view, or None. """ - return _ida_kernwin.pyscv_get_tform(self.__this) - - def GetTCustomControl(self): - """ - Return the TCustomControl underlying this view. - - @return: The TCustomControl underlying this view, or None. - """ - return _ida_kernwin.pyscv_get_tcustom_control(self.__this) + return _ida_kernwin.pyscv_get_widget(self.__this) diff --git a/pywraps/py_kernwin_idaview.hpp b/pywraps/py_kernwin_idaview.hpp index b2f5d8b..034ef46 100644 --- a/pywraps/py_kernwin_idaview.hpp +++ b/pywraps/py_kernwin_idaview.hpp @@ -24,40 +24,28 @@ bool py_idaview_t::Bind(PyObject *self) if ( !PyW_GetStringAttr(self, S_M_TITLE, &title) ) return false; - // Get the IDAView associated to this TForm - TForm *tform = find_tform(title.c_str()); - if ( tform == NULL ) - return false; - TCustomControl *v = get_tform_idaview(tform); - if ( v == NULL ) + // Get the IDAView associated to this TWidget + TWidget *widget = find_widget(title.c_str()); + if ( widget == NULL ) return false; - // Get unique py_idaview_t associated to that tform + // Get unique py_idaview_t associated to that TWidget py_idaview_t *py_view; - TCustomControl *found_view; - if ( pycim_lookup_info.find_by_form(&found_view, (py_customidamemo_t**) &py_view, tform) ) - { - // If we have a py_idaview_t for that form, ensure it has - // the expected view. - QASSERT(30451, found_view == v); - } - else + if ( !pycim_lookup_info.find_by_view((py_customidamemo_t**) &py_view, widget) ) { py_view = new py_idaview_t(); lookup_entry_t &e = pycim_lookup_info.new_entry(py_view); - pycim_lookup_info.commit(e, tform, v); + pycim_lookup_info.commit(e, widget); } // Finally, bind: // py_idaview_t <=> IDAViewWrapper - // py_idaview_t => TCustomControl - bool ok = py_view->bind(self, v); + // py_idaview_t => TWidget + bool ok = py_view->bind(self, widget); if ( ok ) { ok = py_view->collect_pyobject_callbacks(self); - if ( ok ) - py_view->install_custom_viewer_handlers(); - else + if ( !ok ) delete py_view; } return ok; diff --git a/pywraps/py_kernwin_idaview.py b/pywraps/py_kernwin_idaview.py index b009f57..244ef8f 100644 --- a/pywraps/py_kernwin_idaview.py +++ b/pywraps/py_kernwin_idaview.py @@ -3,23 +3,30 @@ #------------------------------------------------------------------------- # IDAViewWrapper #------------------------------------------------------------------------- -import ida_idaapi import _ida_kernwin -class IDAViewWrapper(ida_idaapi.CustomIDAMemo): - """This class wraps access to native IDA views. See kernwin.hpp file""" - def __init__(self, title): - """ - Constructs the IDAViewWrapper object around the view - whose title is 'title'. +class IDAViewWrapper(CustomIDAMemo): + """ + Deprecated. Use View_Hooks instead. - @param title: The title of the existing IDA view. E.g., 'IDA View-A' - """ + Because the lifecycle of an IDAView is not trivial to track (e.g., a user + might close, then re-open the same disassembly view), this wrapper doesn't + bring anything superior to the View_Hooks: quite the contrary, as the + latter is much more generic (and better maps IDA's internal model.) + """ + def __init__(self, title): + CustomIDAMemo.__init__(self) self._title = title def Bind(self): - return _ida_kernwin.pyidag_bind(self) + rc = _ida_kernwin.pyidag_bind(self) + if rc: + self.hook() + return rc def Unbind(self): - return _ida_kernwin.pyidag_unbind(self) + rc = _ida_kernwin.pyidag_unbind(self) + if rc: + self.unhook() + return rc # diff --git a/pywraps/py_kernwin_plgform.hpp b/pywraps/py_kernwin_plgform.hpp index 30bf74b..58621a3 100644 --- a/pywraps/py_kernwin_plgform.hpp +++ b/pywraps/py_kernwin_plgform.hpp @@ -7,18 +7,18 @@ class plgform_t { private: ref_t py_obj; - TForm *form; + TWidget *widget; - static int idaapi s_callback(void *ud, int notification_code, va_list va) + static ssize_t idaapi s_callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; plgform_t *_this = (plgform_t *)ud; - if ( notification_code == ui_tform_visible ) + if ( notification_code == ui_widget_visible ) { - TForm *form = va_arg(va, TForm *); - if ( form == _this->form ) + TWidget *widget = va_arg(va, TWidget *); + if ( widget == _this->widget ) { // Qt: QWidget* // G: HWND @@ -28,21 +28,21 @@ private: PyObject_CallMethod( _this->py_obj.o, (char *)S_ON_CREATE, "O", - PyCObject_FromVoidPtr(form, NULL))); + PyCObject_FromVoidPtr(widget, NULL))); PyW_ShowCbErr(S_ON_CREATE); } } - else if ( notification_code == ui_tform_invisible ) + else if ( notification_code == ui_widget_invisible ) { - TForm *form = va_arg(va, TForm *); - if ( form == _this->form ) + TWidget *widget = va_arg(va, TWidget *); + if ( widget == _this->widget ) { { newref_t py_result( PyObject_CallMethod( _this->py_obj.o, (char *)S_ON_CLOSE, "O", - PyCObject_FromVoidPtr(form, NULL))); + PyCObject_FromVoidPtr(widget, NULL))); PyW_ShowCbErr(S_ON_CLOSE); } _this->unhook(); @@ -53,8 +53,8 @@ private: void unhook() { - unhook_from_notification_point(HT_UI, s_callback, this); - form = NULL; + idapython_unhook_from_notification_point(HT_UI, s_callback, this); + widget = NULL; // Call DECREF at last, since it may trigger __del__ PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -62,24 +62,24 @@ private: } public: - plgform_t(): form(NULL) + plgform_t(): widget(NULL) { } bool show( - PyObject *obj, - const char *caption, - int options) + PyObject *obj, + const char *caption, + int options) { // Already displayed? - TForm *f = find_tform(caption); + TWidget *f = find_widget(caption); if ( f != NULL ) { // Our form? - if ( f == form ) + if ( f == widget ) { // Switch to it - switchto_tform(form, true); + activate_widget(widget, true); return true; } // Fail to create @@ -87,30 +87,27 @@ public: } // Create a form - form = create_tform(caption, NULL); - if ( form == NULL ) + widget = create_empty_widget(caption); + if ( widget == NULL ) return false; - if ( !hook_to_notification_point(HT_UI, s_callback, this) ) + if ( !idapython_hook_to_notification_point(HT_UI, s_callback, this) ) { - form = NULL; + widget = NULL; return false; } py_obj = borref_t(obj); - if ( is_idaq() ) - options |= FORM_QWIDGET; - - this->form = form; - open_tform(form, options); + this->widget = widget; + display_widget(widget, options); return true; } void close(int options = 0) { - if ( form != NULL ) - close_tform(form, options); + if ( widget != NULL ) + close_widget(widget, options); } static PyObject *create() @@ -135,18 +132,18 @@ static PyObject *plgform_new() } static bool plgform_show( - PyObject *py_link, - PyObject *py_obj, - const char *caption, - int options = FORM_TAB|FORM_MENU|FORM_RESTORE) + PyObject *py_link, + PyObject *py_obj, + const char *caption, + int options = WOPN_TAB|WOPN_MENU|WOPN_RESTORE) { DECL_PLGFORM; return plgform->show(py_obj, caption, options); } static void plgform_close( - PyObject *py_link, - int options) + PyObject *py_link, + int options) { DECL_PLGFORM; plgform->close(options); diff --git a/pywraps/py_kernwin_plgform.py b/pywraps/py_kernwin_plgform.py index a3d070b..8237655 100644 --- a/pywraps/py_kernwin_plgform.py +++ b/pywraps/py_kernwin_plgform.py @@ -7,19 +7,19 @@ class PluginForm(object): This form can be used to host additional controls. Please check the PyQt example. """ - FORM_MDI = 0x01 + WOPN_MDI = 0x01 """start by default as MDI (obsolete)""" - FORM_TAB = 0x02 + WOPN_TAB = 0x02 """attached by default to a tab""" - FORM_RESTORE = 0x04 + WOPN_RESTORE = 0x04 """restore state from desktop config""" - FORM_ONTOP = 0x08 + WOPN_ONTOP = 0x08 """form should be "ontop""" - FORM_MENU = 0x10 + WOPN_MENU = 0x10 """form must be listed in the windows menu (automatically set for all plugins)""" - FORM_CENTERED = 0x20 + WOPN_CENTERED = 0x20 """form will be centered on the screen""" - FORM_PERSIST = 0x40 + WOPN_PERSIST = 0x40 """form will persist until explicitly closed with Close()""" @@ -32,19 +32,19 @@ class PluginForm(object): def Show(self, caption, options = 0): """ - Creates the form if not was not created or brings to front if it was already created + Creates the form if not was not created or brings to front if it was already created @param caption: The form caption - @param options: One of PluginForm.FORM_ constants + @param options: One of PluginForm.WOPN_ constants """ - options |= PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE + options |= PluginForm.WOPN_TAB|PluginForm.WOPN_MENU|PluginForm.WOPN_RESTORE return _ida_kernwin.plgform_show(self.__clink__, self, caption, options) @staticmethod def FormToPyQtWidget(form, ctx = sys.modules['__main__']): """ - Use this method to convert a TForm* to a QWidget to be used by PyQt + Use this method to convert a TWidget* to a QWidget to be used by PyQt @param ctx: Context. Reference to a module that already imported SIP and QtGui modules """ @@ -64,7 +64,7 @@ class PluginForm(object): @staticmethod def FormToPySideWidget(form, ctx = sys.modules['__main__']): """ - Use this method to convert a TForm* to a QWidget to be used by PySide + Use this method to convert a TWidget* to a QWidget to be used by PySide @param ctx: Context. Reference to a module that already imported QtGui module """ @@ -107,24 +107,38 @@ class PluginForm(object): """ Closes the form. - @param options: Close options (FORM_SAVE, FORM_NO_CONTEXT, ...) + @param options: Close options (WCLS_SAVE, WCLS_NO_CONTEXT, ...) @return: None """ return _ida_kernwin.plgform_close(self.__clink__, options) - FORM_SAVE = 0x1 + WCLS_SAVE = 0x1 """Save state in desktop config""" - FORM_NO_CONTEXT = 0x2 + WCLS_NO_CONTEXT = 0x2 """Don't change the current context (useful for toolbars)""" - FORM_DONT_SAVE_SIZE = 0x4 + WCLS_DONT_SAVE_SIZE = 0x4 """Don't save size of the window""" - FORM_CLOSE_LATER = 0x8 + WCLS_CLOSE_LATER = 0x8 """This flag should be used when Close() is called from an event handler""" # plg = PluginForm() plg.Show("This is it") + +# +PluginForm.FORM_MDI = PluginForm.WOPN_MDI +PluginForm.FORM_TAB = PluginForm.WOPN_TAB +PluginForm.FORM_RESTORE = PluginForm.WOPN_RESTORE +PluginForm.FORM_ONTOP = PluginForm.WOPN_ONTOP +PluginForm.FORM_MENU = PluginForm.WOPN_MENU +PluginForm.FORM_CENTERED = PluginForm.WOPN_CENTERED +PluginForm.FORM_PERSIST = PluginForm.WOPN_PERSIST +PluginForm.FORM_SAVE = PluginForm.WCLS_SAVE +PluginForm.FORM_NO_CONTEXT = PluginForm.WCLS_NO_CONTEXT +PluginForm.FORM_DONT_SAVE_SIZE = PluginForm.WCLS_DONT_SAVE_SIZE +PluginForm.FORM_CLOSE_LATER = PluginForm.WCLS_CLOSE_LATER +# diff --git a/pywraps/py_kernwin_viewhooks.hpp b/pywraps/py_kernwin_viewhooks.hpp new file mode 100644 index 0000000..a2df757 --- /dev/null +++ b/pywraps/py_kernwin_viewhooks.hpp @@ -0,0 +1,51 @@ + +// + +//--------------------------------------------------------------------------- +// View hooks +//--------------------------------------------------------------------------- +ssize_t idaapi View_Callback(void *ud, int notification_code, va_list va); +class View_Hooks +{ +public: + virtual ~View_Hooks() { unhook(); } + + 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); + } + + // hookgenVIEW:methods +}; +// + + +// +//--------------------------------------------------------------------------- +ssize_t idaapi View_Callback(void *ud, int notification_code, va_list va) +{ + // This hook gets called from the kernel. Ensure we hold the GIL. + PYW_GIL_GET; + class View_Hooks *proxy = (class View_Hooks *)ud; + int 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; +} +// diff --git a/pywraps/py_kernwin_viewhooks.py b/pywraps/py_kernwin_viewhooks.py new file mode 100644 index 0000000..6378a4b --- /dev/null +++ b/pywraps/py_kernwin_viewhooks.py @@ -0,0 +1,214 @@ +# +# ----------------------------------------------------------------------- +# CustomIDAMemo +# ----------------------------------------------------------------------- +class CustomIDAMemo(View_Hooks): + def __init__(self): + View_Hooks.__init__(self) + + def _graph_item_tuple(self, ve): + item = None + if ve.rtype in [TCCRT_GRAPH, TCCRT_PROXIMITY]: + item = ve.location.item + if item is not None: + if item.is_node: + return (item.node,) + else: + return (item.elp.e.src, item.elp.e.dst) + else: + return () + + @staticmethod + def _dummy_cb(*args): + pass + + def _get_cb(self, view, cb_name): + cb = CustomIDAMemo._dummy_cb + if view == self.GetWidget(): + cb = getattr(self, cb_name, cb) + return cb + + def _get_cb_arity(self, cb): + from inspect import getargspec + return len(getargspec(cb).args) + + def view_activated(self, view): + return self._get_cb(view, "OnViewActivated")() + + def view_deactivated(self, view): + return self._get_cb(view, "OnViewDeactivated")() + + def view_keydown(self, view, key, state): + return self._get_cb(view, "OnViewKeydown")(key, state) + + def view_click(self, view, ve): + cb = self._get_cb(view, "OnViewClick") + if cb != CustomIDAMemo._dummy_cb: + arity = self._get_cb_arity(cb) + args = [ve.x, ve.y, ve.state] + if arity >= 5: + args.append(ve.button) + if arity >= 6: + args.append(ve.renderer_pos) + return cb(*tuple(args)) + + def view_dblclick(self, view, ve): + cb = self._get_cb(view, "OnViewDblclick") + if cb != CustomIDAMemo._dummy_cb: + arity = self._get_cb_arity(cb) + args = [ve.x, ve.y, ve.state] + if arity >= 5: + args.append(ve.renderer_pos) + return cb(*tuple(args)) + + def view_curpos(self, view, *args): + return self._get_cb(view, "OnViewCurpos")() + + def view_close(self, view, *args): + rc = self._get_cb(view, "OnClose")() + if view == self.GetWidget(): + ida_idaapi.pycim_view_close(self) + return rc + + def view_switched(self, view, rt): + return self._get_cb(view, "OnViewSwitched")(rt) + + def view_mouse_over(self, view, ve): + cb = self._get_cb(view, "OnViewMouseOver") + if cb != CustomIDAMemo._dummy_cb: + arity = self._get_cb_arity(cb) + gitpl = self._graph_item_tuple(ve) + args = [ve.x, ve.y, ve.state, len(gitpl), gitpl] + if arity >= 7: + args.append(ve.renderer_pos) + return cb(*tuple(args)) + + def view_loc_changed(self, view, now, was): + return self._get_cb(view, "OnViewLocationChanged")(now, was) + + def view_mouse_moved(self, view, ve): + cb = self._get_cb(view, "OnViewMouseMoved") + if cb != CustomIDAMemo._dummy_cb: + gitpl = self._graph_item_tuple(ve) + return cb(ve.x, ve.y, ve.state, len(gitpl), gitpl, ve.renderer_pos) + + # End of hooks->wrapper trampolines + + + def Refresh(self): + """ + Refreshes the view. This causes the OnRefresh() to be called + """ + ida_idaapi.pygc_refresh(self) + + def GetCurrentRendererType(self): + return ida_idaapi.pygc_get_current_renderer_type(self) + + def SetCurrentRendererType(self, rtype): + """ + Set the current view's renderer. + + @param rtype: The renderer type. Should be one of the idaapi.TCCRT_* values. + """ + ida_idaapi.pygc_set_current_renderer_type(self, rtype) + + def SetNodeInfo(self, node_index, node_info, flags): + """ + Set the properties for the given node. + + Example usage (set second nodes's bg color to red): + inst = ... + p = idaapi.node_info_t() + p.bg_color = 0x00ff0000 + inst.SetNodeInfo(1, p, idaapi.NIF_BG_COLOR) + + @param node_index: The node index. + @param node_info: An idaapi.node_info_t instance. + @param flags: An OR'ed value of NIF_* values. + """ + ida_idaapi.pygc_set_node_info(self, node_index, node_info, flags) + + def SetNodesInfos(self, values): + """ + Set the properties for the given nodes. + + Example usage (set first three nodes's bg color to purple): + inst = ... + p = idaapi.node_info_t() + p.bg_color = 0x00ff00ff + inst.SetNodesInfos({0 : p, 1 : p, 2 : p}) + + @param values: A dictionary of 'int -> node_info_t' objects. + """ + ida_idaapi.pygc_set_nodes_infos(self, values) + + def GetNodeInfo(self, node): + """ + Get the properties for the given node. + + @param node: The index of the node. + @return: A tuple (bg_color, frame_color, ea, text), or None. + """ + return ida_idaapi.pygc_get_node_info(self, node) + + def DelNodesInfos(self, *nodes): + """ + Delete the properties for the given node(s). + + @param nodes: A list of node IDs + """ + return ida_idaapi.pygc_del_nodes_infos(self, nodes) + + def CreateGroups(self, groups_infos): + """ + Send a request to modify the graph by creating a + (set of) group(s), and perform an animation. + + Each object in the 'groups_infos' list must be of the format: + { + "nodes" : [, , , ...] # The list of nodes to group + "text" : # The synthetic text for that group + } + + @param groups_infos: A list of objects that describe those groups. + @return: A [, , ...] list of group nodes, or None (failure). + """ + return ida_idaapi.pygc_create_groups(self, groups_infos) + + def DeleteGroups(self, groups, new_current = -1): + """ + Send a request to delete the specified groups in the graph, + and perform an animation. + + @param groups: A list of group node numbers. + @param new_current: A node to focus on after the groups have been deleted + @return: True on success, False otherwise. + """ + return ida_idaapi.pygc_delete_groups(self, groups, new_current) + + def SetGroupsVisibility(self, groups, expand, new_current = -1): + """ + Send a request to expand/collapse the specified groups in the graph, + and perform an animation. + + @param groups: A list of group node numbers. + @param expand: True to expand the group, False otherwise. + @param new_current: A node to focus on after the groups have been expanded/collapsed. + @return: True on success, False otherwise. + """ + return ida_idaapi.pygc_set_groups_visibility(self, groups, expand, new_current) + + def GetWidget(self): + """ + Return the TWidget underlying this view. + + @return: The TWidget underlying this view, or None. + """ + return ida_idaapi.pycim_get_widget(self) + +# ---------------------------------------------------------------------- +# bw-compat/deprecated. You shouldn't rely on this in new code +import ida_idaapi +ida_idaapi.CustomIDAMemo = CustomIDAMemo + +# diff --git a/pywraps/py_lines.hpp b/pywraps/py_lines.hpp index 21ae2a1..f7a930f 100644 --- a/pywraps/py_lines.hpp +++ b/pywraps/py_lines.hpp @@ -5,19 +5,18 @@ //------------------------------------------------------------------------ static PyObject *py_get_user_defined_prefix = NULL; static void idaapi s_py_get_user_defined_prefix( - ea_t ea, - int lnnum, - int indent, - const char *line, - char *buf, - size_t bufsize) + qstring *buf, + ea_t ea, + int lnnum, + int indent, + const char *line) { PYW_GIL_GET; newref_t py_ret( PyObject_CallFunction( py_get_user_defined_prefix, - PY_FMT64 "iis" PY_FMT64, - ea, lnnum, indent, line, bufsize)); + PY_BV_EA "iis" PY_BV_SZ, + bvea_t(ea), lnnum, indent, line)); // Error? Display it // No error? Copy the buffer @@ -27,9 +26,8 @@ static void idaapi s_py_get_user_defined_prefix( char *py_str; if ( PyString_AsStringAndSize(py_ret.o, &py_str, &py_len) != -1 ) { - memcpy(buf, py_str, qmin(bufsize, py_len)); - if ( py_len < bufsize ) - buf[py_len] = '\0'; + buf->qclear(); + buf->append(py_str, py_len); } } } @@ -56,7 +54,6 @@ def set_user_defined_prefix(width, callback): indent and is used for instruction itself. see explanations for printf_line() line - the line to be generated. the line usually contains color tags this argument can be examined to decide whether to generated the prefix - bufsize- the maximum allowed size of the output buffer It returns a buffer of size < bufsize In order to remove the callback before unloading the plugin, specify the width = 0 or the callback = None @@ -103,9 +100,7 @@ def tag_remove(colstr): """ Remove color escape sequences from a string @param colstr: the colored string with embedded tags - @return: - None on failure - or a new string w/o the tags + @return: a new string w/o the tags """ pass # @@ -113,41 +108,18 @@ def tag_remove(colstr): PyObject *py_tag_remove(const char *instr) { PYW_GIL_CHECK_LOCKED_SCOPE(); - size_t sz = strlen(instr); - // Can't call tag_remove() with a size of 0; debug builds will INTERR 1270 - if ( sz > 0 ) - { - char *buf = new char[sz + 5]; - if ( buf == NULL ) - Py_RETURN_NONE; - - ssize_t r = tag_remove(instr, buf, sz); - PyObject *res; - if ( r < 0 ) - { - Py_INCREF(Py_None); - res = Py_None; - } - else - { - res = PyString_FromString(buf); - } - delete [] buf; - return res; - } - else - { - return PyString_FromString(""); - } + qstring qbuf; + tag_remove(&qbuf, instr); + return PyString_FromString(qbuf.c_str()); } //------------------------------------------------------------------------- PyObject *py_tag_addr(ea_t ea) { - char buf[100]; - tag_addr(buf, buf + sizeof(buf), ea); + qstring tag; + tag_addr(&tag, ea); PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyString_FromString(buf); + return PyString_FromString(tag.begin()); } //------------------------------------------------------------------------- @@ -187,35 +159,32 @@ def generate_disassembly(ea, max_lines, as_stack, notags): # */ PyObject *py_generate_disassembly( - ea_t ea, - int max_lines, - bool as_stack, - bool notags) + ea_t ea, + int max_lines, + bool as_stack, + bool notags) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( max_lines <= 0 ) Py_RETURN_NONE; qstring qbuf; - char **lines = new char *[max_lines]; + qstrvec_t lines; int lnnum; - int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack); + int nlines = generate_disassembly(&lines, &lnnum, ea, max_lines, as_stack); newref_t py_tuple(PyTuple_New(nlines)); for ( int i=0; i < nlines; i++ ) { - const char *s = lines[i]; - size_t line_len = strlen(s); + const qstring &l = lines[i]; + const char *s = l.c_str(); if ( notags ) { - qbuf.resize(line_len+5); - tag_remove(s, &qbuf[0], line_len); - s = (const char *)&qbuf[0]; + tag_remove(&qbuf, l); + s = qbuf.c_str(); } PyTuple_SetItem(py_tuple.o, i, PyString_FromString(s)); - qfree(lines[i]); } - delete [] lines; return Py_BuildValue("(iO)", lnnum, py_tuple.o); } // diff --git a/pywraps/py_lines.py b/pywraps/py_lines.py index 158c07c..499c914 100644 --- a/pywraps/py_lines.py +++ b/pywraps/py_lines.py @@ -33,3 +33,9 @@ def COLSTR(str, tag): return SCOLOR_ON + tag + str + SCOLOR_OFF + tag # + +# +COLOR_UTF8=COLOR_ADDR+10 # old value of COLOR_UTF8; shouldn't trigger anything +add_long_cmt=add_extra_cmt +describe=add_extra_line +# diff --git a/pywraps/py_loader.hpp b/pywraps/py_loader.hpp index 99493b9..cc970ea 100644 --- a/pywraps/py_loader.hpp +++ b/pywraps/py_loader.hpp @@ -21,7 +21,7 @@ def mem2base(mem, ea, fpos): pass # */ -static int py_mem2base(PyObject *py_mem, ea_t ea, long fpos = -1) +static int py_mem2base(PyObject *py_mem, ea_t ea, qoff64_t fpos = -1) { Py_ssize_t len; char *buf; diff --git a/pywraps/py_loader.py b/pywraps/py_loader.py new file mode 100644 index 0000000..00298b1 --- /dev/null +++ b/pywraps/py_loader.py @@ -0,0 +1,10 @@ + +# +NEF_TIGHT=0 +@bc695redef +def save_database(outfile, flags=0): + if isinstance(flags, bool): + flags = DBFL_KILL if flags else 0 + return _ida_loader.save_database(outfile, flags) +save_database_ex=save_database +# diff --git a/pywraps/py_moves.hpp b/pywraps/py_moves.hpp new file mode 100644 index 0000000..098974c --- /dev/null +++ b/pywraps/py_moves.hpp @@ -0,0 +1,5 @@ +#ifndef __PYMOVES__ +#define __PYMOVES__ +// +// +#endif diff --git a/pywraps/py_nalt.hpp b/pywraps/py_nalt.hpp index 28744be..49b4b49 100644 --- a/pywraps/py_nalt.hpp +++ b/pywraps/py_nalt.hpp @@ -18,7 +18,7 @@ static int idaapi py_import_enum_cb( { // If no name, try to get the name associated with the 'ea'. It may be coming from IDS qstring name_buf; - if ( name == NULL && get_true_name(&name_buf, ea) > 0 ) + if ( name == NULL && get_name(&name_buf, ea) > 0 ) name = name_buf.begin(); PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -28,8 +28,8 @@ static int idaapi py_import_enum_cb( else py_name = newref_t(PyString_FromString(name)); - newref_t py_ord(Py_BuildValue(PY_FMT64, pyul_t(ord))); - newref_t py_ea(Py_BuildValue(PY_FMT64, pyul_t(ea))); + newref_t py_ord(Py_BuildValue(PY_BV_UVAL, bvuval_t(ord))); + newref_t py_ea(Py_BuildValue(PY_BV_EA, bvea_t(ea))); newref_t py_result( PyObject_CallFunctionObjArgs( (PyObject *)param, @@ -57,31 +57,31 @@ def get_import_module_name(path, fname, callback): static PyObject *py_get_import_module_name(int mod_index) { PYW_GIL_CHECK_LOCKED_SCOPE(); - char buf[MAXSTR]; - if ( !get_import_module_name(mod_index, buf, sizeof(buf)) ) + qstring qbuf; + if ( !get_import_module_name(&qbuf, mod_index) ) Py_RETURN_NONE; - return PyString_FromString(buf); + return PyString_FromStringAndSize(qbuf.begin(), qbuf.length()); } //------------------------------------------------------------------------- /* # -def get_switch_info_ex(ea): +def get_switch_info(ea): """ - Returns the a switch_info_ex_t structure containing the information about the switch. + Returns the a switch_info_t structure containing the information about the switch. Please refer to the SDK sample 'uiswitch' - @return: None or switch_info_ex_t instance + @return: None or switch_info_t instance """ pass # */ -PyObject *py_get_switch_info_ex(ea_t ea) +PyObject *py_get_switch_info(ea_t ea) { - switch_info_ex_t *ex = new switch_info_ex_t(); + switch_info_t *ex = new switch_info_t(); ref_t py_obj; PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0 + if ( ::get_switch_info(ex, ea) <= 0 || (py_obj = create_linked_class_instance(S_IDA_NALT_MODNAME, S_PY_SWIEX_CLSNAME, ex)) == NULL ) { delete ex; @@ -94,7 +94,7 @@ PyObject *py_get_switch_info_ex(ea_t ea) //------------------------------------------------------------------------- /* # -def set_switch_info_ex(ea, switch_info_ex): +def set_switch_info(ea, switch_info): """ Saves the switch information in the database Please refer to the SDK sample 'uiswitch' @@ -103,29 +103,29 @@ def set_switch_info_ex(ea, switch_info_ex): pass # */ -bool py_set_switch_info_ex(ea_t ea, PyObject *py_swi) +bool py_set_switch_info(ea_t ea, PyObject *py_swi) { - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); + switch_info_t *swi = switch_info_t_get_clink(py_swi); if ( swi == NULL ) return false; - set_switch_info_ex(ea, swi); + set_switch_info(ea, *swi); return true; } //------------------------------------------------------------------------- /* # -def del_switch_info_ex(ea): +def del_switch_info(ea): """ Deletes stored switch information """ pass # */ -void py_del_switch_info_ex(ea_t ea) +void py_del_switch_info(ea_t ea) { - del_switch_info_ex(ea); + del_switch_info(ea); } //------------------------------------------------------------------------- @@ -152,28 +152,28 @@ static int py_enum_import_names(int mod_index, PyObject *py_cb) } //------------------------------------------------------------------------- -static PyObject *switch_info_ex_t_create() +static PyObject *switch_info_t_create() { - switch_info_ex_t *inst = new switch_info_ex_t(); + switch_info_t *inst = new switch_info_t(); PYW_GIL_CHECK_LOCKED_SCOPE(); return PyCObject_FromVoidPtr(inst, NULL); } //--------------------------------------------------------------------------- -static bool switch_info_ex_t_destroy(PyObject *py_obj) +static bool switch_info_t_destroy(PyObject *py_obj) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyCObject_Check(py_obj) ) return false; - switch_info_ex_t *inst = (switch_info_ex_t *) PyCObject_AsVoidPtr(py_obj); + switch_info_t *inst = (switch_info_t *) PyCObject_AsVoidPtr(py_obj); delete inst; return true; } -static bool switch_info_ex_t_assign(PyObject *self, PyObject *other) +static bool switch_info_t_assign(PyObject *self, PyObject *other) { - switch_info_ex_t *lhs = switch_info_ex_t_get_clink(self); - switch_info_ex_t *rhs = switch_info_ex_t_get_clink(other); + switch_info_t *lhs = switch_info_t_get_clink(self); + switch_info_t *rhs = switch_info_t_get_clink(other); if ( lhs == NULL || rhs == NULL ) return false; @@ -185,236 +185,219 @@ static bool switch_info_ex_t_assign(PyObject *self, PyObject *other) // Auto generated - begin // -static PyObject *switch_info_ex_t_get_regdtyp(PyObject *self) +static PyObject *switch_info_t_get_regdtype(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue("b", (char)link->regdtyp); + return Py_BuildValue("b", (char)link->regdtype); } -static void switch_info_ex_t_set_regdtyp(PyObject *self, PyObject *value) +static void switch_info_t_set_regdtype(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); - link->regdtyp = (char)PyInt_AsLong(value); + link->regdtype = (char)PyInt_AsLong(value); } -static PyObject *switch_info_ex_t_get_flags2(PyObject *self) +static PyObject *switch_info_t_get_flags(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue("i", link->flags2); + return Py_BuildValue("i", link->flags); } -static void switch_info_ex_t_set_flags2(PyObject *self, PyObject *value) +static void switch_info_t_set_flags(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); - link->flags2 = (int)PyInt_AsLong(value); + link->flags = (uint32)PyInt_AsLong(value); } -static PyObject *switch_info_ex_t_get_jcases(PyObject *self) +static PyObject *switch_info_t_get_jcases(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue("i", link->jcases); } -static void switch_info_ex_t_set_jcases(PyObject *self, PyObject *value) +static void switch_info_t_set_jcases(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); link->jcases = (int)PyInt_AsLong(value); } -static PyObject *switch_info_ex_t_get_regnum(PyObject *self) +static PyObject *switch_info_t_get_regnum(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue("i", (int)link->regnum); } -static void switch_info_ex_t_set_regnum(PyObject *self, PyObject *value) +static void switch_info_t_set_regnum(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); link->regnum = (int)PyInt_AsLong(value); } -static PyObject *switch_info_ex_t_get_flags(PyObject *self) +static PyObject *switch_info_t_get_ncases(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", (ushort)link->flags); -} -static void switch_info_ex_t_set_flags(PyObject *self, PyObject *value) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); - if ( link == NULL ) - return; - PYW_GIL_CHECK_LOCKED_SCOPE(); - link->flags = (uint16)PyInt_AsLong(value); -} - -static PyObject *switch_info_ex_t_get_ncases(PyObject *self) -{ - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue("H", (uint16)link->ncases); } -static void switch_info_ex_t_set_ncases(PyObject *self, PyObject *value) +static void switch_info_t_set_ncases(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); link->ncases = (ushort)PyInt_AsLong(value); } -static PyObject *switch_info_ex_t_get_defjump(PyObject *self) +static PyObject *switch_info_t_get_defjump(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->defjump); + return Py_BuildValue(PY_BV_EA, (bvea_t)link->defjump); } -static void switch_info_ex_t_set_defjump(PyObject *self, PyObject *value) +static void switch_info_t_set_defjump(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); uint64 v(0); PyW_GetNumber(value, &v); - link->defjump = (pyul_t)v; + link->defjump = ea_t(v); } -static PyObject *switch_info_ex_t_get_jumps(PyObject *self) +static PyObject *switch_info_t_get_jumps(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->jumps); + return Py_BuildValue(PY_BV_EA, (bvea_t)link->jumps); } -static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value) +static void switch_info_t_set_jumps(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; PYW_GIL_CHECK_LOCKED_SCOPE(); uint64 v(0); PyW_GetNumber(value, &v); - link->jumps = (pyul_t)v; + link->jumps = ea_t(v); } -static PyObject *switch_info_ex_t_get_elbase(PyObject *self) +static PyObject *switch_info_t_get_elbase(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->elbase); + return Py_BuildValue(PY_BV_EA, (bvea_t)link->elbase); } -static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value) +static void switch_info_t_set_elbase(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; uint64 v(0); PYW_GIL_CHECK_LOCKED_SCOPE(); PyW_GetNumber(value, &v); - link->elbase = (pyul_t)v; + link->elbase = ea_t(v); } -static PyObject *switch_info_ex_t_get_startea(PyObject *self) +static PyObject *switch_info_t_get_startea(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->startea); + return Py_BuildValue(PY_BV_EA, (bvea_t)link->startea); } -static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value) +static void switch_info_t_set_startea(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; uint64 v(0); PYW_GIL_CHECK_LOCKED_SCOPE(); PyW_GetNumber(value, &v); - link->startea = (pyul_t)v; + link->startea = ea_t(v); } -static PyObject *switch_info_ex_t_get_custom(PyObject *self) +static PyObject *switch_info_t_get_custom(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->custom); + return Py_BuildValue(PY_BV_UVAL, (bvuval_t)link->custom); } -static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value) +static void switch_info_t_set_custom(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; uint64 v(0); PYW_GIL_CHECK_LOCKED_SCOPE(); PyW_GetNumber(value, &v); - link->custom = (pyul_t)v; + link->custom = uval_t(v); } -static PyObject *switch_info_ex_t_get_ind_lowcase(PyObject *self) +static PyObject *switch_info_t_get_ind_lowcase(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->ind_lowcase); + return Py_BuildValue(PY_BV_SVAL, (bvsval_t)link->ind_lowcase); } -static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value) +static void switch_info_t_set_ind_lowcase(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; uint64 v(0); PYW_GIL_CHECK_LOCKED_SCOPE(); PyW_GetNumber(value, &v); - link->ind_lowcase = (pyul_t)v; + link->ind_lowcase = sval_t(v); } -static PyObject *switch_info_ex_t_get_values_lowcase(PyObject *self) +static PyObject *switch_info_t_get_values_lowcase(PyObject *self) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( link == NULL ) Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->values); + return Py_BuildValue(PY_BV_EA, (bvea_t)link->values); } -static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value) +static void switch_info_t_set_values_lowcase(PyObject *self, PyObject *value) { - switch_info_ex_t *link = switch_info_ex_t_get_clink(self); + switch_info_t *link = switch_info_t_get_clink(self); if ( link == NULL ) return; uint64 v(0); PYW_GIL_CHECK_LOCKED_SCOPE(); PyW_GetNumber(value, &v); - link->values = (pyul_t)v; + link->values = ea_t(v); } // diff --git a/pywraps/py_nalt.py b/pywraps/py_nalt.py index 08e323b..b28f7ec 100644 --- a/pywraps/py_nalt.py +++ b/pywraps/py_nalt.py @@ -3,23 +3,36 @@ import _ida_idaapi SWI_SPARSE = 0x1 """sparse switch ( value table present ) otherwise lowcase present""" + SWI_V32 = 0x2 """32-bit values in table""" + SWI_J32 = 0x4 """32-bit jump offsets""" + SWI_VSPLIT = 0x8 """value table is split (only for 32-bit values)""" + SWI_DEFAULT = 0x10 """default case is present""" -SWI_END_IN_TBL = 0x20 -"""switchend in table (default entry)""" + +SWI_DEF_IN_TBL = 0x20 +"""default case is an entry in the jump table. +This flag is only applicable in the case of a sparse +nonindirect switch (i.e. a switch with a values table). + == + 1. +The default case entry is the last one in the table +(or the first one in the case of an inversed jump table).""" + SWI_JMP_INV = 0x40 """jumptable is inversed (last entry is for first entry in values table)""" + SWI_SHIFT_MASK = 0x180 """use formula (element*shift + elbase) to find jump targets""" SWI_ELBASE = 0x200 """elbase is present (if not and shift!=0, endof(jumpea) is used)""" + SWI_JSIZE = 0x400 """jump offset expansion bit""" @@ -33,35 +46,48 @@ SWI_SIGNED = 0x2000 """jump table entries are signed""" SWI_CUSTOM = 0x4000 -"""custom jump table - ph.create_switch_xrefs will be called to create code xrefs for the table. it must return 2. custom jump table must be created by the module""" +"""custom jump table. +\ph{create_switch_xrefs} will be called to create code xrefs for the +table. Custom jump table must be created by the module +(see also #SWI_STDTBL)""" -SWI_EXTENDED = 0x8000 -"""this is switch_info_ex_t""" - -SWI2_INDIRECT = 0x0001 +SWI_INDIRECT = 0x00010000 """value table elements are used as indexes into the jump table""" -SWI2_SUBTRACT = 0x0002 + +SWI_SUBTRACT = 0x00020000 """table values are subtracted from the elbase instead of being addded""" +SWI_HXNOLOWCASE = 0x00040000 +"""lowcase value should not be used by the decompiler (internal flag)""" + +SWI_STDTBL = 0x00080000 +"""custom jump table with standard table formatting. +ATM IDA doesn't use SWI_CUSTOM for switches with standard +table formatting. So this flag can be considered as obsolete.""" + +SWI_DEFRET = 0x00100000 +"""return in the default case (defjump==BADADDR)""" + # -------------------------------------------------------------------------- -class switch_info_ex_t(ida_idaapi.py_clinked_object_t): +class switch_info_t(ida_idaapi.py_clinked_object_t): def __init__(self, lnk = None): ida_idaapi.py_clinked_object_t.__init__(self, lnk) + self.bc695_api = False def _create_clink(self): - return _ida_nalt.switch_info_ex_t_create() + return _ida_nalt.switch_info_t_create() def _del_clink(self, lnk): - return _ida_nalt.switch_info_ex_t_destroy(lnk) + return _ida_nalt.switch_info_t_destroy(lnk) def assign(self, other): - return _ida_nalt.switch_info_ex_t_assign(self, other) + return _ida_nalt.switch_info_t_assign(self, other) def is_indirect(self): - return (self.flags & SWI_EXTENDED) != 0 and (self.flags2 & SWI2_INDIRECT) != 0 + return (self.flags & SWI_INDIRECT) != 0 def is_subtract(self): - return (self.flags & SWI_EXTENDED) != 0 and (self.flags2 & SWI2_SUBTRACT) != 0 + return (self.flags & SWI_SUBTRACT) != 0 def get_jtable_size(self): return self.jcases if self.is_indirect() else self.ncases @@ -71,7 +97,7 @@ class switch_info_ex_t(ida_idaapi.py_clinked_object_t): def set_expr(self, r, dt): self.regnum = r - self.regdtyp = dt + self.regdtype = dt def get_shift(self): return (self.flags & SWI_SHIFT_MASK) >> 7 @@ -113,67 +139,62 @@ class switch_info_ex_t(ida_idaapi.py_clinked_object_t): # # Autogenerated # - def __get_regdtyp__(self): - return _ida_nalt.switch_info_ex_t_get_regdtyp(self) - def __set_regdtyp__(self, v): - _ida_nalt.switch_info_ex_t_set_regdtyp(self, v) - def __get_flags2__(self): - return _ida_nalt.switch_info_ex_t_get_flags2(self) - def __set_flags2__(self, v): - _ida_nalt.switch_info_ex_t_set_flags2(self, v) + def __get_regdtype__(self): + return _ida_nalt.switch_info_t_get_regdtype(self) + def __set_regdtype__(self, v): + _ida_nalt.switch_info_t_set_regdtype(self, v) def __get_jcases__(self): - return _ida_nalt.switch_info_ex_t_get_jcases(self) + return _ida_nalt.switch_info_t_get_jcases(self) def __set_jcases__(self, v): - _ida_nalt.switch_info_ex_t_set_jcases(self, v) + _ida_nalt.switch_info_t_set_jcases(self, v) def __get_regnum__(self): - return _ida_nalt.switch_info_ex_t_get_regnum(self) + return _ida_nalt.switch_info_t_get_regnum(self) def __set_regnum__(self, v): - _ida_nalt.switch_info_ex_t_set_regnum(self, v) + _ida_nalt.switch_info_t_set_regnum(self, v) def __get_flags__(self): - return _ida_nalt.switch_info_ex_t_get_flags(self) + return _ida_nalt.switch_info_t_get_flags(self) def __set_flags__(self, v): - _ida_nalt.switch_info_ex_t_set_flags(self, v) + _ida_nalt.switch_info_t_set_flags(self, v) def __get_ncases__(self): - return _ida_nalt.switch_info_ex_t_get_ncases(self) + return _ida_nalt.switch_info_t_get_ncases(self) def __set_ncases__(self, v): - _ida_nalt.switch_info_ex_t_set_ncases(self, v) + _ida_nalt.switch_info_t_set_ncases(self, v) def __get_defjump__(self): - return _ida_nalt.switch_info_ex_t_get_defjump(self) + return _ida_nalt.switch_info_t_get_defjump(self) def __set_defjump__(self, v): - _ida_nalt.switch_info_ex_t_set_defjump(self, v) + _ida_nalt.switch_info_t_set_defjump(self, v) def __get_jumps__(self): - return _ida_nalt.switch_info_ex_t_get_jumps(self) + return _ida_nalt.switch_info_t_get_jumps(self) def __set_jumps__(self, v): - _ida_nalt.switch_info_ex_t_set_jumps(self, v) + _ida_nalt.switch_info_t_set_jumps(self, v) def __get_elbase__(self): - return _ida_nalt.switch_info_ex_t_get_elbase(self) + return _ida_nalt.switch_info_t_get_elbase(self) def __set_elbase__(self, v): - _ida_nalt.switch_info_ex_t_set_elbase(self, v) + _ida_nalt.switch_info_t_set_elbase(self, v) def __get_startea__(self): - return _ida_nalt.switch_info_ex_t_get_startea(self) + return _ida_nalt.switch_info_t_get_startea(self) def __set_startea__(self, v): - _ida_nalt.switch_info_ex_t_set_startea(self, v) + _ida_nalt.switch_info_t_set_startea(self, v) def __get_custom__(self): - return _ida_nalt.switch_info_ex_t_get_custom(self) + return _ida_nalt.switch_info_t_get_custom(self) def __set_custom__(self, v): - _ida_nalt.switch_info_ex_t_set_custom(self, v) + _ida_nalt.switch_info_t_set_custom(self, v) def __get_ind_lowcase__(self): - return _ida_nalt.switch_info_ex_t_get_ind_lowcase(self) + return _ida_nalt.switch_info_t_get_ind_lowcase(self) def __set_ind_lowcase__(self, v): - _ida_nalt.switch_info_ex_t_set_ind_lowcase(self, v) + _ida_nalt.switch_info_t_set_ind_lowcase(self, v) def __get_values_lowcase__(self): - return _ida_nalt.switch_info_ex_t_get_values_lowcase(self) + return _ida_nalt.switch_info_t_get_values_lowcase(self) def __set_values_lowcase__(self, v): - _ida_nalt.switch_info_ex_t_set_values_lowcase(self, v) - regdtyp = property(__get_regdtyp__, __set_regdtyp__) - """size of the switch expression register as dtyp""" - flags2 = property(__get_flags2__, __set_flags2__) + _ida_nalt.switch_info_t_set_values_lowcase(self, v) + regdtype = property(__get_regdtype__, __set_regdtype__) + """size of the switch expression register as dtype""" jcases = property(__get_jcases__, __set_jcases__) - """number of entries in the jump table (SWI2_INDIRECT)""" + """number of entries in the jump table (SWI_INDIRECT)""" regnum = property(__get_regnum__, __set_regnum__) """the switch expression as a register number""" flags = property(__get_flags__, __set_flags__) - """the switch expression as a register number""" + """switch info flags""" ncases = property(__get_ncases__, __set_ncases__) """number of cases (excluding default)""" defjump = property(__get_defjump__, __set_defjump__) @@ -191,3 +212,110 @@ class switch_info_ex_t(ida_idaapi.py_clinked_object_t): lowcase = property(__get_values_lowcase__, __set_values_lowcase__) # + +# +ASCSTR_LAST=7 +ASCSTR_LEN2=STRTYPE_LEN2 +ASCSTR_LEN4=STRTYPE_LEN4 +ASCSTR_PASCAL=STRTYPE_PASCAL +ASCSTR_TERMCHR=STRTYPE_TERMCHR +ASCSTR_ULEN2=STRTYPE_LEN2_16 +ASCSTR_ULEN4=STRTYPE_LEN4_16 +ASCSTR_UNICODE=STRTYPE_C_16 +ASCSTR_UTF16=STRTYPE_C_16 +ASCSTR_UTF32=STRTYPE_C_32 +REF_VHIGH=V695_REF_VHIGH +REF_VLOW=V695_REF_VLOW +SWI_END_IN_TBL=SWI_DEF_IN_TBL +SWI_EXTENDED=0x8000 +SWI2_INDIRECT=SWI_INDIRECT >> 16 +SWI2_SUBTRACT=SWI_SUBTRACT >> 16 +import ida_netnode +RIDX_AUTO_PLUGINS=ida_netnode.BADNODE +change_encoding_name=rename_encoding +@bc695redef +def del_tinfo2(ea, n=None): + if n is not None: + return del_op_tinfo(ea, n) + else: + return del_tinfo(ea) +get_encodings_count=get_encoding_qty +def get_op_tinfo(*args): + import ida_typeinf + if isinstance(args[2], ida_typeinf.tinfo_t): # 6.95: ea, n, tinfo_t + ea, n, tif = args + else: # 7.00: tinfo_t, ea, n + tif, ea, n = args + return _ida_nalt.get_op_tinfo(tif, ea, n) +get_op_tinfo2=get_op_tinfo +@bc695redef +def is_unicode(strtype): + return (strtype & STRWIDTH_MASK) > 0 +set_op_tinfo2=set_op_tinfo +set_tinfo2=set_tinfo +switch_info_t.regdtyp = switch_info_t.regdtype +def get_tinfo(*args): + import ida_typeinf + if isinstance(args[1], ida_typeinf.tinfo_t): # 6.95: ea, tinfo_t + ea, tif = args + else: # 7.00: tinfo_t, ea + tif, ea = args + return _ida_nalt.get_tinfo(tif, ea) +get_tinfo2=get_tinfo +def get_refinfo(*args): + if isinstance(args[2], refinfo_t): # 6.95: ea, n, refinfo_t + ea, n, ri = args + else: # 7.00: refinfo_t, ea, n + ri, ea, n = args + return _ida_nalt.get_refinfo(ri, ea, n) + +get_switch_info_ex=get_switch_info +set_switch_info_ex=set_switch_info +del_switch_info_ex=del_switch_info +switch_info_ex_t_assign=switch_info_t_assign +switch_info_ex_t_create=switch_info_t_create +switch_info_ex_t_destroy=switch_info_t_destroy +switch_info_ex_t_get_custom=switch_info_t_get_custom +switch_info_ex_t_get_defjump=switch_info_t_get_defjump +switch_info_ex_t_get_elbase=switch_info_t_get_elbase +switch_info_ex_t_get_flags=switch_info_t_get_flags +switch_info_ex_t_get_ind_lowcase=switch_info_t_get_ind_lowcase +switch_info_ex_t_get_jcases=switch_info_t_get_jcases +switch_info_ex_t_get_jumps=switch_info_t_get_jumps +switch_info_ex_t_get_ncases=switch_info_t_get_ncases +switch_info_ex_t_get_regdtyp=switch_info_t_get_regdtype +switch_info_ex_t_get_regnum=switch_info_t_get_regnum +switch_info_ex_t_get_startea=switch_info_t_get_startea +switch_info_ex_t_get_values_lowcase=switch_info_t_get_values_lowcase +switch_info_ex_t_set_custom=switch_info_t_set_custom +switch_info_ex_t_set_defjump=switch_info_t_set_defjump +switch_info_ex_t_set_elbase=switch_info_t_set_elbase +switch_info_ex_t_set_flags=switch_info_t_set_flags +switch_info_ex_t_set_ind_lowcase=switch_info_t_set_ind_lowcase +switch_info_ex_t_set_jcases=switch_info_t_set_jcases +switch_info_ex_t_set_jumps=switch_info_t_set_jumps +switch_info_ex_t_set_ncases=switch_info_t_set_ncases +switch_info_ex_t_set_regdtyp=switch_info_t_set_regdtype +switch_info_ex_t_set_regnum=switch_info_t_set_regnum +switch_info_ex_t_set_startea=switch_info_t_set_startea +switch_info_ex_t_set_values_lowcase=switch_info_t_set_values_lowcase + +def __switch_info_t_get_flags__(instance): + return switch_info_t.__get_flags__(instance) | SWI_EXTENDED +def __switch_info_t_set_flags__(instance, v): + if instance.bc695_api: + v |= (switch_info_t.__get_flags__(instance) & 0xFFFF0000) + switch_info_t.__set_flags__(instance, v) +switch_info_t.flags = property(__switch_info_t_get_flags__, __switch_info_t_set_flags__) + +def __switch_info_t_get_flags2__(instance): + instance.bc695_api = True + return switch_info_t.__get_flags__(instance) >> 16 +def __switch_info_t_set_flags2__(instance, v): + instance.bc695_api = True + flags = switch_info_t.__get_flags__(instance) + instance.flags = (flags & 0xFFFF) | (v << 16) +switch_info_t.flags2 = property(__switch_info_t_get_flags2__, __switch_info_t_set_flags2__) + +switch_info_ex_t=switch_info_t +# diff --git a/pywraps/py_name.hpp b/pywraps/py_name.hpp index 4da0238..f30469d 100644 --- a/pywraps/py_name.hpp +++ b/pywraps/py_name.hpp @@ -11,7 +11,7 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) ea_name_vec_t names; PYW_GIL_CHECK_LOCKED_SCOPE(); Py_BEGIN_ALLOW_THREADS; - get_debug_names(ea1, ea2, names); + get_debug_names(&names, ea1, ea2); Py_END_ALLOW_THREADS; PyObject *dict = Py_BuildValue("{}"); if ( dict != NULL ) @@ -19,7 +19,7 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2) for ( ea_name_vec_t::iterator it=names.begin(); it != names.end(); ++it ) { PyDict_SetItem(dict, - Py_BuildValue(PY_FMT64, it->ea), + Py_BuildValue(PY_BV_EA, bvea_t(it->ea)), PyString_FromString(it->name.c_str())); } } @@ -33,6 +33,14 @@ inline qstring py_get_ea_name(ea_t ea, int gtn_flags=0) get_ea_name(&out, ea, gtn_flags); return out; } -//------------------------------------------------------------------------ + +//------------------------------------------------------------------------- +PyObject *py_validate_name(const char *name, nametype_t type, int flags=0) +{ + qstring qname(name); + if ( validate_name(&qname, type, flags) ) + return PyString_FromStringAndSize(qname.c_str(), qname.length()); + else + Py_RETURN_NONE; +} // -//------------------------------------------------------------------------ diff --git a/pywraps/py_name.py b/pywraps/py_name.py index 9fbbd8c..a0e7e49 100644 --- a/pywraps/py_name.py +++ b/pywraps/py_name.py @@ -1,6 +1,9 @@ -import bisect # +import _ida_idaapi +import _ida_funcs +import bisect + class NearestName(object): """ @@ -49,6 +52,64 @@ class NearestName(object): raise StopIteration return self._get_item(index) -extract_name = extract_name2 +def calc_gtn_flags(fromaddr, ea): + """ + Calculate flags for get_ea_name() function + + @param fromaddr: the referring address. May be BADADDR. + @param ea: linear address + + @return: flags + """ + gtn_flags = 0 + if fromaddr != _ida_idaapi.BADADDR: + pfn = _ida_funcs.get_func(fromaddr) + if _ida_funcs.func_contains(pfn, ea): + gtn_flags = GN_LOCAL + return gtn_flags # + +# +GN_INSNLOC=0 +@bc695redef +def demangle_name(name, mask, demreq=DQT_FULL): # make flag optional, so demangle_name & demangle_name2 can use it + return _ida_name.demangle_name(name, mask, demreq) +demangle_name2=demangle_name +@bc695redef +def do_name_anyway(ea, name, maxlen=0): + return force_name(ea, name) +extract_name2=extract_name +get_debug_name2=get_debug_name +@bc695redef +def get_true_name(ea0, ea1=None): + if ea1 is None: + ea = ea0 + else: + ea = ea1 + return get_name(ea) +is_ident_char=is_ident_cp +is_visible_char=is_visible_cp +@bc695redef +def make_visible_name(name, sz=0): + if sz > 0: + name = name[0:sz] + return _ida_name.validate_name(name, VNT_VISIBLE) +@bc695redef +def validate_name2(name, sz=0): + if sz > 0: + name = name[0:sz] + return _ida_name.validate_name(name, VNT_IDENT) +@bc695redef +def validate_name3(name): + return _ida_name.validate_name(name, VNT_IDENT) +isident=is_ident +@bc695redef +def get_name(*args): + if len(args) == 2: + if args[0] != _ida_idaapi.BADADDR: + print("Compatibility get_name(from, ea) was called with non-BADADDR first argument (0x%08x). There is no equivalent in the new API, and the results might be erroneous." % args[0]); + return _ida_name.get_name(args[1]) + else: + return _ida_name.get_name(*args) +# diff --git a/pywraps/py_netnode.py b/pywraps/py_netnode.py new file mode 100644 index 0000000..670d925 --- /dev/null +++ b/pywraps/py_netnode.py @@ -0,0 +1,14 @@ + +# +netnode.alt1st = netnode.altfirst +netnode.alt1st_idx8 = netnode.altfirst_idx8 +netnode.altnxt = netnode.altnext +netnode.char1st = netnode.charfirst +netnode.char1st_idx8 = netnode.charfirst_idx8 +netnode.charnxt = netnode.charnext +netnode.hash1st = netnode.hashfirst +netnode.hashnxt = netnode.hashnext +netnode.sup1st = netnode.supfirst +netnode.sup1st_idx8 = netnode.supfirst_idx8 +netnode.supnxt = netnode.supnext +# diff --git a/pywraps/py_offset.py b/pywraps/py_offset.py new file mode 100644 index 0000000..663064e --- /dev/null +++ b/pywraps/py_offset.py @@ -0,0 +1,10 @@ + +# +calc_reference_basevalue=calc_basevalue +calc_reference_target=calc_target +@bc695redef +def set_offset(ea, n, base): + import ida_idaapi + otype = get_default_reftype(ea) + return op_offset(ea, n, otype, ida_idaapi.BADADDR, base) > 0 +# diff --git a/pywraps/py_pro.hpp b/pywraps/py_pro.hpp index f67a448..1c34647 100644 --- a/pywraps/py_pro.hpp +++ b/pywraps/py_pro.hpp @@ -24,9 +24,9 @@ static PyObject *qstrvec_t_addressof(PyObject *self, size_t idx) static bool qstrvec_t_set( - PyObject *self, - size_t idx, - const char *s) + PyObject *self, + size_t idx, + const char *s) { qstrvec_t *sv = qstrvec_t_get_clink(self); if ( sv == NULL || idx >= sv->size() ) @@ -36,8 +36,8 @@ static bool qstrvec_t_set( } static bool qstrvec_t_from_list( - PyObject *self, - PyObject *py_list) + PyObject *self, + PyObject *py_list) { PYW_GIL_CHECK_LOCKED_SCOPE(); qstrvec_t *sv = qstrvec_t_get_clink(self); @@ -83,9 +83,9 @@ static bool qstrvec_t_clear(PyObject *self, bool qclear) } static bool qstrvec_t_insert( - PyObject *self, - size_t idx, - const char *s) + PyObject *self, + size_t idx, + const char *s) { qstrvec_t *sv = qstrvec_t_get_clink(self); if ( sv == NULL || idx >= sv->size() ) @@ -103,4 +103,24 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx) sv->erase(sv->begin()+idx); return true; } + + +//------------------------------------------------------------------------ +/* +# +def str2user(str): + """ + Insert C-style escape characters to string + + @return: new string with escape characters inserted + """ + pass +# +*/ +PyObject *py_str2user(const char *str) +{ + qstring retstr; + qstr2user(&retstr, str); + return PyString_FromString(retstr.c_str()); +} // diff --git a/pywraps/py_pro.py b/pywraps/py_pro.py index ffc870e..afc419b 100644 --- a/pywraps/py_pro.py +++ b/pywraps/py_pro.py @@ -18,7 +18,7 @@ class _qstrvec_t(ida_idaapi.py_clinked_object_t): For example, in py_askusingform.py, we ctypes-expose to the IDA kernel & UI a qstrvec instance, in case a DropdownListControl is constructed. - That's because that's what AskUsingForm expects, and we have no + That's because that's what ask_form expects, and we have no choice but to make a DropdownListControl hold a qstrvec_t. This is, afaict, the only situation where a Python _qstrvec_t is required. @@ -85,3 +85,12 @@ class _qstrvec_t(ida_idaapi.py_clinked_object_t): return _ida_pro.qstrvec_t_remove(self, idx) # + +# +@bc695redef +def strlwr(s): + return str(s).lower() +@bc695redef +def strupr(s): + return str(s).upper() +# diff --git a/pywraps/py_problems.py b/pywraps/py_problems.py new file mode 100644 index 0000000..50bd3fa --- /dev/null +++ b/pywraps/py_problems.py @@ -0,0 +1,32 @@ +# +import sys +sys.modules["ida_queue"] = sys.modules["ida_problems"] +Q_Qnum=_ida_problems.cvar.PR_END +Q_att=_ida_problems.cvar.PR_ATTN +Q_badstack=_ida_problems.cvar.PR_BADSTACK +Q_collsn=_ida_problems.cvar.PR_COLLISION +Q_decimp=_ida_problems.cvar.PR_DECIMP +Q_disasm=_ida_problems.cvar.PR_DISASM +Q_final=_ida_problems.cvar.PR_FINAL +Q_head=_ida_problems.cvar.PR_HEAD +Q_jumps=_ida_problems.cvar.PR_JUMP +Q_lines=_ida_problems.cvar.PR_MANYLINES +Q_noBase=_ida_problems.cvar.PR_NOBASE +Q_noComm=_ida_problems.cvar.PR_NOCMT +Q_noFop=_ida_problems.cvar.PR_NOFOP +Q_noName=_ida_problems.cvar.PR_NONAME +Q_noRef=_ida_problems.cvar.PR_NOXREFS +Q_noValid=_ida_problems.cvar.PR_ILLADDR +Q_rolled=_ida_problems.cvar.PR_ROLLED +QueueDel=forget_problem +QueueGetMessage=get_problem_desc +QueueGetType=get_problem +QueueIsPresent=is_problem_present +QueueSet=remember_problem +@bc695redef +def get_long_queue_name(t): + return get_problem_name(t, True) +@bc695redef +def get_short_queue_name(t): + return get_problem_name(t, False) +# diff --git a/pywraps/py_range.hpp b/pywraps/py_range.hpp new file mode 100644 index 0000000..4dfe4a0 --- /dev/null +++ b/pywraps/py_range.hpp @@ -0,0 +1,3 @@ + +// +// diff --git a/pywraps/py_range.py b/pywraps/py_range.py new file mode 100644 index 0000000..bf3f205 --- /dev/null +++ b/pywraps/py_range.py @@ -0,0 +1,13 @@ + +# +import sys +sys.modules["ida_area"] = sys.modules["ida_range"] +area_t = range_t +areaset_t = rangeset_t +def __set_startEA(inst, v): + inst.start_ea = v +range_t.startEA = property(lambda self: self.start_ea, __set_startEA) +def __set_endEA(inst, v): + inst.end_ea = v +range_t.endEA = property(lambda self: self.end_ea, __set_endEA) +# diff --git a/pywraps/py_registry.hpp b/pywraps/py_registry.hpp index e7a5e02..6bc656f 100644 --- a/pywraps/py_registry.hpp +++ b/pywraps/py_registry.hpp @@ -31,20 +31,13 @@ static PyObject *_py_reg_subkey_children(const char *name, bool subkeys) PyObject *py_reg_read_string(const char *name, const char *subkey = NULL, const char *def = NULL) { PYW_GIL_CHECK_LOCKED_SCOPE(); - char utf8[MAXSTR * 10]; + qstring utf8; bool ok; Py_BEGIN_ALLOW_THREADS; - if ( def == NULL ) - { - ok = reg_read_string(name, utf8, sizeof(utf8), subkey); - } - else - { - reg_read_string(name, sizeof(utf8), utf8, def, subkey); - ok = true; - } + if ( !reg_read_string(&utf8, name, subkey) && def != NULL ) + utf8 = def; Py_END_ALLOW_THREADS; - return PyString_FromString(ok ? utf8 : ""); + return PyString_FromString(utf8.c_str()); } //------------------------------------------------------------------------- diff --git a/pywraps/py_search.py b/pywraps/py_search.py new file mode 100644 index 0000000..b63322a --- /dev/null +++ b/pywraps/py_search.py @@ -0,0 +1,4 @@ + +# +find_void=find_suspop +# diff --git a/pywraps/py_segment.hpp b/pywraps/py_segment.hpp index 6078646..6887192 100644 --- a/pywraps/py_segment.hpp +++ b/pywraps/py_segment.hpp @@ -1,37 +1,37 @@ // -void segment_t_startEA_set(segment_t *segm, ea_t newea) +void segment_t_start_ea_set(segment_t *segm, ea_t newea) { - if ( getseg(segm->startEA) == segm ) + if ( getseg(segm->start_ea) == segm ) { - PyErr_SetString(PyExc_AttributeError, "Can't modify startEA, please use set_segm_start() instead"); + PyErr_SetString(PyExc_AttributeError, "Can't modify start_ea, please use set_segm_start() instead"); } else { - segm->startEA = newea; + segm->start_ea = newea; } } -ea_t segment_t_startEA_get(segment_t *segm) +ea_t segment_t_start_ea_get(segment_t *segm) { - return segm->startEA; + return segm->start_ea; } -void segment_t_endEA_set(segment_t *segm, ea_t newea) +void segment_t_end_ea_set(segment_t *segm, ea_t newea) { - if ( getseg(segm->startEA) == segm ) + if ( getseg(segm->start_ea) == segm ) { - PyErr_SetString(PyExc_AttributeError, "Can't modify endEA, please use set_segm_end() instead"); + PyErr_SetString(PyExc_AttributeError, "Can't modify end_ea, please use set_segm_end() instead"); } else { - segm->endEA = newea; + segm->end_ea = newea; } } -ea_t segment_t_endEA_get(segment_t *segm) +ea_t segment_t_end_ea_get(segment_t *segm) { - return segm->endEA; + return segm->end_ea; } // diff --git a/pywraps/py_segment.py b/pywraps/py_segment.py new file mode 100644 index 0000000..d72ccac --- /dev/null +++ b/pywraps/py_segment.py @@ -0,0 +1,18 @@ + +# +CSS_NOAREA=CSS_NORANGE +SEGDEL_KEEP=SEGMOD_KEEP +SEGDEL_KEEP0=SEGMOD_KEEP0 +SEGDEL_PERM=SEGMOD_KILL +SEGDEL_SILENT=SEGMOD_SILENT +@bc695redef +def del_segment_cmt(s, rpt): + set_segment_cmt(s, "", rpt) +ask_selector=sel2para +# In 7.0, those were renamed +# - get_true_segm_name -> get_segm_name +# - get_segm_name -> get_visible_segm_name +# alas, since they have the same prototypes, we cannot do much, +# but redirect all to get_segm_name and hope for the best +get_true_segm_name=get_segm_name +# diff --git a/pywraps/py_segregs.py b/pywraps/py_segregs.py new file mode 100644 index 0000000..698cd15 --- /dev/null +++ b/pywraps/py_segregs.py @@ -0,0 +1,40 @@ + +# +import sys +sys.modules["ida_srarea"] = sys.modules["ida_segregs"] +SetDefaultRegisterValue=set_default_sreg_value +copy_srareas=copy_sreg_ranges +def ___looks_like_ea_not_segreg(thing): + # yay heuristics. Not sure how best to do this... + return (type(thing) == long) or (thing > 0x200) +def del_sreg_range(*args): + if ___looks_like_ea_not_segreg(args[1]): # 6.95: rg, ea + ea, rg = args[1], args[0] + else: # 7.00: ea, rg + ea, rg = args + return _ida_segregs.del_sreg_range(ea, rg) +del_srarea=del_sreg_range +getSR=get_sreg +get_prev_srarea=get_prev_sreg_range +get_srarea2=get_sreg_range +def get_sreg_range_num(*args): + if ___looks_like_ea_not_segreg(args[1]): # 6.95: rg, ea + ea, rg = args[1], args[0] + else: # 7.00: ea, rg + ea, rg = args + return _ida_segregs.get_sreg_range_num(ea, rg) +get_srarea_num=get_sreg_range_num +get_srareas_qty2=get_sreg_ranges_qty +getn_srarea2=getn_sreg_range +import ida_idaapi +is_segreg_locked=ida_idaapi._BC695.false_p +class lock_segreg: + def __init__(): + pass +segreg_area_t=sreg_range_t +splitSRarea1=split_sreg_range +split_srarea=split_sreg_range +get_segreg=get_sreg +set_default_segreg_value=set_default_sreg_value + +# diff --git a/pywraps/py_strlist.py b/pywraps/py_strlist.py new file mode 100644 index 0000000..8f6adc1 --- /dev/null +++ b/pywraps/py_strlist.py @@ -0,0 +1,4 @@ +# +def refresh_strlist(*args): + build_strlist() +# diff --git a/pywraps/py_struct.py b/pywraps/py_struct.py new file mode 100644 index 0000000..1233d93 --- /dev/null +++ b/pywraps/py_struct.py @@ -0,0 +1,28 @@ +# +get_member_name2=get_member_name + +def get_member_tinfo(*args): + import ida_typeinf + if isinstance(args[1], ida_typeinf.tinfo_t): # 6.95: mptr, tinfo_t + mptr, tif = args + else: # 7.00: tinfo_t, mptr + tif, mptr = args + return _ida_struct.get_member_tinfo(tif, mptr); + +def get_or_guess_member_tinfo(*args): + import ida_typeinf + if isinstance(args[1], ida_typeinf.tinfo_t): # 6.95: mptr, tinfo_t + mptr, tif = args + else: # 7.00: tinfo_t, mptr + tif, mptr = args + return _ida_struct.get_or_guess_member_tinfo(tif, mptr); + +# note: if needed we might have to re-implement get_member_tinfo() +# and look whether there is a 2nd, 'tinfo_t' parameter (since the +# original get_member_tinfo function has a different signature) +get_member_tinfo2=get_member_tinfo +# same here +get_or_guess_member_tinfo2=get_or_guess_member_tinfo +save_struc2=save_struc +set_member_tinfo2=set_member_tinfo +# diff --git a/pywraps/py_typeinf.hpp b/pywraps/py_typeinf.hpp index 61788de..4a43453 100644 --- a/pywraps/py_typeinf.hpp +++ b/pywraps/py_typeinf.hpp @@ -8,7 +8,7 @@ PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags) tinfo_t tif; qstring name; qtype fields, type; - bool ok = parse_decl2(ti, decl, &name, &tif, flags); + bool ok = parse_decl(&tif, &name, ti, decl, flags); if ( ok ) ok = tif.serialize(&type, &fields, NULL, SUDT_FAST); @@ -27,7 +27,7 @@ PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags) def calc_type_size(ti, tp): """ Returns the size of a type - @param ti: Type info. 'idaapi.cvar.idati' can be passed. + @param ti: Type info. 'None' can be passed. @param tp: type string @return: - None on failure @@ -67,7 +67,7 @@ PyObject *py_calc_type_size(const til_t *ti, PyObject *tp) def apply_type(ti, ea, tp_name, py_type, py_fields, flags) """ Apply the specified type to the address - @param ti: Type info library. 'idaapi.cvar.idati' can be used. + @param ti: Type info library. 'None' can be used. @param py_type: type string @param py_fields: fields string (may be empty or None) @param ea: the address of the object @@ -103,7 +103,7 @@ static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_ { rc = has_ti(ea); if ( rc ) - del_tinfo2(ea); + del_tinfo(ea); } } else @@ -113,9 +113,9 @@ static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_ if ( rc ) { if ( mptr != NULL ) - rc = set_member_tinfo2(sptr, mptr, 0, tif, 0); + rc = set_member_tinfo(sptr, mptr, 0, tif, 0); else - rc = apply_tinfo2(ea, tif, flags); + rc = apply_tinfo(ea, tif, flags); } } Py_END_ALLOW_THREADS; @@ -124,26 +124,28 @@ static bool py_apply_type(til_t *ti, PyObject *py_type, PyObject *py_fields, ea_ //------------------------------------------------------------------------- /* +header: typeinf.hpp # -def print_type(ea, one_line): +def get_arg_addrs(caller): """ - Returns the type of an item - @return: - - None on failure - - The type string with a semicolon. Can be used directly with idc.SetType() + Retrieve addresses of argument initialization instructions + + @param caller: the address of the call instruction + @return: list of instruction addresses """ pass # */ -static PyObject *py_print_type(ea_t ea, bool one_line) +PyObject *py_get_arg_addrs(ea_t caller) { - qstring out; - int flags = PRTYPE_SEMI | (one_line ? PRTYPE_1LINE : PRTYPE_MULTI); - bool ok = print_type3(&out, ea, one_line ? PRTYPE_1LINE : PRTYPE_MULTI); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return PyString_FromString(out.begin()); - Py_RETURN_NONE; + eavec_t addrs; + if ( !get_arg_addrs(&addrs, caller) ) + Py_RETURN_NONE; + int n = addrs.size(); + PyObject *result = PyList_New(n); + for ( size_t i = 0; i < n; ++i ) + PyList_SetItem(result, i, Py_BuildValue(PY_BV_EA, bvea_t(addrs[i]))); + return result; } //------------------------------------------------------------------------- @@ -158,11 +160,11 @@ def py_unpack_object_from_idb(ti, tp, fields, ea, pio_flags = 0): # */ PyObject *py_unpack_object_from_idb( - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - ea_t ea, - int pio_flags = 0) + til_t *ti, + PyObject *py_type, + PyObject *py_fields, + ea_t ea, + int pio_flags = 0) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) @@ -176,16 +178,16 @@ PyObject *py_unpack_object_from_idb( borref_t py_fields_ref(py_fields); // Unpack - type_t *type = (type_t *) PyString_AsString(py_type); + const type_t *type = (const type_t *) PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); idc_value_t idc_obj; error_t err; Py_BEGIN_ALLOW_THREADS; - err = unpack_object_from_idb( + tinfo_t tif; + tif.deserialize(ti, &type, &fields); + err = unpack_idcobj_from_idb( &idc_obj, - ti, - type, - fields, + tif, ea, NULL, pio_flags); @@ -213,7 +215,7 @@ def unpack_object_from_bv(ti, tp, fields, bytes, pio_flags = 0): """ Unpacks a buffer into an object. Returns the error_t returned by idaapi.pack_object_to_idb - @param ti: Type info. 'idaapi.cvar.idati' can be passed. + @param ti: Type info. 'None' can be passed. @param tp: type string @param fields: fields string (may be empty or None) @param bytes: the bytes to unpack @@ -226,11 +228,11 @@ def unpack_object_from_bv(ti, tp, fields, bytes, pio_flags = 0): # */ PyObject *py_unpack_object_from_bv( - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - PyObject *py_bytes, - int pio_flags = 0) + til_t *ti, + PyObject *py_type, + PyObject *py_fields, + PyObject *py_bytes, + int pio_flags = 0) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) || !PyString_Check(py_bytes) ) @@ -244,7 +246,7 @@ PyObject *py_unpack_object_from_bv( borref_t py_fields_ref(py_fields); // Get type strings - type_t *type = (type_t *) PyString_AsString(py_type); + const type_t *type = (const type_t *) PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); // Make a byte vector @@ -255,11 +257,11 @@ PyObject *py_unpack_object_from_bv( idc_value_t idc_obj; error_t err; Py_BEGIN_ALLOW_THREADS; - err = unpack_object_from_bv( + tinfo_t tif; + tif.deserialize(ti, &type, &fields); + err = unpack_idcobj_from_bv( &idc_obj, - ti, - type, - fields, + tif, bytes, pio_flags); Py_END_ALLOW_THREADS; @@ -287,7 +289,7 @@ def pack_object_to_idb(obj, ti, tp, fields, ea, pio_flags = 0): Write a typed object to the database. Raises an exception if wrong parameters were passed or conversion fails Returns the error_t returned by idaapi.pack_object_to_idb - @param ti: Type info. 'idaapi.cvar.idati' can be passed. + @param ti: Type info. 'None' can be passed. @param tp: type string @param fields: fields string (may be empty or None) @param ea: ea to be used while packing @@ -297,12 +299,12 @@ def pack_object_to_idb(obj, ti, tp, fields, ea, pio_flags = 0): # */ PyObject *py_pack_object_to_idb( - PyObject *py_obj, - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - ea_t ea, - int pio_flags = 0) + PyObject *py_obj, + til_t *ti, + PyObject *py_type, + PyObject *py_fields, + ea_t ea, + int pio_flags = 0) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) @@ -322,14 +324,16 @@ PyObject *py_pack_object_to_idb( borref_t py_fields_ref(py_fields); // Get type strings - type_t *type = (type_t *)PyString_AsString(py_type); + const type_t *type = (const type_t *)PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); // Pack // error_t err; error_t err; Py_BEGIN_ALLOW_THREADS; - err = pack_object_to_idb(&idc_obj, ti, type, fields, ea, pio_flags); + tinfo_t tif; + tif.deserialize(ti, &type, &fields); + err = pack_idcobj_to_idb(&idc_obj, tif, ea, pio_flags); Py_END_ALLOW_THREADS; return PyInt_FromLong(err); } @@ -340,7 +344,7 @@ PyObject *py_pack_object_to_idb( def pack_object_to_bv(obj, ti, tp, fields, base_ea, pio_flags = 0): """ Packs a typed object to a string - @param ti: Type info. 'idaapi.cvar.idati' can be passed. + @param ti: Type info. 'None' can be passed. @param tp: type string @param fields: fields string (may be empty or None) @param base_ea: base ea used to relocate the pointers in the packed object @@ -354,12 +358,12 @@ def pack_object_to_bv(obj, ti, tp, fields, base_ea, pio_flags = 0): */ // Returns a tuple(Boolean, PackedBuffer or Error Code) PyObject *py_pack_object_to_bv( - PyObject *py_obj, - til_t *ti, - PyObject *py_type, - PyObject *py_fields, - ea_t base_ea, - int pio_flags=0) + PyObject *py_obj, + til_t *ti, + PyObject *py_type, + PyObject *py_fields, + ea_t base_ea, + int pio_flags=0) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyString_Check(py_type) || !PyWStringOrNone_Check(py_fields) ) @@ -379,22 +383,22 @@ PyObject *py_pack_object_to_bv( borref_t py_fields_ref(py_fields); // Get type strings - type_t *type = (type_t *)PyString_AsString(py_type); + const type_t *type = (const type_t *)PyString_AsString(py_type); const p_list *fields = PyW_Fields(py_fields); // Pack relobj_t bytes; error_t err; Py_BEGIN_ALLOW_THREADS; - err = pack_object_to_bv( + tinfo_t tif; + tif.deserialize(ti, &type, &fields); + err = pack_idcobj_to_bv( &idc_obj, - ti, - type, - fields, + tif, &bytes, NULL, pio_flags); - if ( err == eOk && !bytes.relocate(base_ea, inf.mf) ) + if ( err == eOk && !bytes.relocate(base_ea, inf.is_be()) ) err = -1; Py_END_ALLOW_THREADS; if ( err == eOk ) @@ -412,14 +416,17 @@ int idc_parse_types(const char *input, int flags) if ( (flags & 1) != 0 ) hti |= HTI_FIL; - return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti); + return parse_decls(NULL, input, (flags & 2) == 0 ? msg : NULL, hti); } //------------------------------------------------------------------------- PyObject *py_idc_get_type_raw(ea_t ea) { + tinfo_t tif; qtype type, fields; - bool ok = get_tinfo(ea, &type, &fields); + bool ok = get_tinfo(&tif, ea); + if ( ok ) + ok = tif.serialize(&type, &fields, NULL, SUDT_FAST); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( ok ) return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str()); @@ -432,7 +439,7 @@ PyObject *py_idc_get_local_type_raw(int ordinal) { const type_t *type; const p_list *fields; - bool ok = get_numbered_type(idati, ordinal, &type, &fields); + bool ok = get_numbered_type(NULL, ordinal, &type, &fields); PYW_GIL_CHECK_LOCKED_SCOPE(); if ( ok ) return Py_BuildValue("(ss)", (char *)type, (char *)fields); @@ -443,7 +450,7 @@ PyObject *py_idc_get_local_type_raw(int ordinal) char *idc_guess_type(ea_t ea, char *buf, size_t bufsize) { tinfo_t tif; - if ( guess_tinfo2(ea, &tif) ) + if ( guess_tinfo(&tif, ea) ) { qstring out; if ( tif.print(&out) ) @@ -456,7 +463,7 @@ char *idc_guess_type(ea_t ea, char *buf, size_t bufsize) char *idc_get_type(ea_t ea, char *buf, size_t bufsize) { tinfo_t tif; - if ( get_tinfo2(ea, &tif) ) + if ( get_tinfo(&tif, ea) ) { qstring out; if ( tif.print(&out) ) @@ -473,26 +480,26 @@ int idc_set_local_type(int ordinal, const char *dcl, int flags) { if ( dcl == NULL || dcl[0] == '\0' ) { - if ( !del_numbered_type(idati, ordinal) ) + if ( !del_numbered_type(NULL, ordinal) ) return 0; } else { tinfo_t tif; qstring name; - if ( !parse_decl2(idati, dcl, &name, &tif, flags) ) + if ( !parse_decl(&tif, &name, NULL, dcl, flags) ) return 0; if ( ordinal <= 0 ) { if ( !name.empty() ) - ordinal = get_type_ordinal(idati, name.begin()); + ordinal = get_type_ordinal(NULL, name.begin()); if ( ordinal <= 0 ) - ordinal = alloc_type_ordinal(idati); + ordinal = alloc_type_ordinal(NULL); } - if ( tif.set_numbered_type(idati, ordinal, 0, name.c_str()) != TERR_OK ) + if ( tif.set_numbered_type(NULL, ordinal, 0, name.c_str()) != TERR_OK ) return 0; } return ordinal; @@ -502,14 +509,14 @@ int idc_set_local_type(int ordinal, const char *dcl, int flags) int idc_get_local_type(int ordinal, int flags, char *buf, size_t maxsize) { tinfo_t tif; - if ( !tif.get_numbered_type(idati, ordinal) ) + if ( !tif.get_numbered_type(NULL, ordinal) ) { buf[0] = 0; return false; } qstring res; - const char *name = get_numbered_type_name(idati, ordinal); + const char *name = get_numbered_type_name(NULL, ordinal); if ( !tif.print(&res, name, flags, 2, 40) ) { buf[0] = 0; @@ -540,7 +547,7 @@ PyObject *idc_print_type(PyObject *py_type, PyObject *py_fields, const char *nam bool ok; Py_BEGIN_ALLOW_THREADS; tinfo_t tif; - ok = tif.deserialize(idati, &type, &fields, NULL) + ok = tif.deserialize(NULL, &type, &fields, NULL) && tif.print(&res, name, flags, 2, 40); Py_END_ALLOW_THREADS; if ( ok ) @@ -552,7 +559,7 @@ PyObject *idc_print_type(PyObject *py_type, PyObject *py_fields, const char *nam //------------------------------------------------------------------------- char idc_get_local_type_name(int ordinal, char *buf, size_t bufsize) { - const char *name = get_numbered_type_name(idati, ordinal); + const char *name = get_numbered_type_name(NULL, ordinal); if ( name == NULL ) return false; @@ -582,8 +589,8 @@ PyObject *py_get_named_type(const til_t *til, const char *name, int ntf_flags) const p_list *fields = NULL, *field_cmts = NULL; const char *cmt = NULL; sclass_t sclass = sc_unk; - uint32 value = 0; - int code = get_named_type(til, name, ntf_flags, &type, &fields, &cmt, &field_cmts, &sclass, &value); + uint64 value = 0; + int code = get_named_type(til, name, ntf_flags, &type, &fields, &cmt, &field_cmts, &sclass, (uint32 *) &value); if ( code == 0 ) Py_RETURN_NONE; PyObject *tuple = PyTuple_New(7); @@ -609,7 +616,10 @@ PyObject *py_get_named_type(const til_t *til, const char *name, int ntf_flags) ADD_OR_NONE(cmt != NULL, PyString_FromString(cmt)); ADD_OR_NONE(field_cmts != NULL, PyString_FromString((const char *) field_cmts)); ADD(PyInt_FromLong(long(sclass))); - ADD(PyLong_FromUnsignedLong(long(value))); + if ( (ntf_flags & NTF_64BIT) != 0 ) + ADD(PyLong_FromUnsignedLongLong(value)); + else + ADD(PyLong_FromUnsignedLong(long(value))); #undef ADD_OR_NONE #undef ADD return tuple; @@ -651,69 +661,53 @@ int py_print_decls(text_sink_t &printer, til_t *til, PyObject *py_ordinals, uint } //------------------------------------------------------------------------- -til_t *load_til(const char *tildir, const char *name) +til_t *py_load_til(const char *name, const char *tildir) { - char errbuf[MAXSTR]; - til_t *res = load_til(tildir, name, errbuf, sizeof(errbuf)); + qstring errbuf; + til_t *res = load_til(name, &errbuf, tildir); if ( res == NULL ) - PyErr_SetString(PyExc_RuntimeError, errbuf); + PyErr_SetString(PyExc_RuntimeError, errbuf.c_str()); return res; } //------------------------------------------------------------------------- -til_t *load_til_header_wrap(const char *tildir, const char *name) +til_t *py_load_til_header(const char *tildir, const char *name) { - char errbuf[MAXSTR]; - til_t *res = load_til_header(tildir, name, errbuf, sizeof(errbuf)); + qstring errbuf; + til_t *res = load_til_header(tildir, name, &errbuf); if ( res == NULL ) - PyErr_SetString(PyExc_RuntimeError, errbuf); + PyErr_SetString(PyExc_RuntimeError, errbuf.c_str()); return res; } +#ifdef BC695 +// dummy idati, to generate the cvar. We'll patch the code so +// it does retrieve the real idati through get_idati() +til_t *idati = NULL; +#endif + //------------------------------------------------------------------------- -/* -header: typeinf.hpp -# -def apply_type_to_stkarg(op, v, type, name): - """ - Apply type information to a stack variable - - @param op: reference to instruction operand - @param v: immediate value in the operand (usually op.addr) - @param type: type string. Retrieve from idc.ParseType("type string", flags)[1] - @param name: stack variable name - - @return: Boolean - """ - pass -# -*/ -bool py_apply_type_to_stkarg( - PyObject *py_op, - PyObject *py_uv, - PyObject *py_type, - const char *name) +PyObject *py_remove_tinfo_pointer(tinfo_t *tif, const char *name, const til_t *til) { - uint64 v; - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type) ) - { - return false; - } + const char **pname = name == NULL ? NULL : &name; + bool rc = remove_tinfo_pointer(tif, pname, til); + return Py_BuildValue("(Os)", PyBool_FromLong(rc), pname != NULL ? *pname : NULL); +} + +//------------------------------------------------------------------------- +static PyObject *py_get_numbered_type(const til_t *til, uint32 ordinal) +{ + const type_t *type; + const p_list *fields; + const char *cmt; + const p_list *fieldcmts; + sclass_t sclass; + if ( get_numbered_type(til, ordinal, &type, &fields, &cmt, &fieldcmts, &sclass) ) + return Py_BuildValue("(ssssi)", type, fields, cmt, fieldcmts, sclass); else - { - const type_t *t = (type_t *) PyString_AsString(py_type); - tinfo_t tif; - tif.deserialize(idati, &t); - borref_t br(py_op); - bool rc; - Py_BEGIN_ALLOW_THREADS; - rc = apply_tinfo_to_stkarg(*op, uval_t(v), tif, name); - Py_END_ALLOW_THREADS; - return rc; - } + Py_RETURN_NONE; } + // // @@ -751,7 +745,6 @@ static PyObject *py_tinfo_t_serialize( #undef ADD return tuple; } - // diff --git a/pywraps/py_typeinf.py b/pywraps/py_typeinf.py index 9bd7676..f93f7ea 100644 --- a/pywraps/py_typeinf.py +++ b/pywraps/py_typeinf.py @@ -1,19 +1,127 @@ # -def get_type_size0(ti, tp): - """ - DEPRECATED. Please use calc_type_size instead - Returns the size of a type - @param ti: Type info. 'idaapi.cvar.idati' can be passed. - @param tp: type string - @return: - - None on failure - - The size of the type - """ - return calc_type_size(ti, tp) - import ida_idaapi ida_idaapi._listify_types( reginfovec_t) # + +# +BFI_NOCONST=0 +BFI_NOLOCS=0 +NTF_NOIDB=0 +PRVLOC_STKOFF=PRALOC_VERIFY +PRVLOC_VERIFY=PRALOC_STKOFF +TERR_TOOLONGNAME=TERR_WRONGNAME +@bc695redef +def add_til(name, flags=0): + return _ida_typeinf.add_til(name, flags) +add_til2=add_til +@bc695redef +def apply_decl(arg0, arg1, arg2=None, arg3=0): + if type(arg0) in [int, long]: # old apply_cdecl() + return _ida_typeinf.apply_cdecl(cvar.idati, arg0, arg1, 0) + else: + assert(arg2 is not None) + return _ida_typeinf.apply_cdecl(arg0, arg1, arg2, arg3) +apply_cdecl2=apply_decl +apply_tinfo2=apply_tinfo +calc_c_cpp_name4=calc_c_cpp_name +import ida_idaapi +callregs_init_regs=ida_idaapi._BC695.dummy +choose_local_type=choose_local_tinfo +@bc695redef +def choose_named_type2(root_til, title, ntf_flags, func, out_sym): + class func_pred_t(predicate_t): + def __init__(self, func): + predicate_t.__init__(self) + self.func = func + def should_display(self, til, name, tp, flds): + return self.func(name, tp, flds) + fp = func_pred_t(func) + return choose_named_type(out_sym, root_til, title, ntf_flags, fp) +deref_ptr2=deref_ptr +extract_varloc=extract_argloc +const_vloc_visitor_t=const_aloc_visitor_t +for_all_const_varlocs=for_all_const_arglocs +for_all_varlocs=for_all_arglocs +@bc695redef +def gen_decorate_name3(name, mangle, cc): + return gen_decorate_name(name, mangle, cc, None) # ATM gen_decorate_name doesn't use its tinfo_t +get_enum_member_expr2=get_enum_member_expr +get_idainfo_by_type3=get_idainfo_by_type +@bc695redef +def guess_func_tinfo2(pfn, tif): + return guess_tinfo(pfn.start_ea, tif) +@bc695redef +def load_til(name, tildir=None, *args): + # 6.95 C++ prototypes + # idaman til_t *ida_export load_til(const char *tildir, const char *name, char *errbuf, size_t bufsize); + # idaman til_t *ida_export load_til2( const char *name, char *errbuf, size_t bufsize); + # + # 6.95 Python prototypes + # load_til(tildir, name) + # load_til(tildir, name, errbuf, bufsize) + # load_til2(name, errbuf, bufsize=0) + # + # -> it's virtually impossible to tell whether it's load_til2(), + # or load_til() that's called since they both take 2 first string + # arguments. We'll rely the contents of those strings... + if name is None or name == "": # load_til(), with an empty tildir + name = tildir + tildir = "" + return _ida_typeinf.load_til(name, tildir) + else: + return _ida_typeinf.load_til(name, tildir) +load_til2=load_til +lower_type2=lower_type +optimize_varloc=optimize_argloc +@bc695redef +def parse_decl2(til, decl, tif, flags): + return _ida_typeinf.parse_decl(tif, til, decl, flags) +@bc695redef +def print_type(ea, flags): + if isinstance(flags, bool): + flags = PRTYPE_1LINE if flags else 0 + return _ida_typeinf.print_type(ea, flags) +@bc695redef +def print_type2(ea, flags): + return _ida_typeinf.print_type(ea, flags) +print_type3=_ida_typeinf.print_type +print_varloc=print_argloc +@bc695redef +def resolve_typedef2(til, p, *args): + return _ida_typeinf.resolve_typedef(til, p) +scattered_vloc_t=scattered_aloc_t +set_compiler2=set_compiler +varloc_t=argloc_t +varpart_t=argpart_t +verify_varloc=verify_argloc +vloc_visitor_t=aloc_visitor_t +def guess_tinfo(*args): + if isinstance(args[1], tinfo_t): # 6.95: id, tinfo_t + tid, tif = args + else: # 7.00: tinfo_t, id + tif, tid = args + return _ida_typeinf.guess_tinfo(tif, tid) +guess_tinfo2=guess_tinfo +def find_tinfo_udt_member(*args): + if isinstance(args[2], udt_member_t): # 6.95: typid, strmem_flags, udm + typid, strmem_flags, udm = args + else: # 7.00: udm, typid, strmem_flags + udm, typid, strmem_flags = args + return _ida_typeinf.find_tinfo_udt_member(udm, typid, strmem_flags) +def __tinfo_t_find_udt_member(self, *args): + if isinstance(args[1], udt_member_t): # 6.95: strmem_flags, udm + strmem_flags, udm = args + else: # 7.00: udm, strmem_flags + udm, strmem_flags = args + return _ida_typeinf.tinfo_t_find_udt_member(self, udm, strmem_flags) +tinfo_t.find_udt_member=__tinfo_t_find_udt_member +def save_tinfo(*args): + if isinstance(args[4], tinfo_t): # 6.95: til_t, size_t, name, int, tinfo_t + til, _ord, name, ntf_flags, tif = args + else: # 7.00: tinfo_t, til_t, size_t, name, int + tif, til, _ord, name, ntf_flags = args + return _ida_typeinf.save_tinfo(tif, til, _ord, name, ntf_flags) +# diff --git a/pywraps/py_ua.hpp b/pywraps/py_ua.hpp index fefbe04..169d0cf 100644 --- a/pywraps/py_ua.hpp +++ b/pywraps/py_ua.hpp @@ -9,195 +9,22 @@ // /* # -def init_output_buffer(size = MAXSTR): - """ - This function initialize an output buffer with the given size. - It should be called before using any out_xxxx() functions. - @return: It returns a string. This string should then be passed to MakeLine(). - This function could return None if it failed to create a buffer with the given size. - """ - pass -# -*/ -PyObject *py_init_output_buffer(size_t size = MAXSTR) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - - // Let Python allocate a writable string buffer for us - PyObject *py_str = PyString_FromStringAndSize(NULL, size); - if ( py_str == NULL ) - Py_RETURN_NONE; - - init_output_buffer(PyString_AsString(py_str), size); - return py_str; -} - -//------------------------------------------------------------------------- -/* -# -def term_output_buffer(): - """Use this function to terminate an output buffer.""" - pass -# -*/ -void py_term_output_buffer() -{ - term_output_buffer(); -} - -//------------------------------------------------------------------------- -/* -# def decode_preceding_insn(ea): """ Decodes the preceding instruction. Please check ua.hpp / decode_preceding_insn() @param ea: current ea + @param out: instruction storage @return: tuple(preceeding_ea or BADADDR, farref = Boolean) """ pass # */ -PyObject *py_decode_preceding_insn(ea_t ea) +PyObject *py_decode_preceding_insn(insn_t *out, ea_t ea) { bool farref; - ea_t r = decode_preceding_insn(ea, &farref); + ea_t r = decode_preceding_insn(out, ea, &farref); PYW_GIL_CHECK_LOCKED_SCOPE(); - return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0); -} - -//------------------------------------------------------------------------- -/* -# -def OutValue(op, outflags = 0): - """ - Output immediate value - @param op: operand (of type op_t) - @return: flags of the output value - -1: value is output with COLOR_ERROR - 0: value is output as a number or character or segment - """ - pass -# -*/ -flags_t py_OutValue(PyObject *x, int outflags=0) -{ - op_t *op = op_t_get_clink(x); - if ( op == NULL ) - return 0; - - return OutValue(*op, outflags); -} - -//------------------------------------------------------------------------- -/* -# -def OutImmChar(op, outflags = 0): - """ - Output operand value as a commented character constant - @param op: operand (of type op_t) - @return: None - """ - pass -# -*/ -static void py_OutImmChar(PyObject *x) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(x); - if ( op != NULL ) - OutImmChar(*op); -} - -//------------------------------------------------------------------------- -/* -# -def ua_stkvar2(op, outflags = 0): - """ - Create or modify a stack variable in the function frame. - Please check ua.hpp / ua_stkvar2() - @param op: operand (of type op_t) - @return: None - """ - pass -# -*/ -static bool py_ua_stkvar2(PyObject *x, adiff_t v, int flags) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(x); - return op == NULL ? false : ua_stkvar2(*op, v, flags); -} - -//------------------------------------------------------------------------- -/* -# -def ua_add_off_drefs(op, type): - """ - Add xrefs for offset operand of the current instruction - Please check ua.hpp / ua_add_off_drefs() - @param op: operand (of type op_t) - @return: None - """ - pass -# -*/ -ea_t py_ua_add_off_drefs(PyObject *py_op, dref_t type) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - return op == NULL ? BADADDR : ua_add_off_drefs(*op, type); -} - -//------------------------------------------------------------------------- -/* -# -def ua_add_off_drefs2(op, type, outf): - """ - Add xrefs for offset operand of the current instruction - Please check ua.hpp / ua_add_off_drefs2() - @return: ea_t - """ - pass -# -*/ -ea_t py_ua_add_off_drefs2(PyObject *py_op, dref_t type, int outf) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - return op == NULL ? BADADDR : ua_add_off_drefs2(*op, type, outf); -} - -//------------------------------------------------------------------------- -/* -# -def out_name_expr(op, ea, off): - """ - Output a name expression - @param op: operand (of type op_t) - @param ea: address of expression - @param off: the value of name expression. this parameter is used only to - check that the name expression will have the wanted value. - You may pass BADADDR for this parameter. - @return: true if the name expression has been produced - """ - pass -# -*/ -bool py_out_name_expr( - PyObject *py_op, - ea_t ea, - PyObject *py_off) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *op = op_t_get_clink(py_op); - uint64 v(0); - adiff_t off; - if ( PyW_GetNumber(py_off, &v) ) - off = adiff_t(v); - else - off = BADADDR; - - return op == NULL ? false : out_name_expr(*op, ea, off); + return Py_BuildValue("(" PY_BV_EA "i)", bvea_t(r), farref ? 1 : 0); } //------------------------------------------------------------------------- @@ -210,7 +37,7 @@ def construct_macro(insn): pass # */ -bool py_construct_macro(bool enable, PyObject *build_macro) +bool py_construct_macro(insn_t &insn, bool enable, PyObject *build_macro) { PYW_GIL_CHECK_LOCKED_SCOPE(); @@ -222,588 +49,66 @@ bool py_construct_macro(bool enable, PyObject *build_macro) macro_builders.push(newref_t(build_macro)); struct ida_local lambda_t { - static bool idaapi call_build_macro(insn_t &s, bool may_go_forward) + static bool idaapi call_build_macro(insn_t &insn, bool may_go_forward) { PyObject *py_builder = macro_builders.top().o; - newref_t pyres = PyObject_CallFunction( - py_builder, "O", - may_go_forward ? Py_True : Py_False); - PyW_ShowCbErr("build_macro"); - if ( pyres.o == NULL || pyres.o == Py_None ) - return false; - insn_t *_s = insn_t_get_clink(pyres.o); - if ( _s == NULL ) - return false; - s = *_s; - return true; + ref_t py_res; + ref_t py_mod(PyW_TryImportModule(SWIG_name)); + if ( py_mod != NULL ) + { + ref_t py_insn = try_create_swig_wrapper(py_mod, "insn_t", &insn); + if ( py_insn != NULL ) + { + py_res = newref_t( + PyObject_CallFunction( + py_builder, + "OO", + py_insn.o, + may_go_forward ? Py_True : Py_False)); + PyW_ShowCbErr("build_macro"); + } + } + return py_res.o == Py_True; } }; - bool res = construct_macro(enable, lambda_t::call_build_macro); + bool res = construct_macro(insn, enable, lambda_t::call_build_macro); macro_builders.pop(); return res; } //------------------------------------------------------------------------- -static int py_get_dtyp_by_size(asize_t size) +static int py_get_dtype_by_size(asize_t size) { - return int(get_dtyp_by_size(size)); + return int(get_dtype_by_size(size)); } //------------------------------------------------------------------------- -static PyObject *insn_t_get_op_link(PyObject *py_insn_lnk, int i) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( i < 0 || i >= UA_MAXOP || !PyCObject_Check(py_insn_lnk) ) - Py_RETURN_NONE; - - // Extract C link - insn_t *insn = (insn_t *)PyCObject_AsVoidPtr(py_insn_lnk); - - // Return a link to the operand - return PyCObject_FromVoidPtr(&insn->Operands[i], NULL); -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_create() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(new insn_t(), NULL); -} - -//------------------------------------------------------------------------- -static PyObject *op_t_create() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(new op_t(), NULL); -} - -//------------------------------------------------------------------------- -static bool op_t_assign(PyObject *self, PyObject *other) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *lhs = op_t_get_clink(self); - op_t *rhs = op_t_get_clink(other); - if ( lhs == NULL || rhs == NULL ) - return false; - - *lhs = *rhs; - return true; -} - -//------------------------------------------------------------------------- -static bool insn_t_assign(PyObject *self, PyObject *other) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *lhs = insn_t_get_clink(self); - insn_t *rhs = insn_t_get_clink(other); - if ( lhs == NULL || rhs == NULL ) - return false; - - *lhs = *rhs; - return true; -} - -//------------------------------------------------------------------------- -static bool op_t_destroy(PyObject *py_obj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_obj) ) - return false; - - op_t *op = (op_t *)PyCObject_AsVoidPtr(py_obj); - delete op; - - return true; -} - -//------------------------------------------------------------------------- -static bool insn_t_destroy(PyObject *py_obj) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( !PyCObject_Check(py_obj) ) - return false; - - delete (insn_t *)PyCObject_AsVoidPtr(py_obj); - return true; -} - -//------------------------------------------------------------------------- -// Returns a C link to the global 'cmd' variable -static PyObject *py_get_global_cmd_link() -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - return PyCObject_FromVoidPtr(&::cmd, NULL); -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_is_canon_insn(int itype) -{ - bool ok = ph.is_canon_insn(itype); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_canon_feature(int itype) -{ - uint32 v = ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0; - PYW_GIL_CHECK_LOCKED_SCOPE(); - return Py_BuildValue("I", v); -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_canon_mnem(int itype) -{ - bool ok = ph.is_canon_insn(itype); - PYW_GIL_CHECK_LOCKED_SCOPE(); - if ( ok ) - return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name); - else - Py_RETURN_NONE; -} - -//------------------------------------------------------------------------- -static PyObject *insn_t_get_cs(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->cs); -} - -static void insn_t_set_cs(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - - uint64 v(0); - PyW_GetNumber(value, &v); - link->cs = ea_t(v); -} - -static PyObject *insn_t_get_ip(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->ip); -} - -static void insn_t_set_ip(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->ip = ea_t(v); -} - -static PyObject *insn_t_get_ea(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->ea); -} - -static void insn_t_set_ea(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->ea = ea_t(v); -} - -static PyObject *insn_t_get_itype(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->itype); -} - -static void insn_t_set_itype(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->itype = (uint16)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_size(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->size); -} - -static void insn_t_set_size(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->size = (uint16)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_auxpref(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->auxpref); -} - -static void insn_t_set_auxpref(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->auxpref = (uint16)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_segpref(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->segpref); -} - -static void insn_t_set_segpref(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->segpref = (char)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_insnpref(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->insnpref); -} - -static void insn_t_set_insnpref(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->insnpref = (char)PyInt_AsLong(value); -} - -static PyObject *insn_t_get_flags(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->flags); -} - -static void insn_t_set_flags(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - insn_t *link = insn_t_get_clink(self); - if ( link == NULL ) - return; - link->flags = (char)PyInt_AsLong(value); -} - -//------------------------------------------------------------------------- -static PyObject *op_t_get_n(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->n); -} - -static void op_t_set_n(PyObject *self, PyObject *value) -{ - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->n = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_type(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("B", link->type); -} - -static void op_t_set_type(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->type = (optype_t)PyInt_AsLong(value); -} - -static PyObject *op_t_get_offb(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->offb); -} - -static void op_t_set_offb(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->offb = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_offo(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->offo); -} - -static void op_t_set_offo(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->offo = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_flags(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("B", link->flags); -} - -static void op_t_set_flags(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->flags = (uchar)PyInt_AsLong(value); -} - -static PyObject *op_t_get_dtyp(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->dtyp); -} - -static void op_t_set_dtyp(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->dtyp = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_reg_phrase(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("H", link->reg); -} -static void op_t_set_reg_phrase(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->reg = (uint16)PyInt_AsLong(value); -} - -static PyObject *op_t_get_value(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->value); -} - -static void op_t_set_value(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->value = uval_t(v); -} - -static PyObject *op_t_get_addr(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->addr); -} - -static void op_t_set_addr(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->addr = ea_t(v); -} - -static PyObject *op_t_get_specval(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue(PY_FMT64, (pyul_t)link->specval); -} - -static void op_t_set_specval(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - uint64 v(0); - PyW_GetNumber(value, &v); - link->specval = ea_t(v); -} - -static PyObject *op_t_get_specflag1(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag1); -} - -static void op_t_set_specflag1(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag1 = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_specflag2(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag2); -} - -static void op_t_set_specflag2(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag2 = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_specflag3(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag3); -} - -static void op_t_set_specflag3(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag3 = (char)PyInt_AsLong(value); -} - -static PyObject *op_t_get_specflag4(PyObject *self) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - Py_RETURN_NONE; - return Py_BuildValue("b", link->specflag4); -} - -static void op_t_set_specflag4(PyObject *self, PyObject *value) -{ - PYW_GIL_CHECK_LOCKED_SCOPE(); - op_t *link = op_t_get_clink(self); - if ( link == NULL ) - return; - link->specflag4 = (char)PyInt_AsLong(value); -} - -//------------------------------------------------------------------------- -PyObject *py_get_operand_immvals(ea_t ea, int n) +PyObject *py_get_immvals(ea_t ea, int n) { uvalvec_t storage; storage.resize(2 * UA_MAXOP); - size_t cnt = get_operand_immvals(ea, n, storage.begin()); + flags_t F = get_flags(ea); + size_t cnt = get_immvals(storage.begin(), ea, n, F); PyObject *result = PyList_New(cnt); for ( size_t i = 0; i < cnt; ++i ) - PyList_SetItem(result, i, Py_BuildValue(PY_FMT64, pyul_t(storage[i]))); + PyList_SetItem(result, i, Py_BuildValue(PY_BV_UVAL, bvuval_t(storage[i]))); return result; } +//------------------------------------------------------------------------- +#define DEFINE_WRAP_TYPE_FROM_PTRVAL(Type) \ + static Type *Type##__from_ptrval__(size_t ptrval) \ + { \ + return (Type *) ptrval; \ + } + +DEFINE_WRAP_TYPE_FROM_PTRVAL(insn_t); +DEFINE_WRAP_TYPE_FROM_PTRVAL(op_t); +DEFINE_WRAP_TYPE_FROM_PTRVAL(outctx_base_t); +DEFINE_WRAP_TYPE_FROM_PTRVAL(outctx_t); + +#undef DEFINE_WRAP_TYPE_FROM_PTRVAL + // #endif diff --git a/pywraps/py_ua.py b/pywraps/py_ua.py index d9c8ead..274755d 100644 --- a/pywraps/py_ua.py +++ b/pywraps/py_ua.py @@ -1,294 +1,86 @@ # -import ida_idaapi - -# ----------------------------------------------------------------------- -class op_t(ida_idaapi.py_clinked_object_t): - """Class representing operands""" - def __init__(self, lnk = None): - ida_idaapi.py_clinked_object_t.__init__(self, lnk) - - def _create_clink(self): - return _ida_ua.op_t_create() - - def _del_clink(self, lnk): - return _ida_ua.op_t_destroy(lnk) - - def assign(self, other): - """Copies the contents of 'other' to 'self'""" - return _ida_ua.op_t_assign(self, other) - - def __eq__(self, other): - """Checks if two register operands are equal by checking the register number and its dtype""" - return (self.reg == other.reg) and (self.dtyp == other.dtyp) - - def is_reg(self, r): - """Checks if the register operand is the given processor register""" - return self.type == o_reg and self.reg == r - - def has_reg(self, r): - """Checks if the operand accesses the given processor register""" - return self.reg == r.reg - - # - # Autogenerated - # - def __get_n__(self): - return _ida_ua.op_t_get_n(self) - def __set_n__(self, v): - _ida_ua.op_t_set_n(self, v) - def __get_type__(self): - return _ida_ua.op_t_get_type(self) - def __set_type__(self, v): - _ida_ua.op_t_set_type(self, v) - def __get_offb__(self): - return _ida_ua.op_t_get_offb(self) - def __set_offb__(self, v): - _ida_ua.op_t_set_offb(self, v) - def __get_offo__(self): - return _ida_ua.op_t_get_offo(self) - def __set_offo__(self, v): - _ida_ua.op_t_set_offo(self, v) - def __get_flags__(self): - return _ida_ua.op_t_get_flags(self) - def __set_flags__(self, v): - _ida_ua.op_t_set_flags(self, v) - def __get_dtyp__(self): - return _ida_ua.op_t_get_dtyp(self) - def __set_dtyp__(self, v): - _ida_ua.op_t_set_dtyp(self, v) - def __get_reg_phrase__(self): - return _ida_ua.op_t_get_reg_phrase(self) - def __set_reg_phrase__(self, v): - _ida_ua.op_t_set_reg_phrase(self, v) - def __get_value__(self): - return _ida_ua.op_t_get_value(self) - def __set_value__(self, v): - _ida_ua.op_t_set_value(self, v) - def __get_addr__(self): - return _ida_ua.op_t_get_addr(self) - def __set_addr__(self, v): - _ida_ua.op_t_set_addr(self, v) - def __get_specval__(self): - return _ida_ua.op_t_get_specval(self) - def __set_specval__(self, v): - _ida_ua.op_t_set_specval(self, v) - def __get_specflag1__(self): - return _ida_ua.op_t_get_specflag1(self) - def __set_specflag1__(self, v): - _ida_ua.op_t_set_specflag1(self, v) - def __get_specflag2__(self): - return _ida_ua.op_t_get_specflag2(self) - def __set_specflag2__(self, v): - _ida_ua.op_t_set_specflag2(self, v) - def __get_specflag3__(self): - return _ida_ua.op_t_get_specflag3(self) - def __set_specflag3__(self, v): - _ida_ua.op_t_set_specflag3(self, v) - def __get_specflag4__(self): - return _ida_ua.op_t_get_specflag4(self) - def __set_specflag4__(self, v): - _ida_ua.op_t_set_specflag4(self, v) - - n = property(__get_n__, __set_n__) - type = property(__get_type__, __set_type__) - offb = property(__get_offb__, __set_offb__) - offo = property(__get_offo__, __set_offo__) - flags = property(__get_flags__, __set_flags__) - dtyp = property(__get_dtyp__, __set_dtyp__) - reg = property(__get_reg_phrase__, __set_reg_phrase__) - phrase = property(__get_reg_phrase__, __set_reg_phrase__) - value = property(__get_value__, __set_value__) - addr = property(__get_addr__, __set_addr__) - specval = property(__get_specval__, __set_specval__) - specflag1 = property(__get_specflag1__, __set_specflag1__) - specflag2 = property(__get_specflag2__, __set_specflag2__) - specflag3 = property(__get_specflag3__, __set_specflag3__) - specflag4 = property(__get_specflag4__, __set_specflag4__) - -# ---------------------------------------------------------------------- -# -# Misc constants -# -UA_MAXOP = 6 -"""The maximum number of operands in the insn_t structure""" - -# ----------------------------------------------------------------------- -class insn_t(ida_idaapi.py_clinked_object_t): - """Class representing instructions""" - def __init__(self, lnk = None): - ida_idaapi.py_clinked_object_t.__init__(self, lnk) - - # Create linked operands - self.Operands = [] - for i in xrange(0, UA_MAXOP): - self.Operands.append(op_t(insn_t_get_op_link(self.clink, i))) - - # Convenience operand reference objects - self.Op1 = self.Operands[0] - self.Op2 = self.Operands[1] - self.Op3 = self.Operands[2] - self.Op4 = self.Operands[3] - self.Op5 = self.Operands[4] - self.Op6 = self.Operands[5] - - def assign(self, other): - """Copies the contents of 'other' to 'self'""" - return _ida_ua.insn_t_assign(self, other) - -# -# def copy(self): -# """Returns a new copy of this class""" -# pass -# - - def _create_clink(self): - return _ida_ua.insn_t_create() - - - def _del_clink(self, lnk): - return _ida_ua.insn_t_destroy(lnk) - - - def __iter__(self): - return (self.Operands[idx] for idx in xrange(0, UA_MAXOP)) - - - def __getitem__(self, idx): - """ - Operands can be accessed directly as indexes - @return op_t: Returns an operand of type op_t - """ - if idx >= UA_MAXOP: - raise KeyError - else: - return self.Operands[idx] - - def is_macro(self): - return self.flags & INSN_MACRO != 0 - - def is_canon_insn(self): - return _ida_ua.insn_t_is_canon_insn(self.itype) - - def get_canon_feature(self): - return _ida_ua.insn_t_get_canon_feature(self.itype) - - def get_canon_mnem(self): - return _ida_ua.insn_t_get_canon_mnem(self.itype) - - # - # Autogenerated - # - def __get_cs__(self): - return _ida_ua.insn_t_get_cs(self) - def __set_cs__(self, v): - _ida_ua.insn_t_set_cs(self, v) - def __get_ip__(self): - return _ida_ua.insn_t_get_ip(self) - def __set_ip__(self, v): - _ida_ua.insn_t_set_ip(self, v) - def __get_ea__(self): - return _ida_ua.insn_t_get_ea(self) - def __set_ea__(self, v): - _ida_ua.insn_t_set_ea(self, v) - def __get_itype__(self): - return _ida_ua.insn_t_get_itype(self) - def __set_itype__(self, v): - _ida_ua.insn_t_set_itype(self, v) - def __get_size__(self): - return _ida_ua.insn_t_get_size(self) - def __set_size__(self, v): - _ida_ua.insn_t_set_size(self, v) - def __get_auxpref__(self): - return _ida_ua.insn_t_get_auxpref(self) - def __set_auxpref__(self, v): - _ida_ua.insn_t_set_auxpref(self, v) - def __get_segpref__(self): - return _ida_ua.insn_t_get_segpref(self) - def __set_segpref__(self, v): - _ida_ua.insn_t_set_segpref(self, v) - def __get_insnpref__(self): - return _ida_ua.insn_t_get_insnpref(self) - def __set_insnpref__(self, v): - _ida_ua.insn_t_set_insnpref(self, v) - def __get_flags__(self): - return _ida_ua.insn_t_get_flags(self) - def __set_flags__(self, v): - _ida_ua.insn_t_set_flags(self, v) - - cs = property(__get_cs__, __set_cs__) - ip = property(__get_ip__, __set_ip__) - ea = property(__get_ea__, __set_ea__) - itype = property(__get_itype__, __set_itype__) - size = property(__get_size__, __set_size__) - auxpref = property(__get_auxpref__, __set_auxpref__) - segpref = property(__get_segpref__, __set_segpref__) - insnpref = property(__get_insnpref__, __set_insnpref__) - flags = property(__get_flags__, __set_flags__) - - -# Create 'cmd' into the global scope -cmd = insn_t(_ida_ua.py_get_global_cmd_link()) -"""cmd is a global variable of type insn_t. It is contains information about the last decoded instruction. -This variable is also filled by processor modules when they decode instructions.""" - -# ---------------------------------------------------------------------- -# op_t related constants - -# -# op_t.type -# Description Data field -o_void = 0 # No Operand ---------- -o_reg = 1 # General Register (al,ax,es,ds...) reg -o_mem = 2 # Direct Memory Reference (DATA) addr -o_phrase = 3 # Memory Ref [Base Reg + Index Reg] phrase -o_displ = 4 # Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr -o_imm = 5 # Immediate Value value -o_far = 6 # Immediate Far Address (CODE) addr -o_near = 7 # Immediate Near Address (CODE) addr -o_idpspec0 = 8 # Processor specific type -o_idpspec1 = 9 # Processor specific type -o_idpspec2 = 10 # Processor specific type -o_idpspec3 = 11 # Processor specific type -o_idpspec4 = 12 # Processor specific type -o_idpspec5 = 13 # Processor specific type - # There can be more processor specific types - -# -# op_t.dtyp -# -dt_byte = 0 # 8 bit -dt_word = 1 # 16 bit -dt_dword = 2 # 32 bit -dt_float = 3 # 4 byte -dt_double = 4 # 8 byte -dt_tbyte = 5 # variable size (ph.tbyte_size) -dt_packreal = 6 # packed real format for mc68040 -dt_qword = 7 # 64 bit -dt_byte16 = 8 # 128 bit -dt_code = 9 # ptr to code (not used?) -dt_void = 10 # none -dt_fword = 11 # 48 bit -dt_bitfild = 12 # bit field (mc680x0) -dt_string = 13 # pointer to asciiz string -dt_unicode = 14 # pointer to unicode string -dt_3byte = 15 # 3-byte data -dt_ldbl = 16 # long double (which may be different from tbyte) -dt_byte32 = 17 # 256 bit -dt_byte64 = 18 # 512 bit - -# -# op_t.flags -# -OF_NO_BASE_DISP = 0x80 # o_displ: base displacement doesn't exist meaningful only for o_displ type if set, base displacement (x.addr) doesn't exist. -OF_OUTER_DISP = 0x40 # o_displ: outer displacement exists meaningful only for o_displ type if set, outer displacement (x.value) exists. -PACK_FORM_DEF = 0x20 # !o_reg + dt_packreal: packed factor defined -OF_NUMBER = 0x10 # can be output as number only if set, the operand can be converted to a number only -OF_SHOW = 0x08 # should the operand be displayed? if clear, the operand is hidden and should not be displayed - -# -# insn_t.flags -# -INSN_MACRO = 0x01 # macro instruction -INSN_MODMAC = 0x02 # macros: may modify the database to make room for the macro insn - +ua_mnem = print_insn_mnem # + +# +import ida_idaapi +@bc695redef +def codeSeg(ea, opnum): + insn = insn_t() + if decode_insn(insn, ea): + return _ida_ua.map_code_ea(insn, insn.ops[opnum]) + else: + return ida_idaapi.BADADDR +get_dtyp_by_size=get_dtype_by_size +get_dtyp_flag=get_dtype_flag +get_dtyp_size=get_dtype_size +get_operand_immvals=get_immvals +op_t.dtyp = op_t.dtype +cmd = insn_t() +@bc695redef +def decode_insn(*args): + if len(args) == 1: + tmp = insn_t() + rc = _ida_ua.decode_insn(tmp, args[0]) + cmd.assign(tmp) + return rc + else: + return _ida_ua.decode_insn(*args) +@bc695redef +def create_insn(*args): + if len(args) == 1: + tmp = insn_t() + rc = _ida_ua.create_insn(args[0], tmp) + cmd.assign(tmp) + return rc + else: + return _ida_ua.create_insn(*args) +@bc695redef +def decode_prev_insn(*args): + if len(args) == 1: + tmp = insn_t() + rc = _ida_ua.decode_prev_insn(tmp, args[0]) + cmd.assign(tmp) + return rc + else: + return _ida_ua.decode_prev_insn(*args) +@bc695redef +def decode_preceding_insn(*args): + if len(args) == 1: + tmp = insn_t() + rc = _ida_ua.decode_preceding_insn(tmp, args[0]) + cmd.assign(tmp) + return rc + else: + return _ida_ua.decode_preceding_insn(*args) +import ida_ida +UA_MAXOP=ida_ida.UA_MAXOP +dt_3byte=dt_byte +tbo_123=0 +tbo_132=0 +tbo_213=0 +tbo_231=0 +tbo_312=0 +tbo_321=0 +@bc695redef +def ua_add_cref(opoff, to, rtype): + return cmd.add_cref(to, opoff, rtype) +@bc695redef +def ua_add_dref(opoff, to, rtype): + return cmd.add_dref(to, opoff, rtype) +@bc695redef +def ua_add_off_drefs(x, rtype): + return cmd.add_off_drefs(x, rtype, 0) +@bc695redef +def ua_add_off_drefs2(x, rtype, outf): + return cmd.add_off_drefs(x, rtype, outf) +@bc695redef +def ua_dodata(ea, dtype): + return cmd.create_op_data(ea, 0, dtype) +@bc695redef +def ua_dodata2(opoff, ea, dtype): + return cmd.create_op_data(ea, opoff, dtype) +@bc695redef +def ua_stkvar2(x, v, flags): + return cmd.create_stkvar(x, v, flags) +# diff --git a/pywraps/py_xref.hpp b/pywraps/py_xref.hpp index c5fcdbd..1894994 100644 --- a/pywraps/py_xref.hpp +++ b/pywraps/py_xref.hpp @@ -31,11 +31,11 @@ idaman bool ida_export py_create_switch_xrefs( ea_t insn_ea, PyObject *py_swi) { - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); + switch_info_t *swi = switch_info_t_get_clink(py_swi); if ( swi == NULL ) return false; - create_switch_xrefs(insn_ea, swi); + create_switch_xrefs(insn_ea, *swi); return true; } @@ -74,12 +74,12 @@ idaman cases_and_targets_t *ida_export py_calc_switch_cases( ea_t insn_ea, PyObject *py_swi) { - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); + switch_info_t *swi = switch_info_t_get_clink(py_swi); if ( swi == NULL ) return NULL; cases_and_targets_t *ct = new cases_and_targets_t; - if ( !calc_switch_cases(insn_ea, swi, &ct->cases, &ct->targets) ) + if ( !calc_switch_cases(&ct->cases, &ct->targets, insn_ea, *swi) ) { delete ct; return NULL; @@ -108,11 +108,11 @@ idaman bool ida_export py_create_switch_table( ea_t insn_ea, PyObject *py_swi) { - switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); + switch_info_t *swi = switch_info_t_get_clink(py_swi); if ( swi == NULL ) return false; - create_switch_table(insn_ea, swi); + create_switch_table(insn_ea, *swi); return true; } // diff --git a/pywraps/pywraps.vcproj b/pywraps/pywraps.vcproj index 50335a9..4bcd7ba 100644 --- a/pywraps/pywraps.vcproj +++ b/pywraps/pywraps.vcproj @@ -1082,7 +1082,7 @@ > - - @@ -1154,7 +1150,7 @@ > = decorate_name) PR_USE64 = 0x002000 # supports 64-bit addressing? PR_SGROTHER = 0x004000 # the segment registers don't contain # the segment selectors, something else @@ -212,13 +212,11 @@ PR_BINMEM = 0x010000 # the processor module provides correct PR_SEGTRANS = 0x020000 # the processor module supports # the segment translation feature # (it means it calculates the code - # addresses using the codeSeg() function) + # addresses using the map_code_ea() function) PR_CHK_XREF = 0x040000 # don't allow near xrefs between segments # with different bases PR_NO_SEGMOVE = 0x080000 # the processor module doesn't support move_segm() # (i.e. the user can't move segments) -PR_FULL_HIFXP = 0x100000 # REF_VHIGH operand value contains full operand - # not only the high bits. Meaningful if ph.high_fixup_bits PR_USE_ARG_TYPES = 0x200000 # use ph.use_arg_types callback PR_SCALE_STKVARS = 0x400000 # use ph.get_stkvar_scale callback PR_DELAYED = 0x800000 # has delayed jumps and calls @@ -241,7 +239,7 @@ OOFS_NEEDSIGN = 0x0002 # always out sign (+-) OOF_SIGNED = 0x0004 # output as signed if < 0 OOF_NUMBER = 0x0008 # always as a number OOF_WIDTHMASK = 0x0070 # width of value in bits: -OOFW_IMM = 0x0000 # take from x.dtyp +OOFW_IMM = 0x0000 # take from x.dtype OOFW_8 = 0x0010 # 8 bit width OOFW_16 = 0x0020 # 16 bit width OOFW_24 = 0x0030 # 24 bit width @@ -249,7 +247,7 @@ OOFW_32 = 0x0040 # 32 bit width OOFW_64 = 0x0050 # 32 bit width OOF_ADDR = 0x0080 # output x.addr, otherwise x.value OOF_OUTER = 0x0100 # output outer operand -OOF_ZSTROFF = 0x0200 # meaningful only if isStroff(uFlag) +OOF_ZSTROFF = 0x0200 # meaningful only if is_stroff(uFlag) # append a struct field name if # the field offset is zero? # if AFL_ZSTROFF is set, then this flag @@ -272,7 +270,7 @@ class insn_t(object): self.n = 0 self.segpref = 0 self.size = 0 - self.Operands = [] + self.ops = [] # store the number of operands self.n = noperands @@ -281,16 +279,16 @@ class insn_t(object): for i in xrange(0, noperands): op = op_t() op.n = i - self.Operands.append(op) + self.ops.append(op) setattr(self, 'Op%d' % (i+1), op) def __getitem__(self, i): - return self.Operands[i] + return self.ops[i] # ---------------------------------------------------------------------- class op_t(object): def __init__(self): self.addr = 0 - self.dtyp = 0 + self.dtype = 0 self.flags = 0 self.n = 0 self.offb = 0 diff --git a/swig/area.i b/swig/area.i deleted file mode 100644 index adf220c..0000000 --- a/swig/area.i +++ /dev/null @@ -1,56 +0,0 @@ -%ignore ANODE; -%ignore ANODE2; -%ignore AREA_LONG_COMMENT_TAG; -%ignore area_visitor_t; - -// Ignore the private members in areacb_t -%ignore areacb_t::areasCode; -%ignore areacb_t::infosize; -%ignore areacb_t::lastreq; -%ignore areacb_t::reserved; -%ignore areacb_t::areas; -%ignore areacb_t::move_area_comment; -%ignore areacb_t::pack_and_write_area; -%ignore areacb_t::move_away; - -%ignore areacb_t::read_cb; -%ignore areacb_t::write_cb; -%ignore areacb_t::delcache_cb; -%ignore areacb_t::edit_cb; -%ignore areacb_t::kill_cb; -%ignore areacb_t::new_cb; - -%ignore areacb_t::choose_area; -%ignore areacb_t::choose_area2; -%ignore areacb_t::find_prev_gap; -%ignore areacb_t::find_next_gap; - -%ignore areacb_t::move_areas; -%ignore areacb_t::for_all_areas; - -%ignore areaset_t::count; -%ignore areaset_t::lower_bound; -%ignore areaset_t::upper_bound; -%ignore areaset_t::move_chunk; -%ignore areaset_t::check_move_args; - -%inline %{ -// -// -%} - -%include "area.hpp" - -%extend areacb_t { - areacb_type_t get_type() - { - areacb_type_t t = AREACB_TYPE_UNKNOWN; - if ( $self == &funcs ) - t = AREACB_TYPE_FUNC; - else if ( $self == &segs ) - t = AREACB_TYPE_SEGMENT; - else if ( $self == &hidden_areas ) - t = AREACB_TYPE_HIDDEN_AREA; - return t; - } -} diff --git a/swig/auto.i b/swig/auto.i index 65ce048..669ccd3 100644 --- a/swig/auto.i +++ b/swig/auto.i @@ -2,10 +2,5 @@ #include %} -%ignore autoPlanned; -%ignore nextPlanned; -%ignore autoPeek; -%ignore autoProcess; - %include "auto.hpp" diff --git a/swig/bytes.i b/swig/bytes.i index 76a11c4..e98cd8b 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -2,14 +2,12 @@ #include %} -%import "area.i" +%import "range.i" // Unexported and kernel-only declarations -%ignore FlagsEnable; -%ignore FlagsDisable; %ignore testf_t; -%ignore nextthat; -%ignore prevthat; +%ignore next_that; +%ignore prev_that; %ignore adjust_visea; %ignore prev_visea; %ignore next_visea; @@ -17,19 +15,15 @@ %ignore is_first_visea; %ignore is_last_visea; %ignore is_visible_finally; -%ignore fluFlags; %ignore setFlbits; %ignore clrFlbits; %ignore get_8bit; %ignore get_ascii_char; %ignore del_opinfo; %ignore del_one_opinfo; -%ignore doCode; %ignore get_repeatable_cmt; %ignore get_any_indented_cmt; %ignore del_code_comments; -%ignore doFlow; -%ignore noFlow; %ignore coagulate; %ignore FlagsInit; @@ -37,19 +31,23 @@ %ignore FlagsReset; %ignore flush_flags; %ignore get_flags_linput; -%ignore data_type_t; -%ignore data_format_t; -%ignore get_custom_data_type; -%ignore get_custom_data_format; -%ignore unregister_custom_data_format; -%ignore register_custom_data_format; -%ignore unregister_custom_data_type; -%ignore register_custom_data_type; -%ignore get_many_bytes; -%ignore get_many_bytes_ex; -%ignore get_ascii_contents; -%ignore get_ascii_contents2; +%ignore data_type_t::data_type_t(); +%ignore data_type_t::cbsize; +%ignore data_type_t::ud; +%ignore data_type_t::may_create_at; +%ignore data_type_t::calc_item_size; +%ignore data_format_t::data_format_t(); +%ignore data_format_t::cbsize; +%ignore data_format_t::ud; +%ignore data_format_t::print; +%ignore data_format_t::scan; +%ignore data_format_t::analyze; + +%ignore get_bytes; +%ignore get_strlit_contents; %ignore get_hex_string; +%ignore bin_search; // we redefine our own, w/ 2 params swapped, so we can apply the typemaps below +%rename (bin_search) py_bin_search; // TODO: This could be fixed (if needed) %ignore set_dbgmem_source; @@ -64,8 +62,120 @@ } } +%ignore unregister_custom_data_format; +%rename (unregister_custom_data_format) py_unregister_custom_data_format; +%ignore register_custom_data_format; +%rename (register_custom_data_format) py_register_custom_data_format; +%ignore unregister_custom_data_type; +%rename (unregister_custom_data_type) py_unregister_custom_data_type; +%ignore register_custom_data_type; +%rename (register_custom_data_type) py_register_custom_data_type; +%ignore print_strlit_type; +%rename (print_strlit_type) py_print_strlit_type; + +%{ +// +// +%} + +%{ +// +// +%} + +%extend data_type_t +{ + data_type_t( + PyObject *self, + const char *name, + asize_t value_size=0, + const char *menu_name=NULL, + const char *hotkey=NULL, + const char *asm_keyword=NULL, + int props=0) + { + py_custom_data_type_t *inst = new py_custom_data_type_t( + self, + name, + value_size, + menu_name, + hotkey, + asm_keyword, + props); + return inst; + } + + ~data_type_t() + { + delete (py_custom_data_type_t *) $self; + } + + int __get_id() { return py_custom_data_type_t_get_id($self); } + + %pythoncode + { + id = property(__get_id) + __real__init__ = __init__ + def __init__(self, *args): + self.__real__init__(self, *args) # pass 'self' as part of args +#ifdef BC695 + if _BC695: + def __init__(self, name, value_size = 0, menu_name = None, hotkey = None, asm_keyword = None, props = 0): + args = (name, value_size, menu_name, hotkey, asm_keyword, props) + self.__real__init__(self, *args) # pass 'self' as part of args +#endif + } +} + +%extend data_format_t +{ + data_format_t( + PyObject *self, + const char *name, + asize_t value_size=0, + const char *menu_name=NULL, + int props=0, + const char *hotkey=NULL, + int32 text_width=0) + { + py_custom_data_format_t *inst = new py_custom_data_format_t( + self, + name, + value_size, + menu_name, + props, + hotkey, + text_width); + return inst; + } + + ~data_format_t() + { + delete (py_custom_data_format_t *) $self; + } + + int __get_id() { return py_custom_data_format_t_get_id($self); } + + %pythoncode + { + id = property(__get_id) + __real__init__ = __init__ + def __init__(self, *args): + self.__real__init__(self, *args) # pass 'self' as part of args +#ifdef BC695 + if _BC695: + def __init__(self, name, value_size = 0, menu_name = None, props = 0, hotkey = None, text_width = 0): + args = (name, value_size, menu_name, props, hotkey, text_width) + self.__real__init__(self, *args) # pass 'self' as part of args +#endif + } +} + %include "bytes.hpp" +%apply (char *STRING, int LENGTH) { (const uchar *image, size_t len) }; +%apply (char *) { (const uchar *mask) }; + %clear(void *buf, ssize_t size); %clear(const void *buf, size_t size); @@ -73,22 +183,12 @@ %clear(opinfo_t *); %rename (visit_patched_bytes) py_visit_patched_bytes; -%rename (nextthat) py_nextthat; -%rename (prevthat) py_prevthat; -%rename (get_custom_data_type) py_get_custom_data_type; -%rename (get_custom_data_format) py_get_custom_data_format; -%rename (unregister_custom_data_format) py_unregister_custom_data_format; -%rename (register_custom_data_format) py_register_custom_data_format; -%rename (unregister_custom_data_type) py_unregister_custom_data_type; -%rename (register_custom_data_type) py_register_custom_data_type; -%rename (get_many_bytes) py_get_many_bytes; -%rename (get_many_bytes_ex) py_get_many_bytes_ex; -%rename (get_ascii_contents) py_get_ascii_contents; -%rename (get_ascii_contents2) py_get_ascii_contents2; -%{ -// -// -%} +%rename (next_that) py_next_that; +%rename (prev_that) py_prev_that; + +%rename (get_bytes) py_get_bytes; +%rename (get_bytes_and_mask) py_get_bytes_and_mask; +%rename (get_strlit_contents) py_get_strlit_contents; %inline %{ // @@ -100,11 +200,6 @@ # %} -%{ -// -// -%} - %inline %{ // // diff --git a/swig/dbg.i b/swig/dbg.i index 0ddcbc3..35bf83b 100644 --- a/swig/dbg.i +++ b/swig/dbg.i @@ -12,6 +12,8 @@ %ignore internal_cleanup_appcall; %ignore change_bptlocs; %ignore movbpt_info_t; +%ignore lock_dbgmem_config; +%ignore unlock_dbgmem_config; %ignore source_file_t; %ignore source_item_t; diff --git a/swig/diskio.i b/swig/diskio.i index d675a63..070e564 100644 --- a/swig/diskio.i +++ b/swig/diskio.i @@ -8,7 +8,6 @@ // TODO: These could be wrapped %ignore enumerate_files; %rename (enumerate_files) py_enumerate_files; -%ignore enumerate_system_files; %ignore ioport_bit_t; %ignore ioport_bits_t; %ignore ioport_t; @@ -19,7 +18,6 @@ %ignore free_ioports; %ignore lread; %ignore qlread; -%ignore efilelength; %ignore qlgets; %ignore qlgetc; %ignore lreadbytes; @@ -36,18 +34,39 @@ %ignore make_linput; %ignore unmake_linput; -// FIXME: These should be wrapped for completeness %ignore eread; %ignore ewrite; +%ignore eseek; +%ignore ecreate; +%ignore openR; +%ignore openRT; +%ignore openM; +// some of these functions are used in idc.py: +// %ignore eclose; +// %ignore fopenWT; +// %ignore fopenWB; +// %ignore fopenRT; +// %ignore fopenRB; +// %ignore fopenM; +// %ignore fopenA; + +%ignore qfsize; +%ignore echsize; +%ignore get_free_disk_space; +%ignore call_system; // Ignore kernel-only & unexported symbols %ignore get_thread_priority; -%ignore set_thread_priority; -%ignore checkdspace; %ignore lowdiskgo; %ignore ida_argv; %ignore exename; +%ignore create_bytearray_linput; +%rename (create_bytearray_linput) py_create_bytearray_linput; + +%ignore close_linput; +%rename (close_linput) py_close_linput; + %include "diskio.hpp" %{ diff --git a/swig/enum.i b/swig/enum.i index 78fba87..03b76ee 100644 --- a/swig/enum.i +++ b/swig/enum.i @@ -1,29 +1,8 @@ %{ #include %} -// Kernel only & unexported symbols -%ignore enums; -%ignore init_enums; -%ignore save_enums; -%ignore term_enums; -%ignore set_enum_flag(enum_t, uint32, bool); %ignore get_enum_name(tid_t); -%ignore get_selected_enum; -%ignore add_selected_enum; -%ignore unmark_selected_enums; -%ignore ENUM_REVERSE; -%ignore ENUM_SELMEMS; -%ignore ENUM_QTY_IDX; -%ignore ENUM_FLG_IDX; -%ignore ENUM_FLAGS; -%ignore ENUM_FLAGS_IS_BF; -%ignore ENUM_FLAGS_HIDDEN; -%ignore ENUM_MASKS; -%ignore ENUM_MEMBERS; -%ignore CONST_ENUM; -%ignore CONST_VALUE; -%ignore CONST_BMASK; -%ignore CONST_SERIAL; -%ignore CONST_SERIALS; + +%constant bmask_t DEFMASK = bmask_t(-1); %include "enum.hpp" diff --git a/swig/expr.i b/swig/expr.i index 872d5f7..c5291fd 100644 --- a/swig/expr.i +++ b/swig/expr.i @@ -1,17 +1,28 @@ -%ignore extfun_t; -%ignore funcset_t; +%ignore ext_idcfunc_t; +%ignore idcfuncs_t; %ignore extlang_t; -%ignore extlang; +%ignore extlang_object_t; +%ignore extlang_ptr_t; %ignore extlangs_t; %ignore extlangs; -%ignore register_extlang; -%ignore IDCFuncs; -%ignore set_idc_func; +%ignore install_extlang; +%ignore remove_extlang; +%ignore select_extlang; +%ignore get_extlang; +%ignore get_current_extlang; +%ignore find_extlang; +%ignore find_extlang_by_ext; +%ignore find_extlang_by_name; +%ignore find_extlang_by_index; +%ignore find_extlang_kind_t; +%ignore for_all_extlangs; +%ignore extlang_visitor_t; %ignore set_idc_dtor; %ignore set_idc_method; %ignore set_idc_getattr; %ignore set_idc_setattr; -%ignore set_idc_func_ex; +%ignore add_idc_func; +%ignore del_idc_func; %ignore VarLong; %ignore VarNum; %ignore extlang_get_attr_exists; @@ -25,36 +36,38 @@ %ignore get_extlangs; %ignore create_idc_object; %ignore run_script_func; -%ignore VarString; %ignore VarFloat; %ignore VarFree; -%ignore calcexpr_long; -%ignore Run; -%ignore ExecuteLine; -%ignore ExecuteFile; +%ignore eval_expr_long; +%ignore call_idc_func; +%ignore eval_idc_snippet; %ignore set_idc_func_body; %ignore get_idc_func_body; %ignore idc_vars; %ignore setup_lowcnd_regfuncs; %ignore syntax_highlighter_t; %ignore get_idptype_and_data; -%cstring_output_maxstr_none(char *errbuf, size_t errbufsize); +%ignore idc_resolver_t; +%ignore idc_value_t::_set_long; +%ignore idc_value_t::_set_float; +%ignore idc_value_t::_set_int64; +%ignore idc_value_t::_set_pvoid; +%ignore idc_value_t::_set_string; -%ignore CompileEx; -%rename (CompileEx) CompileEx_wrap; -%ignore Compile; -%rename (Compile) Compile_wrap; -%ignore calcexpr; -%rename (calcexpr) calcexpr_wrap; -%ignore calc_idc_expr; -%rename (calc_idc_expr) calc_idc_expr_wrap; -%ignore CompileLine(const char *line, char *errbuf, size_t errbufsize, uval_t (idaapi*_getname)(const char *name)=NULL); -%ignore CompileLineEx; -%ignore CompileLine; -%rename (CompileLine) CompileLine_wrap; +%ignore eval_expr; +%rename (eval_expr) py_eval_expr; +%ignore eval_idc_expr; +%rename (eval_idc_expr) py_eval_idc_expr; +%ignore compile_idc_file; +%rename (compile_idc_file) py_compile_idc_file; +%ignore compile_idc_text; +%rename (compile_idc_text) py_compile_idc_text; %nonnul_argument_prototype( - bool CompileLine_wrap(const char *nonnul_line, char *errbuf, size_t errbufsize), + bool py_compile_idc_file(const char *nonnul_line, qstring *errbuf), + const char *nonnul_line); +%nonnul_argument_prototype( + bool py_compile_idc_text(const char *nonnul_line, qstring *errbuf), const char *nonnul_line); %{ // @@ -68,6 +81,21 @@ %include "expr.hpp" +%extend idc_value_t +{ + %pythoncode { + str = property(lambda self: self.c_str(), lambda self, v: self.set_string(v)) + } +} + +%ignore qvector::operator==; +%ignore qvector::operator!=; +%ignore qvector::find; +%ignore qvector::has; +%ignore qvector::del; +%ignore qvector::add_unique; +%template(idc_values_t) qvector; + %pythoncode %{ # # diff --git a/swig/fixup.i b/swig/fixup.i index 22543ef..009569c 100644 --- a/swig/fixup.i +++ b/swig/fixup.i @@ -3,14 +3,8 @@ %} %ignore apply_fixup; -%ignore custom_fixup_handler_t; -%ignore custom_fixup_handlers_t; +%ignore fixup_handler_t; %ignore register_custom_fixup; %ignore unregister_custom_fixup; -%ignore set_custom_fixup; - -%nonnul_argument_prototype( - idaman void ida_export set_fixup(ea_t source, const fixup_data_t *nonnul_fp), - const fixup_data_t *nonnul_fp); %include "fixup.hpp" diff --git a/swig/frame.i b/swig/frame.i index b76e32c..e5c4d27 100644 --- a/swig/frame.i +++ b/swig/frame.i @@ -2,7 +2,7 @@ #include %} -%import "area.i" +%import "range.i" %ignore add_frame_spec_member; %ignore del_stkvars; @@ -14,9 +14,6 @@ %ignore get_stkvar; %rename (get_stkvar) py_get_stkvar; -%ignore add_stkvar3; -%rename (add_stkvar3) py_add_stkvar3; - %ignore calc_frame_offset; %ignore add_stkvar; diff --git a/swig/funcs.i b/swig/funcs.i index 0678b01..c6322c1 100644 --- a/swig/funcs.i +++ b/swig/funcs.i @@ -1,8 +1,5 @@ -%import "area.i" - -%cstring_bounded_output_none(char *buf, MAXSTR); -%cstring_bounded_output_none(char *optlibs, MAXSTR); +%import "range.i" // FIXME: Are these really useful? %ignore iterate_func_chunks; @@ -17,9 +14,6 @@ %rename (get_idasgn_desc) py_get_idasgn_desc; %rename (get_idasgn_desc_with_matches) py_get_idasgn_desc_with_matches; -%ignore get_func_cmt; -%rename (get_func_cmt) py_get_func_cmt; - %include "funcs.hpp" %clear(char *buf); @@ -29,3 +23,8 @@ // // %} + +%pythoncode %{ +# +# +%} diff --git a/swig/gdl.i b/swig/gdl.i index 3d27551..8bacc3b 100644 --- a/swig/gdl.i +++ b/swig/gdl.i @@ -2,7 +2,7 @@ #include %} -%import "area.i" +%import "range.i" %ignore cancellable_graph_t; %ignore gdl_graph_t; diff --git a/swig/graph.i b/swig/graph.i index 5cf8440..d40069a 100644 --- a/swig/graph.i +++ b/swig/graph.i @@ -1,10 +1,74 @@ %{ #include %} -%ignore mutable_graph_t; -%ignore graph_visitor_t; + +// "Warning 305: Bad constant value (ignored).", on: +// #define GCC_PUREVIRT = 0 +#pragma SWIG nowarn=305 + +// "Warning 473: Returning a pointer or reference in a director method is not recommended." +%warnfilter(473) mutable_graph_t::nrect; +%warnfilter(473) place_t::clone; +%warnfilter(473) place_t::makeplace; +%warnfilter(473) place_t::name; +%warnfilter(473) place_t::enter; + +// "Warning 517: Director class 'mutable_graph_t' can't be constructed" +%warnfilter(517) mutable_graph_t; + +// most of these aren't defined/exported through graph.hpp +%ignore abstract_graph_t::callback; %ignore abstract_graph_t; +%ignore edge_info_t::add_layout_point; +%ignore edge_infos_wrapper_t::edge_infos_wrapper_t; +%ignore edge_infos_wrapper_t::~edge_infos_wrapper_t; +%ignore graph_dispatcher; +%ignore graph_item_t::operator==; +%ignore mutable_graph_t::add_edge; +%ignore mutable_graph_t::add_node; +%ignore mutable_graph_t::calc_center_of; +%ignore mutable_graph_t::change_visibility; +%ignore mutable_graph_t::check_new_group; +%ignore mutable_graph_t::clone; +%ignore mutable_graph_t::del_edge; +%ignore mutable_graph_t::del_node; +%ignore mutable_graph_t::fix_collapsed_group_edges; +%ignore mutable_graph_t::get_edge; +%ignore mutable_graph_t::groups_are_present; +%ignore mutable_graph_t::insert_simple_nodes; +%ignore mutable_graph_t::insert_visible_nodes; +%ignore mutable_graph_t::move_grouped_nodes; +%ignore mutable_graph_t::move_to_same_place; +%ignore mutable_graph_t::mutable_graph_t; +%ignore mutable_graph_t::redo_layout; +%ignore mutable_graph_t::refresh; +%ignore mutable_graph_t::replace_edge; +%ignore mutable_graph_t::resize; +%ignore mutable_graph_t::set_nrect; +%ignore node_ordering_t::clr; +%ignore node_ordering_t::order; +%ignore point_t::dstr; +%ignore point_t::print; +%ignore pointseq_t::dstr; +%ignore pointseq_t::print; +%ignore rect_t::operator<; +%ignore selection_item_t::selection_item_t(class graph_item_t &); +%feature("nodirector") user_graph_place_t; + +// Those were deprecated before they were available +// to IDAPython, so let's keep it that way. +%ignore viewer_add_menu_item; +%ignore viewer_del_menu_item; + +%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; } +} + %include "graph.hpp" +%ignore graph_visitor_t::visit_node; +%ignore graph_visitor_t::visit_edge; %{ // diff --git a/swig/hexrays.i b/swig/hexrays.i index e4aa107..9828e24 100644 --- a/swig/hexrays.i +++ b/swig/hexrays.i @@ -10,11 +10,6 @@ static void _kludge_use_TPopupMenu(TPopupMenu *) {} %} %inline %{ -namespace Menus -{ - class TPopupMenu; -} -using Menus::TPopupMenu; static void _kludge_use_TPopupMenu(TPopupMenu *m); %} @@ -53,9 +48,11 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); #define AS_PRINTF(format_idx, varg_idx) %ignore vd_printer_t::vprint; +%ignore vd_printer_t::tmpbuf; %ignore string_printer_t::vprint; %ignore vdui_t::vdui_t; %ignore cblock_t::find; +%ignore citem_t::op; %ignore cfunc_t::cfunc_t; %ignore cfunc_t::sv; // lazy member. Use get_pseudocode() instead %ignore cfunc_t::boundaries; // lazy member. Use get_boundaries() instead @@ -88,6 +85,33 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %ignore file_printer_t::_print; %ignore file_printer_t; %ignore qstring_printer_t::qstring_printer_t(const cfunc_t *, qstring &, bool); +%rename (_replace_by) cinsn_t::replace_by; +%rename (_replace_by) cexpr_t::replace_by; +%ignore vcall_helper; +%ignore vcreate_helper; + +%apply uchar { char ignore_micro }; +%feature("nodirector") udc_filter_t::apply; + +// The following must: +// - transfer ownership to the result object, if the argument object had it +// That's because we don't know when one of those functions create +// a new object under the hood +%rename (_ll_lnot) lnot; +%rename (_ll_make_ref) make_ref; +%rename (_ll_dereference) dereference; + +// The following must: +// - mark new object as being owned +// - disown the 'args' object passed as parameter +%rename (_ll_call_helper) call_helper; + +// The following must: +// - mark new object as being owned +%rename (_ll_new_block) new_block; +%rename (_ll_make_num) make_num; +%rename (_ll_create_helper) create_helper; + %extend cfunc_t { %immutable argidx; @@ -120,7 +144,7 @@ static void _kludge_use_TPopupMenu(TPopupMenu *m); %rename(dereference_uint16) operator uint16*; %rename(dereference_const_uint16) operator const uint16*; -#if !defined(__MAC__) || (MACSDKVER >= 1060) +#if !defined(__MAC__) || (MACSDKVER >= 1006) #define HAS_MAP_AT #endif @@ -140,67 +164,223 @@ public: } #endif +//------------------------------------------------------------------------- +%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)); } + + %pythoncode { + obj_id = property(_obj_id) + op = property( + _get_op, + lambda self, v: self._ensure_no_op() and self._set_op(v)) + + 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)) + return True + + def _acquire_ownership(self, v, acquire): + if acquire and (v is not None) and not isinstance(v, (int, long)): + if not v.thisown: + raise Exception("%s is already owned, and cannot be reused" % v) + v.thisown = False + dereg = getattr(v, "_deregister", None) + if dereg: + dereg() + return True + + def _maybe_disown_and_deregister(self): + if self.thisown: + self.thisown = False + self._deregister() + + def _own_and_register(self): + assert(not self.thisown) + self.thisown = True + self._register() + + def replace_by(self, o): + assert(isinstance(o, (cexpr_t, cinsn_t))) + o._maybe_disown_and_deregister() + self._replace_by(o) + } }; -//--------------------------------------------------------------------- -// swig doesn't very much like the way the union is done in this class so we need to wrap all these up. -#define CITEM_MEMBER_REF(name) \ - c##name##_t *c##name const { if ( self->op == cit_##name ) { return self->c##name; } else { return NULL; } } - -%extend cinsn_t { - CITEM_MEMBER_REF(block); - CITEM_MEMBER_REF(expr); - CITEM_MEMBER_REF(if); - CITEM_MEMBER_REF(for); - CITEM_MEMBER_REF(while); - CITEM_MEMBER_REF(do); - CITEM_MEMBER_REF(switch); - CITEM_MEMBER_REF(return); - CITEM_MEMBER_REF(goto); - CITEM_MEMBER_REF(asm); - - bool is_epilog() const { return $self == INS_EPILOG; } -}; -#undef CITEM_MEMBER_REF - //------------------------------------------------------------------------- -#define CEXPR_MEMBER_REF(type, name) \ - type name const { return self->##name; } +#define ___MEMBER_REF_BASE(Type, PName, Cond, Defval, Acquire, Setexpr) \ + Type _get_##PName() const { return self->##PName; } \ + void _set_##PName(Type _v) { self->##PName = Setexpr; } \ + %pythoncode { \ + PName = property( \ + lambda self: self._get_##PName() if Cond else Defval, \ + lambda self, v: Cond \ + and self._ensure_no_obj(self._get_##PName(), #PName, Acquire) \ + and self._acquire_ownership(v, Acquire) \ + and self._set_##PName(v)) \ + } -#define CEXPR_CONDITIONAL_MEMBER_REF(type, name, condition, default_value) \ - type name const { if ( condition ) { return self->##name; } else { return default_value; } } + +//--------------------------------------------------------------------- +// cinsn_t +//--------------------------------------------------------------------- +#define CINSN_MEMBER_REF(Name) \ + ___MEMBER_REF_BASE(c##Name##_t*, c##Name, self.op == cit_##Name, None, True, _v) + +%extend cinsn_t { + cinsn_t(void) + { + cinsn_t *ci = new cinsn_t(); + ci->cblock = NULL; // force clean instance + hexrays_register_python_clearable_instance(ci, hxclr_cinsn); + return ci; + } + + ~cinsn_t(void) + { + hexrays_deregister_python_clearable_instance($self); + delete $self; + } + + 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); + CINSN_MEMBER_REF(for); + CINSN_MEMBER_REF(while); + CINSN_MEMBER_REF(do); + CINSN_MEMBER_REF(switch); + CINSN_MEMBER_REF(return); + CINSN_MEMBER_REF(goto); + CINSN_MEMBER_REF(asm); + + static bool insn_is_epilog(const cinsn_t *insn) const { return insn == INS_EPILOG; } + + %pythoncode { + def is_epilog(self): + return cinsn_t.insn_is_epilog(self) + } +}; +%ignore cinsn_t::cinsn_t; +#undef CINSN_MEMBER_REF + +//------------------------------------------------------------------------- +// cexpr_t +//------------------------------------------------------------------------- +#define CEXPR_MEMBER_REF(Type, PName, Cond, Defval, Acquire) \ + ___MEMBER_REF_BASE(Type, PName, Cond, Defval, Acquire, _v) + +#define CEXPR_MEMBER_REF_STR(Type, PName, Cond, Defval) \ + ___MEMBER_REF_BASE(Type, PName, Cond, Defval, False, ::qstrdup(_v)) %extend cexpr_t { - CEXPR_CONDITIONAL_MEMBER_REF(cnumber_t*, n, self->op == cot_num, NULL); - CEXPR_CONDITIONAL_MEMBER_REF(fnumber_t*, fpc, self->op == cot_fnum, NULL); - var_ref_t* v const { if ( self->op == cot_var ) { return &self->v; } else { return NULL; } } - CEXPR_CONDITIONAL_MEMBER_REF(ea_t, obj_ea, self->op == cot_obj, BADADDR); - CEXPR_MEMBER_REF(int, refwidth); - CEXPR_CONDITIONAL_MEMBER_REF(cexpr_t*, x, op_uses_x(self->op), NULL); - CEXPR_CONDITIONAL_MEMBER_REF(cexpr_t*, y, op_uses_y(self->op), NULL); - CEXPR_CONDITIONAL_MEMBER_REF(carglist_t*, a, self->op == cot_call, NULL); - CEXPR_CONDITIONAL_MEMBER_REF(int, m, self->op == cot_memptr || self->op == cot_memref, 0); - CEXPR_CONDITIONAL_MEMBER_REF(cexpr_t*, z, op_uses_z(self->op), NULL); - CEXPR_CONDITIONAL_MEMBER_REF(int, ptrsize, self->op == cot_ptr || self->op == cot_memptr, 0); - CEXPR_MEMBER_REF(cinsn_t*, insn); - CEXPR_CONDITIONAL_MEMBER_REF(char*, helper, self->op == cot_helper, NULL); - CEXPR_CONDITIONAL_MEMBER_REF(char*, string, self->op == cot_str, NULL); -}; + cexpr_t(void) + { + cexpr_t *ce = new cexpr_t(); + hexrays_register_python_clearable_instance(ce, hxclr_cexpr); + return ce; + } -#undef CEXPR_CONDITIONAL_MEMBER_REF + ~cexpr_t(void) + { + hexrays_deregister_python_clearable_instance($self); + delete $self; + } + + 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; } } + void set_v(const var_ref_t *v) { if ( self->op == cot_var ) { self->v = *v; } } + %pythoncode { + v = property(lambda self: self.get_v(), lambda self, v: self.set_v(v)) + } + CEXPR_MEMBER_REF(ea_t, obj_ea, self.op == cot_obj, ida_idaapi.BADADDR, False); + CEXPR_MEMBER_REF(int, refwidth, True, 0, False); + CEXPR_MEMBER_REF(cexpr_t*, x, op_uses_x(self.op), None, True); + CEXPR_MEMBER_REF(cexpr_t*, y, op_uses_y(self.op), None, True); + CEXPR_MEMBER_REF(carglist_t*, a, self.op == cot_call, None, True); + CEXPR_MEMBER_REF(int, m, (self.op == cot_memptr or self.op == cot_memref), 0, False); + CEXPR_MEMBER_REF(cexpr_t*, z, op_uses_z(self.op), None, True); + CEXPR_MEMBER_REF(int, ptrsize, (self.op == cot_ptr or self.op == cot_memptr), 0, False); + CEXPR_MEMBER_REF(cinsn_t*, insn, self.op == cot_insn, None, True); + CEXPR_MEMBER_REF_STR(char*, helper, self.op == cot_helper, None); + CEXPR_MEMBER_REF_STR(char*, string, self.op == cot_str, None); +}; +%ignore cexpr_t::cexpr_t; + +#undef CEXPR_MEMBER_REF_STR #undef CEXPR_MEMBER_REF //------------------------------------------------------------------------- -#define CTREE_ITEM_MEMBER_REF(type, name) \ - type name const { return self->##name; } +// ctree_item_t +//------------------------------------------------------------------------- +// FIXME: I can't enable setters, because the ctree_item_t doesn't +// have a cleanup() function that would greatly help getting rid of +// objects that were referenced by SWiG proxies, but which have been +// de-owned (see cexpr_t above.) +// #define CTREE_ITEM_MEMBER_REF(type, name) \ +// type get_##name() const { return self->##name; } \ +// void set_##name(type _v) { self->##name = _v; } \ +// %pythoncode { \ +// name = property(lambda self: self.get_##name(), lambda self, v: self.set_##name(v)) \ +// } +// +// #define CTREE_CONDITIONAL_ITEM_MEMBER_REF(type, name, wanted_citype) \ +// type get_##name() const { if ( self->citype == wanted_citype ) { return self->##name; } else { return NULL; } } \ +// void set_##name(type _v) { if ( self->citype == wanted_citype ) { self->##name = _v; } } \ +// %pythoncode { \ +// name = property(lambda self: self.get_##name(), lambda self, v: self.set_##name(v)) \ +// } + +#define CTREE_ITEM_MEMBER_REF(type, name) \ + type _get_##name() const { return self->##name; } \ + %pythoncode { \ + name = property(lambda self: self._get_##name()) \ + } + +#define CTREE_CONDITIONAL_ITEM_MEMBER_REF(type, name, wanted_citype) \ + type _get_##name() const \ + { \ + if ( self->citype == wanted_citype ) \ + return self->##name; \ + else \ + return NULL; \ + } \ + %pythoncode { \ + name = property(lambda self: self._get_##name()) \ + } -#define CTREE_CONDITIONAL_ITEM_MEMBER_REF(type, name, wanted_citype) \ - type name const { if ( self->citype == wanted_citype ) { return self->##name; } else { return NULL; } } %extend ctree_item_t { CTREE_ITEM_MEMBER_REF(citem_t *, it); @@ -259,7 +439,13 @@ typedef qvector strvec_t; %template(user_unions_t) std::map; %template(cinsnptrvec_t) qvector; %template(eamap_t) std::map; -%template(boundaries_t) std::map; +%template(boundaries_t) std::map; + +%ignore boundaries_find; +%rename (boundaries_find) py_boundaries_find; +%ignore boundaries_insert; +%rename (boundaries_insert) py_boundaries_insert; + // WARNING: The order here is VERY important: // 1) The '%extend' directive. Note that // - the template name must be used, not the typedef (i.e., not 'cfuncptr_t') @@ -269,7 +455,7 @@ typedef qvector strvec_t; // - not qualifying the destructor with template parameters // 3) The '%template' directive, that will indeed instantiate // the template for swig. -%{ void hexrays_deregister_python_cfuncptr_t_instance(cfuncptr_t *fp); %} +%{ void hexrays_deregister_python_clearable_instance(void *ptr); %} %extend qrefcnt_t { // The typemap above will take care of registering newly-constructed cfuncptr_t // instances. However, there's no such thing as a destructor typemap. @@ -278,7 +464,7 @@ typedef qvector strvec_t; // be a different destructor (which, of course, makes a ton of sense.) ~qrefcnt_t(void) { - hexrays_deregister_python_cfuncptr_t_instance($self); + hexrays_deregister_python_clearable_instance($self); delete $self; } } @@ -323,6 +509,24 @@ class qlist_cinsn_t_iterator {}; %template(qvector_ccase_t) qvector; %template(lvar_saved_infos_t) qvector; +%extend cblock_t { + cblock_t(void) + { + cblock_t *cb = new cblock_t(); + hexrays_register_python_clearable_instance(cb, hxclr_cblock); + return cb; + } + + ~cblock_t(void) + { + hexrays_deregister_python_clearable_instance($self); + delete $self; + } + + void _deregister() { hexrays_deregister_python_clearable_instance($self); } +} +%ignore cblock_t::cblock_t; + %extend citem_cmt_t { const char *c_str() const { return self->c_str(); } @@ -349,9 +553,6 @@ void qswap(cinsn_t &a, cinsn_t &b); %ignore init_hexrays_plugin; %rename(init_hexrays_plugin) py_init_hexrays_plugin; -%ignore add_custom_viewer_popup_item; -%rename(add_custom_viewer_popup_item) py_add_custom_viewer_popup_item; - %ignore install_hexrays_callback; %rename(install_hexrays_callback) py_install_hexrays_callback; @@ -361,8 +562,8 @@ void qswap(cinsn_t &a, cinsn_t &b); %ignore decompile_many; %rename (decompile_many) py_decompile_many; -%ignore get_tform_vdui; -%rename (get_tform_vdui) py_get_tform_vdui; +%ignore get_widget_vdui; +%rename (get_widget_vdui) py_get_widget_vdui; //------------------------------------------------------------------------- #if SWIG_VERSION == 0x20012 @@ -371,7 +572,7 @@ void qswap(cinsn_t &a, cinsn_t &b); { // ret cfuncptr_t cfuncptr_t *ni = new cfuncptr_t($1); - hexrays_register_python_cfuncptr_t_instance(ni); + hexrays_register_python_clearable_instance(ni, hxclr_cfuncptr); $result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0); } @@ -381,7 +582,7 @@ void qswap(cinsn_t &a, cinsn_t &b); { // ret cfuncptr_t* cfuncptr_t *ni = new cfuncptr_t(*($1)); - hexrays_register_python_cfuncptr_t_instance(ni); + hexrays_register_python_clearable_instance(ni, hxclr_cfuncptr); $result = SWIG_NewPointerObj(ni, $1_descriptor, SWIG_POINTER_OWN | 0); } #else @@ -424,6 +625,18 @@ void qswap(cinsn_t &a, cinsn_t &b); %possible_director_exc(ctree_visitor_t::apply_to) %possible_director_exc(ctree_visitor_t::apply_to_exprs) +%template (fnum_array) wrapped_array_t; +%extend fnumber_t { + wrapped_array_t __get_fnum() { + return wrapped_array_t($self->fnum); + } + + %pythoncode { + fnum = property(__get_fnum) + } +} + + %inline %{ // // diff --git a/swig/ida.i b/swig/ida.i index ab1af4b..4823cfb 100644 --- a/swig/ida.i +++ b/swig/ida.i @@ -1,9 +1,43 @@ // Ignore kernel-only symbols -%ignore dual_text_options_t; %ignore idainfo::align_short_demnames; %ignore idainfo::align_strtype; %ignore idainfo::align_long_demnames; %ignore idainfo::store_user_info; +%ignore idainfo::zero; +%ignore idainfo::padding; +%ignore idainfo::netdelta; +%ignore idainfo::privrange; +%ignore idainfo::padding2; +%ignore idainfo::idainfo; +%ignore idainfo::~idainfo; + +%extend idainfo +{ + qstring get_abiname() + { + qstring buf; + get_abi_name(&buf); + return buf; + } + +#ifdef BC695 + // Compat 6.95; since inf is a cvar, I can't just add properties to it.. + ea_t get_minEA() const { return $self->min_ea; } + void set_minEA(ea_t ea) { $self->min_ea = ea; } + ea_t get_maxEA() const { return $self->max_ea; } + void set_maxEA(ea_t ea) { $self->max_ea = ea; } + qstring get_procName() const { return $self->procname; } +#endif + + %pythoncode { + abiname = property(get_abiname) +#ifdef BC695 + minEA = property(get_minEA, set_minEA) + maxEA = property(get_maxEA, set_maxEA) + procName = property(get_procName) +#endif + } +} %ignore setflag(uchar &where,uchar bit,int value); %ignore setflag(ushort &where,ushort bit,int value); diff --git a/swig/idc.i b/swig/idc.i new file mode 100644 index 0000000..7cf2299 --- /dev/null +++ b/swig/idc.i @@ -0,0 +1,22 @@ + +// This contains helpers needed for idc.py to work correctly + +%{ +#include +#include +%} + +%{ +// +// +%} + +%inline %{ +// +// +%} + +%pythoncode %{ +# +# +%} diff --git a/swig/idd.i b/swig/idd.i index e8942e5..586f7fb 100644 --- a/swig/idd.i +++ b/swig/idd.i @@ -1,6 +1,7 @@ %{ #include #include +#include #include %} @@ -14,7 +15,7 @@ %ignore appcall; %ignore idd_opinfo_t; %ignore gdecode_t; -%apply unsigned char { char dtyp }; +%apply unsigned char { op_dtype_t dtype }; %ignore qvector::operator==; %ignore qvector::operator!=; @@ -24,6 +25,14 @@ %ignore qvector::add_unique; %template(excvec_t) qvector; +%ignore qvector::operator==; +%ignore qvector::operator!=; +%ignore qvector::find; +%ignore qvector::has; +%ignore qvector::del; +%ignore qvector::add_unique; +%template(procinfo_vec_t) qvector; + %include "idd.hpp" // SWIG chokes on the original declaration so it is replicated here @@ -33,7 +42,7 @@ typedef struct ushort fval[6]; // 12: floating point value in the internal representation (see ieee.h) } regval_t; -%clear(char dtyp); +%clear(op_dtype_t dtype); %rename (appcall) py_appcall; diff --git a/swig/idp.i b/swig/idp.i index ee0007a..6f95b45 100644 --- a/swig/idp.i +++ b/swig/idp.i @@ -4,10 +4,9 @@ #include #include #include +#include %} // Ignore the following symbols -%ignore WorkReg; -%ignore AbstractRegister; %ignore rginfo; %ignore insn_t::get_canon_mnem; %ignore insn_t::get_canon_feature; @@ -23,7 +22,6 @@ %ignore IDPOPT_BADTYPE; %ignore IDPOPT_BADVALUE; %ignore set_options_t; -%ignore read_user_config_file; %ignore read_config; %ignore read_config_file; %ignore read_config_string; @@ -36,9 +34,8 @@ %ignore _chkarg_cmd; %ignore ENUM_SIZE; -%ignore asm_t::checkarg_dispatch; -%ignore asm_t::func_header; -%ignore asm_t::func_footer; +%ignore asm_t::out_func_header; +%ignore asm_t::out_func_footer; %ignore asm_t::get_type_name; %ignore instruc_t; %ignore processor_t; @@ -46,11 +43,49 @@ %ignore IDP_Callback; %ignore _py_getreg; +%ignore hook_cb_t; +%ignore hook_type_t; +%ignore hook_to_notification_point; +%ignore unhook_from_notification_point; +%ignore invoke_callbacks; + +// @arnaud +%ignore notify__calc_next_eas; +%ignore notify__custom_ana; +%ignore notify__custom_emu; +%ignore notify__custom_mnem; +%ignore notify__custom_out; +%ignore notify__custom_outop; +%ignore notify__get_autocmt; +%ignore notify__get_dbr_opnum; +%ignore notify__get_operand_string; +%ignore notify__insn_reads_tbit; +%ignore notify__is_basic_block_end; +%ignore notify__is_call_insn; +%ignore notify__is_cond_insn; +%ignore notify__is_indirect_jump; +%ignore notify__is_insn_table_jump; +%ignore notify__is_ret_insn; +%ignore notify__is_sane_insn; +%ignore notify__may_be_func; +%ignore notify__make_code; +// @arnaud ^^^ + +// @arnaud ditch this once all modules are ported +// temporary: +%ignore out_old_data; +%ignore out_old_specea; + %nonnul_argument_prototype( static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *nonnul_line), const char *nonnul_line); %include "idp.hpp" +%include "config.hpp" + +%typemap(check) tinfo_t const* optional_type +{ +} %inline %{ // diff --git a/swig/ints.i b/swig/ints.i deleted file mode 100644 index ae0a682..0000000 --- a/swig/ints.i +++ /dev/null @@ -1,2 +0,0 @@ -%include "ints.i" - diff --git a/swig/kernwin.i b/swig/kernwin.i index caccd5a..22ffe02 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -11,19 +11,21 @@ extern plugin_t PLUGIN; %} // Ignore the va_list functions -%ignore AskUsingForm_cv; -%ignore AskUsingForm_c; -%ignore OpenForm_cv; -%ignore OpenForm_c; +%ignore vask_form; +%ignore ask_form; +%ignore open_form; +%ignore vopen_form; %ignore close_form; -%ignore vaskstr; +%ignore vask_str; +%ignore ask_str; +%ignore ask_ident; +%ignore vask_buttons; +%ignore vask_file; +%ignore vask_yn; %ignore strvec_t; %ignore load_custom_icon; -%ignore vasktext; -%ignore add_menu_item; -%rename (add_menu_item) py_add_menu_item; -%ignore del_menu_item; -%rename (del_menu_item) py_del_menu_item; +%ignore vask_text; +%ignore ask_text; %ignore vwarning; %ignore choose_idasgn; @@ -46,11 +48,6 @@ extern plugin_t PLUGIN; %ignore vnomem; %ignore vmsg; %ignore show_wait_box_v; -%ignore askbuttons_cv; -%ignore askfile_cv; -%ignore askyn_cv; -%ignore askyn_v; -%ignore add_custom_viewer_popup_item; %ignore create_custom_viewer; %ignore take_database_snapshot; %rename (take_database_snapshot) py_take_database_snapshot; @@ -58,7 +55,6 @@ extern plugin_t PLUGIN; %rename (restore_database_snapshot) py_restore_database_snapshot; %ignore destroy_custom_viewer; %ignore destroy_custom_viewerdestroy_custom_viewer; -%ignore set_custom_viewer_popup_menu; %ignore set_custom_viewer_handler; %ignore set_custom_viewer_range; %ignore is_idaview; @@ -66,24 +62,20 @@ extern plugin_t PLUGIN; %ignore set_custom_viewer_handlers; %ignore get_viewer_name; // Ignore these string functions. There are trivial replacements in Python. -%ignore addblanks; %ignore trim; -%ignore skipSpaces; +%ignore skip_spaces; %ignore stristr; %ignore set_nav_colorizer; %rename (set_nav_colorizer) py_set_nav_colorizer; %rename (call_nav_colorizer) py_call_nav_colorizer; -%ignore get_highlighted_identifier; -%rename (get_highlighted_identifier) py_get_highlighted_identifier; - +%ignore get_highlight; +%rename (get_highlight) py_get_highlight; %ignore action_desc_t::handler; %ignore action_handler_t; %ignore register_action; %rename (register_action) py_register_action; -%ignore unregister_action; -%rename (unregister_action) py_unregister_action; %ignore attach_dynamic_action_to_popup; %rename (attach_dynamic_action_to_popup) py_attach_dynamic_action_to_popup; %ignore get_registered_actions; @@ -91,9 +83,9 @@ extern plugin_t PLUGIN; %include "typemaps.i" -%rename (asktext) py_asktext; +%rename (ask_text) py_ask_text; +%rename (ask_str) py_ask_str; %rename (str2ea) py_str2ea; -%rename (str2user) py_str2user; %ignore process_ui_action; %rename (process_ui_action) py_process_ui_action; %ignore execute_sync; @@ -110,11 +102,13 @@ extern plugin_t PLUGIN; %ignore unregister_timer; %rename (unregister_timer) py_unregister_timer; -// Make askaddr(), askseg(), and asklong() return a +%ignore chooser_item_attrs_t::cb; + +// Make ask_addr(), ask_seg(), and ask_long() return a // tuple: (result, value) -%rename (_asklong) asklong; -%rename (_askaddr) askaddr; -%rename (_askseg) askseg; +%rename (_ask_long) ask_long; +%rename (_ask_addr) ask_addr; +%rename (_ask_seg) ask_seg; %ignore qvector::operator==; %ignore qvector::operator!=; @@ -142,6 +136,9 @@ extern plugin_t PLUGIN; %ignore register_loc_converter; %ignore lookup_loc_converter; +%ignore hexplace_t; +%ignore hexplace_gen_t; + %feature("director") UI_Hooks; //------------------------------------------------------------------------- @@ -186,22 +183,20 @@ struct py_action_handler_t : public action_handler_t newref_t pyres(PyObject_CallMethod(pyah.o, (char *)"update", (char *) "O", pyctx.o)); return PyErr_Occurred() ? AST_DISABLE_ALWAYS : ((pyres != NULL && PyInt_Check(pyres.o)) ? action_state_t(PyInt_AsLong(pyres.o)) : AST_DISABLE); } + private: ref_t pyah; bool has_activate; bool has_update; }; -typedef std::map py_action_handlers_t; -static py_action_handlers_t py_action_handlers; - %} %inline %{ -void refresh_lists(void) +void refresh_choosers(void) { Py_BEGIN_ALLOW_THREADS; - callui(ui_list); + callui(ui_refresh_choosers); Py_END_ALLOW_THREADS; } %} @@ -249,7 +244,8 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); PyObject *handler, const char *shortcut = NULL, const char *tooltip = NULL, - int icon = -1) + int icon = -1, + int flags = 0) { action_desc_t *ad = new action_desc_t(); #define DUPSTR(Prop) ad->Prop = Prop == NULL ? NULL : qstrdup(Prop) @@ -260,6 +256,7 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); #undef DUPSTR ad->icon = icon; ad->handler = new py_action_handler_t(handler); + ad->flags = flags | ADF_OWN_HANDLER; ad->owner = &PLUGIN; return ad; } @@ -278,6 +275,22 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); } } +%extend action_ctx_base_t { + + int _get_reg() const { return $self->reg; } + +#ifdef BC695 + twidget_type_t _get_form_type() const { return $self->widget_type; } +#endif + + %pythoncode { + reg = property(_get_reg) +#ifdef BC695 + form_type = property(_get_form_type) +#endif + } +} + //------------------------------------------------------------------------- %extend place_t { static idaplace_t *as_idaplace_t(place_t *p) { return (idaplace_t *) p; } @@ -319,8 +332,13 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); %} //------------------------------------------------------------------------- -// choose +// Choose //------------------------------------------------------------------------- +%{ +// +// +%} + %inline %{ // // @@ -332,39 +350,21 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); %} //------------------------------------------------------------------------- -// choose2 +// ask_form //------------------------------------------------------------------------- %{ -// -// +// +// %} %inline %{ -// -// +// +// %} %pythoncode %{ -# -# -%} - -//------------------------------------------------------------------------- -// askusingform -//------------------------------------------------------------------------- -%{ -// -// -%} - -%inline %{ -// -// -%} - -%pythoncode %{ -# -# +# +# %} @@ -388,8 +388,28 @@ static void _py_unregister_compiled_form(PyObject *py_form, bool shutdown); //------------------------------------------------------------------------- %init %{ -// -// +// +// +%} + +//------------------------------------------------------------------------- +// CustomIDAMemo +//------------------------------------------------------------------------- +%ignore View_Callback; + +%inline %{ +// +// +%} + +%{ +// +// +%} + +%pythoncode %{ +# +# %} diff --git a/swig/lines.i b/swig/lines.i index 008f314..370afbc 100644 --- a/swig/lines.i +++ b/swig/lines.i @@ -1,31 +1,9 @@ // FIXME: These should be fixed %ignore requires_color_esc; -%ignore tag_on; -%ignore tag_off; -%ignore tag_addchr; -%ignore tag_addstr; -%ignore get_user_defined_prefix; // Ignore va_list versions -%ignore printf_line_v; -%ignore gen_colored_cmt_line_v; -%ignore gen_cmt_line_v; -%ignore add_long_cmt_v; -%ignore describex; +%ignore vadd_extra_line; // Kernel-only and unexported symbols -%ignore save_sourcefiles; -%ignore ml_getcmt_t; -%ignore ml_getnam_t; -%ignore ml_genxrf_t; -%ignore ml_saver_t; -%ignore setup_makeline; -%ignore MAKELINE_NONE; -%ignore MAKELINE_BINPREF; -%ignore MAKELINE_VOID; -%ignore MAKELINE_STACK; -%ignore save_line_in_array; -%ignore init_lines_array; -%ignore finish_makeline; -%ignore makeline_producer_t; +%ignore get_last_pfxlen; %ignore closing_comment; %ignore close_comment; %ignore init_lines; diff --git a/swig/loader.i b/swig/loader.i index 8ea78a8..cdfe883 100644 --- a/swig/loader.i +++ b/swig/loader.i @@ -3,7 +3,7 @@ %ignore loader_t::load_file; %ignore loader_t::save_file; %ignore loader_t::move_segm; -%ignore loader_t::init_loader_options; +%ignore loader_t::process_archive; %ignore plugin_t; %ignore vloader_failure; @@ -16,7 +16,6 @@ %ignore free_loaders_list; %ignore get_loader_name_from_dll; %ignore get_loader_name; -%ignore init_loader_options; %ignore load_nonbinary_file; %ignore impinfo_t; %ignore import_module; @@ -33,11 +32,6 @@ %ignore html_line_cb_t; %ignore gen_outline_t; %ignore create_filename_cmt; -%ignore hook_cb_t; -%ignore hook_type_t; -%ignore hook_to_notification_point; -%ignore unhook_from_notification_point; -%ignore invoke_callbacks; // Ignore kernel-only & unexported symbols %ignore LDSC; @@ -58,11 +52,12 @@ %ignore RE_BADATP; %ignore RE_BADMAP; %ignore load_dll_or_die; -%ignore load_dll_or_say; +%ignore load_core_module; +%ignore load_core_module_or_die; +%ignore _load_core_module; %ignore free_dll; %ignore IDP_DESC_START; %ignore IDP_DESC_END; -%ignore get_idp_desc; %ignore get_idp_descs; %ignore init_fileregions; %ignore term_fileregions; @@ -70,9 +65,7 @@ %ignore add_fileregion; %ignore move_fileregions; %ignore del_fileregions; -%ignore enum_processor_modules; %ignore enum_plugins; -%ignore database_id0; %ignore is_database_ext; %ignore is_temp_database; diff --git a/swig/moves.i b/swig/moves.i index 91078b4..4f54de5 100644 --- a/swig/moves.i +++ b/swig/moves.i @@ -11,7 +11,16 @@ %ignore location_t::location_t(bool); %ignore lochist_t::is_hexrays68_compat; %ignore lochist_entry_t::set_place(const place_t &); +%ignore graph_location_info_t::serialize(bytevec_t *) const; +%ignore graph_location_info_t::deserialize(const uchar **, const uchar *); +%ignore renderer_info_pos_t::serialize(bytevec_t *) const; +%ignore renderer_info_pos_t::deserialize(const uchar **, const uchar *); %template(segm_move_info_vec_t) qvector; +%inline %{ +// +// +%} + %include "moves.hpp" diff --git a/swig/nalt.i b/swig/nalt.i index afe8bdd..89c4717 100644 --- a/swig/nalt.i +++ b/swig/nalt.i @@ -8,10 +8,11 @@ %ignore get_import_module_name; %rename (get_import_module_name) py_get_import_module_name; -%ignore NALT_EA; %ignore enum_import_names; %rename (enum_import_names) py_enum_import_names; +%ignore calc_nodeidx; + %ignore get_wide_value; %ignore set_wide_value; %ignore del_wide_value; @@ -41,10 +42,6 @@ %ignore set_ind_purged; -%ignore get_str_type; -%ignore set_str_type; -%ignore del_str_type; - %ignore _get_item_color; %ignore _set_item_color; %ignore _del_item_color; @@ -55,24 +52,6 @@ %ignore get_nalt_rptcmt; %ignore set_nalt_rptcmt; %ignore del_nalt_rptcmt; -%ignore get_fop1; -%ignore set_fop1; -%ignore del_fop1; -%ignore get_fop2; -%ignore set_fop2; -%ignore del_fop2; -%ignore get_fop3; -%ignore set_fop3; -%ignore del_fop3; -%ignore get_fop4; -%ignore set_fop4; -%ignore del_fop4; -%ignore get_fop5; -%ignore set_fop5; -%ignore del_fop5; -%ignore get_fop6; -%ignore set_fop6; -%ignore del_fop6; %ignore get_manual_insn0; %ignore set_manual_insn0; %ignore del_manual_insn0; @@ -80,11 +59,15 @@ %ignore set_graph_groups0; %ignore del_graph_groups0; +%ignore jumptable_info_t; +%ignore del_jumptable_info; +%ignore set_jumptable_info; +%ignore get_jumptable_info; + %ignore switch_info_t; -%ignore switch_info_ex_t; -%ignore get_switch_info_ex; -%ignore set_switch_info_ex; -%ignore del_switch_info_ex; +%ignore get_switch_info; +%ignore set_switch_info; +%ignore del_switch_info; %ignore refinfo_t::_get_target; %ignore refinfo_t::_get_value; @@ -94,7 +77,9 @@ %ignore custom_refinfo_handlers_t; %ignore register_custom_refinfo; %ignore unregister_custom_refinfo; -%ignore get_custom_refinfos; +%ignore get_custom_refinfo_handler; +%ignore refinfo_desc_t; +%ignore get_refinfo_descs; %ignore write_struc_path; %ignore read_struc_path; @@ -113,17 +98,20 @@ %ignore get_switch_info; %ignore set_switch_info; %ignore del_switch_info; -%ignore get_ti; -%ignore set_ti; -%ignore del_ti; -%ignore get_op_tinfo; -%ignore set_op_tinfo; -%ignore del_tinfo; -%ignore get_op_ti; -%ignore set_op_ti; -%ignore del_ti; -%template (ids_array) wrapped_array_t; +%template (custom_data_type_ids_fids_array) wrapped_array_t; + +%extend custom_data_type_ids_t { + wrapped_array_t __getFids() { + return wrapped_array_t($self->fids); + } + + %pythoncode { + fids = property(__getFids) + } +} + +%template (strpath_ids_array) wrapped_array_t; %extend strpath_t { wrapped_array_t __getIds() { @@ -142,9 +130,9 @@ // %} -%rename (get_switch_info_ex) py_get_switch_info_ex; -%rename (set_switch_info_ex) py_set_switch_info_ex; -%rename (del_switch_info_ex) py_del_switch_info_ex; +%rename (get_switch_info) py_get_switch_info; +%rename (set_switch_info) py_set_switch_info; +%rename (del_switch_info) py_del_switch_info; %inline %{ // diff --git a/swig/name.i b/swig/name.i index da18a37..3e95cb2 100644 --- a/swig/name.i +++ b/swig/name.i @@ -18,19 +18,17 @@ %ignore get_ea_name; %rename (get_ea_name) py_get_ea_name; -// Deprecated functions, w/ duplicate names. -// Some are simply aliased (see py_name.py) -%ignore get_debug_name(ea_t *, debug_name_how_t, char *, size_t); -%ignore append_struct_fields(int, const tid_t *, int, flags_t, char *, char *, adiff_t *, adiff_t, bool); - - // Duplicate names, in-out qstring w/ existing // qstring-returning alternatives. %ignore get_visible_name(qstring *, ea_t, int); %ignore get_short_name(qstring *, ea_t, int); %ignore get_long_name(qstring *, ea_t, int); +%ignore get_colored_short_name(qstring *, ea_t, int); +%ignore get_colored_long_name(qstring *, ea_t, int); +%ignore get_demangled_name(qstring *, ea_t, int32, int, int); +%ignore get_colored_demangled_name(qstring *, ea_t, int32, int, int); -// get_true_name & get_colored_name have prototypes such that, +// get_name & get_colored_name have prototypes such that, // once converted to IDAPython, would be problematic because it'd // be impossible for SWiG to tell apart the (ea_t, ea_t) version // from the (ea_t, int) one. @@ -42,18 +40,23 @@ %ignore FNAME(ea_t, int); %rename (FNAME) py_ ## FNAME; +%ignore demangle_name(const char *, uint32, demreq_type_t); + %inline %{ inline qstring py_## FNAME(ea_t ea) { return FNAME(ea); } %} %enddef -%restrict_ambiguous_name_function(get_true_name); +%restrict_ambiguous_name_function(get_name); %restrict_ambiguous_name_function(get_colored_name); %ignore get_debug_names; %rename (get_debug_names) py_get_debug_names; +%ignore validate_name; +%rename (validate_name) py_validate_name; + %{ // // diff --git a/swig/netnode.i b/swig/netnode.i index 4cc4661..f904688 100644 --- a/swig/netnode.i +++ b/swig/netnode.i @@ -6,11 +6,12 @@ %ignore netnode_end; %ignore netnode_next; %ignore netnode_prev; -%ignore netnode_name; %ignore netnode_get_name; %ignore netnode_rename; %ignore netnode_valobj; %ignore netnode_valstr; +%ignore netnode_qvalstr; +%ignore netnode::valstr(char*,size_t) const; %ignore netnode_set; %ignore netnode_delvalue; %ignore netnode_altval; @@ -19,18 +20,27 @@ %ignore netnode_charval_idx8; %ignore netnode_supval; %ignore netnode_supstr; +%ignore netnode_qsupstr; +%ignore netnode::supstr(nodeidx_t,char*,size_t,uchar) const; +%ignore netnode_supstr_ea; +%ignore netnode_qsupstr_ea; +%ignore netnode::supstr_ea(ea_t,char*,size_t,uchar) const; %ignore netnode_supset; %ignore netnode_supdel; -%ignore netnode_sup1st; -%ignore netnode_supnxt; +%ignore netnode_lower_bound; +%ignore netnode_supfirst; +%ignore netnode_supnext; %ignore netnode_suplast; %ignore netnode_supprev; %ignore netnode_supval_idx8; %ignore netnode_supstr_idx8; +%ignore netnode_qsupstr_idx8; +%ignore netnode::supstr_idx8(uchar,char*,size_t,uchar) const; %ignore netnode_supset_idx8; %ignore netnode_supdel_idx8; -%ignore netnode_sup1st_idx8; -%ignore netnode_supnxt_idx8; +%ignore netnode_lower_bound_idx8; +%ignore netnode_supfirst_idx8; +%ignore netnode_supnext_idx8; %ignore netnode_suplast_idx8; %ignore netnode_supprev_idx8; %ignore netnode_supdel_all; @@ -38,15 +48,26 @@ %ignore netnode_supdel_range_idx8; %ignore netnode_hashval; %ignore netnode_hashstr; +%ignore netnode_qhashstr; +%ignore netnode::hashstr(const char*,char*,size_t,uchar) const; %ignore netnode_hashval_long; %ignore netnode_hashset; %ignore netnode_hashdel; -%ignore netnode_hash1st; -%ignore netnode_hashnxt; +%ignore netnode_hashfirst; +%ignore netnode_qhashfirst; +%ignore netnode::hashfirst(char*,size_t,uchar) const; +%ignore netnode_hashnext; +%ignore netnode_qhashnext; +%ignore netnode::hashnext(const char*,char*,size_t,uchar) const; %ignore netnode_hashlast; +%ignore netnode_qhashlast; +%ignore netnode::hashlast(char*,size_t,uchar) const; %ignore netnode_hashprev; +%ignore netnode_qhashprev; +%ignore netnode::hashprev(const char*,char*,size_t,uchar) const; %ignore netnode_blobsize; %ignore netnode_getblob; +%ignore netnode_qgetblob; %ignore netnode_setblob; %ignore netnode_delblob; %ignore netnode_inited; @@ -80,14 +101,18 @@ %ignore netnode::setbase; %ignore netnode::altadjust; -%ignore netnode::getblob(void *buf, size_t *bufsize, nodeidx_t start, char tag); +%ignore netnode::getblob(qstring *buf, nodeidx_t start, uchar tag); +%ignore netnode::getblob(void *buf, size_t *bufsize, nodeidx_t start, uchar tag); +%ignore netnode::getblob_ea(void *buf, size_t *bufsize, ea_t ea, uchar tag); %ignore netnode::operator nodeidx_t; %ignore netnode::validate_names; %constant nodeidx_t BADNODE = nodeidx_t(-1); // Renaming one version of hashset() otherwise SWIG will not be able to activate the other one -%rename (hashset_idx) netnode::hashset(const char *idx, nodeidx_t value, char tag=htag); +%rename (hashset_idx) netnode::hashset(const char *idx, nodeidx_t value, uchar tag=htag); + +%apply char { uchar tag }; %include "netnode.hpp" @@ -98,25 +123,26 @@ return self->operator nodeidx_t(); } - PyObject *getblob(nodeidx_t start, const char *tag) + PyObject *getblob(nodeidx_t start, char tag) { - // Get the blob and let IDA allocate the memory - size_t bufsize; - void *buf = self->getblob(NULL, &bufsize, start, *tag); - if ( buf == NULL ) + bytevec_t blob; + if ( self->getblob(&blob, start, uchar(tag)) <= 0 ) Py_RETURN_NONE; - // Create a Python string - PyObject *py_str = PyString_FromStringAndSize((const char *)buf, bufsize); - // Free memory - qfree(buf); + return PyString_FromStringAndSize((const char *)blob.begin(), blob.size()); + } - return py_str; + PyObject *getblob_ea(ea_t ea, char tag) + { + bytevec_t blob; + if ( self->getblob(&blob, ea, tag) <= 0 ) + Py_RETURN_NONE; + return PyString_FromStringAndSize((const char *)blob.begin(), blob.size()); } PyObject *hashstr_buf(const char *idx, char tag=htag) { char buf[MAXSPECSIZE]; - ssize_t sz = self->hashstr(idx, buf, sizeof(buf), tag); + ssize_t sz = self->hashstr(idx, buf, sizeof(buf), uchar(tag)); if ( sz < 0 ) Py_RETURN_NONE; else @@ -127,10 +153,8 @@ { char *buf; Py_ssize_t sz; - if ( PyString_AsStringAndSize(py_str, &buf, &sz) == -1 ) return false; - else - return self->hashset(idx, buf, sz, tag); + return self->hashset(idx, buf, sz, uchar(tag)); } } diff --git a/swig/pro.i b/swig/pro.i index 5b36439..e1652cb 100644 --- a/swig/pro.i +++ b/swig/pro.i @@ -1,4 +1,32 @@ +%ignore user2str; +%ignore back_char; +%ignore qstr2user; +%ignore user2qstr; +%ignore str2user; +%rename (str2user) py_str2user; +%ignore convert_encoding; +%ignore is_valid_utf8; +%ignore qustrlen; +%ignore put_utf8_char; +%ignore idb_utf8; +%ignore scr_utf8; +%ignore utf8_scr; +%ignore change_codepage; +%ignore utf16_utf8; +%ignore utf8_utf16; +%ignore acp_utf8; +%ignore utf8_wchar16; +%ignore utf8_wchar32; +%ignore skip_utf8; +%ignore expand_argv; +%ignore free_argv; +%ignore qwait; +%ignore qwait_for_handles; +%ignore qwait_timed; +%ignore ida_true_type; +%ignore ida_false_type; + %include "pro.h" // we must include those manually here @@ -15,6 +43,7 @@ %template(int64vec_t) qvector; // for EA64 svalvec_t objects %template(boolvec_t) qvector; %template(strvec_t) qvector; +%template(sizevec_t) qvector; SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t) diff --git a/swig/problems.i b/swig/problems.i new file mode 100644 index 0000000..df3780a --- /dev/null +++ b/swig/problems.i @@ -0,0 +1,5 @@ +%{ +#include +%} + +%include "problems.hpp" diff --git a/swig/queue.i b/swig/queue.i deleted file mode 100644 index 04fcfeb..0000000 --- a/swig/queue.i +++ /dev/null @@ -1,13 +0,0 @@ -%{ -#include -%} -// TODO: This could be wrapped. -%ignore QueueGet; - -// Kernel-only & unexported symbols -%ignore QueueDel(ea_t); - -%ignore mark_ida_decision; -%ignore unmark_ida_decision; - -%include "queue.hpp" diff --git a/swig/range.i b/swig/range.i new file mode 100644 index 0000000..ea5d284 --- /dev/null +++ b/swig/range.i @@ -0,0 +1,14 @@ +%ignore rangeset_t::count; +%ignore rangeset_t::lower_bound; +%ignore rangeset_t::upper_bound; +%ignore rangeset_t::move_chunk; +%ignore rangeset_t::check_move_args; + +%template(rangevec_base_t) qvector; + +%inline %{ +// +// +%} + +%include "range.hpp" diff --git a/swig/registry.i b/swig/registry.i index d137b90..2afb0ec 100644 --- a/swig/registry.i +++ b/swig/registry.i @@ -2,7 +2,8 @@ #include %} %ignore reg_bin_op; -%ignore reg_str_op; +%ignore reg_str_get; +%ignore reg_str_set; %ignore reg_int_op; %ignore _RVN_; %ignore REG_VAL_NAME; diff --git a/swig/segment.i b/swig/segment.i index 1d259af..3abd755 100644 --- a/swig/segment.i +++ b/swig/segment.i @@ -1,6 +1,6 @@ // Ignore functions with callbacks -%import "area.i" +%import "range.i" %ignore enumerate_selectors; %ignore enumerate_segments_with_selector; @@ -22,8 +22,20 @@ %extend segment_t { - ea_t startEA; - ea_t endEA; + ea_t start_ea; + ea_t end_ea; +} + +#ifdef __EA64__ +%apply ulonglong *OUTPUT { sel_t *sel, ea_t *base }; // getn_selector() +#else +%apply unsigned int *OUTPUT { sel_t *sel, ea_t *base }; // getn_selector() +#endif + +%typemap(check) (sel_t *sel, ea_t *base) { + // getn_selector() check + *($1) = BADSEL; + *($2) = BADADDR; } %include "segment.hpp" diff --git a/swig/srarea.i b/swig/segregs.i similarity index 56% rename from swig/srarea.i rename to swig/segregs.i index 60f2a36..deeba1e 100644 --- a/swig/srarea.i +++ b/swig/segregs.i @@ -1,18 +1,13 @@ %{ -#include +#include %} -%import "area.i" +%import "range.i" // Ignore kernel-only symbols -%ignore repairSRarea; - %ignore delete_v660_segreg_t; %ignore v660_segreg_t; -%ignore segreg_t::tag(int n); -%ignore segreg_t::reg(int n); - #define R_es 29 #define R_cs 30 #define R_ss 31 @@ -20,4 +15,4 @@ #define R_fs 33 #define R_gs 34 -%include "srarea.hpp" +%include "segregs.hpp" diff --git a/swig/strlist.i b/swig/strlist.i index 92cb7b1..1c70e5b 100644 --- a/swig/strlist.i +++ b/swig/strlist.i @@ -6,4 +6,58 @@ %ignore strwinsetup_t::save_config; %ignore strwinsetup_t::restore_config; +%extend strwinsetup_t { + + PyObject *_get_strtypes() + { + const bytevec_t &t = $self->strtypes; + size_t n = t.size(); + PyObject *py_t = PyList_New(n); + for ( size_t i = 0, n = t.size(); i < n; ++i ) + PyList_SetItem(py_t, i, PyInt_FromLong(t[i])); + return py_t; + } + + PyObject *_set_strtypes(PyObject *py_t) + { + if ( PySequence_Check(py_t) ) + { + Py_ssize_t n = PySequence_Size(py_t); + bytevec_t t; + t.reserve(n); + for ( size_t i = 0; i < n; ++i ) + { + newref_t pyo(PySequence_GetItem(py_t, i)); + if ( PyInt_Check(pyo.o) ) + { + long stype = PyInt_AsLong(pyo.o); + if ( stype < 0 || stype >= 0x100 ) + { + PyErr_SetString(PyExc_ValueError, "values must be between 0 & 0x100"); + return NULL; + } + t.push_back(uchar(stype)); + } + else + { + PyErr_SetString(PyExc_ValueError, "expected an integer"); + return NULL; + } + } + $self->strtypes.swap(t); + } + else + { + PyErr_SetString(PyExc_TypeError, "expected a list"); + return NULL; + } + Py_RETURN_TRUE; + } + + %pythoncode { + strtypes = property(_get_strtypes, _set_strtypes) + } +} +%ignore strwinsetup_t::strtypes; + %include "strlist.hpp" diff --git a/swig/struct.i b/swig/struct.i index 75e2e34..f75660d 100644 --- a/swig/struct.i +++ b/swig/struct.i @@ -2,10 +2,9 @@ #include %} // Kernel-only symbols -%ignore del_ti; %ignore save_structs; %ignore get_struc_name(tid_t); -%ignore get_member_name2(tid_t); +%ignore get_member_name(tid_t); %ignore get_member_by_id(tid_t, struc_t **); // allow version w/ qstring* only //------------------------------------------------------------------------- diff --git a/swig/tryblks.i b/swig/tryblks.i new file mode 100644 index 0000000..5392bbb --- /dev/null +++ b/swig/tryblks.i @@ -0,0 +1,14 @@ +%{ +#include +%} + +%import "range.i" + +%ignore tryblk_t::reserve; +%ignore tryblk_t::cpp() const; +%ignore tryblk_t::seh() const; + +%template(tryblks_t) qvector; +%template(catchvec_t) qvector; + +%include "tryblks.hpp" diff --git a/swig/typeconv.i b/swig/typeconv.i deleted file mode 100644 index 8741098..0000000 --- a/swig/typeconv.i +++ /dev/null @@ -1,454 +0,0 @@ -//------------------------------------------------------------------------- -// For some reason, SWIG converts char arrays by computing the size -// from the end of the array, and stops when it encounters a '\0'. -// That doesn't work for us, as our API doesn't guarantee that -// bytes past the length we are interested in will be zeroed-out. -// In other words, the following code should *never* be present -// in idaapi_include.cpp: -// ------------------------- -// while (size && ([size - 1] == '\0')) --size; -// ------------------------- -// -%typemap(out) char [ANY], const char[ANY] -{ - %set_output(SWIG_FromCharPtrAndSize($1, strnlen($1, $1_dim0))); -} - -%typemap(varout) char [ANY], const char[ANY] -{ - %set_output(SWIG_FromCharPtrAndSize($1, strnlen($1, $1_dim0))); -} - - -%typemap(out) ssize_t -{ - $result = PyLong_FromLongLong($1); -} - -//--------------------------------------------------------------------- -// Convert an incoming Python list to a tid_t[] array -%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) { - int i, len; - - if (!PySequence_Check($input)) - { - PyErr_SetString(PyExc_TypeError,"Expecting a sequence"); - return NULL; - } - - /* Cap the number of elements to copy */ - len = PySequence_Length($input) < $1_dim0 ? PySequence_Length($input) : $1_dim0; - - for (i =0; i < len; i++) - { - newref_t item(PySequence_GetItem($input,i)); - if (!PyLong_Check(item.o)) - { - PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers"); - return NULL; - } - - temp[i] = PyLong_AsUnsignedLong(item.o); - } - $1 = &temp[0]; -} - -//------------------------------------------------------------------------- -// Same, but with non-fixed sized arrays. -%typemap(in) (const tid_t *path, int plen) (qvector temp) { - if (!PySequence_Check($input)) - { - PyErr_SetString(PyExc_TypeError,"Expecting a sequence"); - return NULL; - } - int plen = PySequence_Length($input); - if ( plen <= 0 ) - { - PyErr_SetString(PyExc_TypeError, "Sequence must have at least 1 item"); - return NULL; - } - temp.resize(plen); - for ( int i =0; i < plen; ++i ) - { - newref_t item(PySequence_GetItem($input,i)); - if (!PyLong_Check(item.o)) - { - PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers"); - return NULL; - } - - temp[i] = PyLong_AsUnsignedLong(item.o); - } - $1 = temp.begin(); - $2 = int(temp.size()); -} - -//--------------------------------------------------------------------- -%define %cstring_output_maxstr_none(TYPEMAP, SIZE) - -%typemap (default) SIZE { - $1 = MAXSTR; - } - -%typemap(in,numinputs=0) (TYPEMAP, SIZE) { - $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; - } - qfree($1); -} -%enddef - -//--------------------------------------------------------------------- -%define %cstring_bounded_output_none(TYPEMAP,MAX) -%typemap(in, numinputs=0) TYPEMAP(char temp[MAX+1]) { - $1 = ($1_ltype) temp; -} -%typemap(argout,fragment="t_output_helper") TYPEMAP { - PyObject *o; - $1[MAX] = 0; - - if ($1 > 0) - { - o = PyString_FromString($1); - } - else - { - o = Py_None; - Py_INCREF(Py_None); - } - $result = t_output_helper($result,o); -} -%enddef - -//--------------------------------------------------------------------- -%define %binary_output_or_none(TYPEMAP, SIZE) -%typemap (default) SIZE { - $1 = MAXSPECSIZE; -} -%typemap(in,numinputs=0) (TYPEMAP, SIZE) { - $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; - } - qfree((void *)$1); -} -%enddef - -//--------------------------------------------------------------------- -%define %binary_output_with_size(TYPEMAP, SIZE) -%typemap (default) SIZE { - size_t ressize = MAXSPECSIZE; - $1 = &ressize; -} -%typemap(in,numinputs=0) (TYPEMAP, SIZE) { - $1 = (char *) qalloc(MAXSPECSIZE+1); -} -%typemap(argout) (TYPEMAP,SIZE) { - Py_XDECREF(resultobj); - if (result) - { - resultobj = PyString_FromStringAndSize((char *)$1, *$2); - } - else - { - Py_INCREF(Py_None); - resultobj = Py_None; - } - qfree((void *)$1); -} -%enddef - -//--------------------------------------------------------------------- -// IN/OUT qstring -//--------------------------------------------------------------------- -%typemap(in,numinputs=0) qstring *result (qstring temp) { - $1 = &temp; -} -%typemap(argout) qstring *result { - Py_XDECREF(resultobj); - if (result) - { - resultobj = PyString_FromStringAndSize($1->begin(), $1->length()); - } - else - { - Py_INCREF(Py_None); - resultobj = Py_None; - } -} -%typemap(freearg) qstring* result -{ - // Nothing. We certainly don't want 'temp' to be deleted. -} - -//--------------------------------------------------------------------- -// md5/sha256 hash retrieval -%typemap(in, numinputs=0) uchar hash[ANY] (uchar temp[$1_dim0]) -{ - $1 = temp; -} - -%typemap(argout) uchar hash[ANY] -{ - Py_XDECREF(resultobj); - if (result) - { - char buf[2*$1_dim0 + 1]; - get_hex_string(buf, sizeof(buf), $1, $1_dim0); - resultobj = PyString_FromString(buf); - } - else - { - Py_INCREF(Py_None); - resultobj = Py_None; - } -} - -// Check that the argument is a callable Python object -//--------------------------------------------------------------------- -%typemap(in) PyObject *pyfunc { - if (!PyCallable_Check($input)) { - PyErr_SetString(PyExc_TypeError, "Expected a callable object"); - return NULL; - } - $1 = $input; -} -// Check that the argument is None or a callable Python object -//--------------------------------------------------------------------- -%typemap(in) PyObject *pyfunc_or_none { - if ($input != Py_None && !PyCallable_Check($input)) { - PyErr_SetString(PyExc_TypeError, "Expected None or a callable object"); - return NULL; - } - $1 = $input; -} -// Check that the argument is None or a tuple -//--------------------------------------------------------------------- -%typemap(in) PyObject *tuple_or_none { - if ($input != Py_None && !PyTuple_Check($input)) { - PyErr_SetString(PyExc_TypeError, "Expected None or a tuple"); - return NULL; - } - $1 = $input; -} -%typemap(in) ea_t -{ - uint64 $1_temp; - if ( !PyW_GetNumber($input, &$1_temp) ) - { - PyErr_SetString(PyExc_TypeError, "Expected an ea_t type"); - return NULL; - } - $1 = ea_t($1_temp); -} -// Use PyLong_FromUnsignedLongLong, because 'long' is 4 bytes on -// windows, and thus the ea_t would be truncated at the -// PyLong_FromUnsignedLong(unsigned int) call time. -%typemap(out) ea_t "$result = PyLong_FromUnsignedLongLong($1);" - -%typemap(in) qtime64_t "$1 = PyLong_AsUnsignedLongLong($input);" -%typemap(out) qtime64_t "$result = PyLong_FromUnsignedLongLong($1);" - -//--------------------------------------------------------------------- -// IN qstring -//--------------------------------------------------------------------- -// This is used to set/retrieve qstring that are structure members. -%typemap(in) qstring* -{ - char *buf; - Py_ssize_t length; - int success = PyString_AsStringAndSize($input, &buf, &length); - if ( success > -1 ) - { - $1 = new qstring(buf, length); - } -} -%typemap(freearg) qstring* -{ - delete $1; -} -%typemap(out) qstring* -{ - $result = PyString_FromStringAndSize($1->c_str(), $1->length()); -} -%typemap(out) qstring -{ - $result = PyString_FromStringAndSize($1.c_str(), $1.length()); -} -%apply qstring { _qstring } -%apply qstring* { _qstring* } - -#ifdef __EA64__ -%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 *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection() -#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 *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection() -#endif - -%apply qstring *result { qstring *label }; -%apply qstring *result { qstring *shortcut }; -%apply qstring *result { qstring *tooltip }; -%apply qstring *result { qstring *out }; -%apply int *OUTPUT { int *icon }; -%apply int *OUTPUT { action_state_t *state }; -%apply bool *OUTPUT { bool *checkable }; -%apply bool *OUTPUT { bool *checked }; -%apply bool *OUTPUT { bool *visibility }; - -//------------------------------------------------------------------------- -// The following is to be used to expose an array of items -// to IDAPython. This will not make a copy (on purpose!). -//------------------------------------------------------------------------- -// -// (Very) heavily inspired by: -// http://stackoverflow.com/questions/7713318/nested-structure-array-access-in-python-using-swig?rq=1 -// -%immutable; -%inline %{ -template -struct wrapped_array_t { - Type (&data)[N]; - wrapped_array_t(Type (&data)[N]) : data(data) { } -}; -%} -%mutable; - -%extend wrapped_array_t { - inline size_t __len__() const { return N; } - - inline const Type& __getitem__(size_t i) const throw(std::out_of_range) { - if (i >= N || i < 0) - 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) - throw std::out_of_range("out of bounds access"); - $self->data[i] = v; - } - - %pythoncode { - __iter__ = ida_idaapi._bounded_getitem_iterator - } -} - -//------------------------------------------------------------------------- -#if SWIG_VERSION == 0x20012 -%typemap(out) tinfo_t {} -%typemap(ret) tinfo_t -{ - // ret tinfo_t - tinfo_t *ni = new tinfo_t($1); - til_register_python_tinfo_t_instance(ni); - $result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0); -} - - -// KLUDGE: We'll let the compiler (or at worse the runtime) -// decide of the flags to use, depending on the method we are currently -// wrapping: at new-time, a SWIG_POINTER_NEW is required. -%typemap(out) tinfo_t* {} -%typemap(ret) tinfo_t* -{ - // ret tinfo_t* - tinfo_t *ni = new tinfo_t(*($1)); - til_register_python_tinfo_t_instance(ni); - if ( strcmp("new_tinfo_t", "$symname") == 0 ) - { - $result = SWIG_NewPointerObj(SWIG_as_voidptr(ni), $1_descriptor, SWIG_POINTER_NEW | 0); - delete $1; - } - else - { - $result = SWIG_NewPointerObj(SWIG_as_voidptr(ni), $1_descriptor, SWIG_POINTER_OWN | 0); - } -} - -%typemap(check) tinfo_t* -{ - if ( $1 == NULL ) - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'"); -} -#else -#error Ensure tinfo_t wrapping is compatible with this version of SWIG -#endif - -// Convert all of these -%cstring_output_maxstr_none(char *buf, size_t 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 len) }; -%apply (char *STRING, int LENGTH) { (const void *value, size_t length) }; -%apply (char *STRING, int LENGTH) { (const void *dataptr,size_t len) }; - -// Create wrapper classes for basic type arrays -%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); - - -%{ -PyObject *qstrvec2pylist(qstrvec_t &vec) -{ - size_t n = vec.size(); - PyObject *py_list = PyList_New(n); - for ( size_t i=0; i < n; ++i ) - PyList_SetItem(py_list, i, PyString_FromString(vec[i].c_str())); - return py_list; -} -%} - -//--------------------------------------------------------------------- -%typemap(out) uint64 { -$result = PyLong_FromUnsignedLongLong((unsigned long long) $1); -} - -//--------------------------------------------------------------------- -%typemap(in) uint64 -{ - uint64 $1_temp; - if ( !PyW_GetNumber($input, &$1_temp) ) - { - PyErr_SetString(PyExc_TypeError, "Expected an uint64 type"); - return NULL; - } - $1 = $1_temp; -} diff --git a/swig/typeinf.i b/swig/typeinf.i index 20da251..58dc76f 100644 --- a/swig/typeinf.i +++ b/swig/typeinf.i @@ -8,40 +8,16 @@ // Most of these could be wrapped if needed %ignore get_cc; %ignore get_cc_type_size; -%ignore set_argloc; -%ignore set_dt; -%ignore set_da; -%ignore set_de; -%ignore get_dt; -%ignore get_da; %ignore get_de; %ignore skip_ptr_type_header; %ignore skip_array_type_header; -%ignore unpack_object_from_idb; -%ignore unpack_object_from_bv; %ignore pack_object_to_idb; -%ignore pack_object_to_bv; %ignore typend; %ignore typlen; %ignore typncpy; %ignore tppncpy; %ignore typcmp; %ignore typdup; -%ignore equal_types; -%ignore resolve_typedef; -%ignore is_resolved_type_const; -%ignore is_resolved_type_void; -%ignore is_resolved_type_ptr; -%ignore is_resolved_type_func; -%ignore is_resolved_type_array; -%ignore is_resolved_type_complex; -%ignore is_resolved_type_struct; -%ignore is_resolved_type_union; -%ignore is_resolved_type_enum; -%ignore is_resolved_type_bitfld; -%ignore is_castable; -%ignore remove_constness; -%ignore remove_pointerness; %ignore get_int_type_bit; %ignore get_unk_type_bit; %ignore tns; @@ -57,17 +33,9 @@ %ignore parse_subtype; %ignore calc_type_size; -%ignore get_type_size; -%ignore get_type_size0; -%ignore skip_type; -%ignore get_pointer_object_size; %ignore descr_t; -%ignore unpack_type; -%ignore print_type_to_one_line; -%ignore print_type_to_many_lines; -%ignore print_type; %ignore show_type; %ignore show_plist; %ignore show_bytes; @@ -77,18 +45,17 @@ %ignore argloc_t::dstr; %ignore argpart_t::copy_from; -%ignore extract_pstr; +%ignore get_numbered_type(const til_t *, uint32, const type_t **, const p_list **, const char **, const p_list **, sclass_t *); +%rename (get_numbered_type) py_get_numbered_type; + %ignore skipName; %ignore extract_comment; %ignore skipComment; %ignore extract_fargcmt; %ignore skip_argloc; -%ignore extract_argloc; %ignore h2ti; %ignore h2ti_warning; -%ignore parse_type; -%ignore parse_types; // We want to handle 'get_named_type()' in a special way, // but not tinfo_t::get_named_type(). // http://stackoverflow.com/questions/27417884/how-do-i-un-ignore-a-specific-method-on-a-templated-class-in-swig @@ -115,18 +82,9 @@ %ignore get_named_type_size; %ignore decorate_name; -%ignore decorate_name3; -%ignore gen_decorate_name; -%ignore calc_bare_name; %ignore calc_bare_name3; -%ignore calc_cpp_name; -%ignore calc_c_cpp_name; -%ignore calc_c_cpp_name3; -%ignore predicate_t; -%ignore local_predicate_t; %ignore tinfo_predicate_t; %ignore local_tinfo_predicate_t; -%ignore choose_named_type; %ignore get_default_align; %ignore align_size; %ignore align_size; @@ -135,56 +93,33 @@ %ignore get_default_enum_size; %ignore max_ptr_size; %ignore based_ptr_name_and_size; -%ignore calc_arglocs; %ignore apply_type; %ignore apply_callee_type; -%ignore guess_func_type; -%ignore guess_type; +%ignore get_arg_addrs; +%rename (get_arg_addrs) py_get_arg_addrs; -%ignore build_funcarg_arrays; -%ignore free_funcarg_arrays; -%ignore extract_func_ret_type; %ignore calc_names_cmts; -%ignore resolve_complex_type; -%ignore visit_strmems; -%ignore foreach_strmem; -%ignore is_type_scalar; -%ignore get_type_signness; -%ignore is_type_signed; -%ignore is_type_unsigned; -%ignore get_struct_member; %ignore idb_type_to_til; %ignore get_idb_type; -%ignore apply_type_to_stkarg; -%rename (apply_type_to_stkarg) py_apply_type_to_stkarg; -%ignore print_type; -%rename (print_type) py_print_type; %rename (calc_type_size) py_calc_type_size; %rename (apply_type) py_apply_type; %ignore use_regarg_type_cb; -%ignore set_op_type_t; %ignore is_stkarg_load_t; %ignore has_delay_slot_t; %ignore gen_use_arg_types; %ignore enable_numbered_types; %ignore compact_numbered_types; -%ignore type_pair_vec_t::add_names; - %ignore callregs_t::findreg; %ignore format_data_info_t; %ignore valinfo_t; -%ignore print_c_data; %ignore print_cdata; -%ignore format_c_data; %ignore format_cdata; -%ignore format_cdata2; %ignore format_c_number; -%ignore get_enum_member_expr; %ignore extend_sign; // Kernel-only symbols @@ -192,10 +127,6 @@ %ignore bitfield_type_data_t::serialize; %ignore func_type_data_t::serialize; %ignore func_type_data_t::deserialize; -%ignore valstr_deprecated_t; -%ignore valinfo_deprecated_t; -%ignore valstr_deprecated2_t; -%ignore valinfo_deprecated2_t; %ignore tinfo_t::serialize(qtype *, qtype *, qtype *, int) const; %ignore custloc_desc_t; @@ -292,14 +223,42 @@ %template(funcargvec_t) qvector; %template(udtmembervec_t) qvector; %template(reginfovec_t) qvector; +%ignore qvector::operator==; +%ignore qvector::operator!=; +%ignore qvector::find; +%ignore qvector::has; +%ignore qvector::del; +%ignore qvector::add_unique; +%template(type_attrs_t) qvector; + +%extend tinfo_t { + PyObject *get_attr(const qstring &key, bool all_attrs=true) + { + bytevec_t bv; + if ( $self->get_attr(key, &bv, all_attrs) ) + return PyString_FromStringAndSize( + (const char *) bv.begin(), + bv.size()); + else + Py_RETURN_NONE; + } +} +%ignore tinfo_t::get_attr; + +%feature("director") predicate_t; + +%ignore load_til; +%rename (load_til) py_load_til; +%ignore load_til_header; +%rename (load_til_header) py_load_til_header; + +%ignore remove_tinfo_pointer; +%rename (remove_tinfo_pointer) py_remove_tinfo_pointer; %include "typeinf.hpp" // Custom wrappers -%rename (load_til) load_til_wrap; -%rename (load_til_header) load_til_header_wrap; -%rename (get_type_size0) py_get_type_size0; %rename (idc_get_type_raw) py_idc_get_type_raw; %rename (idc_get_local_type_raw) py_idc_get_local_type_raw; %rename (unpack_object_from_idb) py_unpack_object_from_idb; diff --git a/swig/ua.i b/swig/ua.i index fbc30c6..e427dfd 100644 --- a/swig/ua.i +++ b/swig/ua.i @@ -3,49 +3,145 @@ #include %} -%ignore insn_t; -%ignore op_t; -%ignore cmd; -%ignore showAsChar; -%ignore out_real; -%ignore init_output_buffer; -%ignore term_output_buffer; -%ignore OutValue; -%ignore OutImmChar; -%ignore out_name_expr; -%ignore ua_stkvar2; -%ignore ua_add_off_drefs; -%ignore ua_add_off_drefs2; -%ignore out_snprintf; -%ignore set_output_ptr; -%ignore get_output_ptr; -%ignore out_insert; -%ignore get_immval; +%ignore print_charlit; +%ignore print_fpval; %ignore get_spoiled_reg; %ignore decode_preceding_insn; -%ignore term_uaterm_ua; %ignore get_operand_immvals; - +%ignore get_immvals; %ignore get_immval; -%ignore ua_stkvar; +%ignore insn_create_op_data; %ignore construct_macro; +%ignore API70_construct_macro; %rename (construct_macro) py_construct_macro; -%ignore get_dtyp_by_size; -%rename (get_dtyp_by_size) py_get_dtyp_by_size; +%ignore get_dtype_by_size; +%rename (get_dtype_by_size) py_get_dtype_by_size; +%ignore outctx_base_t::print_hex_dump; +%ignore outctx_base_t::add_spaces; +%ignore outctx_base_t::nowarn_out_printf; +%ignore outctx_base_t::out_vprintf; +%ignore outctx_base_t::gen_colored_cmt_line_v; +%ignore outctx_base_t::gen_cmt_line_v; +%ignore outctx_base_t::gen_vprintf; +%ignore outctx_base_t::get_xrefgen_state; +%ignore outctx_base_t::get_cmtgen_state; + +%ignore outctx_base_t::regname_idx; +%ignore outctx_base_t::suspop; +%ignore outctx_base_t::F; +%ignore outctx_base_t::outvalues; +%ignore outctx_base_t::outvalue_getn_flags; +%ignore outctx_base_t::user_data; +%ignore outctx_base_t::kern_data; +%ignore outctx_base_t::lnar; +%ignore outctx_base_t::lnar_maxsize; +%ignore outctx_base_t::line_prefix; +%ignore outctx_base_t::prefix_len; +%ignore outctx_base_t::ctxflags; +%ignore outctx_base_t::ind0; +%ignore outctx_base_t::cmt_ea; +%ignore outctx_base_t::cmtbuf; +%ignore outctx_base_t::cmtptr; +%ignore outctx_base_t::cmtcolor; + +%template (operands_array) wrapped_array_t; + +%feature("nodirector") outctx_base_t; +%feature("nodirector") outctx_t; + +%ignore outctx_base_t::outctx_base_t; +%ignore outctx_base_t::~outctx_base_t; +%ignore outctx_t::outctx_t; +%ignore outctx_t::~outctx_t; + +%extend insn_t +{ + wrapped_array_t __get_ops__() + { + return wrapped_array_t($self->ops); + } + op_t *__get_operand__(int n) { QASSERT(30502, n >= 0 && n < UA_MAXOP); return &($self->ops[n]); } + uint16 __get_auxpref__() { return $self->auxpref; } + void __set_auxpref__(uint16 v) { $self->auxpref = v; } + + void assign(const insn_t &other) { *($self) = other; } + + %pythoncode { + ops = property(__get_ops__) +#ifdef BC695 + if _BC695: + Operands = ops +#endif + Op1 = property(lambda self: self.__get_operand__(0)) + Op2 = property(lambda self: self.__get_operand__(1)) + Op3 = property(lambda self: self.__get_operand__(2)) + Op4 = property(lambda self: self.__get_operand__(3)) + Op5 = property(lambda self: self.__get_operand__(4)) + Op6 = property(lambda self: self.__get_operand__(5)) + + auxpref = property(__get_auxpref__, __set_auxpref__) + + def __iter__(self): + return (self.ops[idx] for idx in xrange(0, UA_MAXOP)) + + def __getitem__(self, idx): + """ + Operands can be accessed directly as indexes + @return op_t: Returns an operand of type op_t + """ + if idx >= UA_MAXOP: + raise KeyError + else: + return self.ops[idx] + } +} + +%extend op_t +{ + uint16 __get_reg_phrase__() { return $self->reg; } + void __set_reg_phrase__(uint16 r) { $self->reg = r; } + + // use ea_t so the right value decoders will be used (for the next three) + ea_t __get_value__() { return $self->value; } + void __set_value__(ea_t v) { $self->value = v; } + ea_t __get_addr__() { return $self->addr; } + void __set_addr__(ea_t v) { $self->addr = v; } + ea_t __get_specval__() { return $self->specval; } + void __set_specval__(ea_t v) { $self->specval = v; } + + void assign(const op_t &other) { *($self) = other; } + + %pythoncode { + def has_reg(self, r): + """Checks if the operand accesses the given processor register""" + return self.reg == r.reg + + reg = property(__get_reg_phrase__, __set_reg_phrase__) + phrase = property(__get_reg_phrase__, __set_reg_phrase__) + value = property(__get_value__, __set_value__) + addr = property(__get_addr__, __set_addr__) + specval = property(__get_specval__, __set_specval__) + } +} +/* // @arnaud types! */ +%apply uchar { char offb }; +%apply uchar { char offo }; +%apply uchar { op_dtype_t dtype }; +%apply uchar { char specflag1 }; +%apply uchar { char specflag2 }; +%apply uchar { char specflag3 }; +%apply uchar { char specflag4 }; +%apply uchar { char flags }; + + +%apply ea_t { adiff_t off }; +%apply ea_t { adiff_t off }; %include "ua.hpp" -%rename (init_output_buffer) py_init_output_buffer; -%rename (term_output_buffer) py_term_output_buffer; -%rename (OutValue) py_OutValue; -%rename (OutImmChar) py_OutImmChar; -%rename (out_name_expr) py_out_name_expr; -%rename (ua_stkvar2) py_ua_stkvar2; -%rename (ua_add_off_drefs) py_ua_add_off_drefs; -%rename (ua_add_off_drefs2) py_ua_add_off_drefs2; %rename (decode_preceding_insn) py_decode_preceding_insn; -%rename (get_operand_immvals) py_get_operand_immvals; +%rename (get_immvals) py_get_immvals; %{ // diff --git a/tools/bc695.org b/tools/bc695.org new file mode 100644 index 0000000..38eaf23 --- /dev/null +++ b/tools/bc695.org @@ -0,0 +1,9 @@ +* DONE need to support all modules +* DONE cleanup idc.idc; have a map of correspondances so that we don't need /*ida_...*/ in idc.idc. +* TODO need a chooser_t-backed Chooser2 impl. +* TODO need a graph_viewer_t(or something)-backed GraphViewer impl. +* TODO re-enalbe those: EMPTY_SEL=chooser_t.NO_SELECTION +* TODO kernwin.py: add tests about add_menu_item/del_menu_item; it should be trivial to simulate with actions +* DONE inf.minEA, inf.maxEA -- super frequent! +* DONE ida_typeinf.cvar.idati doesn't exist anymore. Make it re-appear +* DONE re-instate AddCommand on Choose2 & GraphViewer diff --git a/tools/call_dmpapis.sh b/tools/call_dmpapis.sh new file mode 100755 index 0000000..02087a0 --- /dev/null +++ b/tools/call_dmpapis.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +PWD=`pwd` +API695=${PWD}/api695.txt +API700=${PWD}/api700.txt +TVHEADLESS=1 $IDAXBIN/idat -t -A "-S${PWD}/dmpapi.py ${API700}" > /dev/null +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$IDA695OPTBIN TVHEADLESS=1 $IDA695OPTBIN/idal -t -A "-S${PWD}/dmpapi.py ${API695}" > /dev/null + +python cmpapi.py --api-695 ${API695} --api-700 ${API700} diff --git a/tools/chkapi.py b/tools/chkapi.py index 4428f85..6a01435 100644 --- a/tools/chkapi.py +++ b/tools/chkapi.py @@ -2,10 +2,6 @@ from __future__ import with_statement import sys, optparse, re, pprint -ignorable_api_contents = [ - "qwait" - ] - class TextStream: def __init__(self, text): self.text = text @@ -13,7 +9,6 @@ class TextStream: self.maxpoint = len(self.text) self.line_nr = 0 self.char_nr = 0 - self.curline = None def line(self): pt = self.point @@ -84,65 +79,49 @@ def check_cpp(opts): # # Misc. # - "_wrap_areacb_t_get_type" : { - "mustcall" : "get_type", - }, "_wrap_tinfo_t_deserialize__SWIG_2" : { "mustcall" : "tinfo_t_deserialize__SWIG_2", }, "_wrap_get_bpt_group" : { "mustcall" : "PyString_FromStringAndSize", }, - "_wrap_get_jumptable_info" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_get_array_parameters" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_read_dbg_memory" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_write_dbg_memory" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_get_grp_bpts" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_generic_linput_t_read" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_generic_linput64_t_read64" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_linput_buffer_t_read" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_get_ptr_object_size" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_tag_strlen" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_get_next_member_idx" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_get_prev_member_idx" : { - "string" : "resultobj = PyLong_FromLongLong(result)", - }, - "_wrap_guess_tinfo2" : { + # "_wrap_get_array_parameters" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_read_dbg_memory" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_write_dbg_memory" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_get_grp_bpts" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_generic_linput_t_read" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_linput_buffer_t_read" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_tag_strlen" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_get_next_member_idx" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + # "_wrap_get_prev_member_idx" : { + # "string" : "resultobj = PyLong_FromLongLong(result)", + # }, + "_wrap_guess_tinfo" : { "mustcall" : "PyW_GetNumber", }, - "_wrap_IDP_Hooks_adjust_refinfo" : { + "_wrap_IDP_Hooks_ev_adjust_refinfo" : { "string" : "fixup_data_t", }, # char[ANY] out typemap "_wrap_idainfo_tag_get" : { "nostring" : " --size;", }, - # char[ANY] varout typemap - "Swig_var_database_idb_get" : { - "nostring" : " --size;", - }, "_wrap_warning__varargs__" : { "nullptrcheck" : 1, # 1st arg @@ -155,11 +134,11 @@ def check_cpp(opts): "_wrap_tag_remove" : { "nullptrcheck" : 1, }, - "_wrap_CompileLine" : { + "_wrap_compile_idc_file" : { "nullptrcheck" : 1, }, - "_wrap_set_fixup" : { - "nullptrcheck" : 2, + "_wrap_compile_idc_text" : { + "nullptrcheck" : 1, }, "_wrap_get_member_size" : { "nullptrcheck" : 1, @@ -175,14 +154,11 @@ def check_cpp(opts): "_wrap_get_opinfo" : { "string" : ["Py_XDECREF(resultobj)", "Py_INCREF(resultobj)"], }, - "_wrap_get_typeinfo" : { - "string" : ["Py_XDECREF(resultobj)", "Py_INCREF(resultobj)"], + + "_wrap_file2base" : { + "nostring" : ["SWIGTYPE_p_qoff64_t", "qoff64_t *"], }, - # no autoEnabled present - "SWIG_init" : { - "nostring" : "autoEnabled", - }, } functions_coherence_hexrays = { @@ -202,14 +178,36 @@ def check_cpp(opts): "mustcall" : "PyString_FromStringAndSize", }, "delete_qrefcnt_t_Sl_cfunc_t_Sg_" : { - "mustcall" : "hexrays_deregister_python_cfuncptr_t_instance", + "mustcall" : "hexrays_deregister_python_clearable_instance", }, "_wrap__decompile" : { - "mustcall" : "hexrays_register_python_cfuncptr_t_instance", + "mustcall" : "hexrays_register_python_clearable_instance", }, "_wrap_vdui_t_cfunc_get" : { - "mustcall" : "hexrays_register_python_cfuncptr_t_instance", + "mustcall" : "hexrays_register_python_clearable_instance", }, + " delete_cexpr_t" : { + "mustcall" : "hexrays_deregister_python_clearable_instance", + }, + " delete_cinsn_t" : { + "mustcall" : "hexrays_deregister_python_clearable_instance", + }, + " delete_cblock_t" : { + "mustcall" : "hexrays_deregister_python_clearable_instance", + }, + "*new_cexpr_t" : { + "mustcall" : "hexrays_register_python_clearable_instance", + }, + "*new_cinsn_t" : { + "mustcall" : "hexrays_register_python_clearable_instance", + }, + "*new_cblock_t" : { + "mustcall" : "hexrays_register_python_clearable_instance", + }, + "_wrap_boundaries_find" : { + "nostring" : "SWIGTYPE_p_p_cinsn_t", + }, + # # qvector # @@ -275,7 +273,11 @@ def check_cpp(opts): # Read and go through lines for one_file in opts.files.split(","): with open(one_file, "r") as f: - ts = TextStream(f.read()) + raw = f.read() + # ensure we have improved director out type reporting + if raw.find("""in output value of type '""int""'");""") > -1: + raise Exception("Director output value type reporting doesn't appear to be patched") + ts = TextStream(raw) # Process lines STATE_UNKNOWN = 0 @@ -284,6 +286,7 @@ def check_cpp(opts): while not ts.empty(): line = ts.line().rstrip() # dbg("Line: '%s'" % line) + if is_fundecl(line): # dbg("Entering function (from line %d: '%s')" % (ts.line_nr, line)) state = STATE_IN_FUN @@ -291,10 +294,9 @@ def check_cpp(opts): match = api_fname_regex.match(funstart) if match: fname = match.group(1) - if fname not in ignorable_api_contents: - api_contents["functions"].append(fname) + api_contents["functions"].append(fname) funlines = collect_funbody_lines(ts) - KICKME_functions_lines[fname] = funlines + KICKME_functions_lines[fname] = funlines # Do we care about this function? check_for = None for fname in functions_coherence.keys(): @@ -305,12 +307,12 @@ def check_cpp(opts): dbg("Checking function at line %d: '%s'" % (ts.line_nr, check_for)) chk = functions_coherence[check_for] chk["spotted"] = True - def look_for_stuff(stuff, isFuncall, lookForPresence=True): + def look_for_stuff(stuff, is_funcall, lookForPresence=True): if isinstance(stuff, str): stuff = [stuff] for bit in stuff: found = False - bit_pat = ("%s(" % bit) if isFuncall else bit + bit_pat = ("%s(" % bit) if is_funcall else bit dbg("Thing to look for: '%s'" % bit_pat) for funline in funlines: # dbg("Testing line: '%s'" % funline) @@ -360,16 +362,15 @@ def check_cpp(opts): def check_python(opts): types_coherence_base = { - "func_t" : { "mustinherit" : "ida_area.area_t" }, - "hidden_area_t" : { "mustinherit" : "ida_area.area_t" }, - "qbasic_block_t" : { "mustinherit" : "ida_area.area_t" }, - "regvar_t" : { "mustinherit" : "ida_area.area_t" }, - "segment_t" : { "mustinherit" : "ida_area.area_t" }, - "segreg_area_t" : { "mustinherit" : "ida_area.area_t" }, - "segreg_t" : { "mustinherit" : "ida_area.area_t" }, + "func_t" : { "mustinherit" : "ida_range.range_t" }, + "hidden_range_t" : { "mustinherit" : "ida_range.range_t" }, + "qbasic_block_t" : { "mustinherit" : "ida_range.range_t" }, + "regvar_t" : { "mustinherit" : "ida_range.range_t" }, + "segment_t" : { "mustinherit" : "ida_range.range_t" }, + "sreg_range_t" : { "mustinherit" : "ida_range.range_t" }, - "GraphViewer" : { "mustinherit" : "ida_idaapi.CustomIDAMemo" }, - "IDAViewWrapper" : { "mustinherit" : "ida_idaapi.CustomIDAMemo" }, + "GraphViewer" : { "mustinherit" : "ida_kernwin.CustomIDAMemo" }, + "IDAViewWrapper" : { "mustinherit" : "CustomIDAMemo" }, "PyIdc_cvt_int64__" : { "mustinherit" : "pyidc_cvt_helper__" }, "PyIdc_cvt_refclass__" : { "mustinherit" : "pyidc_cvt_helper__" }, "_qstrvec_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, @@ -381,19 +382,17 @@ def check_python(opts): "func_type_data_t" : { "mustinherit" : "funcargvec_t" }, "ida_lowertype_helper_t" : { "mustinherit" : "lowertype_helper_t" }, "idaplace_t" : { "mustinherit" : "place_t" }, - "insn_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, - "location_t" : { "mustinherit" : "curloc" }, - "op_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, + "insn_t" : { "mustinherit" : "object" }, + "op_t" : { "mustinherit" : "object" }, "plugin_t" : { "mustinherit" : "pyidc_opaque_object_t" }, "processor_t" : { "mustinherit" : "ida_idaapi.pyidc_opaque_object_t" }, "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" }, "structplace_t" : { "mustinherit" : "place_t" }, - "switch_info_ex_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, + "switch_info_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, "textctrl_info_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" }, "udt_type_data_t" : { "mustinherit" : "udtmembervec_t" }, - "varpart_t" : { "mustinherit" : "varloc_t" }, # Just look for the presence of those things "BADNODE" : {}, diff --git a/tools/cmpapi.py b/tools/cmpapi.py new file mode 100644 index 0000000..d107d3e --- /dev/null +++ b/tools/cmpapi.py @@ -0,0 +1,671 @@ + +import argparse +p = argparse.ArgumentParser() +p.add_argument("--api-695", required=True, help="Path to the 6.95 API desc file") +p.add_argument("--api-700", required=True, help="Path to the 7.00 API desc file") + +args = p.parse_args() +with open(args.api_695, "r") as fin: + api_695 = eval(fin.read()) +with open(args.api_700, "r") as fin: + api_700 = eval(fin.read()) + +renamed_modules = { + "ida_area" : "ida_range", + "ida_queue" : "ida_problems", + "ida_srarea" : "ida_segregs", + "ida_queue" : "ida_problems", +} + +renamed_symbols = { + "ida_area" : { + "AREACB_TYPE_FUNC" : "RANGE_KIND_FUNC", + "AREACB_TYPE_FUNC" : "RANGE_KIND_FUNC", + "AREACB_TYPE_HIDDEN_AREA" : "RANGE_KIND_HIDDEN_RANGE", + "AREACB_TYPE_SEGMENT" : "RANGE_KIND_SEGMENT", + "AREACB_TYPE_UNKNOWN" : "RANGE_KIND_UNKNOWN", + "area_t_print(*args)" : "range_t_print(*args)", + "areavec_t" : "rangevec_t", + }, + + "ida_auto" : { + "analyze_area" : "plan_and_wait", + "autoCancel" : "auto_cancel", + "autoIsOk" : "auto_is_ok", + "autoMark" : "auto_mark", + "autoUnmark" : "auto_unmark", + "autoWait" : "auto_wait", + }, + + "ida_bytes" : { + "doExtra(_)" : "doExtra(_, *args)", + "noExtra(_)" : "noExtra(_, *args)", + "do3byte(*args)" : "do3byte(_, *args)", + "f_is3byte(*args)" : "f_is3byte(_, *args)", + "get_3byte(*args)" : "get_3byte(_, *args)", + "is3byte(*args)" : "is3byte(_, *args)", + }, + + "ida_dbg" : { + "get_tev_reg_mem_ea(*args)" : "get_tev_reg_mem_ea(_, _)", + "get_tev_reg_mem_qty(*args)" : "get_tev_reg_mem_qty(_)", + "get_tev_reg_val(*args)" : "get_tev_reg_val(_, _)", + }, + + "ida_frame" : { + "ida_area" : "ida_range", + + }, + + "ida_funcs" : { + "ida_area" : "ida_range", + + }, + + "ida_gdl" : { + "ida_area" : "ida_range", + + }, + + "ida_hexrays" : { + "call_helper(*args)" : "call_helper(_, _, *rest)", + "dereference(*args)" : "dereference(_, _, =False)", + "lnot(*args)" : "lnot(_)", + "make_ref(*args)" : "make_ref(_)", + "new_block(*args)" : "new_block()", + }, + + "ida_ida" : { + "ansi2idb(*args)" : "ansi2idb(_, _)", + "idb2scr(*args)" : "idb2scr(_, _)", + "scr2idb(*args)" : "scr2idb(_, _)", + }, + + "ida_kernwin" : { + "TODO" : [ + "Choose", + "EMPTY_SEL", + "END_SEL", + "START_SEL", + ], + "askident(*args)" : "askident(_, _)", + }, + + "ida_segment" : { + "ida_area" : "ida_range", + }, + + "ida_srarea" : { + "ida_area" : "ida_range", + "is_segreg_locked(*args)" : "is_segreg_locked(_, *args)", + }, + + "ida_typeinf" : { + "callregs_init_regs(*args)" : "callregs_init_regs(_, *args)", + "print_type3(*args)" : "print_type", + }, + + "idc" : { + "Fatal(_)" : "Fatal(*args)", + "Warning(_)" : "Warning(*args)", + }, +} + +removed_symbols = { + + "ida_allins" : [ + "NN_vmovntsd", + "NN_vmovntss", + ], + + "ida_area" : [ + "AREACB_TYPE_SRAREA", + "area_visitor2_t", + "areacb_t", + "lock_area", + ], + + "ida_auto" : [ + "autoGetName", + "autoStep", + ], + + "ida_bytes" : [ + "cvar", + # the following have been removed + "doVar", + "f_isUnknown", + "getRadixEA", + "get_data_type_size", + "get_typeinfo", + "ida_area", + "isVar", + "lowbits", + "noImmd", + "power2", + "setFlags", + "set_typeinfo", + ], + + "ida_dbg" : [ + "SRCIT_REGVAR", + "SRCIT_RRLVAR", + "SRCIT_STKVAR", + ], + + "ida_diskio" : [ + "call_system", + "echsize", + "echsize64", + "ecreate", + "ecreateT", + "enumerate_system_files", + "eseek", + "eseek64", + "getdspace", + "openM", + "openR", + "openRT", + "qfsize", + "qfsize64", + "qlgetz64", + "qlseek64", + "qlsize64", + "qltell64", + ], + + "ida_enum" : [ + "const_visitor_t", + "for_all_consts", + "get_bmask_node", + "ENUM_FLAGS_FROMTIL", + "ENUM_FLAGS_GHOST", + "ENUM_FLAGS_WIDTH", + ], + + "ida_expr" : [ + "call_idc_method", + "call_script_method", + "compile_script_file", + "compile_script_func", + "extlang_call_method_exists", + "extlang_compile_file_exists", + "extlang_run_statements_exists", + "extlang_set_attr_exists", + "extlang_unload_procmod", + "get_extlang_fileext", + "get_idcpath", + "install_extlang", + "remove_extlang", + "run_statements", + "select_extlang", + "VarAssign", + "find_extlang_by_ext", + "find_extlang_by_name", + "_IDCFUNC_CB_T", + "call_idc_func__", + ], + + "ida_fixup" : [ + "FIXUP_MASK", + "FIXUP_SELFREL", + "FIXUP_UNUSED", + "FIXUP_VHIGH", + "FIXUP_VLOW", + "get_fixup_base", + "get_fixup_extdef_ea", + "get_fixup_segdef_sel", + "set_custom_fixup_ex", + "set_fixup_ex", + ], + + "ida_frame" : [ + "add_stkvar2", + "add_stkvar3", + ], + + "ida_funcs" : [ + "a2funcoff", + "get_sig_filename", + "std_gen_func_header", + ], + + "ida_gdl" : [ + "display_complex_call_chart", + "display_flow_graph", + "display_simple_call_chart", + "ida_area", + ], + + "ida_graph" : [ + "pyg_add_command", + ], + + "ida_hexrays" : [ + "add_custom_viewer_popup_item", + "vcall_helper", + "vcreate_helper", + ], + + "ida_ida" : [ + "IDAPLACE_HEXDUMP", + "LFLG_UNUSED", + "PREF_VARMARK", + "text_options_t", + "dto_copy_from_inf", + "dto_copy_to_inf", + "dto_init", + ], + + "ida_idd" : [ + "BPT_OLD_EXEC", + "idd_opinfo_old_t", + ], + + "ida_idp" : [ + "create_custom_fixup", + "deleting_enum_const", + "enum_const_created", + "enum_const_deleted", + "gen_abssym", + "gen_comvar", + "gen_extern", + "gen_spcdef", + "intel_data", + "ph_get_high_fixup_bits", + ], + + "ida_kernwin" : [ + "CHOOSER_HOTKEY", + "add_chooser_command", + "add_menu_item", + "add_output_popup", + "choose2_add_command", + "choose_choose", + "create_ea_viewer", + "create_tform", + "del_menu_item", + "enable_menu_item", + "get_tform_idaview", + "obsolete_msg_popup", + "obsolete_view_popup", + "py_menu_item_callback", + "pyscv_add_popup_menu", + "pyscv_clear_popup_menu", + "set_menu_item_icon", + "vumsg", + "choose_enter", + "choose_getl", + "choose_segreg", + "choose_sizer", + "askfile2_cv", + "vaskqstr", + + # ctypes vars + "DEFAULT_MODE", + "RTLD_GLOBAL", + "RTLD_LOCAL", + ], + + "ida_lines" : [ + "ExtraFree", + "MakeBorder", + "MakeLine", + "MakeNull", + "MakeSolidBorder", + "gen_cmt_line", + "gen_collapsed_line", + "generate_big_comment", + "generate_many_lines", + "printf_line", + ], + + "ida_loader" : [ + "load_loader_module", + ], + + "ida_moves" : [ + "CURLOC_SISTACK_ITEMS", + "UNHID_AREA", + "curloc", + "location_t", + ], + + "ida_nalt" : [ + "SWI_SHIFT1", + "del_jumptable_info", + "get_auto_plugins", + "get_jumptable_info", + "ids_array", + "jumptable_info_t", + "set_auto_plugins", + "set_jumptable_info", + "switch_info_t_get_regdtyp", + "switch_info_t_set_regdtyp", + ], + + "ida_name" : [ + "append_struct_fields2", + "gen_name_decl", + ], + + "ida_pro" : [ + "convert_encoding", # wasn't usable (bytevec_t not exposed) + "init_process", + "qsplitpath", # wasn't usable (char **) + "replace_tabs", # wasn't usable (wasn't returning the string) + "vinterr", # wasn't usable (va_list) + "expand_argv", + "free_argv", + "qwait", + "qwait_timed", + ], + + "ida_queue" : [ + "QueueMark", + ], + + "ida_segment" : [ + "std_gen_segm_footer", + ], + + "ida_srarea" : [ + "get_srarea", + "get_srareas_qty", + "getn_srarea", + "segreg_t", + ], + + "ida_strlist" : [ + "set_strlist_options", + ], + + "ida_struct" : [ + "get_member_ti", + "set_member_ti", + "get_or_guess_member_type", + ], + + "ida_typeinf" : [ + "ARGLOC_REG", + "ARGLOC_REG2", + "BAD_VARLOC", + "append_complex_n", + "append_da", + "append_de", + "append_dt", + "append_name", + "append_varloc", + "apply_once_type_and_name", + "apply_type2", + "apply_type_to_stkarg", + "build_array_type", + "build_func_type", + "build_func_type2", + "build_funcarg_info", + "calc_argloc_info", + "calc_func_nargs", + "calc_max_children_qty", + "calc_max_number_of_children", + "calc_varloc_info", + "check_skip_type", + "convert_argloc_to_varloc", + "convert_varloc_to_argloc", + "create_numbered_type_reference", + "extract_and_convert_old_argloc", + "extract_old_argloc", + "for_all_types", + "func_type_info_t", + "funcarg_info_t", + "get_argloc_r1", + "get_argloc_r2", + "get_complex_n", + "get_enum_base_type", + "get_func_cc", + "get_func_cvtarg_map", + "get_func_nargs", + "get_func_rettype", + "get_funcarg_size", + "get_idainfo_by_type2", + "get_name_of_named_type", + "get_ptr_object_size", + "get_referred_ordinal", + "get_scattered_varloc", + "get_spoil_cnt", + "get_stkarg_offset", + "get_strmem", + "get_strmem2", + "get_strmem_by_name", + "get_strmem_t", + "get_tilpath", + "get_type_sign", + "get_type_size0", + "guess_func_tinfo", + "is_castable2", + "is_reg2_argloc", + "is_reg_argloc", + "cleanup_varloc", + "copy_varloc", + "is_resolved_type_struni", + "is_restype_array", + "is_restype_bitfld", + "is_restype_complex", + "is_restype_const", + "is_restype_floating", + "is_restype_func", + "is_restype_ptr", + "is_restype_union", + "is_stack_argloc", + "is_type_only_size", + "is_type_resolvable", + "is_type_scalar2", + "is_type_unk", + "is_type_void_obsolete", + "is_type_voiddef", + "is_valid_full_type", + "make_array_type", + "make_old_argloc", + "parse_types2", + "print_type_to_qstring", + "remove_type_pointer", + "rename_named_type", + "replace_subtypes", + "replace_subtypes2", + "resolve_complex_type2", + "set_complex_n", + "set_named_type64", + "set_scattered_varloc", + "set_spoils", + "skip_spoiled_info", + "skip_varloc", + "split_old_argloc", + "til2idb", + "type_mapper_t", + "type_pair_t", + "type_pair_vec_t", + "type_visitor_t", + "valstrs_deprecated2_t", + "valstrs_deprecated_t", + ], + + "ida_ua" : [ + "OutBadInstruction", + "OutChar", + "OutImmChar", + "OutLine", + "OutLong", + "OutMnem", + "OutValue", + "cmd", + # can't simulate those; they rely on cmd + "dataSeg", + "dataSeg_op", + "dataSeg_opreg", + "init_output_buffer", + "out_addr_tag", + "out_colored_register_line", + "out_keyword", + "out_line", + "out_long", + "out_name_expr", + "out_one_operand", + "out_register", + "out_symbol", + "out_tagoff", + "out_tagon", + "py_get_global_cmd_link", + "term_output_buffer", + "ua_add_off_drefs2", + "ua_ana0", + "ua_code", + "ua_dodata2", + "ua_outop", + "ua_outop2", + "ua_next_byte", + "ua_next_word", + "ua_next_long", + "ua_next_qword", + + # these guys are now handled by SWiG (no more c-link stuff.) + "insn_t_assign", + "insn_t_create", + "insn_t_destroy", + "insn_t_get_auxpref", + "insn_t_get_canon_feature", + "insn_t_get_canon_mnem", + "insn_t_get_cs", + "insn_t_get_ea", + "insn_t_get_flags", + "insn_t_get_insnpref", + "insn_t_get_ip", + "insn_t_get_itype", + "insn_t_get_op_link", + "insn_t_get_segpref", + "insn_t_get_size", + "insn_t_is_canon_insn", + "insn_t_set_auxpref", + "insn_t_set_cs", + "insn_t_set_ea", + "insn_t_set_flags", + "insn_t_set_insnpref", + "insn_t_set_ip", + "insn_t_set_itype", + "insn_t_set_segpref", + "insn_t_set_size", + "op_t_assign", + "op_t_create", + "op_t_destroy", + "op_t_get_addr", + "op_t_get_dtyp", + "op_t_get_flags", + "op_t_get_n", + "op_t_get_offb", + "op_t_get_offo", + "op_t_get_reg_phrase", + "op_t_get_specflag1", + "op_t_get_specflag2", + "op_t_get_specflag3", + "op_t_get_specflag4", + "op_t_get_specval", + "op_t_get_type", + "op_t_get_value", + "op_t_set_addr", + "op_t_set_dtyp", + "op_t_set_flags", + "op_t_set_n", + "op_t_set_offb", + "op_t_set_offo", + "op_t_set_reg_phrase", + "op_t_set_specflag1", + "op_t_set_specflag2", + "op_t_set_specflag3", + "op_t_set_specflag4", + "op_t_set_specval", + "op_t_set_type", + "op_t_set_value", + ], + + "idc" : [ + "ida_srarea", + "ASCSTR_LAST", + "FIXUP_MASK", + "GetOpnd", + "MakeCustomDataEx", + "SW_MICRO", + "SetFlags", + "SetHiddenArea", + "FF_VAR", + "INFFL_LZERO", + "INF_WIDE_HIGH_BYTE_FIRST", + "INF_ABINAME", + "INF_ASCIIFLAGS", + "INF_ASCIIPREF", + "INF_ASCIISERNUM", + "INF_ASCIIZEROES", + "INF_ASCII_BREAK", + "INF_ASSUME", + "INF_AUTO", + "INF_BEGIN_EA", + "INF_CHECKARG", + "INF_CORESTART", + "INF_ENTAB", + "INF_FCORESIZ", + "INF_MF", + "INF_NAMELEN", + "INF_NULL", + "INF_ORG", + "INF_PACKBASE", + "INF_PREFSEG", + "INF_SHOWAUTO", + "INF_SHOWBADS", + "INF_SHOWPREF", + "INF_START_AF", + "INF_VOIDS", + "REF_VHIGH", + "REF_VLOW", + "_invoke_idc_setprm", + "byteValue", + "isFop0", + "isFop1", + "isVar", + "Tabs", + "o_fpreg_arm", + ], +} + +for modname in sorted(api_695.keys()): + m6 = api_695[modname] + new_modname = modname + m7 = api_700[renamed_modules.get(modname, modname)] + for symbol in m6: + symbol_root = symbol + params = "" + paren_idx = symbol_root.find("(") + if paren_idx > -1: + symbol_root, params = symbol_root[0:paren_idx], symbol_root[paren_idx:] + removed_set = removed_symbols.get(modname, []) + if symbol_root in removed_set: + continue + renamed_set = renamed_symbols.get(modname, {}) + if symbol_root in renamed_set.get("TODO", []): + continue + target_symbol = renamed_set.get(symbol_root, symbol_root) + if target_symbol not in m7: + # try looking for a full prototype then + target_symbol = renamed_set.get(symbol, symbol) + if target_symbol not in m7: + add = "" + is_redef = False + if params: + # search for something that might correspond + x = "%s(" % symbol_root + for s in m7: + if s.startswith(x): + # print ("Candidate for '%s': '%s'" % (x, s)) + if s.endswith("bc695redef"): + is_redef = True # symbol was redefined, and marked as such. We assume we know what we're doing + break + else: + add = " => %s" % s + if not is_redef: + print("Missing: '%s.%s'%s" % (modname, symbol, add)) diff --git a/tools/deploy.py b/tools/deploy.py index 8c6cc6c..420f136 100644 --- a/tools/deploy.py +++ b/tools/deploy.py @@ -9,10 +9,10 @@ import sys, re, os, glob major, minor, micro, _, _ = sys.version_info try: - from argparse import ArgumentParser + from argparse import ArgumentParser except: - print "Failed to import module 'argparse'. Upgrade to Python 2.7, copy argparse.py to this directory or try 'apt-get install python-argparse'" - raise + print "Failed to import module 'argparse'. Upgrade to Python 2.7, copy argparse.py to this directory or try 'apt-get install python-argparse'" + raise parser = ArgumentParser() parser.add_argument("-t", "--template", required=True) @@ -20,7 +20,9 @@ parser.add_argument("-o", "--output", required=True) parser.add_argument("-m", "--module", required=True) parser.add_argument("-w", "--pywraps", required=True) parser.add_argument("-d", "--interface-dependencies", type=str, required=True) +parser.add_argument("-l", "--lifecycle-aware", default=False, action="store_true") parser.add_argument("-v", "--verbose", default=False, action="store_true") +parser.add_argument("-b", "--bc695", default=False, action="store_true") args = parser.parse_args() # creates a regular expression @@ -34,7 +36,7 @@ def convert_path(path_in): return os.sep.join(parts) -def apply_tags(template_str, input_str, tags, verbose): +def apply_tags(template_str, input_str, tags, verbose, path): for desc, (expr_str, expr) in tags: # find source pattern matches = expr.findall(input_str) @@ -43,22 +45,35 @@ def apply_tags(template_str, input_str, tags, verbose): print("Failed to match <%s> source expression against '%s', skipping...!" % (desc, expr_str)) continue - # find pattern in destination - dest = expr.search(template_str) - if not dest: - raise Exception("Found <%s> for module '%s' in input, but failed to match in destination" % ( - desc, expr)) + is_695_bwcompat = desc == "pycode_BC695" + + if not is_695_bwcompat: + # find pattern in destination + dest = expr.search(template_str) + if not dest: + raise Exception("Found <%s> for module '%s' in input (%s), but failed to match in destination" % ( + desc, expr_str, path)) # accumulate all the strings to be replaced replaces = [] for src in matches: replaces.append(src) - template_str = template_str[:dest.start(1)] + "\n".join(replaces) + template_str[dest.end(1):] + if is_695_bwcompat: + if args.bc695: + r2 = [] + for r in replaces: + rlines = r.split("\n") + rlines = map(lambda l: " %s" % l, filter(lambda l: len(l.strip()), rlines)) + r2.append("\n".join(rlines)) + replaces = ["", "if _BC695:"] + r2 + ["\n"] + template_str = template_str + "%pythoncode %{" + "\n".join(replaces) + "%}" + else: + template_str = template_str[:dest.start(1)] + "\n".join(replaces) + template_str[dest.end(1):] return template_str -def deploy(module, template, output, pywraps, iface_deps, verbose): +def deploy(module, template, output, pywraps, iface_deps, lifecycle_aware, verbose): template = convert_path(template) output = convert_path(output) @@ -81,10 +96,11 @@ def deploy(module, template, output, pywraps, iface_deps, verbose): ('inline', make_re('inline', tagname, '//')), ('decls', make_re('decls', tagname, '//')), ('init', make_re('init', tagname, '//')), + ('pycode_BC695', make_re('pycode_BC695', tagname, '#')), ) input_str = "".join(file(path, "r").readlines()) - template_str = apply_tags(template_str, input_str, tags, verbose) + template_str = apply_tags(template_str, input_str, tags, verbose, path) # write output file with open(output, 'w') as f: @@ -105,4 +121,24 @@ def deploy(module, template, output, pywraps, iface_deps, verbose): f.write("%include \"header.i\"\n") f.write(template_str) -deploy(args.module, args.template, args.output, args.pywraps, args.interface_dependencies, args.verbose) + if lifecycle_aware: + f.write(""" +%%init %%{ +{ + module_callbacks_t module_lfc; + module_lfc.closebase = ida_%s_closebase; + module_lfc.term = ida_%s_term; + register_module_lifecycle_callbacks(module_lfc); +} +%%} +""" % (module, module)) + +deploy( + args.module, + args.template, + args.output, + args.pywraps, + args.interface_dependencies, + args.lifecycle_aware, + args.verbose) + diff --git a/tools/deploy/header.i.in b/tools/deploy/header.i.in index 8d3c090..720cef4 100644 --- a/tools/deploy/header.i.in +++ b/tools/deploy/header.i.in @@ -9,8 +9,6 @@ // generate directors for all classes that have virtual methods %feature("director"); // exceptions -%feature("nodirector") const_visitor_t; -%feature("nodirector") const_vloc_visitor_t; %feature("nodirector") enumplace_t; %feature("nodirector") generic_linput64_t; %feature("nodirector") generic_linput_t; @@ -20,11 +18,8 @@ %feature("nodirector") qstring_printer_t; %feature("nodirector") simpleline_place_t; %feature("nodirector") structplace_t; -%feature("nodirector") type_mapper_t; -%feature("nodirector") type_visitor_t; %feature("nodirector") vc_printer_t; %feature("nodirector") vd_printer_t; -%feature("nodirector") vloc_visitor_t; %feature("nodirector") qflow_chart_t; %feature("nodirector") lowertype_helper_t; %feature("nodirector") ida_lowertype_helper_t; @@ -57,6 +52,8 @@ void qvector::grow(const long long &x=0); %ignore qvector::grow; %ignore qvector::at(size_t); +%ignore qvector::front; +%ignore qvector::back; // simpleline_t doesn't implement '=='. Therefore, all these cannot be present in the instantiated template. %ignore qvector::operator==; @@ -98,7 +95,6 @@ void qvector::grow(const long long &x=0); %ignore qpipe_read; %ignore qpipe_write; %ignore qpipe_close; -%ignore qwait_for_handles; %ignore qstrlen; %ignore qstrcmp; %ignore qstrstr; @@ -113,6 +109,7 @@ void qvector::grow(const long long &x=0); %ignore c2ustr; %ignore base64_encode; %ignore base64_decode; +%ignore replace_tabs; %ignore utf8_unicode; %ignore unicode_utf8; %ignore win_utf2idb; @@ -174,6 +171,24 @@ ${ALL_IMPORTS} import ida_idaapi } +#ifdef BC695 +%pythoncode { +import sys +_BC695 = sys.modules["__main__"].IDAPYTHON_COMPAT_695_API + +if _BC695: + # This is a decorator for eliminating false-positives when automatically + # performing diffs of API7.0 vs API6.95 (typically, the prototypes for the + # functions using this decorator will have changed, and this is used to + # mark that that change is on-purpose, under control, and should in fact + # provide bw-compat. Usually those prototypes went from '(*args)', to a + # more specialized argument list.) + def bc695redef(func): + func.func_dict["bc695redef"] = True + return func +} +#endif // BC695 + //--------------------------------------------------------------------- %extend qvector { inline size_t __len__() const { return $self->size(); } @@ -199,11 +214,13 @@ import ida_idaapi $self->at(i) = v; } - inline const T&at(size_t i) { + inline const T &at(size_t i) { return __getitem__(i); } %pythoncode { + front = ida_idaapi._qvector_front + back = ida_idaapi._qvector_back __iter__ = ida_idaapi._bounded_getitem_iterator } } @@ -339,11 +356,13 @@ static PyObject *type##_get_clink_ptr(PyObject *self) %set_output(SWIG_FromCharPtrAndSize($1, strnlen($1, $1_dim0))); } - -%typemap(out) ssize_t -{ - $result = PyLong_FromLongLong($1); -} +#ifdef __X64__ +%apply unsigned long long { size_t } +%apply long long { ssize_t } +#else +%apply unsigned long { size_t } +%apply long { ssize_t } +#endif //--------------------------------------------------------------------- // Convert an incoming Python list to a tid_t[] array @@ -405,15 +424,12 @@ static PyObject *type##_get_clink_ptr(PyObject *self) //--------------------------------------------------------------------- %define %cstring_output_maxstr_none(TYPEMAP, SIZE) - %typemap (default) SIZE { $1 = MAXSTR; } - %typemap(in,numinputs=0) (TYPEMAP, SIZE) { $1 = ($1_ltype) qalloc(MAXSTR+1); } - %typemap(argout) (TYPEMAP,SIZE) { Py_XDECREF(resultobj); if (result > 0) @@ -429,28 +445,6 @@ static PyObject *type##_get_clink_ptr(PyObject *self) } %enddef -//--------------------------------------------------------------------- -%define %cstring_bounded_output_none(TYPEMAP,MAX) -%typemap(in, numinputs=0) TYPEMAP(char temp[MAX+1]) { - $1 = ($1_ltype) temp; -} -%typemap(argout,fragment="t_output_helper") TYPEMAP { - PyObject *o; - $1[MAX] = 0; - - if ($1 > 0) - { - o = PyString_FromString($1); - } - else - { - o = Py_None; - Py_INCREF(Py_None); - } - $result = t_output_helper($result,o); -} -%enddef - //--------------------------------------------------------------------- %define %binary_output_or_none(TYPEMAP, SIZE) %typemap (default) SIZE { @@ -474,30 +468,6 @@ static PyObject *type##_get_clink_ptr(PyObject *self) } %enddef -//--------------------------------------------------------------------- -%define %binary_output_with_size(TYPEMAP, SIZE) -%typemap (default) SIZE { - size_t ressize = MAXSPECSIZE; - $1 = &ressize; -} -%typemap(in,numinputs=0) (TYPEMAP, SIZE) { - $1 = (char *) qalloc(MAXSPECSIZE+1); -} -%typemap(argout) (TYPEMAP,SIZE) { - Py_XDECREF(resultobj); - if (result) - { - resultobj = PyString_FromStringAndSize((char *)$1, *$2); - } - else - { - Py_INCREF(Py_None); - resultobj = Py_None; - } - qfree((void *)$1); -} -%enddef - //--------------------------------------------------------------------- // IN/OUT qstring //--------------------------------------------------------------------- @@ -506,7 +476,7 @@ static PyObject *type##_get_clink_ptr(PyObject *self) } %typemap(argout) qstring *result { Py_XDECREF(resultobj); - if (result) + if (result > 0) { resultobj = PyString_FromStringAndSize($1->begin(), $1->length()); } @@ -592,31 +562,46 @@ static PyObject *type##_get_clink_ptr(PyObject *self) //--------------------------------------------------------------------- // IN qstring //--------------------------------------------------------------------- -// This is used to set/retrieve qstring that are structure members. -%typemap(in) qstring* +%define %bytes_container(REFTYPE, CONTAINER_TYPE, START_ACCESSOR, SIZE_ACCESSOR) +%typemap(in) REFTYPE { - char *buf; - Py_ssize_t length; - int success = PyString_AsStringAndSize($input, &buf, &length); - if ( success > -1 ) + if ( PyString_Check($input) ) { - $1 = new qstring(buf, length); + // init properly, so ctor can't crash + char *buf = NULL; + Py_ssize_t length = 0; + /*int success =*/ PyString_AsStringAndSize($input, &buf, &length); + $1 = new CONTAINER_TYPE(buf, length); // build regardless of success + } + else + { + SWIG_exception_fail( + SWIG_ValueError, + "Expected string " "in method '" "$symname" "', argument " "$argnum"" of type 'str'"); } } -%typemap(freearg) qstring* +%typemap(freearg) REFTYPE { delete $1; } -%typemap(out) qstring* +%typemap(out) REFTYPE // e.g., %typemap(out) qstring* { - $result = PyString_FromStringAndSize($1->c_str(), $1->length()); + $result = PyString_FromStringAndSize((const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR()); } -%typemap(out) qstring +%typemap(out) CONTAINER_TYPE // e.g., %typemap(out) qstring { - $result = PyString_FromStringAndSize($1.c_str(), $1.length()); + $result = PyString_FromStringAndSize((const char *) $1.START_ACCESSOR(), $1.SIZE_ACCESSOR()); } -%apply qstring { _qstring } -%apply qstring* { _qstring* } +%typemap(varout) CONTAINER_TYPE // e.g., %typemap(varout) qstring +{ + $result = PyString_FromStringAndSize((const char *) $1.START_ACCESSOR(), $1.SIZE_ACCESSOR()); +} +%enddef + +%bytes_container(qstring *, qstring, c_str, length); +%bytes_container(qstring &, qstring, c_str, length); +%bytes_container(bytevec_t *, bytevec_t, begin, size); +%bytes_container(bytevec_t &, bytevec_t, begin, size); //--------------------------------------------------------------------- // varargs (mostly kernwin.hpp) @@ -634,6 +619,13 @@ static PyObject *type##_get_clink_ptr(PyObject *self) "invalid null pointer " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'"); }; +//------------------------------------------------------------------------- +// for use with insn_t, op_t wrappers +%typemap(in) (size_t ptrval) +{ + $1 = size_t(PyLong_AsUnsignedLongLong($input)); +} + // Help SWIG to figure out the ulonglong type #ifdef SWIGWIN typedef unsigned __int64 ulonglong; @@ -648,20 +640,25 @@ typedef long long longlong; %apply longlong *INOUT { adiff_t *disp }; %apply ulonglong *INOUT { ea_t *addr }; %apply ulonglong *INOUT { sel_t *sel }; -%apply ulonglong *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection() +%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() #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 *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_selection() +%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() #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 }; %apply int *OUTPUT { int *icon }; %apply int *OUTPUT { action_state_t *state }; %apply bool *OUTPUT { bool *checkable }; @@ -789,7 +786,6 @@ static PyObject *qstrvec2pylist(qstrvec_t &vec) $result = PyLong_FromUnsignedLongLong((unsigned long long) $1); } -//--------------------------------------------------------------------- %typemap(in) uint64 { uint64 $1_temp; @@ -801,21 +797,22 @@ $result = PyLong_FromUnsignedLongLong((unsigned long long) $1); $1 = $1_temp; } -%inline %{ -namespace Controls -{ - class TWinControl; - class TCustomControl; // ptr to custom ida viewer +%typemap(in,numinputs=0) uint64 *result (uint64 temp) { + $1 = &temp; } -using Controls::TWinControl; -using Controls::TCustomControl; -%} - -namespace Forms -{ - class TForm; +%typemap(argout) uint64 *result { + Py_XDECREF(resultobj); + if (result > 0) + { + resultobj = PyLong_FromUnsignedLongLong(*(unsigned long long *) $1); + } + else + { + Py_INCREF(Py_None); + resultobj = Py_None; + } } -using Forms::TForm; +%apply uint64 *result { uint64 *out }; // Make get_any_cmt() work %apply unsigned char *OUTPUT { color_t *cmttype }; diff --git a/tools/dmpapi.py b/tools/dmpapi.py new file mode 100644 index 0000000..c3da559 --- /dev/null +++ b/tools/dmpapi.py @@ -0,0 +1,60 @@ + +# helper script, used to dump the contents of the IDA +# APIs (used for 7.00 -> 6.95 compat support) + +import os + +import idc +import idaapi +import inspect +outfile = idc.ARGV[1] + +def formatargspec(argspec): + # only format the default args + values + parts = [] + dflts = argspec.defaults or [] + for i in xrange(len(argspec.args) - len(dflts)): + parts.append("_") + for i in xrange(len(dflts)): + parts.append("=%s" % str(dflts[i])) + if argspec.varargs: + parts.append("*%s" % argspec.varargs) + if argspec.keywords: + parts.append("**%s" % argspec.keywords) + return ", ".join(parts) + + +def dump_module(module, out): + mname = module.__name__ + outmod = [] + out[mname] = outmod + for symbol in sorted(dir(module)): + if symbol.endswith("_swigregister"): + continue + if symbol == "_%s" % mname: # _ida_area + continue + if symbol == "cvar": + continue + srcmod = inspect.getmodule(getattr(module, symbol)) + if srcmod and (srcmod.__name__.find("ctypes") > -1): + continue + thing = getattr(module, symbol) + if inspect.isfunction(thing) or inspect.ismethod(thing): + argspec = inspect.getargspec(thing) + symbol = "%s(%s)" % (symbol, formatargspec(argspec)) + if thing.func_dict.get("bc695redef", False): + symbol = "%s!bc695redef" % symbol + outmod.append(symbol) + +out = {} +for modname in sorted(sys.modules): + module = sys.modules[modname] + if modname.startswith("ida_") or modname in ["idc"]: + # if modname not in ignorable_modules: + dump_module(module, out) + +with open(outfile, "w") as fout: + import pprint + fout.write("%s" % pprint.pformat(out)) + +idc.Exit(0) diff --git a/tools/docs/hrdoc.cfg b/tools/docs/hrdoc.cfg deleted file mode 100644 index 3c1f8e3..0000000 --- a/tools/docs/hrdoc.cfg +++ /dev/null @@ -1,147 +0,0 @@ -[epydoc] -# The list of objects to document. Objects can be named using -# dotted names, module filenames, or package directory names. -# Aliases for this option include "objects" and "values". -modules: idc, idautils, idaapi, ida_allins ida_area ida_auto ida_bytes ida_dbg ida_diskio ida_entry ida_enum ida_expr ida_fixup ida_fpro ida_frame ida_funcs ida_gdl ida_graph ida_hexrays ida_ida ida_idaapi ida_idd ida_idp ida_ints ida_kernwin ida_lines ida_loader ida_moves ida_nalt ida_name ida_netnode ida_offset ida_pro ida_queue ida_registry ida_search ida_segment ida_srarea ida_strlist ida_struct ida_typeinf ida_ua ida_xref - -# The type of output that should be generated. Should be one -# of: html, text, latex, dvi, ps, pdf. -output: html - -# The path to the output directory. May be relative or absolute. -target: hr-html/ - -# An integer indicating how verbose epydoc should be. The default -# value is 0; negative values will supress warnings and errors; -# positive values will give more verbose output. -verbosity: 0 - -# A boolean value indicating that Epydoc should show a tracaback -# in case of unexpected error. By default don't show tracebacks -debug: 0 - -# If True, don't try to use colors or cursor control when doing -# textual output. The default False assumes a rich text prompt -simple-term: 0 - - -### Generation options - -# The default markup language for docstrings, for modules that do -# not define __docformat__. Defaults to epytext. -docformat: epytext - -# Whether or not parsing should be used to examine objects. -parse: yes - -# Whether or not introspection should be used to examine objects. -introspect: yes - -# Don't examine in any way the modules whose dotted name match this -# regular expression pattern. -#exclude - -# Don't perform introspection on the modules whose dotted name match this -# regular expression pattern. -#exclude-introspect - -# Don't perform parsing on the modules whose dotted name match this -# regular expression pattern. -#exclude-parse - -# The format for showing inheritance objects. -# It should be one of: 'grouped', 'listed', 'included'. -inheritance: listed - -# Whether or not to inclue private variables. (Even if included, -# private variables will be hidden by default.) -private: no - -# Whether or not to list each module's imports. -imports: no - -# Whether or not to include syntax highlighted source code in -# the output (HTML only). -sourcecode: no - -# Whether or not to includea a page with Epydoc log, containing -# effective option at the time of generation and the reported logs. -include-log: no - - -### Output options - -# The documented project's name. -name: IDAPython - -# The CSS stylesheet for HTML output. Can be the name of a builtin -# stylesheet, or the name of a file. -css: white - -# The documented project's URL. -url: http://code.google.com/p/idapython/ - -# HTML code for the project link in the navigation bar. If left -# unspecified, the project link will be generated based on the -# project's name and URL. -link: Hex-Rays - -# The "top" page for the documentation. Can be a URL, the name -# of a module or class, or one of the special names "trees.html", -# "indices.html", or "help.html" -#top: os.path - -# An alternative help file. The named file should contain the -# body of an HTML file; navigation bars will be added to it. -#help: my_helpfile.html - -# Whether or not to include a frames-based table of contents. -frames: yes - -# Whether each class should be listed in its own section when -# generating LaTeX or PDF output. -separate-classes: no - - -### API linking options - -# Define a new API document. A new interpreted text role -# will be created -#external-api: epydoc - -# Use the records in this file to resolve objects in the API named NAME. -#external-api-file: epydoc:api-objects.txt - -# Use this URL prefix to configure the string returned for external API. -#external-api-root: epydoc:http://epydoc.sourceforge.net/api - - -### Graph options - -# The list of graph types that should be automatically included -# in the output. Graphs are generated using the Graphviz "dot" -# executable. Graph types include: "classtree", "callgraph", -# "umlclass". Use "all" to include all graph types -#graph: classtree - -# The path to the Graphviz "dot" executable, used to generate -# graphs. -#dotpath: /usr/local/bin/dot - -# The name of one or more pstat files (generated by the profile -# or hotshot module). These are used to generate call graphs. -#pstat: profile.out - -# Specify the font used to generate Graphviz graphs. -# (e.g., helvetica or times). -graph-font: Helvetica - -# Specify the font size used to generate Graphviz graphs. -#graph-font-size: 10 - - -### Return value options - -# The condition upon which Epydoc should exit with a non-zero -# exit status. Possible values are error, warning, docstring_warning -#fail-on: error diff --git a/tools/docs/hrdoc.py b/tools/docs/hrdoc.py index 0a1849e..65c49d8 100644 --- a/tools/docs/hrdoc.py +++ b/tools/docs/hrdoc.py @@ -9,8 +9,8 @@ try: except ImportError as e: import idc import traceback - idc.Message("Couldn't import module %s\n" % traceback.format_exc()) - idc.Exit(-1) + idc.msg("Couldn't import module %s\n" % traceback.format_exc()) + idc.qexit(-1) # -------------------------------------------------------------------------- DOC_DIR = 'hr-html' @@ -111,6 +111,13 @@ def main(): try: print "Generating documentation....." + import ida_pro + try: + ida_pro._BC695 + print "'ida_pro._BC695' exists. Please recompile with BC695=0 (see makefile). Bailing out." + return -1 + except: + pass # ok os.chdir('docs') gen_docs() @@ -126,4 +133,4 @@ def main(): # -------------------------------------------------------------------------- if __name__ == '__main__': main() - Exit(0) + qexit(0) diff --git a/tools/gen_idc_bc695.py b/tools/gen_idc_bc695.py new file mode 100644 index 0000000..23c12a9 --- /dev/null +++ b/tools/gen_idc_bc695.py @@ -0,0 +1,208 @@ + +# This script will do the following things: +# - open idc.idc +# - advance to the compatibility macros section +# - read, and parse each of those +# - if the symbol doesn't exist in the 'idc' module, dump its alias into the output file + +import argparse +p = argparse.ArgumentParser() +p.add_argument("-i", "--idc", required=True, help="Path to the idc.idc file") +p.add_argument("-o", "--output", required=True, help="Path to the output file") +p.add_argument("-d", "--debug-out", default=False, action="store_true", help="Dump code that shows, at ida start-time, what symbols would be overriden by the compat layer") +args = p.parse_args() + +import os + +with open(args.idc, "r") as fin: + inlines = fin.readlines() + +# search for compat macros section, and remove uninteresting lines +for idx in xrange(len(inlines)): + if inlines[idx].replace(" ", "").find("COMPATIBILITYMACROS") > -1: + break +assert(idx < len(inlines)) +inlines=inlines[idx:] + +def nextline(): + global inlines + l = inlines[0].strip() + inlines=inlines[1:] + idx = l.find("//") + if idx > -1: + l = l[0:idx].strip() + return l + +# set of symbols that must not be redefined +forbidden = [ + "GetLocalType", + "AddSeg", + "SetType", + "GetDisasm", + "SetPrcsr", + "GetFloat", + "GetDouble", + "AutoMark", + "is_pack_real", + "set_local_type", + "WriteMap", + "WriteTxt", + "WriteExe", + "CompileEx", + "uprint", + "form", + "Appcall", + "ApplyType", + "GetManyBytes", + "GetString", + "ClearTraceFile", + "FindBinary", + "NextHead", + "ParseTypes", + "PrevHead", + "ProcessUiAction", + "SaveBase", + "eval", + "MakeStr", +] + +symbols_modules = { + "AF_ANORET" : "ida_ida", + "AF_ANORET" : "ida_ida", + "AF_CHKUNI" : "ida_ida", + "AF_DATOFF" : "ida_ida", + "AF_DOCODE" : "ida_ida", + "AF_DODATA" : "ida_ida", + "AF_FTAIL" : "ida_ida", + "AF_HFLIRT" : "ida_ida", + "AF_JUMPTBL" : "ida_ida", + "AF_PURDAT" : "ida_ida", + "AF_REGARG" : "ida_ida", + "AF_SIGCMT" : "ida_ida", + "AF_SIGMLT" : "ida_ida", + "AF_STKARG" : "ida_ida", + "AF_STRLIT" : "ida_ida", + "AF_TRFUNC" : "ida_ida", + "AF_VERSP" : "ida_ida", + "BADADDR" : "ida_idaapi", + "FF_UNUSED" : "ida_bytes", + "FIXUPF_CREATED" : "ida_fixup", + "FIXUPF_EXTDEF" : "ida_fixup", + "FIXUPF_REL" : "ida_fixup", + "FIXUPF_UNUSED" : "ida_fixup", + "FIXUP_OFF8" : "ida_fixup", + "GN_VISIBLE" : "ida_name", + "SEGMOD_KEEP" : "ida_segment", + "SEGMOD_KILL" : "ida_segment", + "SEGMOD_SILENT" : "ida_segment", + "SETPROC_IDB" : "ida_idp", + "SETPROC_LOADER" : "ida_idp", + "SETPROC_LOADER_NON_FATAL" : "ida_idp", + "STRF_AUTO" : "ida_ida", + "STRF_COMMENT" : "ida_ida", + "STRF_GEN" : "ida_ida", + "STRF_SAVECASE" : "ida_ida", + "STRF_SERIAL" : "ida_ida", + "STRTYPE_C" : "ida_nalt", + "STRTYPE_C_16" : "ida_nalt", + "STRTYPE_C_32" : "ida_nalt", + "STRTYPE_LEN2_16" : "ida_nalt", + "STRTYPE_LEN4_16" : "ida_nalt", + "STRTYPE_PASCAL" : "ida_nalt", + "STRTYPE_TERMCHR" : "ida_nalt", + "V695_REF_VHIGH" : "ida_nalt", + "V695_REF_VLOW" : "ida_nalt", + "error" : "ida_kernwin", + "warning" : "ida_kernwin", + "ask_str" : "ida_kernwin", + "ask_file" : "ida_kernwin", + "ask_addr" : "ida_kernwin", + "ask_long" : "ida_kernwin", + "is_mapped" : "ida_bytes", + "decode_insn" : "ida_ua", +} + +import re +def maybe_qualify(s): + last_idx = -1 + for sym, mod in symbols_modules.items(): + idx = s.find(sym) + if idx > last_idx: + s = s.replace(sym, "%s.%s" % (mod, sym)) + last_idx = idx + 1 + len(mod) + return s + +def remove_parens(arg): + m = re.match(r'\s*\((.*)\)\s*$', arg) + if m: + arg = m.group(1) + return arg.strip() + +def fix_ternary_operator(code): + match = re.match(r'([^(]+)\((.*)\)', code) + if match: + changed = False + func = match.group(1) + args = match.group(2) + out = [] + for arg in args.split(','): + m2 = re.match(r'([^?]+)\?(.*):(.*)', arg) + if m2: + cond = remove_parens(m2.group(1)) + ithen = remove_parens(m2.group(2)) + ielse = remove_parens(m2.group(3)) + arg = ithen + ' if ' + cond + ' else ' + ielse + changed = True + out.append(arg.strip()) + if changed: + code = func + '(' + ', '.join(out) + ')' + return code + +import time +funcall_pat = re.compile(r"#define\s+([a-zA-Z0-9_]*)\s*(\([^\)]*\))\s*(.*)") +alias_pat = re.compile(r"#define\s+([a-zA-Z0-9_]*)\s*([a-zA-Z0-9_/\*\.]*)\s*$") +with open(args.output, "w") as fout: + fout.write("# Autogenerated on: %s\n\n" % time.strftime("%c")) + for mod in sorted(list(set(symbols_modules.values()))): + fout.write("import %s\n" % mod) + fout.write("from idc import *\n\n") + while len(inlines): + l = nextline() + if l == "": + continue + repl = None + match = funcall_pat.match(l) + if match: + symbol = match.group(1) + parms = match.group(2) + code = match.group(3) + while True: + has_more = code.endswith("\\") + if has_more: + code = code[0:-1] + code = code + nextline() + else: + break + code = fix_ternary_operator(code) + code = maybe_qualify(code) + repl = "def %s%s: return %s\n" % (symbol, parms, code) + else: + match = alias_pat.match(l) + if match: + symbol = match.group(1) + newsym = match.group(2) + newsym = maybe_qualify(newsym) + repl = "%s=%s\n" % (symbol, newsym) + + if repl and symbol not in forbidden: + if not args.debug_out: + fout.write(repl) + else: + fout.write(""" +try: + import idc + x = idc.%s + print("Would override %s") +except: + pass +""" % (symbol, symbol)) diff --git a/tools/genhooks/genhooks.py b/tools/genhooks/genhooks.py index 61da495..d36ffea 100644 --- a/tools/genhooks/genhooks.py +++ b/tools/genhooks/genhooks.py @@ -81,7 +81,7 @@ def add_enum_value(enumval_el, name, enum_name): rtype = None rdefault = None rexpr = None - recipe_data = recipe[name] if name in recipe else {} + recipe_data = recipe.get(name, {}) if "ignore" in recipe_data and recipe_data["ignore"]: return @@ -197,6 +197,7 @@ def gen_methods(out): pname = p["name"] ptype = p["type"] suppress_for_call = False + final_name = pname if "params" in recipe_data: all_pdata = recipe_data["params"] if pname in all_pdata: @@ -205,9 +206,11 @@ def gen_methods(out): ptype = pdata["type"] if "suppress_for_call" in pdata: suppress_for_call = pdata["suppress_for_call"] + if "rename" in pdata: + final_name = pdata["rename"] if not suppress_for_call: - arg_strs.append("%s %s" % (ptype, pname)) - qnotused_decls += "qnotused(%s); " % pname + arg_strs.append("%s %s" % (ptype, final_name)) + qnotused_decls += "qnotused(%s); " % final_name text = "virtual %s %s(%s) {%s%s}\n" % ( rdata["type"], method_name, @@ -236,7 +239,7 @@ def gen_notifications(out): pname = p["name"] ptype = p["type"] pick_type = ptype - if ptype in ["bool", "char", "uchar", "uint16", "cref_t", "dref_t", "cm_t", "ui_notification_t", "dbg_notification_t"]: + if ptype in ["bool", "char", "uchar", "uint16", "cref_t", "dref_t", "cm_t", "ui_notification_t", "dbg_notification_t", "tcc_renderer_type_t", "range_kind_t", "demreq_type_t"]: cast = ptype pick_type = "int" else: diff --git a/tools/genhooks/recipe_idphooks.py b/tools/genhooks/recipe_idphooks.py index df4381d..26a4b4c 100644 --- a/tools/genhooks/recipe_idphooks.py +++ b/tools/genhooks/recipe_idphooks.py @@ -1,61 +1,40 @@ recipe = { - "last_cb_before_debugger" : {"ignore" : True}, - "last_cb_before_type_callbacks" : {"ignore" : True}, - "get_operand_info" : {"ignore" : True}, - "obsolete_get_operand_info" : {"ignore" : True}, - "loader_elf_machine" : {"ignore" : True}, - "custom_ana" : { + "ev_last_cb_before_debugger" : {"ignore" : True}, + "ev_last_cb_before_type_callbacks" : {"ignore" : True}, + "ev_get_idd_opinfo" : {"ignore" : True}, + "ev_loader_elf_machine" : {"ignore" : True}, + "ev_ana_insn" : { "return" : { "type" : "bool", "default" : "false", - "convertor" : "IDP_Hooks::bool_to_cmdsize", - } - }, - "custom_out" : { - "return" : { - "type" : "bool", - "default" : "false", - "convertor" : "IDP_Hooks::bool_to_2or0", - } - }, - "custom_emu" : { - "return" : { - "type" : "bool", - "default" : "false", - "convertor" : "IDP_Hooks::bool_to_2or0", - } - }, - "custom_outop" : { - "params" : { - "op" : { - "type" : "PyObject *", - "clinked" : { - "module_define" : "S_IDA_UA_MODNAME", - "class_define" : "S_PY_OP_T_CLSNAME", - }, - }, - }, - "return" : { - "type" : "bool", - "default" : "false", - "convertor" : "IDP_Hooks::bool_to_2or0", - } - }, - "custom_mnem" : { - "params" : { - "buf" : { "suppress_for_call" : True, }, - "bufsize" : { "suppress_for_call" : True, }, - }, - "return" : { - "type" : "PyObject *", - "retexpr" : "Py_RETURN_NONE", - "convertor" : "IDP_Hooks::handle_custom_mnem_output", + "convertor" : "IDP_Hooks::bool_to_insn_t_size", "convertor_pass_args" : True, } }, - "rename" : { + "ev_out_insn" : { + "return" : { + "type" : "bool", + "default" : "false", + "convertor" : "IDP_Hooks::bool_to_1or0", + } + }, + "ev_emu_insn" : { + "return" : { + "type" : "bool", + "default" : "false", + "convertor" : "IDP_Hooks::bool_to_1or0", + } + }, + "ev_out_operand" : { + "return" : { + "type" : "bool", + "default" : "false", + "convertor" : "IDP_Hooks::bool_to_1or0", + } + }, + "ev_rename" : { "params" : { "flags" : { "suppress_for_call" : True, @@ -63,12 +42,7 @@ recipe = { }, }, }, - "savebase" : { - "return" : { - "type" : "void" - } - }, - "assemble" : { + "ev_assemble" : { "return" : { "type" : "PyObject *", "retexpr" : "Py_RETURN_NONE", @@ -81,13 +55,16 @@ recipe = { }, }, }, - "decorate_name3" : { + "ev_decorate_name" : { "params" : { "cc" : { "type" : "int", "convertor" : "IDP_Hooks::cm_t_to_int", }, "outbuf" : { "suppress_for_call" : True, }, + "type" : { + "rename" : "optional_type", + } }, "return" : { "type" : "PyObject *", @@ -96,10 +73,9 @@ recipe = { "convertor_pass_args" : True, } }, - "get_reg_name" : { + "ev_get_reg_name" : { "params" : { "buf" : { "suppress_for_call" : True, }, - "bufsize" : { "suppress_for_call" : True, }, }, "return" : { "type" : "PyObject *", @@ -108,7 +84,7 @@ recipe = { "convertor_pass_args" : True, } }, - "delay_slot_insn" : { + "ev_delay_slot_insn" : { "params" : { "ea" : { "type" : "ea_t", @@ -130,4 +106,28 @@ recipe = { "convertor_pass_args" : True, }, }, + "ev_use_regarg_type" : { + "params" : { + "idx" : { "suppress_for_call" : True, }, + }, + "return" : { + "type" : "PyObject *", + "retexpr" : "Py_RETURN_NONE", + "convertor" : "IDP_Hooks::handle_use_regarg_type_output", + "convertor_pass_args" : True, + }, + }, + "ev_demangle_name" : { + "params" : { + "outbuf" : { "suppress_for_call" : True, }, + "res" : { "suppress_for_call" : True, }, + "demreq" : { "cast_needed" : "int", "type" : "int" }, + }, + "return" : { + "type" : "PyObject *", + "retexpr" : "Py_RETURN_NONE", + "convertor" : "IDP_Hooks::handle_demangle_name_output", + "convertor_pass_args" : True, + }, + }, } diff --git a/tools/genhooks/recipe_uihooks.py b/tools/genhooks/recipe_uihooks.py index e75461a..8fc2826 100644 --- a/tools/genhooks/recipe_uihooks.py +++ b/tools/genhooks/recipe_uihooks.py @@ -12,8 +12,7 @@ recipe = { }, "get_ea_hint" : { "params" : { - "buf" : { "suppress_for_call" : True, }, - "bufsize" : { "suppress_for_call" : True, }, + "buf" : { "suppress_for_call" : True, }, }, "return" : { "type" : "PyObject *", @@ -47,10 +46,8 @@ recipe = { } }, - "genfile_callback" : {"ignore" : True}, - "get_chooser_item_attrs" : {"ignore" : True}, "idp_event" : {"ignore" : True}, - "list" : {"ignore" : True}, + "refresh_choosers" : {"ignore" : True}, "load_dbg_dbginfo" : {"ignore" : True}, } diff --git a/tools/genhooks/recipe_viewhooks.py b/tools/genhooks/recipe_viewhooks.py new file mode 100644 index 0000000..b81fdce --- /dev/null +++ b/tools/genhooks/recipe_viewhooks.py @@ -0,0 +1,3 @@ + +recipe = { +} diff --git a/tools/genswigheader.py b/tools/genswigheader.py index 6bc5ee3..67ef267 100644 --- a/tools/genswigheader.py +++ b/tools/genswigheader.py @@ -31,7 +31,7 @@ with open(args.input, "rb") as fin: parts.append("#if defined(IDA_MODULE_PRO)") parts.append("// nothing; has to be handled in pro.i") parts.append("#else") - required_headers = ["pro", "ida", "xref", "typeinf", "enum", "netnode", "area", "lines", "kernwin", "bytes", "auto", "nalt"] + required_headers = ["pro", "ida", "xref", "typeinf", "enum", "netnode", "range", "lines", "kernwin", "bytes", "auto", "nalt"] for rh in required_headers: add_imports_from_dep(rh) parts.append("#endif") diff --git a/tools/idapython_implib.def.in b/tools/idapython_implib.def.in index 913ec40..5b56539 100644 --- a/tools/idapython_implib.def.in +++ b/tools/idapython_implib.def.in @@ -6,11 +6,11 @@ EXPORTS PyW_GetNumber PyW_GetNumberAsIDC PyW_GetStringAttr - PyW_IntVecToPyList + PyW_SizeVecToPyList PyW_IsSequenceType PyW_ObjectToString PyW_PyListToEaVec - PyW_PyListToIntVec + PyW_PyListToSizeVec PyW_PyListToStrVec PyW_register_compiled_form PyW_ShowCbErr @@ -25,8 +25,8 @@ EXPORTS idcvar_to_pyvar lookup_info_t_commit lookup_info_t_del_by_py_view - lookup_info_t_find_by_form lookup_info_t_find_by_py_view + lookup_info_t_find_by_view lookup_info_t_new_entry meminfo_vec_t_to_py py_customidamemo_t_bind @@ -35,10 +35,8 @@ EXPORTS py_customidamemo_t_create_groups py_customidamemo_t_del_nodes_infos py_customidamemo_t_delete_groups - py_customidamemo_t_ensure_view_callbacks_installed py_customidamemo_t_get_current_renderer_type py_customidamemo_t_get_node_info - py_customidamemo_t_install_custom_viewer_handlers py_customidamemo_t_set_current_renderer_type py_customidamemo_t_set_groups_visibility py_customidamemo_t_set_node_info @@ -52,6 +50,7 @@ EXPORTS pyvar_walk_list pyw_convert_idc_args set_script_timeout + set_interruptible_state til_deregister_python_array_type_data_t_instance til_deregister_python_func_type_data_t_instance til_deregister_python_ptr_type_data_t_instance @@ -62,5 +61,9 @@ EXPORTS til_register_python_ptr_type_data_t_instance til_register_python_tinfo_t_instance til_register_python_udt_type_data_t_instance + try_create_swig_wrapper + idapython_hook_to_notification_point + idapython_unhook_from_notification_point + register_module_lifecycle_callbacks pycim_lookup_info DATA - PLUGIN DATA + %PLUGIN_DATA_EXP% diff --git a/tools/patch_codegen.py b/tools/patch_codegen.py index 1a726d4..3b4db59 100644 --- a/tools/patch_codegen.py +++ b/tools/patch_codegen.py @@ -2,44 +2,68 @@ import os, re try: - from argparse import ArgumentParser + from argparse import ArgumentParser except: - print "Failed to import module 'argparse'. Upgrade to Python 2.7, copy argparse.py to this directory or try 'apt-get install python-argparse'" - raise + print "Failed to import module 'argparse'. Upgrade to Python 2.7, copy argparse.py to this directory or try 'apt-get install python-argparse'" + raise parser = ArgumentParser(description='Patch some code generation, so it builds') parser.add_argument("-f", "--file", required=True) parser.add_argument("-p", "--patches", required=True) parser.add_argument("-v", "--verbose", default=False, action="store_true") +parser.add_argument("-V", "--apply-valist-patches", default=False, action="store_true") args = parser.parse_args() +patched_cmt = "// patched by patch_codegen.py" if os.path.isfile(args.patches): with open(args.patches, "r") as fin: patches = eval(fin.read()) - regex = re.compile(r"SWIGINTERN PyObject \*_wrap_([a-zA-Z0-9_]*)\(.*") + wrap_regex = re.compile(r"SWIGINTERN PyObject \*_wrap_([a-zA-Z0-9_]*)\(.*") + director_method_regex = re.compile(r".*(SwigDirector_[a-zA-Z0-9_]*::[a-zA-Z0-9_]*)\(.*") + swig_clink_var_get_regex = re.compile(r"SWIGINTERN PyObject \*(Swig_var_[a-zA-Z0-9_]*_get).*") + swig_clink_var_set_regex = re.compile(r"SWIGINTERN int (Swig_var_[a-zA-Z0-9_]*_set).*") + lines = [] with open(args.file, "rb") as f: STAT_UNKNOWN = {} STAT_IN_FUNCTION = {} stat = STAT_UNKNOWN func_patches = [] + entered_function = False for line in f: - m = regex.match(line) + m = wrap_regex.match(line) + if not m: + m = director_method_regex.match(line) + if not m: + m = swig_clink_var_get_regex.match(line) + if not m: + m = swig_clink_var_set_regex.match(line) if m: stat = STAT_IN_FUNCTION fname = m.group(1) + entered_function = True func_patches = patches.get(fname, []) else: for patch_kind, patch_data in func_patches: if patch_kind == "va_copy": - dst_va, src_va = patch_data - target = "%s = *%s;" % (dst_va, src_va) - if line.strip() == target: - line = "set_vva(%s, *%s); // patched by patch_codegen.py\n" % (dst_va, src_va) + if args.apply_valist_patches: + dst_va, src_va = patch_data + target = "%s = *%s;" % (dst_va, src_va) + if line.strip() == target: + line = "set_vva(%s, *%s); %s\n" % (dst_va, src_va, patched_cmt) + elif patch_kind == "acquire_gil": + if entered_function: + line = " PYW_GIL_GET; %s\n%s" % (patched_cmt, line) + elif patch_kind == "repl_text": + idx = line.find(patch_data[0]) + if idx > -1: + line = line.rstrip().replace(patch_data[0], patch_data[1]) + line = "%s %s\n" % (line, patched_cmt) else: raise Exception("Unknown patch kind: %s" % patch_kind) + entered_function = False lines.append(line) tmp_file = "%s.tmp" % args.file diff --git a/tools/patch_codegen/hexrays.py b/tools/patch_codegen/hexrays.py index 0b91764..647d5c9 100644 --- a/tools/patch_codegen/hexrays.py +++ b/tools/patch_codegen/hexrays.py @@ -5,4 +5,13 @@ "vcall_helper" : [ ("va_copy", ("arg4", "temp")), ], + "SwigDirector_microcode_filter_t::match" : [ + ("acquire_gil", True) + ], + "SwigDirector_microcode_filter_t::apply" : [ + ("acquire_gil", True) + ], + "SwigDirector_udc_filter_t::match" : [ + ("acquire_gil", True) + ], } diff --git a/tools/patch_codegen/kernwin.py b/tools/patch_codegen/kernwin.py index d2f095e..cd6b38f 100644 --- a/tools/patch_codegen/kernwin.py +++ b/tools/patch_codegen/kernwin.py @@ -1,11 +1,5 @@ { - "askfile2_cv" : [ - ("va_copy", ("arg5", "temp")), - ], - "vaskqstr" : [ - ("va_copy", ("arg3", "temp")), - ], - "vumsg" : [ - ("va_copy", ("arg2", "temp")), + "vask_file" : [ + ("va_copy", ("arg4", "temp")), ], } diff --git a/tools/patch_codegen/pro.py b/tools/patch_codegen/pro.py deleted file mode 100644 index 24bcf52..0000000 --- a/tools/patch_codegen/pro.py +++ /dev/null @@ -1,5 +0,0 @@ -{ - "vinterr" : [ - ("va_copy", ("arg4", "temp")), - ] -} diff --git a/tools/patch_codegen/typeinf.py b/tools/patch_codegen/typeinf.py new file mode 100644 index 0000000..cd3f3fb --- /dev/null +++ b/tools/patch_codegen/typeinf.py @@ -0,0 +1,10 @@ +{ + "Swig_var_idati_set" : [ + ("repl_text" , ( + "idati = reinterpret_cast< til_t * >(argp);", + "// idati = reinterpret_cast< til_t * >(argp);")), + ], + "Swig_var_idati_get" : [ + ("repl_text" , ("SWIG_as_voidptr(idati)", "SWIG_as_voidptr(/*idati*/ get_idati())")), + ], +} diff --git a/tools/patch_directors_cc.py b/tools/patch_directors_cc.py index 6af3529..6adbc25 100644 --- a/tools/patch_directors_cc.py +++ b/tools/patch_directors_cc.py @@ -50,14 +50,52 @@ patches = [ # const_aloc_visitor_t "virtual int idaapi visit_location", - # area_visitor2_t - "virtual int idaapi visit_area", + # range_visitor_t + "virtual int idaapi visit_range", # highlighter_cbs_t "virtual void idaapi set_style", "virtual int32 idaapi prev_block_state", "virtual int32 idaapi cur_block_state", "virtual void idaapi set_block_state", + + # predicate_t + "virtual bool idaapi should_display", + + # graph_visitor_t + "virtual int idaapi visit_node", + "virtual int idaapi visit_edge", + + # graph_node_visitor_t + "virtual int idaapi visit_node", + "virtual bool idaapi is_forbidden_edge", + + # graph_path_visitor_t + "virtual int idaapi walk_forward", + "virtual int idaapi walk_backward", + + # mutable_graph_t + "virtual rect_t &idaapi nrect", + "virtual edge_info_t *idaapi get_edge", + "virtual abstract_graph_t *idaapi clone", + "virtual bool idaapi set_nrect", + "virtual bool idaapi set_edge", + "virtual int idaapi add_node", + "virtual ssize_t idaapi del_node", + "virtual bool idaapi add_edge", + "virtual bool idaapi del_edge", + "virtual bool idaapi replace_edge", + "virtual bool idaapi refresh", + "virtual mutable_graph_t *idaapi clone", + "virtual bool idaapi redo_layout", + "virtual void idaapi resize", + "virtual ea_t idaapi calc_group_ea", + "virtual bool idaapi is_user_graph", + + # codegen_t + "virtual mreg_t idaapi load_operand", + "virtual int idaapi analyze_prolog", + "virtual int idaapi gen_micro", ] diff --git a/tools/typemaps-supplement/pymacros.swg b/tools/typemaps-supplement/pymacros.swg new file mode 100644 index 0000000..b9044e0 --- /dev/null +++ b/tools/typemaps-supplement/pymacros.swg @@ -0,0 +1,9 @@ + +// We'll take advantage of the fact that SWiG's 'python.swg' includes +// an "unqualified" 'pymacros.swg', for us to override a SWiG define +// that will be used for generating exception text (and which I have +// found no other way to redefine). Then, we'll include the real +// 'pymacros.swg' file, as if nothing happened. +#define SWIG_DirOutFail(code, msg) Swig::DirectorTypeMismatchException::raise(SWIG_ErrorType(code), msg " in method '$symname'") + +%include