diff --git a/api_contents2.txt b/api_contents2.txt index 2f62f11..d37f388 100644 --- a/api_contents2.txt +++ b/api_contents2.txt @@ -8144,6 +8144,7 @@ 'next_not_tail', 'next_that', 'next_unknown', + 'next_visea', 'node2ea', 'node_info_t_bg_color_get', 'node_info_t_bg_color_set', @@ -8688,6 +8689,7 @@ 'prev_not_tail', 'prev_that', 'prev_unknown', + 'prev_visea', 'print_argloc', 'print_decls', 'print_idcv', @@ -11109,6 +11111,7 @@ 'udt_type_data_t_pack_set', 'udt_type_data_t_sda_get', 'udt_type_data_t_sda_set', + 'udt_type_data_t_set_vftable', 'udt_type_data_t_swap', 'udt_type_data_t_taudt_bits_get', 'udt_type_data_t_taudt_bits_set', diff --git a/api_contents3.txt b/api_contents3.txt index c6a1dda..7000b6a 100644 --- a/api_contents3.txt +++ b/api_contents3.txt @@ -8148,6 +8148,7 @@ 'next_not_tail', 'next_that', 'next_unknown', + 'next_visea', 'node2ea', 'node_info_t_bg_color_get', 'node_info_t_bg_color_set', @@ -8692,6 +8693,7 @@ 'prev_not_tail', 'prev_that', 'prev_unknown', + 'prev_visea', 'print_argloc', 'print_decls', 'print_idcv', @@ -11113,6 +11115,7 @@ 'udt_type_data_t_pack_set', 'udt_type_data_t_sda_get', 'udt_type_data_t_sda_set', + 'udt_type_data_t_set_vftable', 'udt_type_data_t_swap', 'udt_type_data_t_taudt_bits_get', 'udt_type_data_t_taudt_bits_set', diff --git a/idapython.cpp b/idapython.cpp index 2612554..f98439d 100644 --- a/idapython.cpp +++ b/idapython.cpp @@ -27,7 +27,7 @@ #include #include #include - +#include #if defined (PY_MAJOR_VERSION) && (PY_MAJOR_VERSION < 3) // in Python 2.x many APIs accept char * instead of const char * GCC_DIAG_OFF(write-strings) @@ -783,11 +783,11 @@ idapython_plugin_t::idapython_plugin_t() // Cleaning up Python idapython_plugin_t::~idapython_plugin_t() { - if ( !initialized || Py_IsInitialized() == 0 ) - return; - QASSERT(30616, instance == this); + if ( !initialized || Py_IsInitialized() == 0 ) + goto SKIP_CLEANUP; + if ( PyGILState_GetThisThreadState() ) { // Note: No 'PYW_GIL_GET' here, as it would try to release @@ -829,10 +829,66 @@ idapython_plugin_t::~idapython_plugin_t() const hook_data_t &hd = hook_data_vec[i-1]; idapython_unhook_from_notification_point(hd.type, hd.cb, hd.ud); } - +SKIP_CLEANUP: instance = nullptr; } +#ifdef __NT__ +// for MessageBox() +#pragma comment(lib, "user32") +#endif +//-------------------------------------------------------------------------- +// show an error message, possibly during teardown of the process +AS_PRINTF(1, 2) static void lerror(const char *format, ...) +{ + va_list va; + va_start(va, format); +#ifdef __NT__ + char buf[MAXSTR]; + qvsnprintf(buf, sizeof(buf), format, va); + // use MB_SERVICE_NOTIFICATION to prevent UI message loop from running since ida.exe is mostly shut down at this point + // and can crash if messages get processed + MessageBox(NULL, buf, "IDA", MB_ICONERROR|MB_SERVICE_NOTIFICATION); +#else + qveprintf(format, va); + //qgetchar(); +#endif +} + +#define ERRMSG "Unexpected fatal error while intitailizing Python runtime. Please run idapyswitch to confirm or change the used Python runtime" + +volatile sig_atomic_t initdone = 0; +//------------------------------------------------------------------------- +// some Python runtimes may call abort() or exit() if they don't like something +// catch this to avoid silent IDA exit +static void exithandler(void) +{ + if ( !initdone ) + { + initdone = 1; + lerror(ERRMSG); + // return to caller to continue exiting normally + } +} + +//lint -e2761 call to non-async-signal-safe function '' within signal handler '' +//lint -e2762 call to signal registration function 'signal' within signal handler 'aborthandler' +//------------------------------------------------------------------------- +// catch unexpected abort() call +static void aborthandler(int sig) +{ + lerror(ERRMSG); + initdone = 1; // avoid duplicate message on exit + // from https://www.gnu.org/software/libc/manual/html_node/Termination-in-Handler.html + /* Now reraise the signal. We reactivate the signal's + default handling, which is to terminate the process. + We could just call exit or abort, + but reraising the signal sets the return status + from the process correctly. */ + signal(sig, SIG_DFL); + raise(sig); +} + //------------------------------------------------------------------------- // Initialize the Python environment bool idapython_plugin_t::init() @@ -913,8 +969,18 @@ bool idapython_plugin_t::init() } } + + typedef void(*SignalHandlerPointer)(int); + // catch unexpected abort() + SignalHandlerPointer previousHandler = signal(SIGABRT, aborthandler); + // ... and exit() + atexit(exithandler); + // Start the interpreter Py_InitializeEx(0 /* Don't catch SIGPIPE, SIGXFZ, SIGXFSZ & SIGINT signals */); + // disable handlers + initdone = 1; + signal(SIGABRT, previousHandler); if ( !Py_IsInitialized() ) { diff --git a/out_of_tree/parsed_notifications.zip b/out_of_tree/parsed_notifications.zip index c9d7522..edb3b1c 100644 Binary files a/out_of_tree/parsed_notifications.zip and b/out_of_tree/parsed_notifications.zip differ diff --git a/pydoc_injections2.txt b/pydoc_injections2.txt index a6d8123..87d8095 100644 --- a/pydoc_injections2.txt +++ b/pydoc_injections2.txt @@ -2942,6 +2942,15 @@ next_unknown(*args) @param ea (C++: ea_t) @param maxea (C++: ea_t) +Help on function next_visea in module ida_bytes: + +next_visea(*args) + Get next visible address. + + next_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function num_flag in module ida_bytes: num_flag(*args) @@ -3266,6 +3275,15 @@ prev_unknown(*args) @param ea (C++: ea_t) @param minea (C++: ea_t) +Help on function prev_visea in module ida_bytes: + +prev_visea(*args) + Get previous visible address. + + prev_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function print_strlit_type in module ida_bytes: print_strlit_type(*args) @@ -70612,10 +70630,10 @@ Help on function op_offset in module ida_offset: op_offset(*args) See 'op_offset_ex()' - op_offset(ea, n, type, target=BADADDR, base=0, tdelta=0) -> bool + op_offset(ea, n, type_and_flags, target=BADADDR, base=0, tdelta=0) -> bool @param ea (C++: ea_t) @param n (C++: int) - @param type (C++: reftype_t) + @param type_and_flags (C++: uint32) @param target (C++: ea_t) @param base (C++: ea_t) @param tdelta (C++: adiff_t) @@ -84282,6 +84300,9 @@ class udt_type_data_t(udtmembervec_t) | is_vftable(self, *args) | is_vftable(self) -> bool | + | set_vftable(self, *args) + | set_vftable(self) + | | swap(self, *args) | swap(self, r) | @param r (C++: udt_type_data_t &) @@ -92178,10 +92199,10 @@ Help on function op_offset in module ida_offset: op_offset(*args) See 'op_offset_ex()' - op_offset(ea, n, type, target=BADADDR, base=0, tdelta=0) -> bool + op_offset(ea, n, type_and_flags, target=BADADDR, base=0, tdelta=0) -> bool @param ea (C++: ea_t) @param n (C++: int) - @param type (C++: reftype_t) + @param type_and_flags (C++: uint32) @param target (C++: ea_t) @param base (C++: ea_t) @param tdelta (C++: adiff_t) diff --git a/pydoc_injections3.txt b/pydoc_injections3.txt index 23bc0ad..fcb193b 100644 --- a/pydoc_injections3.txt +++ b/pydoc_injections3.txt @@ -2939,6 +2939,15 @@ next_unknown(*args) -> 'ea_t' @param ea (C++: ea_t) @param maxea (C++: ea_t) +Help on function next_visea in module ida_bytes: + +next_visea(*args) -> 'ea_t' + Get next visible address. + + next_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function num_flag in module ida_bytes: num_flag(*args) -> 'flags_t' @@ -3263,6 +3272,15 @@ prev_unknown(*args) -> 'ea_t' @param ea (C++: ea_t) @param minea (C++: ea_t) +Help on function prev_visea in module ida_bytes: + +prev_visea(*args) -> 'ea_t' + Get previous visible address. + + prev_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function print_strlit_type in module ida_bytes: print_strlit_type(*args) -> 'PyObject *' @@ -84757,6 +84775,9 @@ class udt_type_data_t(udtmembervec_t) | is_vftable(self, *args) -> 'bool' | is_vftable(self) -> bool | + | set_vftable(self, *args) -> 'void' + | set_vftable(self) + | | swap(self, *args) -> 'void' | swap(self, r) | @param r (C++: udt_type_data_t &) diff --git a/pywraps/py_bytes.hpp b/pywraps/py_bytes.hpp index 103c095..fac9aa2 100644 --- a/pywraps/py_bytes.hpp +++ b/pywraps/py_bytes.hpp @@ -328,6 +328,26 @@ static PyObject *py_get_8bit(ea_t ea, uint32 v, int nbit) uchar octet = get_8bit(&ea, &v, &nbit); return Py_BuildValue("(i" PY_BV_EA "ki)", int(uint32(octet)), bvea_t(ea), v, nbit); } + +//------------------------------------------------------------------------- +/* +# +def bin_search(start_ea, end_ea, image, imask, step, flags): + """ + Search for a set of bytes in the program + + @param start_ea: linear address, start of range to search + @param end_ea: linear address, end of range to search (exclusive) + @param image: the set of bytes to search for + @param imask: a bitfield representing the mask in 'image' (can be None) + @param step: either BIN_SEARCH_FORWARD, or BIN_SEARCH_BACKWARD + @param flags: combination of BIN_SEARCH_* flags + @return: the address of a match, or ida_idaapi.BADADDR if not found + """ + pass +# +*/ + // #endif diff --git a/pywraps/py_search.py b/pywraps/py_search.py index b63322a..8624977 100644 --- a/pywraps/py_search.py +++ b/pywraps/py_search.py @@ -1,4 +1,8 @@ +# +SEARCH_UNICODE = 0x40 # Deprecated. For find_binary() +# + # find_void=find_suspop # diff --git a/release_api_contents2.txt b/release_api_contents2.txt index 53cc7f4..116b046 100644 --- a/release_api_contents2.txt +++ b/release_api_contents2.txt @@ -7441,6 +7441,7 @@ 'next_not_tail', 'next_that', 'next_unknown', + 'next_visea', 'node2ea', 'node_info_t_bg_color_get', 'node_info_t_bg_color_set', @@ -7921,6 +7922,7 @@ 'prev_not_tail', 'prev_that', 'prev_unknown', + 'prev_visea', 'print_argloc', 'print_decls', 'print_idcv', diff --git a/release_api_contents3.txt b/release_api_contents3.txt index b107954..c6c27e2 100644 --- a/release_api_contents3.txt +++ b/release_api_contents3.txt @@ -7445,6 +7445,7 @@ 'next_not_tail', 'next_that', 'next_unknown', + 'next_visea', 'node2ea', 'node_info_t_bg_color_get', 'node_info_t_bg_color_set', @@ -7925,6 +7926,7 @@ 'prev_not_tail', 'prev_that', 'prev_unknown', + 'prev_visea', 'print_argloc', 'print_decls', 'print_idcv', diff --git a/release_pydoc_injections2.txt b/release_pydoc_injections2.txt index 421da17..52acfc4 100644 --- a/release_pydoc_injections2.txt +++ b/release_pydoc_injections2.txt @@ -585,12 +585,15 @@ Help on function bin_search in module ida_bytes: bin_search(*args) bin_search(start_ea, end_ea, image, imask, step, flags) -> ea_t - start_ea: ea_t - end_ea: ea_t - image: bytevec_t const & - imask: bytevec_t const & - step: int - flags: int + Search for a set of bytes in the program + + @param start_ea: linear address, start of range to search + @param end_ea: linear address, end of range to search (exclusive) + @param image: the set of bytes to search for + @param imask: a bitfield representing the mask in 'image' (can be None) + @param step: either BIN_SEARCH_FORWARD, or BIN_SEARCH_BACKWARD + @param flags: combination of BIN_SEARCH_* flags + @return: the address of a match, or ida_idaapi.BADADDR if not found Help on function byte_flag in module ida_bytes: @@ -2942,6 +2945,15 @@ next_unknown(*args) @param ea (C++: ea_t) @param maxea (C++: ea_t) +Help on function next_visea in module ida_bytes: + +next_visea(*args) + Get next visible address. + + next_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function num_flag in module ida_bytes: num_flag(*args) @@ -3266,6 +3278,15 @@ prev_unknown(*args) @param ea (C++: ea_t) @param minea (C++: ea_t) +Help on function prev_visea in module ida_bytes: + +prev_visea(*args) + Get previous visible address. + + prev_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function print_strlit_type in module ida_bytes: print_strlit_type(*args) diff --git a/release_pydoc_injections3.txt b/release_pydoc_injections3.txt index 9cc67f6..0719188 100644 --- a/release_pydoc_injections3.txt +++ b/release_pydoc_injections3.txt @@ -584,12 +584,15 @@ Help on function bin_search in module ida_bytes: bin_search(*args) -> 'ea_t' bin_search(start_ea, end_ea, image, imask, step, flags) -> ea_t - start_ea: ea_t - end_ea: ea_t - image: bytevec_t const & - imask: bytevec_t const & - step: int - flags: int + Search for a set of bytes in the program + + @param start_ea: linear address, start of range to search + @param end_ea: linear address, end of range to search (exclusive) + @param image: the set of bytes to search for + @param imask: a bitfield representing the mask in 'image' (can be None) + @param step: either BIN_SEARCH_FORWARD, or BIN_SEARCH_BACKWARD + @param flags: combination of BIN_SEARCH_* flags + @return: the address of a match, or ida_idaapi.BADADDR if not found Help on function byte_flag in module ida_bytes: @@ -2939,6 +2942,15 @@ next_unknown(*args) -> 'ea_t' @param ea (C++: ea_t) @param maxea (C++: ea_t) +Help on function next_visea in module ida_bytes: + +next_visea(*args) -> 'ea_t' + Get next visible address. + + next_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function num_flag in module ida_bytes: num_flag(*args) -> 'flags_t' @@ -3263,6 +3275,15 @@ prev_unknown(*args) -> 'ea_t' @param ea (C++: ea_t) @param minea (C++: ea_t) +Help on function prev_visea in module ida_bytes: + +prev_visea(*args) -> 'ea_t' + Get previous visible address. + + prev_visea(ea) -> ea_t + @param ea (C++: ea_t) + @return: BADADDR if none exists. + Help on function print_strlit_type in module ida_bytes: print_strlit_type(*args) -> 'PyObject *' diff --git a/swig/bytes.i b/swig/bytes.i index a88f59f..b948cff 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -7,8 +7,6 @@ %ignore next_that; %ignore prev_that; %ignore adjust_visea; -%ignore prev_visea; -%ignore next_visea; %ignore visit_patched_bytes; %ignore is_first_visea; %ignore is_last_visea; diff --git a/swig/search.i b/swig/search.i index 356b51f..21d1e92 100644 --- a/swig/search.i +++ b/swig/search.i @@ -6,6 +6,11 @@ %ignore search; %ignore user2bin; +%pythoncode %{ +# +# +%} + %inline %{ // //