Files
2025-03-13 16:17:53 +01:00

522 lines
14 KiB
C++

#ifndef __PY_IDP__
#define __PY_IDP__
//-------------------------------------------------------------------------
//<inline(py_idp)>
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
static PyObject *AssembleLine(
ea_t ea,
ea_t cs,
ea_t ip,
bool use32,
const char *line)
{
if ( line != nullptr )
{
char buf[MAXSTR];
int inslen = processor_t::assemble((uchar *)buf, ea, cs, ip, use32, line);
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( inslen > 0 )
return PyBytes_FromStringAndSize(buf, inslen);
}
Py_RETURN_NONE;
}
//---------------------------------------------------------------------------
bool assemble(
ea_t ea,
ea_t cs,
ea_t ip,
bool use32,
const char *line)
{
char buf[MAXSTR];
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = false;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
int inslen = processor_t::assemble((uchar *)buf, ea, cs, ip, use32, line);
if ( inslen > 0 )
{
patch_bytes(ea, buf, inslen);
rc = true;
}
SWIG_PYTHON_THREAD_END_ALLOW;
return rc;
}
//-------------------------------------------------------------------------
static size_t ph_get_id()
{
return PH.id;
}
//-------------------------------------------------------------------------
static size_t ph_get_version()
{
return PH.version;
}
//-------------------------------------------------------------------------
static size_t ph_get_flag()
{
return PH.flag;
}
//-------------------------------------------------------------------------
static size_t ph_get_cnbits()
{
return PH.cnbits;
}
//-------------------------------------------------------------------------
static size_t ph_get_dnbits()
{
return PH.dnbits;
}
//-------------------------------------------------------------------------
static size_t ph_get_reg_first_sreg()
{
return PH.reg_first_sreg;
}
//-------------------------------------------------------------------------
static size_t ph_get_reg_last_sreg()
{
return PH.reg_last_sreg;
}
//-------------------------------------------------------------------------
static size_t ph_get_segreg_size()
{
return PH.segreg_size;
}
//-------------------------------------------------------------------------
static size_t ph_get_reg_code_sreg()
{
return PH.reg_code_sreg;
}
//-------------------------------------------------------------------------
static size_t ph_get_reg_data_sreg()
{
return PH.reg_data_sreg;
}
//-------------------------------------------------------------------------
static size_t ph_get_icode_return()
{
return PH.icode_return;
}
//-------------------------------------------------------------------------
static size_t ph_get_instruc_start()
{
return PH.instruc_start;
}
//-------------------------------------------------------------------------
static size_t ph_get_instruc_end()
{
return PH.instruc_end;
}
//-------------------------------------------------------------------------
static size_t ph_get_tbyte_size()
{
return PH.tbyte_size;
}
//-------------------------------------------------------------------------
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
PYW_GIL_CHECK_LOCKED_SCOPE();
processor_t &ph = PH;
PyObject *py_result = PyList_New(ph.instruc_end - ph.instruc_start);
for ( const instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end;
p != end;
++p )
{
PyList_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature));
}
return py_result;
}
//-------------------------------------------------------------------------
static PyObject *ph_get_regnames()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
processor_t &ph = PH;
PyObject *py_result = PyList_New(ph.regs_num);
for ( Py_ssize_t i=0; i < ph.regs_num; i++ )
PyList_SetItem(py_result, i, PyUnicode_FromString(ph.reg_names[i]));
return py_result;
}
//---------------------------------------------------------------------------
static const regval_t *idaapi _py_getreg(
const char *name,
const regval_t *regvals);
//-------------------------------------------------------------------------
static PyObject *ph_get_operand_info(
ea_t ea,
int n)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool ok = false;
idd_opinfo_t opinf;
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
do
{
if ( dbg == nullptr || n == - 1 )
break;
// Allocate register space
thid_t tid = get_current_thread();
regvals_t regvalues;
regvalues.resize(dbg->nregisters);
// Read registers
if ( get_reg_vals(tid, -1, regvalues.begin()) != DRC_OK )
break;
// Call the processor module
if ( processor_t::notify(processor_t::ev_get_idd_opinfo,
&opinf,
ea,
n,
tid,
_py_getreg,
regvalues.begin()) == 0 )
{
break;
}
ok = true;
} while (false);
SWIG_PYTHON_THREAD_END_ALLOW;
if ( ok )
return Py_BuildValue("(i" PY_BV_EA "Kii)",
opinf.modified,
bvea_t(opinf.ea),
opinf.value.ival,
opinf.debregidx,
opinf.value_size);
else
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
static void ph_calcrel(bytevec_t *out_relbits, size_t *out_consumed, ea_t ea)
{
processor_t::calcrel(out_relbits, out_consumed, ea);
}
//-------------------------------------------------------------------------
static ssize_t ph_find_reg_value(uval_t *out, const insn_t &insn, int reg)
{
return processor_t::find_reg_value(out, insn, reg);
}
//-------------------------------------------------------------------------
static ssize_t ph_find_op_value(uval_t *out, const insn_t &insn, int op)
{
return processor_t::find_op_value(out, insn, op);
}
//-------------------------------------------------------------------------
static ssize_t ph_get_reg_accesses(
reg_accesses_t *accvec,
const insn_t &insn,
int flags)
{
return processor_t::get_reg_accesses(accvec, insn, flags);
}
//-------------------------------------------------------------------------
static ssize_t ph_get_abi_info(
qstrvec_t *abi_names,
qstrvec_t *abi_opts,
comp_t comp)
{
return processor_t::get_abi_info(abi_names, abi_opts, comp);
}
//---------------------------------------------------------------------------
// IDP hooks
//---------------------------------------------------------------------------
// Necessary forward declarations; idp.hpp itself doesn't need them.
struct mblock_t;
struct proc_def;
struct libfunc_t;
ssize_t idaapi IDP_Callback(void *ud, int notification_code, va_list va);
struct IDP_Hooks : public hooks_base_t
{
// hookgenIDP:methodsinfo_decl
IDP_Hooks(uint32 _flags=0, uint32 _hkcb_flags=HKCB_GLOBAL)
: hooks_base_t("ida_idp.IDP_Hooks", IDP_Callback, HT_IDP, _flags, _hkcb_flags) {}
bool hook() { return hooks_base_t::hook(); }
bool unhook() { return hooks_base_t::unhook(); }
#ifdef TESTABLE_BUILD
PyObject *dump_state(bool assert_all_reimplemented=false) { return hooks_base_t::dump_state(mappings, mappings_size, assert_all_reimplemented); }
#endif
// hookgenIDP:methods
ssize_t dispatch(int code, va_list va)
{
ssize_t ret = 0;
switch ( code )
{
// hookgenIDP:notifications
}
return ret;
}
protected:
static PyObject *new_PyObject_from_idpopt_value(
int value_type,
const void *value)
{
switch ( value_type )
{
case IDPOPT_STR:
return PyUnicode_FromString((const char *) value);
case IDPOPT_NUM:
#ifdef __EA64__
return PyLong_FromLongLong(*(const uval_t *) value);
#else
return PyLong_FromLong(*(const uval_t *) value);
#endif
case IDPOPT_BIT:
return PyLong_FromLong(*(const int *) value);
case IDPOPT_I64:
return PyLong_FromLongLong(*(const int64 *) value);
default:
return nullptr;
}
}
private:
static ssize_t bool_to_insn_t_size(bool in, const insn_t *insn) { return in ? insn->size : 0; }
static ssize_t bool_to_1or0(bool in) { return in ? 1 : 0; }
static ssize_t cm_t_to_ssize_t(cm_t cm) { return ssize_t(cm); }
static bool _handle_qstring_output(PyObject *o, qstring *buf)
{
bool is_str = o != nullptr && PyUnicode_Check(o);
if ( is_str && buf != nullptr )
PyUnicode_as_qstring(buf, o);
Py_XDECREF(o);
return is_str;
}
static ssize_t handle_custom_mnem_output(PyObject *o, qstring *out, const insn_t *)
{
return _handle_qstring_output(o, out) && !out->empty() ? 1 : 0;
}
static ssize_t handle_assemble_output(
PyObject *o,
uchar *bin,
ea_t /*ea*/,
ea_t /*cs*/,
ea_t /*ip*/,
bool /*use32*/,
const char * /*line*/)
{
ssize_t rc = 0;
if ( o != nullptr && PyBytes_Check(o) )
{
char *s;
Py_ssize_t len = 0;
if ( PyBytes_AsStringAndSize(o, &s, &len) != -1 )
{
if ( len > MAXSTR )
len = MAXSTR;
memcpy(bin, s, len);
}
rc = ssize_t(len);
}
Py_XDECREF(o);
return rc;
}
static ssize_t handle_get_reg_name_output(PyObject *o, qstring *buf, int /*reg*/, size_t /*width*/, int /*reghi*/)
{
return _handle_qstring_output(o, buf) ? buf->length() : 0;
}
static ssize_t handle_decorate_name3_output(PyObject *o, qstring *outbuf, const char * /*name*/, bool /*mangle*/, int /*cc*/, const tinfo_t * /*type*/)
{
return _handle_qstring_output(o, outbuf) ? 1 : 0;
}
static ssize_t handle_delay_slot_insn_output(PyObject *o, ea_t *pea, bool *pbexec, bool *pfexec)
{
if ( PySequence_Check(o) && PySequence_Size(o) == 3 )
{
newref_t py_ea(PySequence_GetItem(o, 0));
newref_t py_bexec(PySequence_GetItem(o, 1));
newref_t py_fexec(PySequence_GetItem(o, 2));
uint64 nea = 0;
if ( PyW_GetNumber(py_ea.o, &nea)
&& PyBool_Check(py_bexec.o)
&& PyBool_Check(py_fexec.o) )
{
if ( pea != nullptr )
*pea = nea;
if ( pbexec != nullptr )
*pbexec = py_bexec.o == Py_True;
if ( pfexec != nullptr )
*pfexec = py_fexec.o == Py_True;
return 1;
}
}
return -1;
}
static ssize_t handle_use_regarg_type_output(PyObject *o, int *idx, ea_t, const funcargvec_t *)
{
ssize_t rc = 0;
if ( PySequence_Check(o) && PySequence_Size(o) == 2 )
{
newref_t py_rc(PySequence_GetItem(o, 0));
newref_t py_idx(PySequence_GetItem(o, 1));
if ( PyLong_Check(py_rc.o) && PyLong_Check(py_idx.o) )
{
rc = PyLong_AsLong(py_rc.o);
*idx = PyLong_AsLong(py_idx.o);
}
}
return rc;
}
static ssize_t handle_demangle_name_output(
PyObject *o,
int32 *out_res,
qstring *out,
const char * /*name*/,
uint32 /*disable_mask*/,
demreq_type_t /*demreq*/)
{
ssize_t rc = 0;
if ( PySequence_Check(o) && PySequence_Size(o) == 3 )
{
newref_t py_rc(PySequence_GetItem(o, 0));
newref_t py_out(PySequence_GetItem(o, 1));
newref_t py_out_res(PySequence_GetItem(o, 2));
qstring qs;
if ( PyLong_Check(py_rc.o)
&& PyLong_Check(py_out_res.o)
&& PyUnicode_Check(py_out.o)
&& PyUnicode_as_qstring(&qs, py_out.o) )
{
rc = PyLong_AsLong(py_rc.o);
*out_res = PyLong_AsLong(py_out_res.o);
if ( out != nullptr )
out->swap(qs);
}
}
return rc;
}
static ssize_t handle_find_value_output(
PyObject *o,
uval_t *out,
const insn_t * /*pinsn*/,
int /*reg*/)
{
uint64 num;
ssize_t rc = PyW_GetNumber(o, &num);
if ( rc )
*out = num;
return rc;
}
static ssize_t handle_get_autocmt_output(
PyObject *o,
qstring *buf,
const insn_t * /*pinsn*/)
{
return PyUnicode_Check(o) && PyUnicode_as_qstring(buf, o);
}
static ssize_t handle_get_operand_string_output(
PyObject *o,
qstring *buf,
const insn_t * /*pinsn*/,
int /*opnum*/)
{
return PyUnicode_Check(o) && PyUnicode_as_qstring(buf, o);
}
};
//-------------------------------------------------------------------------
static PyObject *_wrap_addr_in_pycapsule(void *addr);
PyObject *get_idp_notifier_addr(PyObject *)
{
return _wrap_addr_in_pycapsule((void *) IDP_Callback);
}
//-------------------------------------------------------------------------
PyObject *get_idp_notifier_ud_addr(IDP_Hooks *hooks)
{
return _wrap_addr_in_pycapsule(hooks);
}
//-------------------------------------------------------------------------
inline bool delay_slot_insn(ea_t *ea, bool *bexec, bool *fexec)
{
processor_t &ph = PH;
return ph.delay_slot_insn(ea, bexec, fexec);
}
//-------------------------------------------------------------------------
inline const char *get_reg_info(const char *regname, bitrange_t *bitrange)
{
processor_t &ph = PH;
return ph.get_reg_info(regname, bitrange);
}
//-------------------------------------------------------------------------
inline size_t sizeof_ldbl(void)
{
processor_t &ph = PH;
return ph.sizeof_ldbl();
}
//</inline(py_idp)>
//-------------------------------------------------------------------------
//<code(py_idp)>
// hookgenIDP:methodsinfo_def
//-------------------------------------------------------------------------
static PyObject *_wrap_addr_in_pycapsule(void *addr)
{
return PyCapsule_New(addr, VALID_CAPSULE_NAME, nullptr);
}
//-------------------------------------------------------------------------
ssize_t idaapi IDP_Callback(void *ud, int code, va_list va)
{
// hookgenIDP:safecall=IDP_Hooks
}
//-------------------------------------------------------------------------
static const regval_t *idaapi _py_getreg(
const char *name,
const regval_t *regvals)
{
for ( int i=dbg->nregisters - 1; i >= 0; i-- )
{
if ( strieq(name, dbg->regs(i).name) )
return &regvals[i];
}
static regval_t rv;
return &rv;
}
//-------------------------------------------------------------------------
//</code(py_idp)>
//-------------------------------------------------------------------------
#endif