cemu-idapython/swig/idp.i
2010-06-28 12:36:40 +00:00

612 lines
17 KiB
OpenEdge ABL

// Ignore the following symbols
%ignore WorkReg;
%ignore AbstractRegister;
%ignore rginfo;
%ignore insn_t::get_canon_mnem;
%ignore insn_t::get_canon_feature;
%ignore insn_t::is_canon_insn;
%ignore bytes_t;
%ignore IDPOPT_STR;
%ignore IDPOPT_NUM;
%ignore IDPOPT_BIT;
%ignore IDPOPT_FLT;
%ignore IDPOPT_I64;
%ignore IDPOPT_OK;
%ignore IDPOPT_BADKEY;
%ignore IDPOPT_BADTYPE;
%ignore IDPOPT_BADVALUE;
%ignore set_options_t;
%ignore read_user_config_file;
%ignore s_preline;
%ignore ca_operation_t;
%ignore _chkarg_cmd;
%ignore ENUM_SIZE;
%ignore asm_t::checkarg_dispatch;
%ignore asm_t::func_header;
%ignore asm_t::func_footer;
%ignore asm_t::get_type_name;
%ignore instruc_t;
%ignore processor_t;
%ignore ph;
%ignore IDB_Callback;
%ignore IDP_Callback;
%ignore free_processor_module;
%ignore read_config_file;
%ignore gen_idb_event;
%include "idp.hpp"
%feature("director") IDB_Hooks;
%feature("director") IDP_Hooks;
%inline %{
int idaapi IDB_Callback(void *ud, int notification_code, va_list va);
class IDB_Hooks
{
public:
virtual ~IDB_Hooks() {};
bool hook() { return hook_to_notification_point(HT_IDB, IDB_Callback, this); }
bool unhook() { return unhook_from_notification_point(HT_IDB, IDB_Callback, this); }
/* Hook functions to override in Python */
virtual int byte_patched(ea_t ea) { return 0; };
virtual int cmt_changed(ea_t, bool repeatable_cmt) { return 0; };
virtual int ti_changed(ea_t ea, const type_t *type, const p_list *fnames) { msg("ti_changed hook not supported yet\n"); return 0; };
virtual int op_ti_changed(ea_t ea, int n, const type_t *type, const p_list *fnames) { msg("op_ti_changed hook not supported yet\n"); return 0; };
virtual int op_type_changed(ea_t ea, int n) { return 0; };
virtual int enum_created(enum_t id) { return 0; };
virtual int enum_deleted(enum_t id) { return 0; };
virtual int enum_bf_changed(enum_t id) { return 0; };
virtual int enum_renamed(enum_t id) { return 0; };
virtual int enum_cmt_changed(enum_t id) { return 0; };
virtual int enum_member_created(enum_t id, const_t cid) { return 0; };
virtual int enum_member_deleted(enum_t id, const_t cid) { return 0; };
virtual int struc_created(tid_t struc_id) { return 0; };
virtual int struc_deleted(tid_t struc_id) { return 0; };
virtual int struc_renamed(struc_t *sptr) { return 0; };
virtual int struc_expanded(struc_t *sptr) { return 0; };
virtual int struc_cmt_changed(tid_t struc_id) { return 0; };
virtual int struc_member_created(struc_t *sptr, member_t *mptr) { return 0; };
virtual int struc_member_deleted(struc_t *sptr, tid_t member_id) { return 0; };
virtual int struc_member_renamed(struc_t *sptr, member_t *mptr) { return 0; };
virtual int struc_member_changed(struc_t *sptr, member_t *mptr) { return 0; };
virtual int thunk_func_created(func_t *pfn) { return 0; };
virtual int func_tail_appended(func_t *pfn, func_t *tail) { return 0; };
virtual int func_tail_removed(func_t *pfn, ea_t tail_ea) { return 0; };
virtual int tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; };
virtual int func_noret_changed(func_t *pfn) { return 0; };
virtual int segm_added(segment_t *s) { return 0; };
virtual int segm_deleted(ea_t startEA) { return 0; };
virtual int segm_start_changed(segment_t *s) { return 0; };
virtual int segm_end_changed(segment_t *s) { return 0; };
virtual int segm_moved(ea_t from, ea_t to, asize_t size) { return 0; };
};
// Assemble an instruction into the database (display a warning if an error is found)
// args:
// ea_t ea - linear address of instruction
// ea_t cs - cs of instruction
// ea_t ip - ip of instruction
// bool use32 - is 32bit segment?
// const char *line - line to assemble
// returns: 1: success, 0: failure
inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
int inslen;
char buf[MAXSTR];
if (ph.notify != NULL)
{
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
if (inslen > 0)
{
patch_many_bytes(ea, buf, inslen);
return 1;
}
}
return 0;
}
//<inline(py_idp)>
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
/*
#<pydoc>
def AssembleLine(ea, cs, ip, use32, line):
"""
Assemble an instruction to a buffer (display a warning if an error is found)
@param ea: linear address of instruction
@param cs: cs of instruction
@param ip: ip of instruction
@param use32: is 32bit segment
@param line: line to assemble
@return:
- None on failure
- or a string containing the assembled instruction
"""
pass
#</pydoc>
*/
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
int inslen;
char buf[MAXSTR];
if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
{
return PyString_FromStringAndSize(buf, inslen);
}
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_tbyte_size():
"""
Returns the 'ph.tbyte_size' field as defined in he processor module
"""
pass
#</pydoc>
*/
static size_t ph_get_tbyte_size()
{
return ph.tbyte_size;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_id():
"""
Returns the 'ph.id' field
"""
pass
#</pydoc>
*/
static size_t ph_get_id()
{
return ph.id;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_instruc():
"""
Returns a list of tuples (instruction_name, instruction_feature) containing the
instructions list as defined in he processor module
"""
pass
#</pydoc>
*/
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start);
for ( instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end;
p != end;
++p )
{
PyTuple_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature));
}
return py_result;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_regnames():
"""
Returns the list of register names as defined in the processor module
"""
pass
#</pydoc>
*/
static PyObject *ph_get_regnames()
{
Py_ssize_t i = 0;
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
return py_result;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
class IDP_Hooks(object):
def custom_ana(self):
"""
Analyzes and decodes an instruction at idaapi.cmd.ea
- cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
- cmd.size must be set to the instruction length
@return: Boolean
- False if the instruction is not recognized
- True if the instruction was decoded. idaapi.cmd should be filled in that case.
"""
pass
def custom_out(self):
"""
Outputs the instruction defined in idaapi.cmd
@return: Boolean (whether this instruction can be outputted or not)
"""
pass
def custom_emu(self):
"""
Emulate instruction, create cross-references, plan to analyze
subsequent instructions, modify flags etc. Upon entrance to this function
all information about the instruction is in 'cmd' structure.
@return: Boolean (whether this instruction has been emulated or not)
"""
pass
def custom_outop(self, op):
"""
Notification to generate operand text.
If False was returned, then the standard operand output function will be called.
The output buffer is inited with init_output_buffer()
and this notification may use out_...() functions to form the operand text
@return: Boolean (whether the operand has been outputted or not)
"""
def custom_mnem(self):
"""
Prints the mnemonic of the instruction defined in idaapi.cmd
@return:
- None: No mnemonic. IDA will use the default mnemonic value if present
- String: The desired mnemonic string
"""
def is_sane_insn(self, no_crefs):
"""
is the instruction sane for the current file type?
@param no_crefs:
- 1: the instruction has no code refs to it.
ida just tries to convert unexplored bytes
to an instruction (but there is no other
reason to convert them into an instruction)
- 0: the instruction is created because
of some coderef, user request or another
weighty reason.
@return: 1-ok, <=0-no, the instruction isn't likely to appear in the program
"""
pass
def is_sane_insn(self, no_crefs):
"""
can a function start here?
@param state: autoanalysis phase
0: creating functions
1: creating chunks
@return: integer (probability 0..100)
"""
pass
#</pydoc>
*/
int idaapi IDP_Callback(void *ud, int notification_code, va_list va);
class IDP_Hooks
{
public:
virtual ~IDP_Hooks()
{
}
bool hook()
{
return hook_to_notification_point(HT_IDP, IDP_Callback, this);
}
bool unhook()
{
return unhook_from_notification_point(HT_IDP, IDP_Callback, this);
}
virtual bool custom_ana()
{
return false;
}
virtual bool custom_out()
{
return false;
}
virtual bool custom_emu()
{
return false;
}
virtual bool custom_outop(PyObject *py_op)
{
return false;
}
virtual PyObject *custom_mnem()
{
return NULL;
}
virtual int is_sane_insn(int no_crefs)
{
return 0;
}
virtual int may_be_func(int state)
{
return 0;
}
};
//</inline(py_idp)>
%}
%{
int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
{
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
ea_t ea, ea2;
bool repeatable_cmt;
/*type_t *type;*/
/* p_list *fnames; */
int n;
enum_t id;
const_t cid;
tid_t struc_id;
struc_t *sptr;
member_t *mptr;
tid_t member_id;
func_t *pfn;
func_t *tail;
segment_t *seg;
asize_t size;
try {
switch (notification_code)
{
case idb_event::byte_patched:
ea = va_arg(va, ea_t);
return proxy->byte_patched(ea);
case idb_event::cmt_changed:
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int);
return proxy->cmt_changed(ea, repeatable_cmt);
#if 0
case idb_event::ti_changed:
ea = va_arg(va, ea_t);
type = va_arg(va, type_t *);
fnames = va_arg(va, fnames);
return proxy->ti_changed(ea, type, fnames);
case idb_event::op_ti_changed:
ea = va_arg(va, ea_t);
n = va_arg(va, int);
type = va_arg(va, type_t *);
fnames = va_arg(va, fnames);
return proxy->op_ti_changed(ea, n, type, fnames);
#endif
case idb_event::op_type_changed:
ea = va_arg(va, ea_t);
n = va_arg(va, int);
return proxy->op_type_changed(ea, n);
case idb_event::enum_created:
id = va_arg(va, enum_t);
return proxy->enum_created(id);
case idb_event::enum_deleted:
id = va_arg(va, enum_t);
return proxy->enum_deleted(id);
case idb_event::enum_bf_changed:
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id);
case idb_event::enum_cmt_changed:
id = va_arg(va, enum_t);
return proxy->enum_cmt_changed(id);
case idb_event::enum_member_created:
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_created(id, cid);
case idb_event::enum_member_deleted:
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_deleted(id, cid);
case idb_event::struc_created:
struc_id = va_arg(va, tid_t);
return proxy->struc_created(struc_id);
case idb_event::struc_deleted:
struc_id = va_arg(va, tid_t);
return proxy->struc_deleted(struc_id);
case idb_event::struc_renamed:
sptr = va_arg(va, struc_t *);
return proxy->struc_renamed(sptr);
case idb_event::struc_expanded:
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr);
case idb_event::struc_cmt_changed:
struc_id = va_arg(va, tid_t);
return proxy->struc_cmt_changed(struc_id);
case idb_event::struc_member_created:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_created(sptr, mptr);
case idb_event::struc_member_deleted:
sptr = va_arg(va, struc_t *);
member_id = va_arg(va, tid_t);
return proxy->struc_member_deleted(sptr, member_id);
case idb_event::struc_member_renamed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_renamed(sptr, mptr);
case idb_event::struc_member_changed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr);
case idb_event::thunk_func_created:
pfn = va_arg(va, func_t *);
return proxy->thunk_func_created(pfn);
case idb_event::func_tail_appended:
pfn = va_arg(va, func_t *);
tail = va_arg(va, func_t *);
return proxy->func_tail_appended(pfn, tail);
case idb_event::func_tail_removed:
pfn = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->func_tail_removed(pfn, ea);
case idb_event::tail_owner_changed:
tail = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea);
case idb_event::func_noret_changed:
pfn = va_arg(va, func_t *);
return proxy->func_noret_changed(pfn);
case idb_event::segm_added:
seg = va_arg(va, segment_t *);
return proxy->segm_added(seg);
case idb_event::segm_deleted:
ea = va_arg(va, ea_t);
return proxy->segm_deleted(ea);
case idb_event::segm_start_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg);
case idb_event::segm_end_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg);
case idb_event::segm_moved:
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t);
size = va_arg(va, asize_t);
return proxy->segm_moved(ea, ea2, size);
}
}
catch (Swig::DirectorException &)
{
msg("Exception in IDP Hook function:\n");
if (PyErr_Occurred())
{
PyErr_Print();
}
}
return 0;
}
//<code(py_idp)>
//-------------------------------------------------------------------------
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
{
IDP_Hooks *proxy = (IDP_Hooks *)ud;
int ret;
try
{
switch ( notification_code )
{
default:
ret = 0;
break;
case processor_t::custom_ana:
ret = proxy->custom_ana() ? 1 + cmd.size : 0;
break;
case processor_t::custom_out:
ret = proxy->custom_out() ? 2 : 0;
break;
case processor_t::custom_emu:
ret = proxy->custom_emu() ? 2 : 0;
break;
case processor_t::custom_outop:
{
op_t *op = va_arg(va, op_t *);
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
if ( py_obj == NULL )
break;
ret = proxy->custom_outop(py_obj) ? 2 : 0;
Py_XDECREF(py_obj);
break;
}
case processor_t::custom_mnem:
{
PyObject *py_ret = proxy->custom_mnem();
if ( py_ret != NULL && PyString_Check(py_ret) )
{
char *outbuffer = va_arg(va, char *);
size_t bufsize = va_arg(va, size_t);
qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize);
ret = 2;
}
else
{
ret = 0;
}
Py_XDECREF(py_ret);
break;
}
case processor_t::is_sane_insn:
{
int no_crefs = va_arg(va, int);
ret = proxy->is_sane_insn(no_crefs);
break;
}
case processor_t::may_be_func:
{
int state = va_arg(va, int);
ret = proxy->may_be_func(state);
break;
}
}
}
catch (Swig::DirectorException &)
{
msg("Exception in IDP Hook function:\n");
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
}
//-------------------------------------------------------------------------
//</code(py_idp)>
%}