bugfixes:

- ph_get_operand_info() would crash IDA sometimes
- idc.SetBptCond() was broken
- idc.GetFunctionCmt() was memory leaking
- Form.GetFieldValue() was failing for numeric controls
- Exceptions originating from the director classes will be displayed

And other minor mods...
This commit is contained in:
elias.bachaalany 2011-06-10 14:54:03 +00:00
parent c29e1ef2da
commit 88aa875c55
15 changed files with 225 additions and 111 deletions

View File

@ -2418,10 +2418,7 @@ def GetLongPrm(offset):
val = _IDC_GetAttr(idaapi.cvar.inf, _INFMAP, offset)
if offset == INF_PROCNAME:
# procName is a character array
# strip it at the terminating zero
idx = val.find('\0')
if idx != -1:
val = val[:idx]
val = idaapi.as_cstr(val)
return val
def GetShortPrm(offset):

View File

@ -155,7 +155,7 @@ Py_ssize_t pyvar_walk_list(
PyObject *PyW_IntVecToPyList(const intvec_t &intvec);
// Converts an Python list to an intvec
void PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec);
bool PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec);
// Returns a reference to a class
PyObject *get_idaapi_attr(const char *attr);

View File

@ -6,7 +6,13 @@ typedef struct
} regval_t;
%ignore dbg;
%ignore register_srcinfo_provider;
%ignore unregister_srcinfo_provider;
%ignore appcall_info_t;
%ignore get_manual_regions;
%ignore internal_appcall;
%ignore internal_cleanup_appcall;
%ignore source_file_t;
%ignore source_item_t;
%ignore srcinfo_provider_t;
@ -15,6 +21,7 @@ typedef struct
%ignore bpt_t::eval_cond;
%ignore bpt_t::write;
%ignore bpt_t::erase;
%ignore bpt_t::cndbody;
%rename (get_manual_regions) py_get_manual_regions;
%ignore set_manual_regions;
%ignore inform_idc_about_debthread;
@ -28,6 +35,22 @@ static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
//</code(py_dbg)>
%}
%extend bpt_t
{
PyObject *condition;
}
%{
PyObject *bpt_t_condition_get(bpt_t *bpt)
{
return PyString_FromString(bpt->cndbody.c_str());
}
void bpt_t_condition_set(bpt_t *bpt, PyObject *val)
{
if ( PyString_Check(val) )
bpt->cndbody = PyString_AsString(val);
}
%}
%inline %{
//<inline(py_dbg)>

View File

@ -3,7 +3,6 @@
// FIXME: Are these really useful?
%ignore iterate_func_chunks;
%ignore get_idasgn_desc;
%ignore get_idasgn_header_by_short_name;
// Kernel-only & unexported symbols
@ -27,8 +26,13 @@
%ignore create_func_eas_array;
%ignore auto_add_func_tails;
%ignore read_tails;
%ignore get_idasgn_desc;
%rename (get_idasgn_desc) py_get_idasgn_desc;
%ignore get_func_cmt;
%rename (get_func_cmt) py_get_func_cmt;
%include "funcs.hpp"
%clear(char *buf);
@ -65,9 +69,10 @@ def get_idasgn_desc(n):
@param n: number of signature in the list (0..get_idasgn_qty()-1)
@return: None on failure or tuple(signame, optlibs)
"""
pass
#</pydoc>
*/
static PyObject *ida_export py_get_idasgn_desc(int n)
static PyObject *py_get_idasgn_desc(int n)
{
char signame[MAXSTR];
char optlibs[MAXSTR];
@ -78,4 +83,31 @@ static PyObject *ida_export py_get_idasgn_desc(int n)
return Py_BuildValue("(ss)", signame, optlibs);
}
//-----------------------------------------------------------------------
/*
#<pydoc>
def get_func_cmt(fn, repeatable):
"""
Retrieve function comment
@param fn: function instance
@param repeatable: retrieve repeatable or non-repeatable comments
@return: None on failure or the comment
"""
pass
#</pydoc>
*/
static PyObject *py_get_func_cmt(func_t *fn, bool repeatable)
{
char *s = get_func_cmt(fn, repeatable);
if ( s == NULL )
{
Py_RETURN_NONE;
}
else
{
PyObject *py_s = PyString_FromString(s);
qfree(s);
return py_s;
}
}
%}

View File

@ -407,7 +407,7 @@ private:
}
// a graph viewer lost focus
void on_lostfocus(graph_viewer_t *gv)
void on_lostfocus(graph_viewer_t * /*gv*/)
{
PYW_GIL_ENSURE;
PyObject *result = PyObject_CallMethod(
@ -700,7 +700,7 @@ private:
self = NULL;
}
static void SelectNode(PyObject *self, int nid)
static void SelectNode(PyObject *self, int /*nid*/)
{
py_graph_t *_this = extract_this(self);
if ( _this == NULL || _this->form == NULL )

View File

@ -153,7 +153,7 @@ class pycvt_t
else if ( (ft > FT_FIRST_NUM && ft < FT_LAST_NUM) && PyW_GetNumber(py_attr, &val.u64) )
; // nothing to be done
// A string array?
else if ( (ft == FT_STRARR || ft == FT_NUM16ARR || FT_CHRARR_STATIC )
else if ( (ft == FT_STRARR || ft == FT_NUM16ARR || ft == FT_CHRARR_STATIC )
&& (PyList_CheckExact(py_attr) || PyW_IsSequenceType(py_attr)) )
{
// Return a reference to the attribute
@ -492,7 +492,7 @@ PyObject *PyW_IntVecToPyList(const intvec_t &intvec)
//---------------------------------------------------------------------------
static int idaapi pylist_to_intvec_cb(
PyObject *py_item,
Py_ssize_t index,
Py_ssize_t /*index*/,
void *ud)
{
intvec_t &intvec = *(intvec_t *)ud;
@ -504,10 +504,10 @@ static int idaapi pylist_to_intvec_cb(
return CIP_OK;
}
void PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec)
bool PyW_PyListToIntVec(PyObject *py_list, intvec_t &intvec)
{
intvec.clear();
(void)pyvar_walk_list(py_list, pylist_to_intvec_cb, &intvec);
return pyvar_walk_list(py_list, pylist_to_intvec_cb, &intvec) != CIP_FAILED;
}
//---------------------------------------------------------------------------
@ -1207,9 +1207,9 @@ int pyvar_to_idcvar(
idc_var->set_int64(PyLong_AsLongLong(attr));
Py_DECREF(attr);
return CIP_OK;
//
// BYREF
//
//
// BYREF
//
case PY_ICID_BYREF:
{
// BYREF always require this parameter
@ -1822,6 +1822,7 @@ import struct
import traceback
import os
import sys
import bisect
import __builtin__
# -----------------------------------------------------------------------
@ -1852,6 +1853,13 @@ PY_ICID_BYREF = 1
PY_ICID_OPAQUE = 2
"""opaque object"""
# Step trace options (used with set_step_trace_options())
ST_OVER_DEBUG_SEG = 0x01
"""step tracing will be disabled when IP is in a debugger segment"""
ST_OVER_LIB_FUNC = 0x02
"""step tracing will be disabled when IP is in a library function"""
# -----------------------------------------------------------------------
class pyidc_opaque_object_t(object):
"""This is the base class for all Python<->IDC opaque objects"""

View File

@ -1,5 +1,9 @@
%ignore debugger_t;
%ignore memory_info_t;
%ignore lowcnd_t;
%ignore lowcnd_vec_t;
%ignore update_bpt_info_t;
%ignore update_bpt_vec_t;
%ignore register_info_t;
%ignore appcall;
%ignore idd_opinfo_t;
@ -355,7 +359,8 @@ static PyObject *dbg_get_name()
{
if ( dbg == NULL )
Py_RETURN_NONE;
return PyString_FromString(dbg->name);
else
return PyString_FromString(dbg->name);
}
//-------------------------------------------------------------------------

View File

@ -421,8 +421,7 @@ static PyObject *ph_get_operand_info(
// Allocate register space
thid_t tid = get_current_thread();
regvals_t regvalues;
regvalues.reserve(dbg->registers_size);
regvalues.resize(dbg->registers_size);
// Read registers
if ( dbg->read_registers(tid, -1, regvalues.begin()) != 1 )
break;
@ -809,22 +808,22 @@ public:
return 0;
}
virtual int is_call_insn(ea_t ea)
virtual int is_call_insn(ea_t /*ea*/)
{
return 0;
}
virtual int is_ret_insn(ea_t ea, bool strict)
virtual int is_ret_insn(ea_t /*ea*/, bool /*strict*/)
{
return 0;
}
virtual PyObject *assemble(
ea_t ea,
ea_t cs,
ea_t ip,
bool use32,
const char *line)
ea_t /*ea*/,
ea_t /*cs*/,
ea_t /*ip*/,
bool /*use32*/,
const char * /*line*/)
{
return NULL;
}
@ -1070,9 +1069,9 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
}
}
}
catch (Swig::DirectorException &)
catch (Swig::DirectorException &e)
{
msg("Exception in IDP Hook function:\n");
msg("Exception in IDP Hook function: %s\n", e.getMessage());
if ( PyErr_Occurred() )
PyErr_Print();
}
@ -1249,9 +1248,9 @@ int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
return proxy->segm_moved(ea, ea2, size);
}
}
catch (Swig::DirectorException &)
catch (Swig::DirectorException &e)
{
msg("Exception in IDB Hook function:\n");
msg("Exception in IDB Hook function: %s\n", e.getMessage());
if (PyErr_Occurred())
{
PyErr_Print();

View File

@ -11,6 +11,10 @@
%rename (del_menu_item) py_del_menu_item;
%ignore vwarning;
%ignore choose_idasgn;
%rename (choose_idasgn) py_choose_idasgn;
%ignore msg;
%rename (msg) py_msg;
@ -105,7 +109,22 @@ void refresh_lists(void)
%inline %{
//<inline(py_kernwin)>
//------------------------------------------------------------------------
static PyObject *py_choose_idasgn()
{
char *name = choose_idasgn();
if ( name == NULL )
{
Py_RETURN_NONE;
}
else
{
PyObject *py_str = PyString_FromString(name);
qfree(name);
return py_str;
}
}
//------------------------------------------------------------------------
/*
@ -416,6 +435,7 @@ class UI_Hooks(object):
@return: Ignored
"""
pass
#</pydoc>
*/
@ -436,7 +456,7 @@ public:
return unhook_from_notification_point(HT_UI, UI_Callback, this);
}
virtual int preprocess(const char *name)
virtual int preprocess(const char * /*name*/)
{
return 0;
}
@ -467,9 +487,9 @@ char *idaapi choose_getl(void *self, uint32 n, char *buf)
{
PYW_GIL_ENSURE;
PyObject *pyres = PyObject_CallMethod(
(PyObject *)self,
"getl",
"l",
(PyObject *)self,
"getl",
"l",
n);
PYW_GIL_RELEASE;
@ -478,7 +498,7 @@ char *idaapi choose_getl(void *self, uint32 n, char *buf)
qstrncpy(buf, "<Empty>", MAXSTR);
else
qstrncpy(buf, res, MAXSTR);
Py_XDECREF(pyres);
return buf;
}
@ -586,18 +606,6 @@ static void formchgcbfa_refresh_field(size_t p_fa, int fid)
return fa->refresh_field(fid);
}
//---------------------------------------------------------------------------
static void formchgcbfa_set_field_value(
size_t p_fa,
int fid,
int ft,
PyObject *py_val,
size_t sz)
{
DECLARE_FORM_ACTIONS;
return fa->refresh_field(fid);
}
//---------------------------------------------------------------------------
static PyObject *formchgcbfa_get_field_value(
size_t p_fa,
@ -609,7 +617,7 @@ static PyObject *formchgcbfa_get_field_value(
switch ( ft )
{
// button - uint32
case 4:
case 4:
{
uint32 val;
if ( fa->get_field_value(fid, &val) )
@ -617,7 +625,7 @@ static PyObject *formchgcbfa_get_field_value(
break;
}
// ushort
case 2:
case 2:
{
ushort val;
if ( fa->get_field_value(fid, &val) )
@ -625,7 +633,7 @@ static PyObject *formchgcbfa_get_field_value(
break;
}
// string label
case 1:
case 1:
{
char val[MAXSTR];
if ( fa->get_field_value(fid, val) )
@ -633,7 +641,7 @@ static PyObject *formchgcbfa_get_field_value(
break;
}
// string input
case 3:
case 3:
{
qstring val;
val.resize(sz + 1);
@ -641,7 +649,7 @@ static PyObject *formchgcbfa_get_field_value(
return PyString_FromString(val.begin());
break;
}
case 5:
case 5:
{
intvec_t intvec;
// Returned as 1-base
@ -653,6 +661,54 @@ static PyObject *formchgcbfa_get_field_value(
return PyW_IntVecToPyList(intvec);
}
break;
}
// Numeric control
case 6:
{
union
{
sel_t sel;
sval_t sval;
uval_t uval;
ulonglong ull;
} u;
switch ( sz )
{
case 'S': // sel_t
{
if ( fa->get_field_value(fid, &u.sel) )
return Py_BuildValue(PY_FMT64, u.sel);
break;
}
// sval_t
case 'n':
case 'N':
case 'D':
case 'O':
case 'Y':
case 'H':
{
if ( fa->get_field_value(fid, &u.sval) )
return Py_BuildValue(PY_SFMT64, u.sval);
break;
}
case 'L': // uint64
case 'l': // int64
{
if ( fa->get_field_value(fid, &u.ull) )
return Py_BuildValue(sz == 'L' ? "K" : "L", u.ull);
break;
}
case 'M': // uval_t
case '$': // ea_t
{
if ( fa->get_field_value(fid, &u.uval) )
return Py_BuildValue(PY_FMT64, u.uval);
break;
}
}
break;
}
}
Py_RETURN_NONE;
@ -670,39 +726,44 @@ static bool formchgcbfa_set_field_value(
switch ( ft )
{
// button - uint32
case 4:
case 4:
{
uint32 val = PyLong_AsUnsignedLong(py_val);
return fa->set_field_value(fid, &val);
}
// ushort
case 2:
case 2:
{
ushort val = PyLong_AsUnsignedLong(py_val) & 0xffff;
return fa->set_field_value(fid, &val);
}
// strings
case 3:
case 1:
case 3:
case 1:
return fa->set_field_value(fid, PyString_AsString(py_val));
// intvec_t
case 5:
case 5:
{
intvec_t intvec;
// Passed as 0-based
PyW_PyListToIntVec(py_val, intvec);
if ( !PyW_PyListToIntVec(py_val, intvec) )
break;
// Make 1-based
for ( intvec_t::iterator it=intvec.begin(); it != intvec.end(); ++it)
(*it)++;
bool ok = fa->set_field_value(fid, &intvec);
return ok;
return fa->set_field_value(fid, &intvec);
}
// Numeric
case 6:
{
uint64 num;
if ( PyW_GetNumber(py_val, &num) )
return fa->set_field_value(fid, &num);
}
// unknown
default:
return false;
}
return false;
}
#undef DECLARE_FORM_ACTIONS
@ -739,9 +800,9 @@ int idaapi UI_Callback(void *ud, int notification_code, va_list va)
break;
}
}
catch (Swig::DirectorException &)
catch (Swig::DirectorException &e)
{
msg("Exception in UI Hook function:\n");
msg("Exception in UI Hook function: %s\n", e.getMessage());
if ( PyErr_Occurred() )
PyErr_Print();
}
@ -768,7 +829,7 @@ bool idaapi py_menu_item_callback(void *userdata)
return false;
}
bool ret = PyObject_IsTrue(result);
bool ret = PyObject_IsTrue(result) != 0;
Py_DECREF(result);
return ret;
}
@ -2331,7 +2392,7 @@ private:
}
// The user clicked
static bool idaapi s_cv_click(TCustomControl *cv, int shift, void *ud)
static bool idaapi s_cv_click(TCustomControl * /*cv*/, int shift, void *ud)
{
customviewer_t *_this = (customviewer_t *)ud;
return _this->on_click(shift);
@ -3675,7 +3736,7 @@ class Form(object):
def __init__(self, tp, value):
cls = Form.fieldtype_to_ctype(tp, self.DefI64)
if cls is None:
raise TypeError("Invalid field type: %s" % tp)
raise TypeError("Invalid numeric field type: %s" % tp)
# Get a pointer type to the ctype type
self.arg = pointer(cls(value))
@ -4566,7 +4627,7 @@ class Form(object):
Converts a control object to a tuple containing the field id
and the associated buffer size
"""
# Input control depend on the associate buffer size (supplied by the user)
# Input control depend on the associated buffer size (supplied by the user)
# Make sure you check instances types taking into account inheritance
if isinstance(ctrl, Form.EmbeddedChooserControl):
@ -4578,6 +4639,9 @@ class Form(object):
return (3, min(_idaapi.MAXSTR, ctrl.size))
elif isinstance(ctrl, Form.ColorInput):
return (4, 0)
elif isinstance(ctrl, Form.NumericInput):
# Pass the numeric control type
return (6, ord(ctrl.tp[0]))
elif isinstance(ctrl, Form.InputControl):
return (1, ctrl.size)
else:

View File

@ -11,7 +11,6 @@
%ignore get_struct_operand;
%ignore set_debug_names;
%ignore get_debug_name;
%ignore get_debug_names;
%ignore nameVa;
// Unexported & kernel-only
@ -31,8 +30,11 @@
%ignore is_exit_name;
%ignore dummy_name_ea;
%ignore get_debug_names;
%rename (get_debug_names) py_get_debug_names;
%inline %{
//<inline(py_name)>
//------------------------------------------------------------------------
PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
{
// Get debug names
@ -50,11 +52,12 @@ PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
}
return dict;
}
//------------------------------------------------------------------------
//</inline(py_name)>
%}
%pythoncode %{
import bisect
#<pycode(py_name)>
class NearestName:
"""
@ -103,5 +106,6 @@ class NearestName:
raise StopIteration
return self._get_item(index)
#</pycode(py_name)>
%}
%include "name.hpp"

View File

@ -8,6 +8,8 @@
%ignore reloc_info_t; // swig under mac chokes on this
%ignore qmutex_create;
%ignore qiterator;
%ignore qrefcnt_t;
%ignore qmutex_free;
%ignore qmutex_lock;
%ignore qmutex_t;

View File

@ -9,6 +9,6 @@
// Add a get_member() member function to struc_t.
// This helps to access the members array in the class.
%extend struc_t {
member_t * get_member(int index) { return &(self->members[index]); }
member_t *get_member(int index) { return &(self->members[index]); }
}

View File

@ -1,20 +1,20 @@
// Convert an incoming Python list to a tid_t[] array
// Convert an incoming Python list to a tid_t[] array
%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) {
int i, len;
if (!PySequence_Check($input))
if (!PySequence_Check($input))
{
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
return NULL;
}
/* Cap the number of elements to copy */
/* Cap the number of elements to copy */
len = PySequence_Length($input) < $1_dim0 ? PySequence_Length($input) : $1_dim0;
for (i =0; i < len; i++)
for (i =0; i < len; i++)
{
PyObject *o = PySequence_GetItem($input,i);
if (!PyLong_Check(o))
if (!PyLong_Check(o))
{
Py_XDECREF(o);
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
@ -32,11 +32,7 @@
$1 = MAXSTR;
}
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
#ifdef __cplusplus
$1 = ($1_ltype) new char[MAXSTR+1];
#else
$1 = ($1_ltype) malloc(MAXSTR+1);
#endif
$1 = ($1_ltype) qalloc(MAXSTR+1);
}
%typemap(out) ssize_t {
/* REMOVING ssize_t return value in $symname */
@ -51,11 +47,7 @@
Py_INCREF(Py_None);
resultobj = Py_None;
}
#ifdef __cplusplus
delete [] $1;
#else
free($1);
#endif
qfree($1);
}
%enddef
@ -85,11 +77,7 @@
$1 = MAXSPECSIZE;
}
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
#ifdef __cplusplus
$1 = (char *) new char[MAXSPECSIZE+1];
#else
$1 = (char *) malloc(MAXSPECSIZE+1);
#endif
$1 = (char *) qalloc(MAXSPECSIZE+1);
}
%typemap(out) ssize_t {
/* REMOVING ssize_t return value in $symname */
@ -104,11 +92,7 @@
Py_INCREF(Py_None);
resultobj = Py_None;
}
#ifdef __cplusplus
delete [] (char *)$1;
#else
free((char *)$1);
#endif
qfree((void *)$1);
}
%enddef
@ -118,11 +102,7 @@
$1 = &ressize;
}
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
#ifdef __cplusplus
$1 = (char *) new char[MAXSPECSIZE+1];
#else
$1 = (char *) malloc(MAXSPECSIZE+1);
#endif
$1 = (char *) qalloc(MAXSPECSIZE+1);
}
%typemap(out) ssize_t {
/* REMOVING ssize_t return value in $symname */
@ -137,11 +117,7 @@
Py_INCREF(Py_None);
resultobj = Py_None;
}
#ifdef __cplusplus
delete [] (char *)$1;
#else
free((char *)$1);
#endif
qfree((void *)$1);
}
%enddef

