From 8495e5205b32b5c1c7d2d5802c30d03474b25f65 Mon Sep 17 00:00:00 2001 From: "elias.bachaalany" Date: Tue, 13 Jul 2010 16:43:53 +0000 Subject: [PATCH] - renamed pywraps related utility functions to PyW_ - refactored some code - fixed some potential PyObject leaks - added cli_t support --- python.cpp | 20 ++--- python/idc.py | 1 + pywraps.hpp | 22 +++-- swig/bytes.i | 131 ++++++++++++--------------- swig/diskio.i | 2 + swig/graph.i | 24 ++--- swig/idaapi.i | 90 ++++++++++++------- swig/idd.i | 11 ++- swig/kernwin.i | 235 ++++++++++++++++++++++++++++++------------------- swig/nalt.i | 14 +-- swig/typeinf.i | 2 + swig/ua.i | 18 ++-- 12 files changed, 316 insertions(+), 254 deletions(-) diff --git a/python.cpp b/python.cpp index 1f4b5a0..dc42ee1 100644 --- a/python.cpp +++ b/python.cpp @@ -450,7 +450,7 @@ static bool IDAPython_ExecFile(const char *FileName, char *errbuf, size_t errbuf // Failure at this point means the script was interrupted qstring err; - if ( PyGetError(&err) || py_ret == NULL ) + if ( PyW_GetError(&err) || py_ret == NULL ) { PyErr_Clear(); if ( err.empty() ) @@ -695,7 +695,7 @@ bool idaapi IDAPython_extlang_create_object( parse_py_modname(name, modname, clsname, MAXSTR); // Get a reference to the module - py_mod = PyImport_TryImportModule(modname); + py_mod = PyW_TryImportModule(modname); if ( py_mod == NULL ) { qsnprintf(errbuf, errbufsize, "Could not import module '%s'!", modname); @@ -703,7 +703,7 @@ bool idaapi IDAPython_extlang_create_object( } // Get the class reference - py_cls = PyObject_TryGetAttrString(py_mod, clsname); + py_cls = PyW_TryGetAttrString(py_mod, clsname); if ( py_cls == NULL ) { qsnprintf(errbuf, errbufsize, "Could not find class type '%s'!", clsname); @@ -742,7 +742,7 @@ bool idaapi IDAPython_extlang_get_attr( do { // Get a reference to the module - py_mod = PyImport_TryImportModule(S_MAIN); + py_mod = PyW_TryImportModule(S_MAIN); if ( py_mod == NULL ) break; @@ -753,7 +753,7 @@ bool idaapi IDAPython_extlang_get_attr( { // (1) Get attribute from main module if ( obj->vtype == VT_STR2 ) - py_obj = PyObject_TryGetAttrString(py_mod, obj->c_str()); + py_obj = PyW_TryGetAttrString(py_mod, obj->c_str()); // (2) see if opaque object else { @@ -779,7 +779,7 @@ bool idaapi IDAPython_extlang_get_attr( // then work with main module py_obj = py_mod; } - PyObject *py_attr = PyObject_TryGetAttrString(py_obj, attr); + PyObject *py_attr = PyW_TryGetAttrString(py_obj, attr); // No attribute? if ( py_attr == NULL ) { @@ -832,7 +832,7 @@ bool idaapi IDAPython_extlang_set_attr( do { // Get a reference to the module - py_mod = PyImport_TryImportModule(S_MAIN); + py_mod = PyW_TryImportModule(S_MAIN); if ( py_mod == NULL ) break; @@ -840,7 +840,7 @@ bool idaapi IDAPython_extlang_set_attr( { // Get the attribute reference (from just a name) if ( obj->vtype == VT_STR2 ) - py_obj = PyObject_TryGetAttrString(py_mod, obj->c_str()); + py_obj = PyW_TryGetAttrString(py_mod, obj->c_str()); else { int cvt = idcvar_to_pyvar(*obj, &py_obj); @@ -937,7 +937,7 @@ bool idaapi IDAPython_extlang_call_method( break; } - py_method = PyObject_TryGetAttrString(py_obj, method_name); + py_method = PyW_TryGetAttrString(py_obj, method_name); if ( py_method == NULL || !PyCallable_Check(py_method) ) { qsnprintf(errbuf, errbufsize, "The input object does not have a callable method called '%s'", method_name); @@ -1114,7 +1114,7 @@ void convert_idc_args() } // Get reference to the IDC module (it is imported by init.py) - PyObject *py_mod = PyImport_TryImportModule(S_IDC_MODNAME); + PyObject *py_mod = PyW_TryImportModule(S_IDC_MODNAME); if ( py_mod != NULL ) PyObject_SetAttrString(py_mod, S_IDC_ARGS_VARNAME, py_args); diff --git a/python/idc.py b/python/idc.py index bb44b15..99d64a7 100644 --- a/python/idc.py +++ b/python/idc.py @@ -2334,6 +2334,7 @@ def FindImmediate (ea, flag, value): return idaapi.find_imm(ea, flag, value) SEARCH_UP = idaapi.SEARCH_UP # search backward SEARCH_DOWN = idaapi.SEARCH_DOWN # search forward SEARCH_NEXT = idaapi.SEARCH_NEXT # start the search at the next/prev item + # useful only for FindText() and FindBinary() SEARCH_CASE = idaapi.SEARCH_CASE # search case-sensitive # (only for bin&txt search) SEARCH_REGEX = idaapi.SEARCH_REGEX # enable regular expressions (only for text) diff --git a/pywraps.hpp b/pywraps.hpp index 43b8936..d559596 100644 --- a/pywraps.hpp +++ b/pywraps.hpp @@ -61,25 +61,31 @@ insn_t *insn_t_get_clink(PyObject *self); op_t *op_t_get_clink(PyObject *self); // Tries to import a module and swallows the exception if it fails and returns NULL -PyObject *PyImport_TryImportModule(const char *name); +PyObject *PyW_TryImportModule(const char *name); // Tries to get an attribute and swallows the exception if it fails and returns NULL -PyObject *PyObject_TryGetAttrString(PyObject *py_var, const char *attr); +PyObject *PyW_TryGetAttrString(PyObject *py_var, const char *attr); // Converts a Python number (LONGLONG or normal integer) to an IDC variable (VT_LONG or VT_INT64) -bool PyGetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var); +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, + qstring *str); // Converts a Python number to an uint64 and indicates whether the number was a long number -bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL); +bool PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL); // Checks if an Python object can be treated like a sequence -bool PyIsSequenceType(PyObject *obj); +bool PyW_IsSequenceType(PyObject *obj); // Returns an error string from the last exception (and clears it) -bool PyGetError(qstring *out = NULL); +bool PyW_GetError(qstring *out = NULL); // If an error occured (it calls PyGetError) it displays it and return TRUE -bool PyShowErr(const char *cb_name); +bool PyW_ShowErr(const char *cb_name); // Utility function to create a class instance whose constructor takes zero arguments PyObject *create_idaapi_class_instance0(const char *clsname); @@ -92,7 +98,7 @@ bool init_pywraps(); void deinit_pywraps(); // Returns the string representation of a PyObject -bool PyObjectToString(PyObject *obj, qstring *out); +bool PyW_ObjectToString(PyObject *obj, qstring *out); // Utility function to convert a python object to an IDC object // and sets a python exception on failure. diff --git a/swig/bytes.i b/swig/bytes.i index a703cc4..ca7fd05 100644 --- a/swig/bytes.i +++ b/swig/bytes.i @@ -120,7 +120,7 @@ static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next) class py_custom_data_type_t { data_type_t dt; - qstring name, menu_name, hotkey, asm_keyword; + qstring dt_name, dt_menu_name, dt_hotkey, dt_asm_keyword; int dtid; // The data format id PyObject *py_self; // Associated Python object @@ -132,7 +132,7 @@ class py_custom_data_type_t { py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_MAY_CREATE_AT, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(nbytes)); - PyShowErr(S_MAY_CREATE_AT); + PyW_ShowErr(S_MAY_CREATE_AT); bool ok = py_result != NULL && PyObject_IsTrue(py_result); Py_XDECREF(py_result); return ok; @@ -150,16 +150,20 @@ class py_custom_data_type_t // this callback is required only for varsize datatypes py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_CALC_ITEM_SIZE, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(maxsize)); - if ( PyShowErr(S_CALC_ITEM_SIZE) || py_result == NULL ) + if ( PyW_ShowErr(S_CALC_ITEM_SIZE) || py_result == NULL ) return 0; uint64 num = 0; - PyGetNumber(py_result, &num); + PyW_GetNumber(py_result, &num); Py_XDECREF(py_result); return asize_t(num); } public: - const char *get_name() const { return name.c_str(); } + const char *get_name() const + { + return dt_name.c_str(); + } + py_custom_data_type_t() { dtid = -1; @@ -175,64 +179,47 @@ public: memset(&dt, 0, sizeof(dt)); dt.cbsize = sizeof(dt); dt.ud = this; + PyObject *py_attr = NULL; do { // name - py_attr = PyObject_TryGetAttrString(py_obj, S_NAME); - if ( py_attr == NULL || !PyString_Check(py_attr) ) + if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) ) break; - name = PyString_AsString(py_attr); - dt.name = name.c_str(); - Py_DECREF(py_attr); + dt.name = dt_name.c_str(); + + // 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 = PyObject_TryGetAttrString(py_obj, S_VALUE_SIZE); - if ( py_attr != NULL ) + py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); + if ( py_attr != NULL && PyInt_Check(py_attr) ) dt.value_size = PyInt_AsLong(py_attr); Py_XDECREF(py_attr); // props - py_attr = PyObject_TryGetAttrString(py_obj, S_PROPS); - if ( py_attr != NULL ) + py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); + if ( py_attr != NULL && PyInt_Check(py_attr) ) dt.props = PyInt_AsLong(py_attr); Py_XDECREF(py_attr); - // menu_name - py_attr = PyObject_TryGetAttrString(py_obj, S_MENU_NAME); - if ( py_attr != NULL && PyString_Check(py_attr) ) - { - menu_name = PyString_AsString(py_attr); - dt.menu_name = menu_name.c_str(); - } - Py_XDECREF(py_attr); - - // asm_keyword - py_attr = PyObject_TryGetAttrString(py_obj, S_ASM_KEYWORD); - if ( py_attr != NULL && PyString_Check(py_attr) ) - { - asm_keyword = PyString_AsString(py_attr); - dt.asm_keyword = asm_keyword.c_str(); - } - Py_XDECREF(py_attr); - - // hotkey - py_attr = PyObject_TryGetAttrString(py_obj, S_HOTKEY); - if ( py_attr != NULL && PyString_Check(py_attr) ) - { - hotkey = PyString_AsString(py_attr); - dt.hotkey = hotkey.c_str(); - } - Py_XDECREF(py_attr); - // may_create_at - py_attr = PyObject_TryGetAttrString(py_obj, S_MAY_CREATE_AT); + py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT); if ( py_attr != NULL && PyCallable_Check(py_attr) ) dt.may_create_at = s_may_create_at; Py_XDECREF(py_attr); // calc_item_size - py_attr = PyObject_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE); + py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE); if ( py_attr != NULL && PyCallable_Check(py_attr) ) dt.calc_item_size = s_calc_item_size; Py_XDECREF(py_attr); @@ -256,6 +243,7 @@ public: // Done with attribute py_attr = NULL; } while ( false ); + Py_XDECREF(py_attr); return dtid; } @@ -290,7 +278,7 @@ private: data_format_t df; int dfid; PyObject *py_self; - qstring name, menu_name, hotkey; + qstring df_name, df_menu_name, df_hotkey; static bool idaapi s_print( // convert to colored string void *ud, // user-defined data @@ -319,7 +307,7 @@ private: Py_DECREF(py_value); // Error while calling the function? - if ( PyShowErr(S_PRINTF) || py_result == NULL ) + if ( PyW_ShowErr(S_PRINTF) || py_result == NULL ) return false; bool ok = false; @@ -356,7 +344,7 @@ private: operand_num); // Error while calling the function? - if ( PyShowErr(S_SCAN) || py_result == NULL) + if ( PyW_ShowErr(S_SCAN) || py_result == NULL) return false; bool ok = false; @@ -414,7 +402,7 @@ private: { py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_ANALYZE, PY_FMT64 "i", pyul_t(current_ea),operand_num); - PyShowErr(S_ANALYZE); + PyW_ShowErr(S_ANALYZE); Py_XDECREF(py_result); } public: @@ -424,7 +412,7 @@ public: py_self = NULL; } - const char *get_name() const { return name.c_str(); } + const char *get_name() const { return df_name.c_str(); } int register_df(int dtid, PyObject *py_obj) { @@ -436,66 +424,54 @@ public: df.cbsize = sizeof(df); df.ud = this; PyObject *py_attr = NULL; + do { // name - py_attr = PyObject_TryGetAttrString(py_obj, S_NAME); - if ( py_attr == NULL || !PyString_Check(py_attr) ) + if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) ) break; - name = PyString_AsString(py_attr); - df.name = name.c_str(); - Py_DECREF(py_attr); + df.name = df_name.c_str(); - // menu_name - py_attr = PyObject_TryGetAttrString(py_obj, S_MENU_NAME); - if ( py_attr != NULL && PyString_Check(py_attr) ) - { - menu_name = PyString_AsString(py_attr); - df.menu_name = menu_name.c_str(); - } - Py_XDECREF(py_attr); + // 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 = PyObject_TryGetAttrString(py_obj, S_PROPS); - if ( py_attr != NULL ) + py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); + if ( py_attr != NULL && PyInt_Check(py_attr) ) df.props = PyInt_AsLong(py_attr); Py_XDECREF(py_attr); // hotkey - py_attr = PyObject_TryGetAttrString(py_obj, S_HOTKEY); - if ( py_attr != NULL && PyString_Check(py_attr) ) - { - hotkey = PyString_AsString(py_attr); - df.hotkey = hotkey.c_str(); - } - Py_XDECREF(py_attr); + if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) ) + df.hotkey = df_hotkey.c_str(); // value_size - py_attr = PyObject_TryGetAttrString(py_obj, S_VALUE_SIZE); - if ( py_attr != NULL ) + py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); + if ( py_attr != NULL && PyInt_Check(py_attr) ) df.value_size = PyInt_AsLong(py_attr); Py_XDECREF(py_attr); // text_width - py_attr = PyObject_TryGetAttrString(py_obj, S_TEXT_WIDTH); - if ( py_attr != NULL ) + py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH); + if ( py_attr != NULL && PyInt_Check(py_attr) ) df.text_width = PyInt_AsLong(py_attr); Py_XDECREF(py_attr); // print cb - py_attr = PyObject_TryGetAttrString(py_obj, S_PRINTF); + py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF); if ( py_attr != NULL && PyCallable_Check(py_attr) ) df.print = s_print; Py_XDECREF(py_attr); // scan cb - py_attr = PyObject_TryGetAttrString(py_obj, S_SCAN); + py_attr = PyW_TryGetAttrString(py_obj, S_SCAN); if ( py_attr != NULL && PyCallable_Check(py_attr) ) df.scan = s_scan; Py_XDECREF(py_attr); // analyze cb - py_attr = PyObject_TryGetAttrString(py_obj, S_ANALYZE); + py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE); if ( py_attr != NULL && PyCallable_Check(py_attr) ) df.analyze = s_analyze; Py_XDECREF(py_attr); @@ -517,6 +493,7 @@ public: Py_DECREF(py_attr); py_attr = NULL; } while ( false ); + Py_XDECREF(py_attr); return dfid; } diff --git a/swig/diskio.i b/swig/diskio.i index 7387b2c..6d280ba 100644 --- a/swig/diskio.i +++ b/swig/diskio.i @@ -439,10 +439,12 @@ PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback { if ( !PyString_Check(path) || !PyString_Check(fname) || !PyCallable_Check(callback) ) break; + const char *_path = PyString_AsString(path); const char *_fname = PyString_AsString(fname); if ( _path == NULL || _fname == NULL ) break; + char answer[MAXSTR]; answer[0] = '\0'; int r = enumerate_files(answer, sizeof(answer), _path, _fname, py_enumerate_files_cb, callback); diff --git a/swig/graph.i b/swig/graph.i index 610e678..97dcda8 100644 --- a/swig/graph.i +++ b/swig/graph.i @@ -140,7 +140,7 @@ private: } // Refer to the nodes - PyObject *nodes = PyObject_TryGetAttrString(self, S_M_NODES); + PyObject *nodes = PyW_TryGetAttrString(self, S_M_NODES); if ( ret == NULL || !PyList_Check(nodes) ) { Py_XDECREF(nodes); @@ -148,8 +148,8 @@ private: } // Refer to the edges - PyObject *edges = PyObject_TryGetAttrString(self, S_M_EDGES); - if ( ret == NULL || !PyList_Check(nodes) ) + PyObject *edges = PyW_TryGetAttrString(self, S_M_EDGES); + if ( ret == NULL || !PyList_Check(edges) ) { Py_DECREF(nodes); Py_XDECREF(edges); @@ -498,7 +498,7 @@ private: static py_graph_t *extract_this(PyObject *self) { // Try to extract "this" from the python object - PyObject *py_this = PyObject_TryGetAttrString(self, S_M_THIS); + PyObject *py_this = PyW_TryGetAttrString(self, S_M_THIS); if ( py_this == NULL || !PyCObject_Check(py_this) ) { Py_XDECREF(py_this); @@ -531,16 +531,6 @@ private: refresh_viewer(gv); } - static bool extract_title(PyObject *self, qstring *title) - { - PyObject *py_title = PyObject_TryGetAttrString(self, S_M_TITLE); - if ( py_title == NULL ) - return false; - *title = PyString_AsString(py_title); - Py_DECREF(py_title); - return true; - } - int create(PyObject *self, const char *title) { // check what callbacks we have @@ -566,7 +556,7 @@ private: cb_flags = 0; for ( int i=0; i:\n%s", cb_name, err_str.c_str()); return true; @@ -466,7 +490,7 @@ bool PyShowErr(const char *cb_name) static int get_pyidc_cvt_type(PyObject *py_var) { // Check if this our special by reference object - PyObject *attr = PyObject_TryGetAttrString(py_var, S_PY_IDCCVT_ID_ATTR); + PyObject *attr = PyW_TryGetAttrString(py_var, S_PY_IDCCVT_ID_ATTR); if ( attr == NULL ) return -1; if ( !(PyInt_Check(attr) || PyLong_Check(attr)) ) @@ -506,7 +530,7 @@ Py_ssize_t pyvar_walk_list( int (idaapi *cb)(PyObject *py_item, Py_ssize_t index, void *ud), void *ud) { - if ( !PyList_CheckExact(py_list) && !PyIsSequenceType(py_list) ) + if ( !PyList_CheckExact(py_list) && !PyW_IsSequenceType(py_list) ) return CIP_FAILED; bool is_seq = !PyList_CheckExact(py_list); @@ -547,7 +571,7 @@ int pyvar_to_idcvar( if ( py_var == NULL || py_var == Py_None ) idc_var->set_long(0); // Numbers? - else if ( PyGetNumberAsIDC(py_var, idc_var) ) + else if ( PyW_GetNumberAsIDC(py_var, idc_var) ) return CIP_OK; // String else if ( PyString_Check(py_var) ) @@ -566,7 +590,7 @@ int pyvar_to_idcvar( else if ( PyCObject_Check(py_var) ) idc_var->set_pvoid(PyCObject_AsVoidPtr(py_var)); // Is it a Python list? - else if ( PyList_CheckExact(py_var) || PyIsSequenceType(py_var) ) + else if ( PyList_CheckExact(py_var) || PyW_IsSequenceType(py_var) ) { // Create the object VarObject(idc_var); @@ -590,7 +614,7 @@ int pyvar_to_idcvar( { // Form the attribute name PyObject *py_int = PyInt_FromSsize_t(i); - ok = PyObjectToString(py_int, &attr_name); + ok = PyW_ObjectToString(py_int, &attr_name); if ( !ok ) break; Py_DECREF(py_int); @@ -628,7 +652,7 @@ int pyvar_to_idcvar( PyObject *val = PySequence_GetItem(py_item, 1); // Get key's string representation - PyObjectToString(key, &key_name); + PyW_ObjectToString(key, &key_name); // Convert the attribute into an IDC value idc_value_t v; @@ -669,7 +693,7 @@ int pyvar_to_idcvar( // case PY_ICID_INT64: // Get the value attribute - attr = PyObject_TryGetAttrString(py_var, S_PY_IDCCVT_VALUE_ATTR); + attr = PyW_TryGetAttrString(py_var, S_PY_IDCCVT_VALUE_ATTR); if ( attr == NULL ) return false; idc_var->set_int64(PyLong_AsLongLong(attr)); @@ -685,7 +709,7 @@ int pyvar_to_idcvar( return CIP_FAILED; // Get the value attribute - attr = PyObject_TryGetAttrString(py_var, S_PY_IDCCVT_VALUE_ATTR); + attr = PyW_TryGetAttrString(py_var, S_PY_IDCCVT_VALUE_ATTR); if ( attr == NULL ) return CIP_FAILED; @@ -796,7 +820,7 @@ int idcvar_to_pyvar( return CIP_FAILED; *py_var = PyObject_CallFunctionObjArgs(py_cls, PyLong_FromLongLong(idc_var.i64), NULL); Py_DECREF(py_cls); - if ( PyGetError() || *py_var == NULL ) + if ( PyW_GetError() || *py_var == NULL ) return CIP_FAILED; break; } @@ -845,7 +869,7 @@ int idcvar_to_pyvar( // Create a byref object with None value. We populate it later *py_var = PyObject_CallFunctionObjArgs(py_cls, Py_None, NULL); Py_DECREF(py_cls); - if ( PyGetError() || *py_var == NULL ) + if ( PyW_GetError() || *py_var == NULL ) return CIP_FAILED; } int t = *py_var == NULL ? -1 : get_pyidc_cvt_type(*py_var); @@ -859,7 +883,7 @@ int idcvar_to_pyvar( return CIP_FAILED; // Can we recycle the object? - PyObject *new_py_val = PyObject_TryGetAttrString(*py_var, S_PY_IDCCVT_VALUE_ATTR); + PyObject *new_py_val = PyW_TryGetAttrString(*py_var, S_PY_IDCCVT_VALUE_ATTR); if ( new_py_val != NULL ) { // Recycle @@ -902,7 +926,7 @@ int idcvar_to_pyvar( return CIP_FAILED; obj = PyObject_CallFunctionObjArgs(py_cls, NULL); Py_DECREF(py_cls); - if ( PyGetError() || obj == NULL ) + if ( PyW_GetError() || obj == NULL ) return CIP_FAILED; } else @@ -1130,7 +1154,7 @@ public: break; } Py_DECREF(py_code); - if ( PyGetError(&err) || py_result == NULL ) + if ( PyW_GetError(&err) || py_result == NULL ) { warning("notify_when(): Error occured while notifying object.\n%s", err.c_str()); ok = false; @@ -1269,17 +1293,17 @@ class pycvt_t attr_t &val) { PyObject *py_attr; - if ( (py_attr = PyObject_TryGetAttrString(py_obj, attrname)) == NULL ) + if ( (py_attr = PyW_TryGetAttrString(py_obj, attrname)) == NULL ) return FT_NOT_FOUND; int cvt = FT_OK; if ( ft == FT_STR || ft == FT_CHAR && PyString_Check(py_attr) ) val.str = PyString_AsString(py_attr); - else if ( (ft > FT_FIRST_NUM && ft < FT_LAST_NUM) && PyGetNumber(py_attr, &val.u64) ) + else if ( (ft > FT_FIRST_NUM && ft < FT_LAST_NUM) && PyW_GetNumber(py_attr, &val.u64) ) ; // nothing to be done // A string array? else if ( (ft == FT_STRARR || ft == FT_NUM16ARR || FT_CHRARR_STATIC ) - && (PyList_CheckExact(py_attr) || PyIsSequenceType(py_attr)) ) + && (PyList_CheckExact(py_attr) || PyW_IsSequenceType(py_attr)) ) { // Return a reference to the attribute val.py_obj = py_attr; @@ -1338,7 +1362,7 @@ class pycvt_t void *ud) { uint64 val; - if ( !PyGetNumber(py_item, &val) ) + if ( !PyW_GetNumber(py_item, &val) ) return CIP_FAILED; uint64vec_t *vec = (uint64vec_t *)ud; vec->push_back(val); diff --git a/swig/idd.i b/swig/idd.i index c3092e9..85d3187 100644 --- a/swig/idd.i +++ b/swig/idd.i @@ -2,6 +2,7 @@ %ignore memory_info_t; %ignore register_info_t; %ignore appcall; +%ignore idd_opinfo_t; %ignore gdecode_t; %apply unsigned char { char dtyp }; @@ -70,7 +71,7 @@ PyObject *py_appcall( if ( (debug & IDA_DEBUG_APPCALL) != 0 ) { qstring s; - PyObjectToString(py_item, &s); + PyW_ObjectToString(py_item, &s); msg("obj[%d]->%s\n", int(i), s.c_str()); } // Convert it @@ -285,7 +286,7 @@ def dbg_read_memory(ea, sz): static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) { uint64 ea, sz; - if ( !dbg_can_query() || !PyGetNumber(py_ea, &ea) || !PyGetNumber(py_sz, &sz) ) + if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) ) Py_RETURN_NONE; // Create a Python string @@ -322,7 +323,7 @@ def dbg_write_memory(ea, buffer): static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf) { uint64 ea; - if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyGetNumber(py_ea, &ea) ) + if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyW_GetNumber(py_ea, &ea) ) Py_RETURN_NONE; size_t sz = PyString_GET_SIZE(py_buf); @@ -385,7 +386,9 @@ def dbg_can_query(): This function can be used to check if the debugger can be queried: - debugger is loaded - process is suspended - - process is not suspended but can take requests + - process is not suspended but can take requests. In this case some requests like + memory read/write, bpt management succeed and register querying will fail. + Check if idaapi.get_process_state() < 0 to tell if the process is suspended @return: Boolean """ pass diff --git a/swig/kernwin.i b/swig/kernwin.i index 26f62dd..07da901 100644 --- a/swig/kernwin.i +++ b/swig/kernwin.i @@ -164,7 +164,7 @@ int py_execute_sync(PyObject *py_callable, int reqf) //------------------------------------------------------------------------ // Some defines #define POPUP_NAMES_COUNT 4 -#define MAX_CHOOSER_MENU_COMMANDS 10 +#define MAX_CHOOSER_MENU_COMMANDS 12 #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)); } @@ -222,6 +222,7 @@ private: 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) static chooser_cb_t *menu_cbs[MAX_CHOOSER_MENU_COMMANDS]; int menu_cb_idx; //------------------------------------------------------------------------ @@ -334,7 +335,7 @@ private: // delete this instance if none modal if ( (flags & CH_MODAL) == 0 ) delete this; -} + } int on_delete_line(int lineno) { @@ -391,6 +392,7 @@ private: Py_XDECREF(pyres); return res; } + void on_get_line_attr(int lineno, chooser_item_attrs_t *attr) { PyObject *pyres = PyObject_CallMethod(self, (char *)S_ON_GET_LINE_ATTR, "i", lineno - 1); @@ -407,6 +409,7 @@ private: } Py_XDECREF(pyres); } + public: //------------------------------------------------------------------------ // Public methods @@ -418,14 +421,17 @@ public: menu_cb_idx = 0; self = NULL; } + static py_choose2_t *find_chooser(const char *title) { return (py_choose2_t *) get_chooser_obj(title); } + void close() { close_chooser(title.c_str()); } + bool activate() { TForm *frm = find_tform(title.c_str()); @@ -477,29 +483,30 @@ public: { if ( menu_cb_idx >= MAX_CHOOSER_MENU_COMMANDS ) return -1; + bool ret = add_chooser_command(title.c_str(), caption, menu_cbs[menu_cb_idx], menu_index, icon, flags); if ( !ret ) return -1; + return menu_cb_idx++; } int show(PyObject *self) { PyObject *attr; - // get title - if ( (attr = PyObject_TryGetAttrString(self, "title")) == NULL ) + // get flags + if ( (attr = PyW_TryGetAttrString(self, S_FLAGS)) == NULL ) return -1; - qstring title = PyString_AsString(attr); + int flags = PyInt_Check(attr) != 0 ? PyInt_AsLong(attr) : 0; Py_DECREF(attr); - // get flags - if ( (attr = PyObject_TryGetAttrString(self, "flags")) == NULL ) + qstring title; + // get the title + if ( !PyW_GetStringAttr(self, S_TITLE, &title) ) return -1; - int flags = PyInt_AsLong(attr); - Py_DECREF(attr); // get columns - if ( (attr = PyObject_TryGetAttrString(self, "cols")) == NULL ) + if ( (attr = PyW_TryGetAttrString(self, "cols")) == NULL ) return -1; // get col count @@ -535,7 +542,7 @@ public: // get *deflt int deflt = -1; - if ( (attr = PyObject_TryGetAttrString(self, "deflt")) != NULL ) + if ( (attr = PyW_TryGetAttrString(self, "deflt")) != NULL ) { deflt = PyInt_AsLong(attr); Py_DECREF(attr); @@ -543,7 +550,7 @@ public: // get *icon int icon = -1; - if ( (attr = PyObject_TryGetAttrString(self, "icon")) != NULL ) + if ( (attr = PyW_TryGetAttrString(self, "icon")) != NULL ) { icon = PyInt_AsLong(attr); Py_DECREF(attr); @@ -554,7 +561,7 @@ public: static const char *pt_attrs[qnumber(pts)] = {"x1", "y1", "x2", "y2"}; for ( int i=0; iself = self; // Create chooser - int r = this->choose2(flags, ncols, &widths[0], title.c_str(), deflt, popup_names, icon, pts[0], pts[1], pts[2], pts[3]); + int r = this->choose2( + flags, + ncols, + &widths[0], + title.c_str(), + deflt, + popup_names, + icon, + pts[0], + pts[1], + pts[2], + pts[3]); // Clear temporary popup_names if ( popup_names != NULL ) { for ( int i=0; i %} -#endif +#endif // __NT__ %inline %{ uint32 idaapi choose_sizer(void *self) @@ -1836,10 +1864,10 @@ void idaapi choose_enter(void *self, uint32 n) } uint32 choose_choose(void *self, - int flags, - int x0,int y0, - int x1,int y1, - int width) + int flags, + int x0,int y0, + int x1,int y1, + int width) { PyObject *pytitle; const char *title; @@ -1871,7 +1899,7 @@ uint32 choose_choose(void *self, NULL, /* destroy */ NULL, /* popup_names */ NULL /* get_icon */ - ); + ); Py_XDECREF(pytitle); return r; } @@ -1980,11 +2008,11 @@ def add_menu_item(menupath, name, hotkey, flags, callback, args): @param name: name of the menu item (~x~ is used to denote Alt-x hot letter) @param hotkey: hotkey for the menu item (may be empty) @param flags: one of SETMENU_... consts - @callback: function which gets called when the user selects the menu item. + @param callback: function which gets called when the user selects the menu item. The function callback is of the form: def callback(*args): pass - @param: args: tuple containing the arguments + @param args: tuple containing the arguments @return: None or a menu context (to be used by del_menu_item()) """ @@ -1999,23 +2027,50 @@ static PyObject *py_add_menu_item( PyObject *pyfunc, PyObject *args) { - if ( !PyTuple_Check(args) ) + bool no_args; + + 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 = menupath; ctx->menupath.append(name); + // Save callback data ctx->cb_data = cb_data; + + // Return context to user return PyCObject_FromVoidPtr(ctx, NULL); } @@ -2074,67 +2129,67 @@ uint32 choose_choose(PyObject *self, %pythoncode %{ class Choose: - """ - Choose - class for choose() with callbacks - """ - def __init__(self, list, title, flags=0): - self.list = list - self.title = title + """ + Choose - class for choose() with callbacks + """ + def __init__(self, list, title, flags=0): + self.list = list + self.title = title - self.flags = flags - self.x0 = -1 - self.x1 = -1 - self.y0 = -1 - self.y1 = -1 + self.flags = flags + self.x0 = -1 + self.x1 = -1 + self.y0 = -1 + self.y1 = -1 - self.width = -1 + self.width = -1 - # 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 & 1) == 0: - self.refhack = self + # 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 & 1) == 0: + self.refhack = self - def sizer(self): - """ - Callback: sizer - returns the length of the list - """ - return len(self.list) + def sizer(self): + """ + Callback: sizer - returns the length of the list + """ + return len(self.list) - def getl(self, n): - """ - Callback: getl - get one item from the list - """ - if n == 0: - return self.title - if n <= self.sizer(): - return str(self.list[n-1]) - else: - return "" + def getl(self, n): + """ + Callback: getl - get one item from the list + """ + if n == 0: + return self.title + if n <= self.sizer(): + return str(self.list[n-1]) + else: + return "" - def ins(self): - pass + def ins(self): + pass - def update(self, n): - pass + def update(self, n): + pass - def edit(self, n): - pass + def edit(self, n): + pass - def enter(self, n): - print "enter(%d) called" % n + def enter(self, n): + print "enter(%d) called" % n - def destroy(self): - pass + def destroy(self): + pass - def get_icon(self, n): - pass + def get_icon(self, n): + pass - def choose(self): - """ - choose - Display the choose dialogue - """ - return _idaapi.choose_choose(self, self.flags, self.x0, self.y0, self.x1, self.y1, self.width) + def choose(self): + """ + choose - Display the choose dialogue + """ + return _idaapi.choose_choose(self, self.flags, self.x0, self.y0, self.x1, self.y1, self.width) # DP_LEFT = 0x0001 diff --git a/swig/nalt.i b/swig/nalt.i index eb14cc6..6f5c23a 100644 --- a/swig/nalt.i +++ b/swig/nalt.i @@ -370,7 +370,7 @@ static void switch_info_ex_t_set_defjump(PyObject *self, PyObject *value) switch_info_ex_t *link = switch_info_ex_t_get_clink(self); if ( link == NULL ) return; - uint64 v(0); PyGetNumber(value, &v); + uint64 v(0); PyW_GetNumber(value, &v); link->defjump = (pyul_t)v; } @@ -386,7 +386,7 @@ static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value) switch_info_ex_t *link = switch_info_ex_t_get_clink(self); if ( link == NULL ) return; - uint64 v(0); PyGetNumber(value, &v); + uint64 v(0); PyW_GetNumber(value, &v); link->jumps = (pyul_t)v; } @@ -403,7 +403,7 @@ static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->elbase = (pyul_t)v; } @@ -420,7 +420,7 @@ static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->startea = (pyul_t)v; } @@ -437,7 +437,7 @@ static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->custom = (pyul_t)v; } @@ -454,7 +454,7 @@ static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->ind_lowcase = (pyul_t)v; } @@ -471,7 +471,7 @@ static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->values = (pyul_t)v; } diff --git a/swig/typeinf.i b/swig/typeinf.i index 0bd804b..36d1557 100644 --- a/swig/typeinf.i +++ b/swig/typeinf.i @@ -193,9 +193,11 @@ PyObject *py_get_type_size0(const til_t *ti, PyObject *tp) PyErr_SetString(PyExc_ValueError, "String expected!"); return NULL; } + size_t sz = get_type_size0(ti, (type_t *)PyString_AsString(tp)); if ( sz == BADSIZE ) Py_RETURN_NONE; + return PyInt_FromLong(sz); } diff --git a/swig/ua.i b/swig/ua.i index 510e118..601f7a0 100644 --- a/swig/ua.i +++ b/swig/ua.i @@ -143,7 +143,7 @@ PyObject *py_get_stkvar(PyObject *py_op, PyObject *py_v) { op_t *op = op_t_get_clink(py_op); uint64 v; - if ( op == NULL || !PyGetNumber(py_v, &v) ) + if ( op == NULL || !PyW_GetNumber(py_v, &v) ) Py_RETURN_NONE; sval_t actval; @@ -176,7 +176,7 @@ bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags) { op_t *op = op_t_get_clink(py_op); uint64 v; - return ( op == NULL || !PyGetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true; + return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true; } //------------------------------------------------------------------------- @@ -217,7 +217,7 @@ bool py_apply_type_to_stkarg( { uint64 v; op_t *op = op_t_get_clink(py_op); - if ( op == NULL || !PyGetNumber(py_uv, &v) || !PyString_Check(py_type)) + if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type)) return false; else return apply_type_to_stkarg(*op, uval_t(v), (type_t *) PyString_AsString(py_type), name); @@ -322,7 +322,7 @@ bool py_out_name_expr( op_t *op = op_t_get_clink(py_op); uint64 v(0); adiff_t off; - if ( PyGetNumber(py_off, &v) ) + if ( PyW_GetNumber(py_off, &v) ) off = adiff_t(v); else off = BADADDR; @@ -450,7 +450,7 @@ static void insn_t_set_cs(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->cs = ea_t(v); } @@ -468,7 +468,7 @@ static void insn_t_set_ip(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->ip = ea_t(v); } @@ -486,7 +486,7 @@ static void insn_t_set_ea(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->ea = ea_t(v); } @@ -728,7 +728,7 @@ static void op_t_set_addr(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->addr = ea_t(v); } @@ -746,7 +746,7 @@ static void op_t_set_specval(PyObject *self, PyObject *value) if ( link == NULL ) return; uint64 v(0); - PyGetNumber(value, &v); + PyW_GetNumber(value, &v); link->specval = ea_t(v); }