/* header: typeinf.hpp #<pydoc> def apply_type_to_stkarg(op, v, type, name): """ Apply type information to a stack variable @param op: reference to instruction operand @param v: immediate value in the operand (usually op.addr) @param type: type string. Retrieve from idc.ParseType("type string", flags)[1] @param name: stack variable name @return: Boolean """ pass #</pydoc> */ bool py_apply_type_to_stkarg( PyObject *py_op, PyObject *py_uv, PyObject *py_type, const char *name) { uint64 v; PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *op = op_t_get_clink(py_op); if ( op == NULL || !PyW_GetNumber(py_uv, &v) || !PyString_Check(py_type)) { return false; } else { const type_t *t = (type_t *) PyString_AsString(py_type); tinfo_t tif; tif.deserialize(idati, &t); borref_t br(py_op); bool rc; Py_BEGIN_ALLOW_THREADS; rc = apply_tinfo_to_stkarg(*op, uval_t(v), tif, name); Py_END_ALLOW_THREADS; return rc; } }
/* header: frame.hpp #<pydoc> def add_stkvar3(op, v, flags): """ Automatically add stack variable if doesn't exist Processor modules should use ua_stkvar2() @param op: reference to instruction operand @param v: immediate value in the operand (usually op.addr) @param flags: combination of STKVAR_... constants @return: Boolean """ pass #</pydoc> */ bool py_add_stkvar3(PyObject *py_op, PyObject *py_v, int flags) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *op = op_t_get_clink(py_op); uint64 v; return ( op == NULL || !PyW_GetNumber(py_v, &v) || !add_stkvar3(*op, sval_t(v), flags)) ? false : true; }
/* #<pydoc> def OutImmChar(op, outflags = 0): """ Output operand value as a commented character constant @param op: operand (of type op_t) @return: None """ pass #</pydoc> */ static void py_OutImmChar(PyObject *x) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *op = op_t_get_clink(x); if ( op != NULL ) OutImmChar(*op); }
/* #<pydoc> def dbg_read_memory(ea, sz): """ Reads from the debugee's memory at the specified ea @return: - The read buffer (as a string) - Or None on failure """ pass #</pydoc> */ static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz) { PYW_GIL_CHECK_LOCKED_SCOPE(); uint64 ea, sz; if ( !dbg_can_query() || !PyW_GetNumber(py_ea, &ea) || !PyW_GetNumber(py_sz, &sz) ) Py_RETURN_NONE; // Create a Python string PyObject *ret = PyString_FromStringAndSize(NULL, Py_ssize_t(sz)); if ( ret == NULL ) Py_RETURN_NONE; // Get the internal buffer Py_ssize_t len; char *buf; PyString_AsStringAndSize(ret, &buf, &len); if ( (size_t)read_dbg_memory(ea_t(ea), buf, size_t(sz)) != sz ) { // Release the string on failure Py_DECREF(ret); // Return None on failure Py_RETURN_NONE; } return ret; }
static PyObject *py_add_menu_item( const char *menupath, const char *name, const char *hotkey, int flags, PyObject *pyfunc, PyObject *args) { PYW_GIL_CHECK_LOCKED_SCOPE(); bool no_args; // No slash in the menu path? const char *p = strrchr(menupath, '/'); if ( p == NULL ) Py_RETURN_NONE; 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.append(menupath, p - menupath + 1); ctx->menupath.append(name); // Save callback data ctx->cb_data = cb_data; // Return context to user return PyCObject_FromVoidPtr(ctx, NULL); }
//------------------------------------------------------------------------- // callback for enumerating imports // ea: import address // name: import name (NULL if imported by ordinal) // ord: import ordinal (0 for imports by name) // param: user parameter passed to enum_import_names() // return: 1-ok, 0-stop enumeration static int idaapi py_import_enum_cb( ea_t ea, const char *name, uval_t ord, void *param) { // If no name, try to get the name associated with the 'ea'. It may be coming from IDS char name_buf[MAXSTR]; if ( name == NULL ) name = get_true_name(BADADDR, ea, name_buf, sizeof(name_buf)); PYW_GIL_CHECK_LOCKED_SCOPE(); ref_t py_name; if ( name == NULL ) py_name = borref_t(Py_None); else py_name = newref_t(PyString_FromString(name)); newref_t py_ord(Py_BuildValue(PY_FMT64, pyul_t(ord))); newref_t py_ea(Py_BuildValue(PY_FMT64, pyul_t(ea))); newref_t py_result( PyObject_CallFunctionObjArgs( (PyObject *)param, py_ea.o, py_name.o, py_ord.o, NULL)); return py_result != NULL && PyObject_IsTrue(py_result.o) ? 1 : 0; }
//------------------------------------------------------------------------- PyObject *py_tag_addr(ea_t ea) { char buf[100]; tag_addr(buf, buf + sizeof(buf), ea); PYW_GIL_CHECK_LOCKED_SCOPE(); return PyString_FromString(buf); }
/* #<pydoc> def set_user_defined_prefix(width, callback): """ User-defined line-prefixes are displayed just after the autogenerated line prefixes. In order to use them, the plugin should call the following function to specify its width and contents. @param width: the width of the user-defined prefix @param callback: a get_user_defined_prefix callback to get the contents of the prefix. Its arguments: ea - linear address lnnum - line number indent - indent of the line contents (-1 means the default instruction) indent and is used for instruction itself. see explanations for printf_line() line - the line to be generated. the line usually contains color tags this argument can be examined to decide whether to generated the prefix bufsize- the maximum allowed size of the output buffer It returns a buffer of size < bufsize In order to remove the callback before unloading the plugin, specify the width = 0 or the callback = None """ pass #</pydoc> */ static PyObject *py_set_user_defined_prefix(size_t width, PyObject *pycb) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( width == 0 || pycb == Py_None ) { // Release old callback reference Py_XDECREF(py_get_user_defined_prefix); // ...and clear it py_get_user_defined_prefix = NULL; // Uninstall user defind prefix set_user_defined_prefix(0, NULL); } else if ( PyCallable_Check(pycb) ) { // Release old callback reference Py_XDECREF(py_get_user_defined_prefix); // Copy new callback and hold a reference py_get_user_defined_prefix = pycb; Py_INCREF(py_get_user_defined_prefix); set_user_defined_prefix(width, s_py_get_user_defined_prefix); } else { Py_RETURN_FALSE; } Py_RETURN_TRUE; }
//------------------------------------------------------------------------- PyObject *py_tag_addr(ea_t ea) { qstring tag; tag_addr(&tag, ea); PYW_GIL_CHECK_LOCKED_SCOPE(); return PyString_FromString(tag.begin()); }
//<code(py_bytes)> //------------------------------------------------------------------------ static bool idaapi py_testf_cb(flags_t flags, void *ud) { PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_flags(PyLong_FromUnsignedLong(flags)); newref_t result(PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags.o, NULL)); return result != NULL && PyObject_IsTrue(result.o); }
/* #<pydoc> def tag_remove(colstr): """ Remove color escape sequences from a string @param colstr: the colored string with embedded tags @return: a new string w/o the tags """ pass #</pydoc> */ PyObject *py_tag_remove(const char *instr) { PYW_GIL_CHECK_LOCKED_SCOPE(); qstring qbuf; tag_remove(&qbuf, instr); return PyString_FromString(qbuf.c_str()); }
/* #<pydoc> def enum_import_names(mod_index, callback): """ Enumerate imports from a specific module. Please refer to ex_imports.py example. @param mod_index: The module index @param callback: A callable object that will be invoked with an ea, name (could be None) and ordinal. @return: 1-finished ok, -1 on error, otherwise callback return value (<=0) """ pass #</pydoc> */ static int py_enum_import_names(int mod_index, PyObject *py_cb) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyCallable_Check(py_cb) ) return -1; return enum_import_names(mod_index, py_import_enum_cb, py_cb); }
/* #<pydoc> def generate_disassembly(ea, max_lines, as_stack, notags): """ Generate disassembly lines (many lines) and put them into a buffer @param ea: address to generate disassembly for @param max_lines: how many lines max to generate @param as_stack: Display undefined items as 2/4/8 bytes @return: - None on failure - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing the most important line number and a tuple of generated lines """ pass #</pydoc> */ PyObject *py_generate_disassembly( ea_t ea, int max_lines, bool as_stack, bool notags) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( max_lines <= 0 ) Py_RETURN_NONE; qstring qbuf; char **lines = new char *[max_lines]; int lnnum; int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack); newref_t py_tuple(PyTuple_New(nlines)); for ( int i=0; i<nlines; i++ ) { const char *s = lines[i]; size_t line_len = strlen(s); if ( notags ) { qbuf.resize(line_len+5); tag_remove(s, &qbuf[0], line_len); s = (const char *)&qbuf[0]; } PyTuple_SetItem(py_tuple.o, i, PyString_FromString(s)); qfree(lines[i]); } delete [] lines; return Py_BuildValue("(iO)", lnnum, py_tuple.o); }
/* #<pydoc> def decode_preceding_insn(ea): """ Decodes the preceding instruction. Please check ua.hpp / decode_preceding_insn() @param ea: current ea @return: tuple(preceeding_ea or BADADDR, farref = Boolean) """ pass #</pydoc> */ PyObject *py_decode_preceding_insn(ea_t ea) { bool farref; ea_t r = decode_preceding_insn(ea, &farref); PYW_GIL_CHECK_LOCKED_SCOPE(); return Py_BuildValue("(" PY_FMT64 "i)", pyul_t(r), farref ? 1 : 0); }
/* #<pydoc> def generate_disassembly(ea, max_lines, as_stack, notags): """ Generate disassembly lines (many lines) and put them into a buffer @param ea: address to generate disassembly for @param max_lines: how many lines max to generate @param as_stack: Display undefined items as 2/4/8 bytes @return: - None on failure - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing the most important line number and a tuple of generated lines """ pass #</pydoc> */ PyObject *py_generate_disassembly( ea_t ea, int max_lines, bool as_stack, bool notags) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( max_lines <= 0 ) Py_RETURN_NONE; qstring qbuf; qstrvec_t lines; int lnnum; int nlines = generate_disassembly(&lines, &lnnum, ea, max_lines, as_stack); newref_t py_tuple(PyTuple_New(nlines)); for ( int i=0; i < nlines; i++ ) { const qstring &l = lines[i]; const char *s = l.c_str(); if ( notags ) { tag_remove(&qbuf, l); s = qbuf.c_str(); } PyTuple_SetItem(py_tuple.o, i, PyString_FromString(s)); } return Py_BuildValue("(iO)", lnnum, py_tuple.o); }
// Get definition of a registered custom data format and returns a dictionary static PyObject *py_get_custom_data_type(int dtid) { PYW_GIL_CHECK_LOCKED_SCOPE(); const data_type_t *dt = get_custom_data_type(dtid); if ( dt == NULL ) Py_RETURN_NONE; return py_data_type_to_py_dict(dt); }
// Get definition of a registered custom data format and returns a dictionary static PyObject *py_get_custom_data_format(int dtid, int fid) { PYW_GIL_CHECK_LOCKED_SCOPE(); const data_format_t *df = get_custom_data_format(dtid, fid); if ( df == NULL ) Py_RETURN_NONE; return py_data_format_to_py_dict(df); }
static void insn_t_set_auxpref(PyObject *self, PyObject *value) { PYW_GIL_CHECK_LOCKED_SCOPE(); insn_t *link = insn_t_get_clink(self); if ( link == NULL ) return; link->auxpref = (uint16)PyInt_AsLong(value); }
static void insn_t_set_flags(PyObject *self, PyObject *value) { PYW_GIL_CHECK_LOCKED_SCOPE(); insn_t *link = insn_t_get_clink(self); if ( link == NULL ) return; link->flags = (char)PyInt_AsLong(value); }
static PyObject *op_t_get_specval(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *link = op_t_get_clink(self); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue(PY_FMT64, (pyul_t)link->specval); }
static void op_t_set_reg_phrase(PyObject *self, PyObject *value) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *link = op_t_get_clink(self); if ( link == NULL ) return; link->reg = (uint16)PyInt_AsLong(value); }
static PyObject *op_t_get_reg_phrase(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *link = op_t_get_clink(self); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue("H", link->reg); }
static void op_t_set_type(PyObject *self, PyObject *value) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *link = op_t_get_clink(self); if ( link == NULL ) return; link->type = (optype_t)PyInt_AsLong(value); }
/* #<pydoc> def internal_get_sreg_base(): """ Get the sreg base, for the given thread. @return: The sreg base, or BADADDR on failure. """ pass #</pydoc> */ static ea_t py_internal_get_sreg_base(thid_t tid, int sreg_value) { PYW_GIL_CHECK_LOCKED_SCOPE(); ea_t answer; return internal_get_sreg_base(tid, sreg_value, &answer) < 1 ? BADADDR : answer; }
static void op_t_set_specflag4(PyObject *self, PyObject *value) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *link = op_t_get_clink(self); if ( link == NULL ) return; link->specflag4 = (char)PyInt_AsLong(value); }
static PyObject *insn_t_get_flags(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); insn_t *link = insn_t_get_clink(self); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue("b", link->flags); }
/* #<pydoc> def visit_patched_bytes(ea1, ea2, callable): """ Enumerates patched bytes in the given range and invokes a callable @param ea1: start address @param ea2: end address @param callable: a Python callable with the following prototype: callable(ea, fpos, org_val, patch_val). If the callable returns non-zero then that value will be returned to the caller and the enumeration will be interrupted. @return: Zero if the enumeration was successful or the return value of the callback if enumeration was interrupted. """ pass #</pydoc> */ static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyCallable_Check(py_callable) ) return 0; else return visit_patched_bytes(ea1, ea2, py_visit_patched_bytes_cb, py_callable); }
//------------------------------------------------------------------------ // Wraps the (next|prev)that() static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyCallable_Check(py_callable) ) return BADADDR; else return (next ? next_that : prev_that)(ea, bound, py_testf_cb, py_callable); }
static PyObject *op_t_get_specflag4(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); op_t *link = op_t_get_clink(self); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue("b", link->specflag4); }
static PyObject *insn_t_get_ea(PyObject *self) { PYW_GIL_CHECK_LOCKED_SCOPE(); insn_t *link = insn_t_get_clink(self); if ( link == NULL ) Py_RETURN_NONE; return Py_BuildValue(PY_FMT64, (pyul_t)link->ea); }