View File

@ -150,6 +150,10 @@
%ignore regobj_t;
%ignore build_func_type;
%ignore append_type_name;
%ignore for_all_types_ex;
%ignore pdb2ti;
%include "typeinf.hpp"
// Custom wrappers

View File

@ -414,7 +414,7 @@ static PyObject *py_get_global_cmd_link()
}
//-------------------------------------------------------------------------
PyObject *insn_t_is_canon_insn(int itype)
static PyObject *insn_t_is_canon_insn(int itype)
{
if ( ph.is_canon_insn(itype) )
Py_RETURN_TRUE;
@ -423,13 +423,13 @@ PyObject *insn_t_is_canon_insn(int itype)
}
//-------------------------------------------------------------------------
PyObject *insn_t_get_canon_feature(int itype)
static PyObject *insn_t_get_canon_feature(int itype)
{
return Py_BuildValue("I", ph.is_canon_insn(itype) ? ph.instruc[itype-ph.instruc_start].feature : 0);
}
//-------------------------------------------------------------------------
PyObject *insn_t_get_canon_mnem(int itype)
static PyObject *insn_t_get_canon_mnem(int itype)
{
if ( ph.is_canon_insn(itype) )
return Py_BuildValue("s", ph.instruc[itype-ph.instruc_start].name);