static void idaapi s_py_get_user_defined_prefix( ea_t ea, int lnnum, int indent, const char *line, char *buf, size_t bufsize) { PYW_GIL_GET; newref_t py_ret( PyObject_CallFunction( py_get_user_defined_prefix, PY_FMT64 "iis" PY_FMT64, ea, lnnum, indent, line, bufsize)); // Error? Display it // No error? Copy the buffer if ( !PyW_ShowCbErr("py_get_user_defined_prefix") ) { Py_ssize_t py_len; char *py_str; if ( PyString_AsStringAndSize(py_ret.o, &py_str, &py_len) != -1 ) { memcpy(buf, py_str, qmin(bufsize, py_len)); if ( py_len < bufsize ) buf[py_len] = '\0'; } } }
// !=NULL means variable size datatype static asize_t idaapi s_calc_item_size( // This function is used to determine // size of the (possible) item at 'ea' void *ud, // user-defined data ea_t ea, // address of the item asize_t maxsize) // maximal size of the item { PYW_GIL_GET; // Returns: 0-no such item can be created/displayed // this callback is required only for varsize datatypes py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; newref_t py_result( PyObject_CallMethod( _this->py_self, (char *)S_CALC_ITEM_SIZE, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(maxsize))); if ( PyW_ShowCbErr(S_CALC_ITEM_SIZE) || py_result == NULL ) return 0; uint64 num = 0; PyW_GetNumber(py_result.o, &num); return asize_t(num); }
static bool idaapi s_print( // convert to colored string void *ud, // user-defined data qstring *out, // output buffer. may be NULL const void *value, // value to print. may not be NULL asize_t size, // size of value in bytes ea_t current_ea, // current address (BADADDR if unknown) int operand_num, // current operand number int dtid) // custom data type id { PYW_GIL_GET; // Build a string from the buffer newref_t py_value(PyString_FromStringAndSize( (const char *)value, Py_ssize_t(size))); if ( py_value == NULL ) return false; py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; newref_t py_result(PyObject_CallMethod( _this->py_self, (char *)S_PRINTF, "O" PY_FMT64 "ii", py_value.o, pyul_t(current_ea), operand_num, dtid)); // Error while calling the function? if ( PyW_ShowCbErr(S_PRINTF) || py_result == NULL ) return false; bool ok = false; if ( PyString_Check(py_result.o) ) { Py_ssize_t len; char *buf; if ( out != NULL && PyString_AsStringAndSize(py_result.o, &buf, &len) != -1 ) { out->qclear(); out->append(buf, len); } ok = true; } return ok; }
// may create data? NULL means always may static bool idaapi s_may_create_at( void *ud, // user-defined data ea_t ea, // address of the future item size_t nbytes) // size of the future item { py_custom_data_type_t *_this = (py_custom_data_type_t *)ud; PYW_GIL_GET; newref_t py_result( PyObject_CallMethod( _this->py_self, (char *)S_MAY_CREATE_AT, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(nbytes))); PyW_ShowCbErr(S_MAY_CREATE_AT); return py_result != NULL && PyObject_IsTrue(py_result.o); }
//--------------------------------------------------------------------------- static int idaapi py_visit_patched_bytes_cb( ea_t ea, qoff64_t fpos, uint64 o, uint64 v, void *ud) { PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_result( PyObject_CallFunction( (PyObject *)ud, PY_BV_EA "LKK", bvea_t(ea), fpos, o, v)); PyW_ShowCbErr("visit_patched_bytes"); return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0; }
static void idaapi s_analyze( // analyze custom data format occurrence void *ud, // user-defined data ea_t current_ea, // current address (BADADDR if unknown) int operand_num) // current operand number // this callback can be used to create // xrefs from the current item. // this callback may be missing. { PYW_GIL_GET; py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; newref_t py_result( PyObject_CallMethod( _this->py_self, (char *)S_ANALYZE, PY_FMT64 "i", pyul_t(current_ea), operand_num)); PyW_ShowCbErr(S_ANALYZE); }
static bool idaapi s_scan( // convert from uncolored string void *ud, // user-defined data bytevec_t *value, // output buffer. may be NULL const char *input, // input string. may not be NULL ea_t current_ea, // current address (BADADDR if unknown) int operand_num, // current operand number (-1 if unknown) qstring *errstr) // buffer for error message { PYW_GIL_GET; py_custom_data_format_t *_this = (py_custom_data_format_t *) ud; newref_t py_result( PyObject_CallMethod( _this->py_self, (char *)S_SCAN, "s" PY_FMT64, input, pyul_t(current_ea), operand_num)); // Error while calling the function? if ( PyW_ShowCbErr(S_SCAN) || py_result == NULL) return false; bool ok = false; do { // We expect a tuple(bool, string|None) if ( !PyTuple_Check(py_result.o) || PyTuple_Size(py_result.o) != 2 ) break; borref_t py_bool(PyTuple_GetItem(py_result.o, 0)); borref_t py_val(PyTuple_GetItem(py_result.o, 1)); // Get return code from Python ok = PyObject_IsTrue(py_bool.o); // We expect None or the value (depending on probe) if ( ok ) { // Probe-only? Then okay, no need to extract the 'value' if ( value == NULL ) break; Py_ssize_t len; char *buf; if ( PyString_AsStringAndSize(py_val.o, &buf, &len) != -1 ) { value->qclear(); value->append(buf, len); } } // An error occured? else { // Make sure the user returned (False, String) if ( py_bool.o != Py_False || !PyString_Check(py_val.o) ) { *errstr = "Invalid return value returned from the Python callback!"; break; } // Get the error message *errstr = PyString_AsString(py_val.o); } } while ( false ); return ok; }