From 223e4a526830fd27fec91c4c4e73073fc6fc1946 Mon Sep 17 00:00:00 2001 From: "elias.bachaalany@gmail.com" Date: Wed, 6 Mar 2013 07:44:10 +0000 Subject: [PATCH] Applied patches from Hex-Rays: - added MakeYword - wrap obsolete IDA API functions too, so that old scripts continue to work - added debugger trace related functions in idc.py BUGFIX: IDAPython would fail with a cryptic error message if there was no free space on the current disk BUGFIX: site-packages directory was missing from sys.path BUGFIX: functions for working with additional lines (LineA/LineB etc) were broken BUGFIX: GetFixup* functions from idc.py were broken BUGFIX: IDA could not start if another python27.dll was present in PATH and importing site.py for that Python installation failed BUGFIX: SaveBase() was broken BUGFIX: IDAPython would fail with a cryptic error message if there was no free space on the current disk BUGFIX: IDAPython: site-packages directory was missing from sys.path BUGFIX: IDAPython: functions for working with additional lines (LineA/LineB etc) were broken BUGFIX: IDAPython: GetFixup* functions from idc.py were broken BUGFIX: IDAPython: IDA could not start if another python27.dll was present in PATH and importing site.py for that Python installation failed BUGFIX: IDAPython: SaveBase() was broken BUGFIX: Dbg/Idp hooks automatically unhook when hook object is not referenced anymore note: these patches are already applied in IDAPython that comes with IDA Pro 6.4 --- python.cpp | 49 ++--- python/idc.py | 387 +++++++++++++++++++++++++++++++++++++--- pywraps.hpp | 6 +- pywraps/deploy.bat | 4 +- pywraps/py_custdata.py | 22 ++- pywraps/py_custview.hpp | 5 +- pywraps/py_dbg.hpp | 2 +- pywraps/py_graph.hpp | 4 +- pywraps/py_idp.hpp | 3 +- pywraps/py_lines.hpp | 24 +-- pywraps/py_ua.py | 2 + pywraps/sidc.py | 2 + swig/bytes.i | 24 +-- swig/dbg.i | 2 +- swig/fixup.i | 5 + swig/funcs.i | 6 + swig/graph.i | 4 +- swig/idaapi.i | 4 - swig/idp.i | 5 +- swig/kernwin.i | 17 +- swig/lines.i | 31 ++-- swig/loader.i | 5 - swig/nalt.i | 5 + swig/netnode.i | 1 + swig/typeinf.i | 3 + swig/ua.i | 2 + 26 files changed, 501 insertions(+), 123 deletions(-) diff --git a/python.cpp b/python.cpp index 9b21cea..0b8add5 100644 --- a/python.cpp +++ b/python.cpp @@ -18,8 +18,6 @@ #define _SSIZE_T_DEFINED 1 #endif -#include -#include #ifdef __LINUX__ #include #endif @@ -28,13 +26,10 @@ #endif #include #include -#include -#include -#include #include +#include #include #include -#include #include "pywraps.hpp" //------------------------------------------------------------------------- @@ -83,6 +78,7 @@ static char g_idapython_dir[QMAXPATH]; // Prototypes and forward declarations // Alias to SWIG_Init +//lint -esym(526,init_idaapi) not defined extern "C" void init_idaapi(void); // Plugin run() callback @@ -127,8 +123,8 @@ static bool g_alert_auto_scripts = true; static bool g_remove_cwd_sys_path = false; static bool g_use_local_python = false; -static void end_execution(); -static void begin_execution(); +static void end_execution(void); +static void begin_execution(void); //------------------------------------------------------------------------ // This callback is called on various interpreter events @@ -154,6 +150,10 @@ static int break_check(PyObject *obj, _frame *frame, int what, PyObject *arg) #ifdef ENABLE_PYTHON_PROFILING return tracefunc(obj, frame, what, arg); #else + qnotused(obj); + qnotused(frame); + qnotused(what); + qnotused(arg); return 0; #endif } @@ -200,6 +200,7 @@ static void end_execution() } //------------------------------------------------------------------------- +//lint -esym(714,disable_script_timeout) Symbol not referenced void disable_script_timeout() { // Clear timeout @@ -210,6 +211,7 @@ void disable_script_timeout() } //------------------------------------------------------------------------- +//lint -esym(714,set_script_timeout) Symbol not referenced int set_script_timeout(int timeout) { // Update the timeout @@ -411,6 +413,20 @@ bool CheckScriptFiles() // Caller of this function should call handle_python_error() to clear the exception and print the error static int PyRunFile(const char *FileName) { +#ifdef __NT__ + // if the current disk has no space (sic, the current directory, not the one + // with the input file), PyRun_File() will die with a cryptic message that + // C runtime library could not be loaded. So we check the disk space before + // calling it. + char curdir[QMAXPATH]; + if ( _getcwd(curdir, sizeof(curdir)) == NULL + || getdspace(curdir) == 0 ) + { + warning("No free disk space on %s, python will not be available", curdir); + return 0; + } +#endif + PyObject *PyFileObject = PyFile_FromString((char*)FileName, "r"); PyObject *globals = GetMainGlobals(); if ( globals == NULL || PyFileObject == NULL ) @@ -536,14 +552,6 @@ static bool RunScript(const char *script) return ok; } -//------------------------------------------------------------------------- -bool idaapi IDAPython_Menu_Callback(void *ud) -{ - // note: on 64-bit systems the pointer will be truncated to 32-bits! - run((ssize_t)ud); - return true; -} - //------------------------------------------------------------------------- // This function parses a name into two different components (if it applies). // Example: @@ -766,7 +774,6 @@ bool idaapi IDAPython_extlang_create_object( ok = pyw_convert_idc_args(args, nargs, pargs, NULL, errbuf, errbufsize); if ( !ok ) break; - ok = false; // Call the constructor PYW_GIL_ENSURE; @@ -861,7 +868,7 @@ bool idaapi IDAPython_extlang_get_attr( break; result->set_string(clsname); - cvt = CIP_OK; + cvt = CIP_OK; //lint !e838 break; } @@ -908,6 +915,7 @@ 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 @@ -969,6 +977,7 @@ 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, @@ -1055,7 +1064,7 @@ bool idaapi IDAPython_extlang_call_method( } //------------------------------------------------------------------------- -extlang_t extlang_python = +const extlang_t extlang_python = { sizeof(extlang_t), 0, @@ -1142,7 +1151,7 @@ bool idaapi IDAPYthon_cli_complete_line( return false; PYW_GIL_ENSURE; - PyObject *py_ret = PyObject_CallFunction(py_complete, "sisi", prefix, n, line, x); + PyObject *py_ret = PyObject_CallFunction(py_complete, "sisi", prefix, n, line, x); //lint !e1776 PYW_GIL_RELEASE; Py_DECREF(py_complete); diff --git a/python/idc.py b/python/idc.py index 62dc40c..ef1af2c 100644 --- a/python/idc.py +++ b/python/idc.py @@ -464,20 +464,19 @@ def SaveBase(idbname, flags=0): @param idbname: name of the idb file. if empty, the current idb file will be used. - @param flags: DBFL_BAK or 0 + @param flags: combination of idaapi.DBFL_... bits or 0 """ if len(idbname) == 0: idbname = GetIdbPath() saveflags = idaapi.cvar.database_flags - if flags & DBFL_BAK: - idaapi.cvar.database_flags |= DBFL_BAK - else: - idaapi.cvar.database_flags &= ~DBFL_BAK + mask = idaapi.DBFL_KILL | idaapi.DBFL_COMP | idaapi.DBFL_BAK + idaapi.cvar.database_flags &= ~mask + idaapi.cvar.database_flags |= flags & mask res = idaapi.save_database(idbname, 0) idaapi.cvar.database_flags = saveflags return res -DBFL_BAK = 0x04 # create backup file +DBFL_BAK = idaapi.DBFL_BAK # for compatiblity with older versions, eventually delete this def Exit(code): @@ -671,6 +670,12 @@ def MakeArray(ea, nitems): """ flags = idaapi.getFlags(ea) + if idaapi.isCode(flags) or idaapi.isTail(flags) or idaapi.isAlign(flags): + return False + + if idaapi.isCode(flags) or idaapi.isTail(flags) or idaapi.isAlign(flags): + return False + if idaapi.isUnknown(flags): flags = idaapi.FF_BYTE @@ -765,7 +770,7 @@ def MakeQword(ea): def MakeOword(ea): """ - Convert the current item to a octa word (16 bytes) + Convert the current item to an octa word (16 bytes/128 bits) @param ea: linear address @@ -774,6 +779,28 @@ def MakeOword(ea): return idaapi.doOwrd(ea, 16) +def MakeYword(ea): + """ + Convert the current item to a ymm word (32 bytes/256 bits) + + @param ea: linear address + + @return: 1-ok, 0-failure + """ + return idaapi.doYwrd(ea, 32) + + +def MakeYword(ea): + """ + Convert the current item to a ymm word (32 bytes/256 bits) + + @param ea: linear address + + @return: 1-ok, 0-failure + """ + return idaapi.doYwrd(ea, 32) + + def MakeFloat(ea): """ Convert the current item to a floating point (4 bytes) @@ -1323,7 +1350,7 @@ def ExtLinA(ea, n, line): Specify an additional line to display before the generated ones. @param ea: linear address - @param n: number of anterior additioal line (0..MAX_ITEM_LINES) + @param n: number of anterior additional line (0..MAX_ITEM_LINES) @param line: the line to display @return: None @@ -1333,7 +1360,8 @@ def ExtLinA(ea, n, line): additional line #149, your line will not be displayed. MAX_ITEM_LINES is defined in IDA.CFG """ - idaapi.ExtraUpdate(ea, line, idaapi.E_PREV + n) + idaapi.update_extra_cmt(ea, idaapi.E_PREV + n, line) + idaapi.doExtra(ea) def ExtLinB(ea, n, line): @@ -1341,7 +1369,7 @@ def ExtLinB(ea, n, line): Specify an additional line to display after the generated ones. @param ea: linear address - @param n: number of posterior additioal line (0..MAX_ITEM_LINES) + @param n: number of posterior additional line (0..MAX_ITEM_LINES) @param line: the line to display @return: None @@ -1351,7 +1379,8 @@ def ExtLinB(ea, n, line): and there is no additional line #149, your line will not be displayed. MAX_ITEM_LINES is defined in IDA.CFG """ - idaapi.ExtraUpdate(ea, line, idaapi.E_NEXT + n) + idaapi.update_extra_cmt(ea, idaapi.E_NEXT + n, line) + idaapi.doExtra(ea) def DelExtLnA(ea, n): @@ -1359,11 +1388,11 @@ def DelExtLnA(ea, n): Delete an additional anterior line @param ea: linear address - @param n: number of anterior additioal line (0..500) + @param n: number of anterior additional line (0..500) @return: None """ - idaapi.ExtraDel(ea, idaapi.E_PREV + n) + idaapi.del_extra_cmt(ea, idaapi.E_PREV + n) def DelExtLnB(ea, n): @@ -1371,11 +1400,11 @@ def DelExtLnB(ea, n): Delete an additional posterior line @param ea: linear address - @param n: number of posterior additioal line (0..500) + @param n: number of posterior additional line (0..500) @return: None """ - idaapi.ExtraDel(ea, idaapi.E_NEXT + n) + idaapi.del_extra_cmt(ea, idaapi.E_NEXT + n) def SetManualInsn(ea, insn): @@ -2308,7 +2337,7 @@ def LineA(ea, num): @return: anterior line string """ - return idaapi.ExtraGet(ea, idaapi.E_PREV + num) + return idaapi.get_extra_cmt(ea, idaapi.E_PREV + num) def LineB(ea, num): @@ -2320,7 +2349,7 @@ def LineB(ea, num): @return: posterior line string """ - return idaapi.ExtraGet(ea, idaapi.E_NEXT + num) + return idaapi.get_extra_cmt(ea, idaapi.E_NEXT + num) def GetCommentEx(ea, repeatable): @@ -6954,6 +6983,159 @@ def DelHiddenArea(ea): return idaapi.del_hidden_area(ea) + +def GetStepTraceOptions(): + """ + Get step current tracing options + + @return: a combination of ST_... constants + """ + return idaapi.get_step_trace_options() + + +def SetStepTraceOptions(options): + """ + Set step current tracing options. + @param options: combination of ST_... constants + """ + return idaapi.set_step_trace_options(options) + + +ST_OVER_DEBUG_SEG = 0x01 # step tracing will be disabled when IP is in a debugger segment +ST_OVER_LIB_FUNC = 0x02 # step tracing will be disabled when IP is in a library function +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): + """ + Load a previously recorded binary trace file + @param filename: trace file + """ + return idaapi.load_trace_file(filename, None) + +def SaveTraceFile(filename, description): + """ + Save current trace to a binary trace file + @param filename: trace file + """ + return idaapi.save_trace_file(filename, description) + +def CheckTraceFile(filename): + """ + Check the given binary trace file + @param filename: trace file + """ + return idaapi.is_valid_trace_file(filename) + +def ClearTraceFile(filename): + """ + Clear the current trace buffer + """ + return idaapi.clear_trace() + +def GetTraceDesc(filename): + """ + Get the trace description of the given binary trace file + @param filename: trace file + """ + return idaapi.get_trace_file_desc(filename) + +def SetTraceDesc(filename, description): + """ + Update the trace description of the given binary trace file + @param filename: trace file + @description: trace description + """ + return idaapi.set_trace_file_desc(filename, description) + +def GetMaxTev(): + """ + Return the total number of recorded events + """ + return idaapi.get_tev_qty() + +def GetTevEa(tev): + """ + Return the address of the specified event + @param tev: event number + """ + return idaapi.get_tev_ea(tev) + +TEV_NONE = 0 # no event +TEV_INSN = 1 # an instruction trace +TEV_CALL = 2 # a function call trace +TEV_RET = 3 # a function return trace +TEV_BPT = 4 # write, read/write, execution trace +TEV_MEM = 5 # memory layout changed +TEV_EVENT = 6 # debug event + +def GetTevType(tev): + """ + Return the type of the specified event (TEV_... constants) + @param tev: event number + """ + return idaapi.get_tev_type(tev) + +def GetTevTid(tev): + """ + Return the thread id of the specified event + @param tev: event number + """ + return idaapi.get_tev_tid(tev) + +def GetTevRegVal(tev, reg): + """ + Return the register value for the specified event + @param tev: event number + @param reg: register name (like EAX, RBX, ...) + """ + return idaapi.get_tev_reg_val(tev, reg) + +def GetTevRegMemQty(tev): + """ + Return the number of memory addresses recorded for the specified event + @param tev: event number + """ + return idaapi.get_tev_reg_mem_qty(tev) + +def GetTevRegMem(tev, idx): + """ + Return the memory pointed by 'index' for the specified event + @param tev: event number + @param idx: memory address index + """ + return idaapi.get_tev_reg_mem(tev, idx) + +def GetTevRegMemEa(tev, idx): + """ + Return the address pointed by 'index' for the specified event + @param tev: event number + @param idx: memory address index + """ + return idaapi.get_tev_reg_mem_ea(tev, idx) + +def GetTevCallee(tev): + """ + Return the address of the callee for the specified event + @param tev: event number + """ + return idaapi.get_call_tev_callee(tev) + +def GetTevReturn(tev): + """ + Return the return address for the specified event + @param tev: event number + """ + return idaapi.get_ret_tev_return(tev) + +def GetBptTevEa(tev): + """ + Return the address of the specified TEV_BPT event + @param tev: event number + """ + return idaapi.get_bpt_tev_ea(tev) + + #-------------------------------------------------------------------------- # D E B U G G E R I N T E R F A C E #-------------------------------------------------------------------------- @@ -7784,13 +7966,17 @@ BPT_WRITE = 1 # Hardware: Write access BPT_RDWR = 3 # Hardware: Read/write access BPT_SOFT = 4 # Software breakpoint -BPTATTR_COUNT = 4 -BPTATTR_FLAGS = 5 -BPT_BRK = 0x01 # the debugger stops on this breakpoint -BPT_TRACE = 0x02 # the debugger adds trace information when this breakpoint is reached -BPT_UPDMEM = 0x04 # refresh the memory layout and contents before evaluating bpt condition -BPT_ENABLED = 0x08 # enabled? -BPT_LOWCND = 0x10 # condition is calculated at low level (on the server side) +BPTATTR_COUNT = 4 +BPTATTR_FLAGS = 5 +BPT_BRK = 0x001 # the debugger stops on this breakpoint +BPT_TRACE = 0x002 # the debugger adds trace information when this breakpoint is reached +BPT_UPDMEM = 0x004 # refresh the memory layout and contents before evaluating bpt condition +BPT_ENABLED = 0x008 # enabled? +BPT_LOWCND = 0x010 # condition is calculated at low level (on the server side) +BPT_TRACEON = 0x020 # enable tracing when the breakpoint is reached +BPT_TRACE_INSN = 0x040 # instruction tracing +BPT_TRACE_FUNC = 0x080 # function tracing +BPT_TRACE_BBLK = 0x100 # basic block tracing BPTATTR_COND = 6 # Breakpoint condition. NOTE: the return value is a string in this case @@ -7960,6 +8146,159 @@ TRACE_STEP = 0x0 # lowest level trace. trace buffers are not maintained TRACE_INSN = 0x1 # instruction level trace TRACE_FUNC = 0x2 # function level trace (calls & rets) + +def GetStepTraceOptions(): + """ + Get step current tracing options + + @return: a combination of ST_... constants + """ + return idaapi.get_step_trace_options() + + +def SetStepTraceOptions(options): + """ + Set step current tracing options. + @param options: combination of ST_... constants + """ + return idaapi.set_step_trace_options(options) + + +ST_OVER_DEBUG_SEG = 0x01 # step tracing will be disabled when IP is in a debugger segment +ST_OVER_LIB_FUNC = 0x02 # step tracing will be disabled when IP is in a library function +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): + """ + Load a previously recorded binary trace file + @param filename: trace file + """ + return idaapi.load_trace_file(filename, None) + +def SaveTraceFile(filename, description): + """ + Save current trace to a binary trace file + @param filename: trace file + """ + return idaapi.save_trace_file(filename, description) + +def CheckTraceFile(filename): + """ + Check the given binary trace file + @param filename: trace file + """ + return idaapi.is_valid_trace_file(filename) + +def ClearTraceFile(filename): + """ + Clear the current trace buffer + """ + return idaapi.clear_trace() + +def GetTraceDesc(filename): + """ + Get the trace description of the given binary trace file + @param filename: trace file + """ + return idaapi.get_trace_file_desc(filename) + +def SetTraceDesc(filename, description): + """ + Update the trace description of the given binary trace file + @param filename: trace file + @description: trace description + """ + return idaapi.set_trace_file_desc(filename, description) + +def GetMaxTev(): + """ + Return the total number of recorded events + """ + return idaapi.get_tev_qty() + +def GetTevEa(tev): + """ + Return the address of the specified event + @param tev: event number + """ + return idaapi.get_tev_ea(tev) + +TEV_NONE = 0 # no event +TEV_INSN = 1 # an instruction trace +TEV_CALL = 2 # a function call trace +TEV_RET = 3 # a function return trace +TEV_BPT = 4 # write, read/write, execution trace +TEV_MEM = 5 # memory layout changed +TEV_EVENT = 6 # debug event + +def GetTevType(tev): + """ + Return the type of the specified event (TEV_... constants) + @param tev: event number + """ + return idaapi.get_tev_type(tev) + +def GetTevTid(tev): + """ + Return the thread id of the specified event + @param tev: event number + """ + return idaapi.get_tev_tid(tev) + +def GetTevRegVal(tev, reg): + """ + Return the register value for the specified event + @param tev: event number + @param reg: register name (like EAX, RBX, ...) + """ + return idaapi.get_tev_reg_val(tev, reg) + +def GetTevRegMemQty(tev): + """ + Return the number of memory addresses recorded for the specified event + @param tev: event number + """ + return idaapi.get_tev_reg_mem_qty(tev) + +def GetTevRegMem(tev, idx): + """ + Return the memory pointed by 'index' for the specified event + @param tev: event number + @param idx: memory address index + """ + return idaapi.get_tev_reg_mem(tev, idx) + +def GetTevRegMemEa(tev, idx): + """ + Return the address pointed by 'index' for the specified event + @param tev: event number + @param idx: memory address index + """ + return idaapi.get_tev_reg_mem_ea(tev, idx) + +def GetTevCallee(tev): + """ + Return the address of the callee for the specified event + @param tev: event number + """ + return idaapi.get_call_tev_callee(tev) + +def GetTevReturn(tev): + """ + Return the return address for the specified event + @param tev: event number + """ + return idaapi.get_ret_tev_return(tev) + +def GetBptTevEa(tev): + """ + Return the address of the specified TEV_BPT event + @param tev: event number + """ + return idaapi.get_bpt_tev_ea(tev) + + #-------------------------------------------------------------------------- # C O L O R S #-------------------------------------------------------------------------- diff --git a/pywraps.hpp b/pywraps.hpp index c0a8cbe..815bb84 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -141,8 +141,8 @@ bool PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var); // Returns a qstring from a Python attribute string bool PyW_GetStringAttr( - PyObject *py_obj, - const char *attr_name, + 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 @@ -205,7 +205,7 @@ int idcvar_to_pyvar( // Walks a Python list or Sequence and calls the callback Py_ssize_t pyvar_walk_list( - PyObject *py_list, + PyObject *py_list, int (idaapi *cb)(PyObject *py_item, Py_ssize_t index, void *ud) = NULL, void *ud = NULL); diff --git a/pywraps/deploy.bat b/pywraps/deploy.bat index 0b9d094..6cf4dba 100644 --- a/pywraps/deploy.bat +++ b/pywraps/deploy.bat @@ -91,11 +91,11 @@ echo Deploying lines rem -------------------------------------------------------------------------- echo Deploying pc_win32_appcall -%PY% deploy.py appcalltest py_appcall.py ..\..\..\ida\tests\input\pc_win32_appcall.pe.hints +%PY% deploy.py appcalltest py_appcall.py ..\..\..\tests\input\pc_win32_appcall.pe.hints rem -------------------------------------------------------------------------- echo Deploying ex_custdata example -%PY% deploy.py ex_custdata ..\examples\ex_custdata.py ..\..\..\ida\tests\input\pc_win32_custdata1.pe.hints +%PY% deploy.py ex_custdata ..\examples\ex_custdata.py ..\..\..\tests\input\pc_win32_custdata1.pe.hints rem -------------------------------------------------------------------------- echo Deploying ex_formchooser diff --git a/pywraps/py_custdata.py b/pywraps/py_custdata.py index f9dee53..563bbf2 100644 --- a/pywraps/py_custdata.py +++ b/pywraps/py_custdata.py @@ -167,7 +167,7 @@ class data_format_t(object): # pass # # ----------------------------------------------------------------------- -def __walk_types_and_formats(formats, type_action, format_action): +def __walk_types_and_formats(formats, type_action, format_action, installing): broken = False for f in formats: if len(f) == 1: @@ -177,13 +177,19 @@ def __walk_types_and_formats(formats, type_action, format_action): else: dt = f[0] dfs = f[1:] - if not type_action(dt): + # install data type before installing formats + if installing and not type_action(dt): broken = True break + # process formats using the correct dt.id for df in dfs: if not format_action(df, dt.id): broken = True break + # uninstall data type after uninstalling formats + if not installing and not type_action(dt): + broken = True + break return not broken # ----------------------------------------------------------------------- @@ -208,16 +214,16 @@ def register_data_types_and_formats(formats): def __reg_format(df, dtid): df.register(dtid) if dtid == 0: - print "Registering format '%s' with built-in types, ID=%d" % (df.name, df.id) + print "Registered format '%s' with built-in types, ID=%d" % (df.name, df.id) else: - print " Registering format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid) + print " Registered format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid) return df.id != -1 def __reg_type(dt): dt.register() - print "Registering type '%s', ID=%d" % (dt.name, dt.id) + print "Registered type '%s', ID=%d" % (dt.name, dt.id) return dt.id != -1 - ok = __walk_types_and_formats(formats, __reg_type, __reg_format) + ok = __walk_types_and_formats(formats, __reg_type, __reg_format, True) return 1 if ok else -1 # ----------------------------------------------------------------------- @@ -226,15 +232,15 @@ def unregister_data_types_and_formats(formats): unregisters multiple data types and formats at once. """ def __unreg_format(df, dtid): - df.unregister(dtid) print "%snregistering format '%s'" % ("U" if dtid == 0 else " u", df.name) + df.unregister(dtid) return True def __unreg_type(dt): print "Unregistering type '%s', ID=%d" % (dt.name, dt.id) dt.unregister() return True - ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format) + ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format, False) return 1 if ok else -1 # diff --git a/pywraps/py_custview.hpp b/pywraps/py_custview.hpp index 5abdd67..c77ebe4 100644 --- a/pywraps/py_custview.hpp +++ b/pywraps/py_custview.hpp @@ -522,7 +522,7 @@ public: if ( _form == NULL ) return false; - open_tform(_form, FORM_TAB|FORM_MENU|FORM_RESTORE); + open_tform(_form, FORM_TAB|FORM_MENU|FORM_RESTORE|FORM_QWIDGET); return true; } }; @@ -807,7 +807,8 @@ public: //-------------------------------------------------------------------------- bool jumpto(size_t ln, int x, int y) { - return customviewer_t::jumpto(&simpleline_place_t(ln), x, y); + simpleline_place_t l(ln); + return customviewer_t::jumpto(&l, x, y); } //-------------------------------------------------------------------------- diff --git a/pywraps/py_dbg.hpp b/pywraps/py_dbg.hpp index 0e3cff2..a5669a2 100644 --- a/pywraps/py_dbg.hpp +++ b/pywraps/py_dbg.hpp @@ -466,7 +466,7 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va); class DBG_Hooks { public: - virtual ~DBG_Hooks() {}; + 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); }; diff --git a/pywraps/py_graph.hpp b/pywraps/py_graph.hpp index 602017b..b35590c 100644 --- a/pywraps/py_graph.hpp +++ b/pywraps/py_graph.hpp @@ -562,7 +562,7 @@ private: void show() { - open_tform(form, FORM_TAB|FORM_MENU); + open_tform(form, FORM_TAB|FORM_MENU|FORM_QWIDGET); } static py_graph_t *extract_this(PyObject *self) @@ -666,7 +666,7 @@ private: qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title); id.create(grnode); gv = create_graph_viewer(form, id, s_callback, this, 0); - open_tform(form, FORM_TAB | FORM_MENU); + open_tform(form, FORM_TAB | FORM_MENU | FORM_QWIDGET); if ( gv != NULL ) viewer_fit_window(gv); } diff --git a/pywraps/py_idp.hpp b/pywraps/py_idp.hpp index 847b96b..93a061e 100644 --- a/pywraps/py_idp.hpp +++ b/pywraps/py_idp.hpp @@ -674,6 +674,7 @@ class IDP_Hooks public: virtual ~IDP_Hooks() { + unhook(); } bool hook() @@ -795,7 +796,7 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va); class IDB_Hooks { public: - virtual ~IDB_Hooks() {}; + virtual ~IDB_Hooks() { unhook(); }; bool hook() { diff --git a/pywraps/py_lines.hpp b/pywraps/py_lines.hpp index 8063010..9c7f962 100644 --- a/pywraps/py_lines.hpp +++ b/pywraps/py_lines.hpp @@ -13,7 +13,7 @@ static void idaapi s_py_get_user_defined_prefix( size_t bufsize) { PyObject *py_ret = PyObject_CallFunction( - py_get_user_defined_prefix, + py_get_user_defined_prefix, PY_FMT64 "iis" PY_FMT64, ea, lnnum, indent, line, bufsize); @@ -53,11 +53,11 @@ def set_user_defined_prefix(width, callback): lnnum - line number indent - indent of the line contents (-1 means the default instruction) 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 + 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 """ pass @@ -69,7 +69,7 @@ static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb) { // Release old callback reference Py_XDECREF(py_get_user_defined_prefix); - + // ...and clear it py_get_user_defined_prefix = NULL; @@ -101,7 +101,7 @@ def tag_remove(colstr): """ Remove color escape sequences from a string @param colstr: the colored string with embedded tags - @return: + @return: None on failure or a new string w/o the tags """ @@ -114,7 +114,7 @@ PyObject *py_tag_remove(const char *instr) 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 ) @@ -162,22 +162,22 @@ int py_tag_advance(const char *line, int cnt) def generate_disassembly(ea, max_lines, as_stack, notags): """ Generate disassembly lines (many lines) and put them into a buffer - + @param ea: address to generate disassembly for @param max_lines: how many lines max to generate @param as_stack: Display undefined items as 2/4/8 bytes - @return: + @return: - None on failure - - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing + - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing the most important line number and a tuple of generated lines """ pass # */ PyObject *py_generate_disassembly( - ea_t ea, - int max_lines, - bool as_stack, + ea_t ea, + int max_lines, + bool as_stack, bool notags) { if ( max_lines <= 0 ) diff --git a/pywraps/py_ua.py b/pywraps/py_ua.py index 7adcb5d..2d8eb9a 100644 --- a/pywraps/py_ua.py +++ b/pywraps/py_ua.py @@ -440,6 +440,8 @@ 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 diff --git a/pywraps/sidc.py b/pywraps/sidc.py index 58848df..9a448b7 100644 --- a/pywraps/sidc.py +++ b/pywraps/sidc.py @@ -70,6 +70,8 @@ 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 diff --git a/swig/bytes.i b/swig/bytes.i index b17d2a9..ba08b19 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -33,8 +33,6 @@ %ignore noFlow; %ignore doRef; %ignore noRef; -%ignore doExtra; -%ignore noExtra; %ignore coagulate; %ignore coagulate_dref; %ignore init_hidden_areas; @@ -1160,7 +1158,7 @@ class data_format_t(object): # pass # # ----------------------------------------------------------------------- -def __walk_types_and_formats(formats, type_action, format_action): +def __walk_types_and_formats(formats, type_action, format_action, installing): broken = False for f in formats: if len(f) == 1: @@ -1170,13 +1168,19 @@ def __walk_types_and_formats(formats, type_action, format_action): else: dt = f[0] dfs = f[1:] - if not type_action(dt): + # install data type before installing formats + if installing and not type_action(dt): broken = True break + # process formats using the correct dt.id for df in dfs: if not format_action(df, dt.id): broken = True break + # uninstall data type after uninstalling formats + if not installing and not type_action(dt): + broken = True + break return not broken # ----------------------------------------------------------------------- @@ -1201,16 +1205,16 @@ def register_data_types_and_formats(formats): def __reg_format(df, dtid): df.register(dtid) if dtid == 0: - print "Registering format '%s' with built-in types, ID=%d" % (df.name, df.id) + print "Registered format '%s' with built-in types, ID=%d" % (df.name, df.id) else: - print " Registering format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid) + print " Registered format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid) return df.id != -1 def __reg_type(dt): dt.register() - print "Registering type '%s', ID=%d" % (dt.name, dt.id) + print "Registered type '%s', ID=%d" % (dt.name, dt.id) return dt.id != -1 - ok = __walk_types_and_formats(formats, __reg_type, __reg_format) + ok = __walk_types_and_formats(formats, __reg_type, __reg_format, True) return 1 if ok else -1 # ----------------------------------------------------------------------- @@ -1219,15 +1223,15 @@ def unregister_data_types_and_formats(formats): unregisters multiple data types and formats at once. """ def __unreg_format(df, dtid): - df.unregister(dtid) print "%snregistering format '%s'" % ("U" if dtid == 0 else " u", df.name) + df.unregister(dtid) return True def __unreg_type(dt): print "Unregistering type '%s', ID=%d" % (dt.name, dt.id) dt.unregister() return True - ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format) + ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format, False) return 1 if ok else -1 # diff --git a/swig/dbg.i b/swig/dbg.i index b49aa74..10f5fcd 100644 --- a/swig/dbg.i +++ b/swig/dbg.i @@ -119,7 +119,7 @@ int idaapi DBG_Callback(void *ud, int notification_code, va_list va); class DBG_Hooks { public: - virtual ~DBG_Hooks() {}; + 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); }; diff --git a/swig/fixup.i b/swig/fixup.i index d900cb3..2d31d56 100644 --- a/swig/fixup.i +++ b/swig/fixup.i @@ -1,6 +1,11 @@ %ignore apply_fixup; %ignore convert_fixups; %ignore move_fixups; +%ignore custom_fixup_handler_t; +%ignore custom_fixup_handlers_t; +%ignore register_custom_fixup; +%ignore unregister_custom_fixup; +%ignore set_custom_fixup; %include "fixup.hpp" diff --git a/swig/funcs.i b/swig/funcs.i index 5bac8ec..77b6411 100644 --- a/swig/funcs.i +++ b/swig/funcs.i @@ -35,6 +35,12 @@ %include "funcs.hpp" +%inline %{ +#ifndef FUNC_STATICDEF +#define FUNC_STATICDEF 0x00000008 +#endif +%} + %clear(char *buf); %clear(char *optlibs); diff --git a/swig/graph.i b/swig/graph.i index 4f32f24..6faf7cc 100644 --- a/swig/graph.i +++ b/swig/graph.i @@ -564,7 +564,7 @@ private: void show() { - open_tform(form, FORM_TAB|FORM_MENU); + open_tform(form, FORM_TAB|FORM_MENU|FORM_QWIDGET); } static py_graph_t *extract_this(PyObject *self) @@ -668,7 +668,7 @@ private: qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title); id.create(grnode); gv = create_graph_viewer(form, id, s_callback, this, 0); - open_tform(form, FORM_TAB | FORM_MENU); + open_tform(form, FORM_TAB | FORM_MENU | FORM_QWIDGET); if ( gv != NULL ) viewer_fit_window(gv); } diff --git a/swig/idaapi.i b/swig/idaapi.i index 283eea2..a22ba06 100644 --- a/swig/idaapi.i +++ b/swig/idaapi.i @@ -54,10 +54,6 @@ static PyObject *type##_get_clink_ptr(PyObject *self) #define USE_DANGEROUS_FUNCTIONS 1 #endif -#ifndef NO_OBSOLETE_FUNCS - #define NO_OBSOLETE_FUNCS 1 -#endif - #ifdef HAVE_SSIZE_T #define _SSIZE_T_DEFINED 1 #endif diff --git a/swig/idp.i b/swig/idp.i index ea5c4d3..ccc10ce 100644 --- a/swig/idp.i +++ b/swig/idp.i @@ -1,5 +1,5 @@ // Ignore the following symbols -%ignore WorkReg; +%ignore WorkReg; %ignore AbstractRegister; %ignore rginfo; %ignore insn_t::get_canon_mnem; @@ -715,6 +715,7 @@ class IDP_Hooks public: virtual ~IDP_Hooks() { + unhook(); } bool hook() @@ -836,7 +837,7 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va); class IDB_Hooks { public: - virtual ~IDB_Hooks() {}; + virtual ~IDB_Hooks() { unhook(); }; bool hook() { diff --git a/swig/kernwin.i b/swig/kernwin.i index 5d348e9..949de38 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -3352,7 +3352,7 @@ public: if ( _form == NULL ) return false; - open_tform(_form, FORM_TAB|FORM_MENU|FORM_RESTORE); + open_tform(_form, FORM_TAB|FORM_MENU|FORM_RESTORE|FORM_QWIDGET); return true; } }; @@ -3637,7 +3637,8 @@ public: //-------------------------------------------------------------------------- bool jumpto(size_t ln, int x, int y) { - return customviewer_t::jumpto(&simpleline_place_t(ln), x, y); + simpleline_place_t l(ln); + return customviewer_t::jumpto(&l, x, y); } //-------------------------------------------------------------------------- @@ -5703,12 +5704,12 @@ class Choose: """ old = set_script_timeout(0) n = _idaapi.choose_choose( - self, - self.flags, - self.x0, - self.y0, - self.x1, - self.y1, + self, + self.flags, + self.x0, + self.y0, + self.x1, + self.y1, self.width, self.deflt, self.icon) diff --git a/swig/lines.i b/swig/lines.i index ce901b4..f932a82 100644 --- a/swig/lines.i +++ b/swig/lines.i @@ -35,10 +35,9 @@ %ignore set_makeline_producer; %ignore closing_comment; %ignore close_comment; -%ignore copy_extra_lines; -%ignore ExtraLines; -%ignore ExtraKill; -%ignore ExtraFree; +%ignore copy_extra_cmts; +%ignore gen_extra_cmts; +%ignore get_first_free_extra_cmtidx; %ignore Dumper; %ignore init_lines; %ignore save_lines; @@ -87,7 +86,7 @@ static void idaapi s_py_get_user_defined_prefix( size_t bufsize) { PyObject *py_ret = PyObject_CallFunction( - py_get_user_defined_prefix, + py_get_user_defined_prefix, PY_FMT64 "iis" PY_FMT64, ea, lnnum, indent, line, bufsize); @@ -127,11 +126,11 @@ def set_user_defined_prefix(width, callback): lnnum - line number indent - indent of the line contents (-1 means the default instruction) 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 + 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 """ pass @@ -143,7 +142,7 @@ static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb) { // Release old callback reference Py_XDECREF(py_get_user_defined_prefix); - + // ...and clear it py_get_user_defined_prefix = NULL; @@ -175,7 +174,7 @@ def tag_remove(colstr): """ Remove color escape sequences from a string @param colstr: the colored string with embedded tags - @return: + @return: None on failure or a new string w/o the tags """ @@ -188,7 +187,7 @@ PyObject *py_tag_remove(const char *instr) 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 ) @@ -236,22 +235,22 @@ int py_tag_advance(const char *line, int cnt) def generate_disassembly(ea, max_lines, as_stack, notags): """ Generate disassembly lines (many lines) and put them into a buffer - + @param ea: address to generate disassembly for @param max_lines: how many lines max to generate @param as_stack: Display undefined items as 2/4/8 bytes - @return: + @return: - None on failure - - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing + - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing the most important line number and a tuple of generated lines """ pass # */ PyObject *py_generate_disassembly( - ea_t ea, - int max_lines, - bool as_stack, + ea_t ea, + int max_lines, + bool as_stack, bool notags) { if ( max_lines <= 0 ) diff --git a/swig/loader.i b/swig/loader.i index 49c2f66..cd186c4 100644 --- a/swig/loader.i +++ b/swig/loader.i @@ -85,10 +85,6 @@ %ignore is_database_ext; %ignore ida_database_memory; %ignore ida_workdir; -%ignore DBFL_KILL; -%ignore DBFL_COMP; -%ignore DBFL_BAK; -%ignore DBFL_TEMP; %ignore is_temp_database; %ignore pe_create_idata; %ignore pe_load_resources; @@ -118,7 +114,6 @@ %ignore update_snapshot_attributes; %ignore build_snapshot_tree; %ignore visit_snapshot_tree; -%ignore save_database_ex; %ignore snapshot_t; %ignore snapshots_t; %ignore load_plugin; diff --git a/swig/nalt.i b/swig/nalt.i index 56848f2..cf1c3ac 100644 --- a/swig/nalt.i +++ b/swig/nalt.i @@ -6,6 +6,11 @@ %ignore NALT_EA; %ignore enum_import_names; %rename (enum_import_names) py_enum_import_names; +%ignore custom_refinfo_handler_t; +%ignore custom_refinfo_handlers_t; +%ignore register_custom_refinfo; +%ignore unregister_custom_refinfo; +%ignore get_custom_refinfos; %include "nalt.hpp" diff --git a/swig/netnode.i b/swig/netnode.i index 7908dac..89a1fab 100644 --- a/swig/netnode.i +++ b/swig/netnode.i @@ -74,6 +74,7 @@ %ignore netnode::inited; %ignore netnode::init; %ignore netnode::flush; +%ignore netnode::get_linput; %ignore netnode::term; %ignore netnode::killbase; %ignore netnode::getdrive; diff --git a/swig/typeinf.i b/swig/typeinf.i index 392c78f..274bc77 100644 --- a/swig/typeinf.i +++ b/swig/typeinf.i @@ -88,6 +88,7 @@ %ignore gen_decorate_name; %ignore calc_bare_name; %ignore calc_cpp_name; +%ignore calc_c_cpp_name; %ignore predicate_t; %ignore choose_named_type; %ignore get_default_align; @@ -129,6 +130,7 @@ %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; @@ -163,6 +165,7 @@ %ignore for_all_types_ex; %ignore fix_idb_type; %ignore pdb2ti; +%ignore process_sdacl_padding; %include "typeinf.hpp" diff --git a/swig/ua.i b/swig/ua.i index 6656715..f5622c2 100644 --- a/swig/ua.i +++ b/swig/ua.i @@ -1276,6 +1276,8 @@ 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