//-------------------------------------------------------------------------- const char *PyBBMatcher::init() { PYW_GIL_GET; const char *err = call_init_file(); if (err != NULL) return err; py_matcher_module = PyW_TryImportModule(STR_PY_MATCH_MODULE); if (py_matcher_module == NULL) return "BBMatch module is not present"; //NOTE: To create an object instance, get a reference to the class // then call PyObject_CallFunctionObjArgs(py_cls, NULL) py_instref = PyW_TryGetAttrString(py_matcher_module, "bbMatcher"); if (py_instref == NULL) return "BBMatcher instance not present"; py_meth_find_similar = PyW_TryGetAttrString(py_instref, "FindSimilar"); py_meth_save_state = PyW_TryGetAttrString(py_instref, "SaveState"); py_meth_load_state = PyW_TryGetAttrString(py_instref, "LoadState"); py_meth_analyze = PyW_TryGetAttrString(py_instref, "Analyze"); if ( py_meth_find_similar == NULL || py_meth_save_state == NULL || py_meth_load_state == NULL || py_meth_analyze == NULL) { return "Failed to find one or more needed methods"; } return NULL; }
//------------------------------------------------------------------------- // Checks if the given py_var is a special PyIdc_cvt_helper object. // It does that by examining the magic attribute and returns its numeric value. // It returns -1 if the object is not a recognized helper object. // Any Python object can be treated as an cvt object if this attribute is created. static int get_pyidc_cvt_type(PyObject *py_var) { PYW_GIL_CHECK_LOCKED_SCOPE(); // Check if this our special by reference object ref_t attr(PyW_TryGetAttrString(py_var, S_PY_IDCCVT_ID_ATTR)); if ( attr == NULL || (!PyInt_Check(attr.o) && !PyLong_Check(attr.o)) ) return -1; return (int)PyInt_AsLong(attr.o); }
int register_dt(PyObject *py_obj) { PYW_GIL_CHECK_LOCKED_SCOPE(); // Already registered? if ( dtid >= 0 ) return dtid; memset(&dt, 0, sizeof(dt)); dt.cbsize = sizeof(dt); dt.ud = this; do { ref_t py_attr; // name if ( !PyW_GetStringAttr(py_obj, S_NAME, &dt_name) ) break; 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 = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); if ( py_attr != NULL && PyInt_Check(py_attr.o) ) dt.value_size = PyInt_AsLong(py_attr.o); py_attr = ref_t(); // props py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); if ( py_attr != NULL && PyInt_Check(py_attr.o) ) dt.props = PyInt_AsLong(py_attr.o); py_attr = ref_t(); // may_create_at py_attr = PyW_TryGetAttrString(py_obj, S_MAY_CREATE_AT); if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) dt.may_create_at = s_may_create_at; py_attr = ref_t(); // calc_item_size py_attr = PyW_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE); if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) dt.calc_item_size = s_calc_item_size; py_attr = ref_t(); // Now try to register dtid = register_custom_data_type(&dt); if ( dtid < 0 ) break; // Hold reference to the PyObject Py_INCREF(py_obj); py_self = py_obj; py_attr = newref_t(PyInt_FromLong(dtid)); PyObject_SetAttrString(py_obj, S_ID, py_attr.o); } while ( false ); return dtid; }
int register_df(int dtid, PyObject *py_obj) { // Already registered? if ( dfid >= 0 ) return dfid; memset(&df, 0, sizeof(df)); df.cbsize = sizeof(df); df.ud = this; PYW_GIL_CHECK_LOCKED_SCOPE(); do { ref_t py_attr; // name if ( !PyW_GetStringAttr(py_obj, S_NAME, &df_name) ) break; df.name = df_name.c_str(); // menu_name (optional) if ( PyW_GetStringAttr(py_obj, S_MENU_NAME, &df_menu_name) ) df.menu_name = df_menu_name.c_str(); // props py_attr = PyW_TryGetAttrString(py_obj, S_PROPS); if ( py_attr != NULL && PyInt_Check(py_attr.o) ) df.props = PyInt_AsLong(py_attr.o); // hotkey if ( PyW_GetStringAttr(py_obj, S_HOTKEY, &df_hotkey) ) df.hotkey = df_hotkey.c_str(); // value_size py_attr = PyW_TryGetAttrString(py_obj, S_VALUE_SIZE); if ( py_attr != NULL && PyInt_Check(py_attr.o) ) df.value_size = PyInt_AsLong(py_attr.o); // text_width py_attr = PyW_TryGetAttrString(py_obj, S_TEXT_WIDTH); if ( py_attr != NULL && PyInt_Check(py_attr.o) ) df.text_width = PyInt_AsLong(py_attr.o); // print cb py_attr = PyW_TryGetAttrString(py_obj, S_PRINTF); if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) df.print = s_print; // scan cb py_attr = PyW_TryGetAttrString(py_obj, S_SCAN); if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) df.scan = s_scan; // analyze cb py_attr = PyW_TryGetAttrString(py_obj, S_ANALYZE); if ( py_attr != NULL && PyCallable_Check(py_attr.o) ) df.analyze = s_analyze; // Now try to register dfid = register_custom_data_format(dtid, &df); if ( dfid < 0 ) break; // Hold reference to the PyObject Py_INCREF(py_obj); py_self = py_obj; // Update the format ID py_attr = newref_t(PyInt_FromLong(dfid)); PyObject_SetAttrString(py_obj, S_ID, py_attr.o); } while ( false ); return dfid; }
static void py_get_int(PyObject *self, T *prm, const char *name) { ref_t attr(PyW_TryGetAttrString(self, name)); if ( attr != NULL && attr.o != Py_None ) *prm = T(PyInt_AsLong(attr.o)); }
//------------------------------------------------------------------------- // Converts an IDC variable to a Python variable // If py_var points to an existing object then the object will be updated // If py_var points to an existing immutable object then ZERO is returned // Returns one of CIP_xxxx. Check pywraps.hpp int idcvar_to_pyvar( const idc_value_t &idc_var, ref_t *py_var) { PYW_GIL_CHECK_LOCKED_SCOPE(); switch ( idc_var.vtype ) { case VT_PVOID: if ( *py_var == NULL ) { newref_t nr(PyCObject_FromVoidPtr(idc_var.pvoid, NULL)); *py_var = nr; } else { return CIP_IMMUTABLE; } break; case VT_INT64: { // Recycle? if ( *py_var != NULL ) { // Recycling an int64 object? int t = get_pyidc_cvt_type(py_var->o); if ( t != PY_ICID_INT64 ) return CIP_IMMUTABLE; // Cannot recycle immutable object // Update the attribute PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64)); return CIP_OK; } ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_INT64)); if ( py_cls == NULL ) return CIP_FAILED; *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, PyLong_FromLongLong(idc_var.i64), NULL)); if ( PyW_GetError() || *py_var == NULL ) return CIP_FAILED; break; } #if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC) case VT_STR: *py_var = newref_t(PyString_FromString(idc_var.str)); break; #endif case VT_STR2: if ( *py_var == NULL ) { const qstring &s = idc_var.qstr(); *py_var = newref_t(PyString_FromStringAndSize(s.begin(), s.length())); break; } else return CIP_IMMUTABLE; // Cannot recycle immutable object case VT_LONG: // Cannot recycle immutable objects if ( *py_var != NULL ) return CIP_IMMUTABLE; *py_var = newref_t(cvt_to_pylong(idc_var.num)); break; case VT_FLOAT: if ( *py_var == NULL ) { double x; if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 0 ) INTERR(30160); *py_var = newref_t(PyFloat_FromDouble(x)); break; } else return CIP_IMMUTABLE; case VT_REF: { if ( *py_var == NULL ) { ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_BYREF)); if ( py_cls == NULL ) return CIP_FAILED; // Create a byref object with None value. We populate it later *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, Py_None, NULL)); if ( PyW_GetError() || *py_var == NULL ) return CIP_FAILED; } int t = get_pyidc_cvt_type(py_var->o); if ( t != PY_ICID_BYREF ) return CIP_FAILED; // Dereference // (Since we are not using VREF_COPY flag, we can safely const_cast) idc_value_t *dref_v = VarDeref(const_cast<idc_value_t *>(&idc_var), VREF_LOOP); if ( dref_v == NULL ) return CIP_FAILED; // Can we recycle the object? ref_t new_py_val(PyW_TryGetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR)); if ( new_py_val != NULL ) { // Recycle t = idcvar_to_pyvar(*dref_v, &new_py_val); // Success? Nothing more to be done if ( t == CIP_OK ) return CIP_OK; // Clear it so we don't recycle it new_py_val = ref_t(); } // Try to convert (not recycle) if ( idcvar_to_pyvar(*dref_v, &new_py_val) != CIP_OK ) return CIP_FAILED; // Update the attribute PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, new_py_val.o); break; } // Can convert back into a Python object or Python dictionary // (Depending if py_var will be recycled and it was a dictionary) case VT_OBJ: { // Check if this IDC object has __cvt_id__ and the __idc_cvt_value__ fields idc_value_t idc_val; if ( VarGetAttr(&idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val) == eOk && VarGetAttr(&idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val) == eOk ) { // Extract the object *py_var = borref_t((PyObject *) idc_val.pvoid); return CIP_OK_OPAQUE; } ref_t obj; bool is_dict = false; // Need to create a new object? if ( *py_var == NULL ) { // Get skeleton class reference ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_APPCALL_SKEL_OBJ)); if ( py_cls == NULL ) return CIP_FAILED; // Call constructor obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL)); if ( PyW_GetError() || obj == NULL ) return CIP_FAILED; } else { // Recycle existing variable obj = *py_var; if ( PyDict_Check(obj.o) ) is_dict = true; } // Walk the IDC attributes and store into python for (const char *attr_name = VarFirstAttr(&idc_var); attr_name != NULL; attr_name = VarNextAttr(&idc_var, attr_name) ) { // Get the attribute idc_value_t v; VarGetAttr(&idc_var, attr_name, &v, true); // Convert attribute to a python value (recursively) ref_t py_attr; int cvt = idcvar_to_pyvar(v, &py_attr); if ( cvt <= CIP_IMMUTABLE ) return CIP_FAILED; if ( is_dict ) PyDict_SetItemString(obj.o, attr_name, py_attr.o); else PyObject_SetAttrString(obj.o, attr_name, py_attr.o); } *py_var = obj; break; } // Unhandled type default: *py_var = ref_t(); return CIP_FAILED; } return CIP_OK; }
//------------------------------------------------------------------------- // Converts a Python variable into an IDC variable // This function returns on one CIP_XXXX int pyvar_to_idcvar( const ref_t &py_var, idc_value_t *idc_var, int *gvar_sn) { PYW_GIL_CHECK_LOCKED_SCOPE(); // None / NULL if ( py_var == NULL || py_var.o == Py_None ) { idc_var->set_long(0); } // Numbers? else if ( PyW_GetNumberAsIDC(py_var.o, idc_var) ) { return CIP_OK; } // String else if ( PyString_Check(py_var.o) ) { idc_var->_set_string(PyString_AsString(py_var.o), PyString_Size(py_var.o)); } // Boolean else if ( PyBool_Check(py_var.o) ) { idc_var->set_long(py_var.o == Py_True ? 1 : 0); } // Float else if ( PyFloat_Check(py_var.o) ) { double dresult = PyFloat_AsDouble(py_var.o); ieee_realcvt((void *)&dresult, idc_var->e, 3); idc_var->vtype = VT_FLOAT; } // void* else if ( PyCObject_Check(py_var.o) ) { idc_var->set_pvoid(PyCObject_AsVoidPtr(py_var.o)); } // Python list? else if ( PyList_CheckExact(py_var.o) || PyW_IsSequenceType(py_var.o) ) { // Create the object VarObject(idc_var); // Determine list size and type bool is_seq = !PyList_CheckExact(py_var.o); Py_ssize_t size = is_seq ? PySequence_Size(py_var.o) : PyList_Size(py_var.o); bool ok = true; qstring attr_name; // Convert each item for ( Py_ssize_t i=0; i<size; i++ ) { // Get the item ref_t py_item; if ( is_seq ) py_item = newref_t(PySequence_GetItem(py_var.o, i)); else py_item = borref_t(PyList_GetItem(py_var.o, i)); // Convert the item into an IDC variable idc_value_t v; ok = pyvar_to_idcvar(py_item, &v, gvar_sn) >= CIP_OK; if ( ok ) { // Form the attribute name newref_t py_int(PyInt_FromSsize_t(i)); ok = PyW_ObjectToString(py_int.o, &attr_name); if ( !ok ) break; // Store the attribute VarSetAttr(idc_var, attr_name.c_str(), &v); } if ( !ok ) break; } return ok ? CIP_OK : CIP_FAILED; } // Dictionary: we convert to an IDC object else if ( PyDict_Check(py_var.o) ) { // Create an empty IDC object VarObject(idc_var); // Get the dict.items() list newref_t py_items(PyDict_Items(py_var.o)); // Get the size of the list qstring key_name; bool ok = true; Py_ssize_t size = PySequence_Size(py_items.o); for ( Py_ssize_t i=0; i<size; i++ ) { // Get item[i] -> (key, value) PyObject *py_item = PyList_GetItem(py_items.o, i); // Extract key/value newref_t key(PySequence_GetItem(py_item, 0)); newref_t val(PySequence_GetItem(py_item, 1)); // Get key's string representation PyW_ObjectToString(key.o, &key_name); // Convert the attribute into an IDC value idc_value_t v; ok = pyvar_to_idcvar(val, &v, gvar_sn) >= CIP_OK; if ( ok ) { // Store the attribute VarSetAttr(idc_var, key_name.c_str(), &v); } if ( !ok ) break; } return ok ? CIP_OK : CIP_FAILED; } // Possible function? else if ( PyCallable_Check(py_var.o) ) { idc_var->clear(); idc_var->vtype = VT_FUNC; idc_var->funcidx = -1; // Does not apply return CIP_OK; } // Objects: // - pyidc_cvt objects: int64, byref, opaque // - other python objects else { // Get the type int cvt_id = get_pyidc_cvt_type(py_var.o); switch ( cvt_id ) { // // INT64 // case PY_ICID_INT64: { // Get the value attribute ref_t attr(PyW_TryGetAttrString(py_var.o, S_PY_IDCCVT_VALUE_ATTR)); if ( attr == NULL ) return false; idc_var->set_int64(PyLong_AsLongLong(attr.o)); return CIP_OK; } // // BYREF // case PY_ICID_BYREF: { // BYREF always require this parameter if ( gvar_sn == NULL ) return CIP_FAILED; // Get the value attribute ref_t attr(PyW_TryGetAttrString(py_var.o, S_PY_IDCCVT_VALUE_ATTR)); if ( attr == NULL ) return CIP_FAILED; // Create a global variable char buf[MAXSTR]; qsnprintf(buf, sizeof(buf), S_PY_IDC_GLOBAL_VAR_FMT, *gvar_sn); idc_value_t *gvar = add_idc_gvar(buf); // Convert the python value into the IDC global variable bool ok = pyvar_to_idcvar(attr, gvar, gvar_sn) >= CIP_OK; if ( ok ) { (*gvar_sn)++; // Create a reference to this global variable VarRef(idc_var, gvar); } return ok ? CIP_OK : CIP_FAILED; } // // OPAQUE // case PY_ICID_OPAQUE: { if ( !wrap_PyObject_ptr(py_var, idc_var) ) return CIP_FAILED; return CIP_OK_OPAQUE; } // // Other objects // default: // A normal object? newref_t py_dir(PyObject_Dir(py_var.o)); Py_ssize_t size = PyList_Size(py_dir.o); if ( py_dir == NULL || !PyList_Check(py_dir.o) || size == 0 ) return CIP_FAILED; // Create the IDC object VarObject(idc_var); for ( Py_ssize_t i=0; i<size; i++ ) { borref_t item(PyList_GetItem(py_dir.o, i)); const char *field_name = PyString_AsString(item.o); if ( field_name == NULL ) continue; size_t len = strlen(field_name); // Skip private attributes if ( (len > 2 ) && (strncmp(field_name, "__", 2) == 0 ) && (strncmp(field_name+len-2, "__", 2) == 0) ) { continue; } idc_value_t v; // Get the non-private attribute from the object newref_t attr(PyObject_GetAttrString(py_var.o, field_name)); if (attr == NULL // Convert the attribute into an IDC value || pyvar_to_idcvar(attr, &v, gvar_sn) < CIP_OK) { return CIP_FAILED; } // Store the attribute VarSetAttr(idc_var, field_name, &v); } } } return CIP_OK; }