From 866e631dc7e53152f91f9a232b2ac94ecc088971 Mon Sep 17 00:00:00 2001 From: "elias.bachaalany@gmail.com" Date: Tue, 4 Feb 2014 02:31:52 +0000 Subject: [PATCH] Added IDA Pro 6.1 SP1 changes (thanks to Arnaud from Hex-Rays) --- python.cpp | 3 +-- python/idautils.py | 17 ++++++++++------- python/idc.py | 20 ++++++++++---------- python/init.py | 9 +++++++++ pywraps.hpp | 4 ---- pywraps/py_idaapi.hpp | 2 +- pywraps/py_idaapi.py | 4 ++-- swig/bytes.i | 5 +++++ swig/idaapi.i | 6 +++--- swig/lines.i | 1 - swig/nalt.i | 12 ++++++++++++ swig/typeconv.i | 42 +++++++++++++++++++++++++++++++++++++++++- 12 files changed, 94 insertions(+), 31 deletions(-) diff --git a/python.cpp b/python.cpp index 6e56fd8..61a051f 100644 --- a/python.cpp +++ b/python.cpp @@ -1022,9 +1022,8 @@ bool idaapi IDAPython_extlang_calcexpr( begin_execution(); result = newref_t(PyRun_String(expr, Py_eval_input, globals, globals)); end_execution(); - } - if ( ok && result != NULL ) ok = return_python_result(rv, result, errbuf, errbufsize); + } return ok; } diff --git a/python/idautils.py b/python/idautils.py index c014ee1..4c9b134 100644 --- a/python/idautils.py +++ b/python/idautils.py @@ -330,7 +330,7 @@ def Structs(): def StructMembers(sid): """ - Get a list of structure members information. + Get a list of structure members information (or stack vars if given a frame). @param sid: ID of the structure. @@ -338,14 +338,17 @@ def StructMembers(sid): @note: If 'sid' does not refer to a valid structure, an exception will be raised. + @note: This will not return 'holes' in structures/stack frames; + it only returns defined structure members. """ - off = idc.GetFirstMember(sid) - if off == idaapi.BADNODE: + m = idc.GetFirstMember(sid) + if m == -1: raise Exception("No structure with ID: 0x%x" % sid) - members = idc.GetMemberQty(sid) - for idx in range(0, members): - yield (off, idc.GetMemberName(sid, off), idc.GetMemberSize(sid, off)) - off = idc.GetStrucNextOff(sid, off) + while (m != idaapi.BADADDR): + name = idc.GetMemberName(sid, m) + if name: + yield (m, name, idc.GetMemberSize(sid, m)) + m = idc.GetStrucNextOff(sid, m) def DecodePrecedingInstruction(ea): diff --git a/python/idc.py b/python/idc.py index 58e311c..0d82fbc 100644 --- a/python/idc.py +++ b/python/idc.py @@ -4943,7 +4943,7 @@ def GetStrucName(sid): @param sid: structure type ID - @return: -1 if bad structure type ID is passed + @return: None if bad structure type ID is passed otherwise returns structure type name. """ return idaapi.get_struc_name(sid) @@ -5023,8 +5023,8 @@ def GetStrucPrevOff(sid, offset): @param sid: structure type ID @param offset: current offset - @return: -1 if bad structure type ID is passed - or no (more) offsets in the structure + @return: -1 if bad structure type ID is passed, + idaapi.BADADDR if no (more) offsets in the structure, otherwise returns previous offset in a structure. @note: IDA allows 'holes' between members of a @@ -5052,8 +5052,8 @@ def GetStrucNextOff(sid, offset): @param sid: structure type ID @param offset: current offset - @return: -1 if bad structure type ID is passed - or no (more) offsets in the structure + @return: -1 if bad structure type ID is passed, + idaapi.BADADDR if no (more) offsets in the structure, otherwise returns next offset in a structure. @note: IDA allows 'holes' between members of a @@ -5077,8 +5077,8 @@ def GetFirstMember(sid): @param sid: structure type ID - @return: -1 if bad structure type ID is passed - or structure has no members + @return: -1 if bad structure type ID is passed, + idaapi.BADADDR if structure has no members, otherwise returns offset of the first member. @note: IDA allows 'holes' between members of a @@ -5102,8 +5102,8 @@ def GetLastMember(sid): @param sid: structure type ID - @return: -1 if bad structure type ID is passed - or structure has no members + @return: -1 if bad structure type ID is passed, + idaapi.BADADDR if structure has no members, otherwise returns offset of the last member. @note: IDA allows 'holes' between members of a @@ -5212,7 +5212,7 @@ def GetMemberSize(sid, member_offset): at offset 2, then 2,3,4,5 denote the same structure member. - @return: -1 if bad structure type ID is passed + @return: None if bad structure type ID is passed, or no such member in the structure otherwise returns size of the specified member in bytes. diff --git a/python/init.py b/python/init.py index b5d0de1..227357b 100644 --- a/python/init.py +++ b/python/init.py @@ -72,6 +72,15 @@ _orig_stdout = sys.stdout; _orig_stderr = sys.stderr; sys.stdout = sys.stderr = IDAPythonStdOut() +# ----------------------------------------------------------------------- +# Initialize the help, with our own stdin wrapper, that'll query the user +# ----------------------------------------------------------------------- +import pydoc +class IDAPythonHelpPrompter: + def readline(self): + return idaapi.askstr(0, '', 'Help topic?') +help = pydoc.Helper(input = IDAPythonHelpPrompter(), output = sys.stdout) + # Assign a default sys.argv sys.argv = [""] diff --git a/pywraps.hpp b/pywraps.hpp index 792b5c0..c43b3e1 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -111,12 +111,8 @@ public: // Declare a variable to acquire/release the GIL #define PYW_GIL_GET gil_lock_t lock; -#ifdef _DEBUG -#define GIL_CHKCONDFAIL (PyGILState_GetThisThreadState() != _PyThreadState_Current) -#else #define GIL_CHKCONDFAIL (((debug & IDA_DEBUG_PLUGIN) == IDA_DEBUG_PLUGIN) \ && PyGILState_GetThisThreadState() != _PyThreadState_Current) -#endif #define PYW_GIL_CHECK_LOCKED_SCOPE() \ do \ diff --git a/pywraps/py_idaapi.hpp b/pywraps/py_idaapi.hpp index 6b8cc85..8b19f72 100644 --- a/pywraps/py_idaapi.hpp +++ b/pywraps/py_idaapi.hpp @@ -167,7 +167,7 @@ static error_t idaapi idc_py_invoke0( idc_value_t *argv, idc_value_t *res) { - PYW_GIL_CHECK_LOCKED_SCOPE(); + PYW_GIL_GET; PyObject *pyfunc = (PyObject *) argv[0].pvoid; newref_t py_result(PyObject_CallFunctionObjArgs(pyfunc, NULL)); diff --git a/pywraps/py_idaapi.py b/pywraps/py_idaapi.py index 1a65807..63a9370 100644 --- a/pywraps/py_idaapi.py +++ b/pywraps/py_idaapi.py @@ -20,7 +20,7 @@ import bisect import __builtin__ import imp -def require(modulename): +def require(modulename, package=None): """ Load, or reload a module. @@ -41,7 +41,7 @@ def require(modulename): else: import importlib import inspect - m = importlib.import_module(modulename) + m = importlib.import_module(modulename, package) frame_obj, filename, line_number, function_name, lines, index = inspect.stack()[1] importer_module = inspect.getmodule(frame_obj) if importer_module is None: # No importer module; called from command line diff --git a/swig/bytes.i b/swig/bytes.i index aed1331..14bec39 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -4,6 +4,11 @@ // For get_enum_id() %apply unsigned char *OUTPUT { uchar *serial }; +// get_[first|last]_serial_enum_member() won't take serials as input; it'll be present as output +%apply unsigned char *OUTPUT { uchar *out_serial }; +// get_[next|prev]_serial_enum_member() take serials as input, and have the result present as output +%apply unsigned char *INOUT { uchar *in_out_serial }; + // Unexported and kernel-only declarations %ignore FlagsEnable; %ignore FlagsDisable; diff --git a/swig/idaapi.i b/swig/idaapi.i index 90e7777..89638cc 100644 --- a/swig/idaapi.i +++ b/swig/idaapi.i @@ -1347,7 +1347,7 @@ static error_t idaapi idc_py_invoke0( idc_value_t *argv, idc_value_t *res) { - PYW_GIL_CHECK_LOCKED_SCOPE(); + PYW_GIL_GET; PyObject *pyfunc = (PyObject *) argv[0].pvoid; newref_t py_result(PyObject_CallFunctionObjArgs(pyfunc, NULL)); @@ -2115,7 +2115,7 @@ import bisect import __builtin__ import imp -def require(modulename): +def require(modulename, package=None): """ Load, or reload a module. @@ -2136,7 +2136,7 @@ def require(modulename): else: import importlib import inspect - m = importlib.import_module(modulename) + m = importlib.import_module(modulename, package) frame_obj, filename, line_number, function_name, lines, index = inspect.stack()[1] importer_module = inspect.getmodule(frame_obj) if importer_module is None: # No importer module; called from command line diff --git a/swig/lines.i b/swig/lines.i index f444322..fe3b634 100644 --- a/swig/lines.i +++ b/swig/lines.i @@ -37,7 +37,6 @@ %ignore close_comment; %ignore copy_extra_cmts; %ignore gen_extra_cmts; -%ignore get_first_free_extra_cmtidx; %ignore Dumper; %ignore init_lines; %ignore save_lines; diff --git a/swig/nalt.i b/swig/nalt.i index 426c2a9..1e9a716 100644 --- a/swig/nalt.i +++ b/swig/nalt.i @@ -12,6 +12,18 @@ %ignore unregister_custom_refinfo; %ignore get_custom_refinfos; +%template (ids_array) wrapped_array; + +%extend strpath_t { + wrapped_array __getIds() { + return wrapped_array($self->ids); + } + + %pythoncode { + ids = property(__getIds) + } +} + %include "nalt.hpp" %{ diff --git a/swig/typeconv.i b/swig/typeconv.i index 20bb647..0cfb718 100644 --- a/swig/typeconv.i +++ b/swig/typeconv.i @@ -127,7 +127,7 @@ else { Py_INCREF(Py_None); - resultobj = Py_None; + resultobj = Py_None; } qfree((void *)$1); } @@ -154,6 +154,7 @@ } $1 = ea_t($1_temp); } + //------------------------------------------------------------------------- // Convert qstring %typemap(in) qstring* @@ -166,14 +167,17 @@ $1 = new qstring(buf, length); } } + %typemap(freearg) qstring* { delete $1; } + %typemap(out) qstring* { $result = PyString_FromStringAndSize($1->c_str(), $1->length()); } + #ifdef __EA64__ %apply longlong *INOUT { sval_t *value }; %apply ulonglong *INOUT { ea_t *addr }; @@ -183,3 +187,39 @@ %apply unsigned int *INOUT { ea_t *addr }; %apply unsigned int *INOUT { sel_t *sel }; #endif + + +//------------------------------------------------------------------------- +// 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 { + Type (&data)[N]; + wrapped_array(Type (&data)[N]) : data(data) { } +}; +%} +%mutable; + +%extend wrapped_array { + 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; + } +} +