Files
idapython-src/tools/deploy/header.i.in
T
Arnaud Diederen 7ee60670f9 Backported fixes
2021-09-13 08:05:30 +02:00

1857 lines
55 KiB
Plaintext

#ifndef __HEADER_I__
#define __HEADER_I__
%{
#ifndef USE_DANGEROUS_FUNCTIONS
#define USE_DANGEROUS_FUNCTIONS 1
#endif
#include <pro.h>
#undef DEPRECATED
#define DEPRECATED
%}
%{
#include "../../../idapy.hpp"
%}
#define SWIG_PYTHON_LEGACY_BOOL 1
%{
class plugin_t;
#ifdef __NT__
idaman __declspec(dllimport) plugin_t PLUGIN;
#else
extern plugin_t PLUGIN;
#endif
%}
// Auto-inserted header
// generate directors for all classes that have virtual methods
%feature("director");
// exceptions
%feature("nodirector") enumplace_t;
%feature("nodirector") generic_linput64_t;
%feature("nodirector") generic_linput_t;
%feature("nodirector") place_t;
%feature("nodirector") idaplace_t;
%feature("nodirector") qrefcnt_obj_t;
%feature("nodirector") qstring_printer_t;
%feature("nodirector") simpleline_place_t;
%feature("nodirector") structplace_t;
%feature("nodirector") qflow_chart_t;
%feature("nodirector") lowertype_helper_t;
%feature("nodirector") ida_lowertype_helper_t;
%warnfilter(473) user_lvar_visitor_t::get_info_mapping_for_saving; // Returning a pointer or reference in a director method is not recommended
// * http://swig.10945.n7.nabble.com/How-to-release-Python-GIL-td5027.html
// * http://stackoverflow.com/questions/1576737/releasing-python-gil-in-c-code
// * http://matt.eifelle.com/2007/11/23/enabling-thread-support-in-swig-and-python/
%nothread; // We don't want SWIG to release the GIL for *every* IDA API call.
// Suppress 'previous definition of XX' warnings
#pragma SWIG nowarn=302
// and others...
#pragma SWIG nowarn=312
#pragma SWIG nowarn=325
#pragma SWIG nowarn=314
#pragma SWIG nowarn=362
#pragma SWIG nowarn=383
#pragma SWIG nowarn=389
#pragma SWIG nowarn=401
#pragma SWIG nowarn=451
#pragma SWIG nowarn=454 // Setting a pointer/reference variable may leak memory
#pragma SWIG nowarn=514 // Director base class 'x' has no virtual destructor.
// Do not create separate wrappers for default arguments
%feature("compactdefaultargs");
%ignore qvector::at(size_t);
%ignore qvector::front;
%ignore qvector::back;
%ignore qlist::iterator::operator--;
%ignore qlist::const_iterator::operator--;
%ignore qlist::reverse_iterator::operator--;
%ignore qlist::const_reverse_iterator::operator--;
// To be used e.g., when a '#define' in the source code
// defines a uint32 value with the highest bit set, so that
// SWiG knows it's not a negative integer.
%define %predefine_uint32_macro(NAME, VALUE)
%rename (NAME) PY_##NAME;
%constant uint32 PY_##NAME = uint32(VALUE);
%ignore NAME;
%enddef
%define %uncomparable_elements_qvector(ELEMENT_TYPE, VECTOR_TYPE)
%ignore qvector<ELEMENT_TYPE>::operator==;
%ignore qvector<ELEMENT_TYPE>::operator!=;
%ignore qvector<ELEMENT_TYPE>::find;
%ignore qvector<ELEMENT_TYPE>::has;
%ignore qvector<ELEMENT_TYPE>::del;
%ignore qvector<ELEMENT_TYPE>::add_unique;
%template(VECTOR_TYPE) qvector<ELEMENT_TYPE>;
%enddef
%ignore wchar2char;
%ignore hit_counter_t;
%ignore reg_hit_counter;
%ignore create_hit_counter;
%ignore hit_counter_timer;
%ignore print_all_counters;
%ignore incrementer_t;
%ignore reloc_info_t; // swig under mac chokes on this
%ignore qmutex_create;
%ignore qiterator;
%ignore qmutex_free;
%ignore qmutex_lock;
%ignore qmutex_t;
%ignore qmutex_unlock;
%ignore qsem_create;
%ignore qsem_free;
%ignore qsem_post;
%ignore qsem_wait;
%ignore qsemaphore_t;
%ignore qthread_cb_t;
%ignore qthread_create;
%ignore qthread_free;
%ignore qthread_join;
%ignore qthread_kill;
%ignore qthread_self;
%ignore qthread_same;
%ignore qthread_t;
%ignore qhandle_t;
%ignore qpipe_create;
%ignore qpipe_read;
%ignore qpipe_write;
%ignore qpipe_close;
%ignore qstrlen;
%ignore qstrcmp;
%ignore qstrstr;
%ignore qstrchr;
%ignore qstrrchr;
%ignore bytevec_t;
%ignore qstrvec_t;
%ignore reloc_info_t;
%ignore relobj_t;
%ignore wchar2char;
%ignore u2cstr;
%ignore c2ustr;
%ignore base64_encode;
%ignore base64_decode;
%ignore replace_tabs;
%ignore utf8_unicode;
%ignore unicode_utf8;
%ignore win_utf2idb;
%ignore char2oem;
%ignore oem2char;
%ignore set_codepages;
%ignore get_codepages;
%ignore convert_codepage;
%ignore test_bit;
%ignore set_bit;
%ignore clear_bit;
%ignore set_all_bits;
%ignore clear_all_bits;
%ignore interval::last;
%ignore interval::overlap;
%ignore interval::includes;
%ignore interval::contains;
%ignore qrotl;
%ignore qrotr;
%ignore setflag;
%ignore read2bytes;
%ignore rotate_left;
//%ignore qswap;
%ignore swap32;
%ignore swap16;
%ignore swap_value;
%ignore qalloc_or_throw;
%ignore qrealloc_or_throw;
%ignore get_buffer_for_sysdir;
%ignore get_buffer_for_winerr;
%ignore call_atexits;
%ignore launch_process_params_t;
%ignore launch_process;
%ignore term_process;
%ignore get_process_exit_code;
%ignore BELOW_NORMAL_PRIORITY_CLASS;
%ignore parse_command_line;
%ignore parse_command_line2;
%ignore parse_command_line3;
%rename (parse_command_line3) py_parse_command_line;
%ignore qgetenv;
%ignore qsetenv;
%ignore qctime;
%ignore qlocaltime;
%ignore qstrftime;
%ignore qstrftime64;
%ignore qstrtok;
%ignore qstrlwr;
%ignore qstrupr;
// Do not move this. We need to override the define from pro.h
#define CASSERT(type)
%pythoncode {
import ida_idaapi
}
#ifdef BC695
%pythoncode {
import sys
_BC695 = sys.modules["__main__"].IDAPYTHON_COMPAT_695_API
if _BC695:
## This is a helper for replacing an existing function, with a wrapper
## providing backwards-compatibility for API 6.95 -- typically because
## the number/types of arguments changed, while the function name itself
## remained the same in 7.0.
## (Note that this shouldn't be used for functions that don't exist
## in the vanilla 7.0 API, such as 'choose_named_type2'.)
def bc695redef(func):
ida_idaapi._BC695.replace_fun(func)
return func
}
#endif // BC695
//---------------------------------------------------------------------
%extend qvector {
inline size_t __len__() const { return $self->size(); }
// The fact that we are returning a const version of a reference to the
// type is what allows SWIG to generate a wrapper for this method, that
// will build an proper object (int, unsigned int, ...) instead
// of a pointer. Remove the 'const', and you'll see that, in
// SWIGINTERN PyObject *_wrap_uvalvec_t___getitem__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
// it will produce this:
// resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_unsigned_int, 0 | 0 );
// instead of that:
// resultobj = SWIG_From_unsigned_SS_int(static_cast< unsigned int >(*result));
inline const T &__getitem__(size_t i) const
{
if ( i >= $self->size() )
throw std::out_of_range("out of bounds access");
return $self->at(i);
}
inline void __setitem__(size_t i, const T &v)
{
if ( i >= $self->size() )
throw std::out_of_range("out of bounds access");
$self->at(i) = v;
}
%pythoncode {
front = ida_idaapi._qvector_front
back = ida_idaapi._qvector_back
__iter__ = ida_idaapi._bounded_getitem_iterator
}
}
//---------------------------------------------------------------------
%extend qlist {
inline size_t __len__() const { return $self->size(); }
inline const T &__getitem__(size_t i) const
{
if ( i >= $self->size() )
throw std::out_of_range("out of bounds access");
qlist<T>::const_iterator it = $self->begin();
for ( size_t _i = 0; _i < i; ++_i )
++it;
return *it;
}
inline void __setitem__(size_t i, const T &v)
{
if ( i >= $self->size() )
throw std::out_of_range("out of bounds access");
qlist<T>::iterator it = $self->begin();
for ( size_t _i = 0; _i < i; ++_i )
++it;
*it = v;
}
inline void insert(size_t i, const T &v)
{
if ( i > $self->size() )
throw std::out_of_range("out of bounds access");
qlist<T>::iterator it = $self->begin();
for ( size_t _i = 0; _i < i; ++_i )
++it;
$self->insert(it, v);
}
inline bool remove(const T &v)
{
qlist<T>::iterator it = $self->begin();
for ( ; it != $self->end(); ++it )
{
if ( *it == v )
{
$self->erase(it);
return true;
}
}
return false;
}
%pythoncode {
front = ida_idaapi._qvector_front
back = ida_idaapi._qvector_back
__iter__ = ida_idaapi._bounded_getitem_iterator
def find(self, item):
it = self.begin()
for i in range(self.size()):
if it.cur == item:
return it
next(it)
def index(self, item):
it = self.begin()
for i in range(self.size()):
if it.cur == item:
return i
next(it)
def at(self, index):
it = self.begin()
for i in range(self.size()):
if i == index:
return it.cur
next(it)
}
}
#if IDAPYTHON_MODULE_hexrays
%define %ida_hexrays_wrapper_exception_catch()
catch ( const vd_failure_t &e ) { __raise_vdf(e); SWIG_fail; }
%enddef
#else
%define %ida_hexrays_wrapper_exception_catch()%enddef
#endif
%define %exception_set_default_handlers()
%exception {
try
{
$action
}
catch ( const std::bad_alloc &ba ) { __raise_ba(ba); SWIG_fail; }
catch ( const std::out_of_range &e ) { __raise_oor(e); SWIG_fail; }
catch ( const interr_exc_t &e ) { __raise_ie(e); SWIG_fail; }%ida_hexrays_wrapper_exception_catch()
catch ( const Swig::DirectorException &e ) { __raise_de(e); SWIG_fail; }
catch ( const std::exception &e ) { __raise_e(e); SWIG_fail; }
catch ( ... ) { __raise_u(); SWIG_fail; }
}
%enddef
%exception_set_default_handlers();
// Enable automatic docstring generation
%feature(autodoc,2);
%{
/* strnlen() arrived on OSX at v10.7. Provide it ourselves if needed. */
#ifdef __MAC__
#ifndef MAC_OS_X_VERSION_10_7
#define MAC_OS_X_VERSION_10_7 1070
#endif
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)
inline size_t strnlen(const char *s, size_t maxlen)
{
const char *found = (const char *) memchr(s, 0, maxlen);
return found != NULL ? size_t(found - s) : maxlen;
}
#endif
#endif
%}
%define SWIG_DECLARE_PY_CLINKED_OBJECT(type)
%inline %{
static PyObject *type##_create()
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyCapsule_New(new type(), VALID_CAPSULE_NAME, NULL);
}
static bool type##_destroy(PyObject *py_obj)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
if ( !PyCapsule_IsValid(py_obj, VALID_CAPSULE_NAME) )
return false;
delete (type *)PyCapsule_GetPointer(py_obj, VALID_CAPSULE_NAME);
return true;
}
static type *type##_get_clink(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return (type *)pyobj_get_clink(self);
}
static PyObject *type##_get_clink_ptr(PyObject *self)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
return PyLong_FromUnsignedLongLong(
PTR2U64(pyobj_get_clink(self)));
}
%}
%enddef
// We use those special maps because SWIG wraps passed PyObject* with 'SwigPtr_PyObject' and 'SwigVar_PyObject'
// They act like autoptr and decrement the reference of the object when the scope ends
// We need to keep a reference outside SWIG and let the caller manage its references
%typemap(directorin) PyObject * "/*%din%*/Py_XINCREF($1_name);$input = $1_name;"
%typemap(directorout) PyObject * "/*%dout%*/$result = result;Py_XINCREF($result);"
//---------------------------------------------------------------------
#ifdef PY3
%define %treat_serialized_tinfo_raw_pointer_as_bytes_1(_TYPE)
%typemap(in) _TYPE *
{ // %treat_serialized_tinfo_raw_pointer_as_bytes_1 %typemap(in) _TYPE *
if ( $input == Py_None )
$1 = ($1_ltype) NULL;
else if ( PyBytes_Check($input) )
$1 = ($1_ltype) PyBytes_AsString($input);
else
SWIG_exception_fail(
SWIG_ValueError,
"Expected bytes " "in method '" "$symname" "', argument " "$argnum"" of type 'bytes'");
}
%typemap(directorin) _TYPE *
{ // %treat_serialized_tinfo_raw_pointer_as_bytes_1 %typemap(directorin) _TYPE *
$input = PyBytes_FromString($1 != NULL ? (const char *) $1 : "");
}
%typemap(out) _TYPE *
{ // %treat_serialized_tinfo_raw_pointer_as_bytes_1 %typemap(out) _TYPE *
$result = PyBytes_FromString($1 != NULL ? (const char *) $1 : "");
}
// 'typecheck' typemaps are used for polymorphism. We want to favor
// tinfo_t wrappers at the expense of 'type_t *' ones, so we want the
// precedence for this to be very low.
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) _TYPE *
{ // %treat_serialized_tinfo_raw_pointer_as_bytes_1 %typemap(typecheck) _TYPE *
$1 = ($input == Py_None || PyBytes_Check($input)) ? 1 : 0;
}
%enddef
%define %treat_serialized_tinfo_raw_pointer_as_bytes(TYPE)
%treat_serialized_tinfo_raw_pointer_as_bytes_1(TYPE);
%treat_serialized_tinfo_raw_pointer_as_bytes_1(const TYPE);
%enddef
#else
%define %treat_serialized_tinfo_raw_pointer_as_bytes(TYPE)
%apply char * { TYPE * }
%apply const char * { const TYPE * }
%enddef
#endif
%treat_serialized_tinfo_raw_pointer_as_bytes(type_t);
%treat_serialized_tinfo_raw_pointer_as_bytes(p_list);
//-------------------------------------------------------------------------
// For some reason, SWIG converts char arrays by computing the size
// from the end of the array, and stops when it encounters a '\0'.
// That doesn't work for us, as our API doesn't guarantee that
// bytes past the length we are interested in will be zeroed-out.
// In other words, the following code should *never* be present
// in idaapi_include.cpp:
// -------------------------
// while (size && (<name-of-variable>[size - 1] == '\0')) --size;
// -------------------------
//
%typemap(out) char [ANY], const char[ANY]
{
%set_output(SWIG_FromCharPtrAndSize($1, strnlen($1, $1_dim0)));
}
%typemap(varout) char [ANY], const char[ANY]
{
%set_output(SWIG_FromCharPtrAndSize($1, strnlen($1, $1_dim0)));
}
%apply unsigned long long { size_t }
%apply long long { ssize_t }
//---------------------------------------------------------------------
// 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))
{
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
return NULL;
}
/* Cap the number of elements to copy */
len = PySequence_Length($input) < $1_dim0 ? PySequence_Length($input) : $1_dim0;
for (i =0; i < len; i++)
{
newref_t item(PySequence_GetItem($input,i));
if (!PyLong_Check(item.o))
{
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
return NULL;
}
temp[i] = PyLong_AsUnsignedLong(item.o);
}
$1 = &temp[0];
}
//-------------------------------------------------------------------------
// Same, but with non-fixed sized arrays.
%typemap(in) (const tid_t *path, int plen) (qvector<tid_t> temp) {
if (!PySequence_Check($input))
{
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
return NULL;
}
int plen = PySequence_Length($input);
if ( plen <= 0 )
{
PyErr_SetString(PyExc_TypeError, "Sequence must have at least 1 item");
return NULL;
}
temp.resize(plen);
for ( int i =0; i < plen; ++i )
{
newref_t item(PySequence_GetItem($input,i));
if (!PyLong_Check(item.o))
{
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
return NULL;
}
temp[i] = PyLong_AsUnsignedLong(item.o);
}
$1 = temp.begin();
$2 = int(temp.size());
}
%{
SWIGINTERN PyObject *_maybe_cstring_result(
PyObject *resultobj,
const char *cstr,
int result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
return IDAPyStr_FromUTF8(cstr);
}
SWIGINTERN PyObject *_sized_cstring_result(
PyObject *resultobj,
const char *cstr,
size_t cstrsz)
{
Py_XDECREF(resultobj);
return IDAPyStr_FromUTF8AndSize(cstr, cstrsz);
}
SWIGINTERN PyObject *_maybe_sized_cstring_result(
PyObject *resultobj,
const char *cstr,
size_t cstrsz,
int result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
return IDAPyStr_FromUTF8AndSize(cstr, cstrsz);
}
SWIGINTERN PyObject *_maybe_cstring_result_on_charptr_using_allocated_buf(
PyObject *resultobj,
const char *result,
char *buf)
{
Py_XDECREF(resultobj);
PyObject *out = NULL;
if ( result != NULL )
{
out = IDAPyStr_FromUTF8(buf);
}
else
{
Py_INCREF(Py_None);
out = Py_None;
}
qfree(buf);
return out;
}
SWIGINTERN PyObject *_maybe_cstring_result_on_charptr_using_qbuf(
PyObject *resultobj,
const char *result,
const qstring &buf)
{
Py_XDECREF(resultobj);
if ( result == NULL )
Py_RETURN_NONE;
return IDAPyStr_FromUTF8AndSize(buf.begin(), buf.length());
}
SWIGINTERN PyObject *_maybe_binary_result(
PyObject *resultobj,
void *buf,
ssize_t result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
#ifdef PY3
return PyBytes_FromStringAndSize((const char *) buf, result);
#else
return PyString_FromStringAndSize((const char *) buf, result);
#endif
}
SWIGINTERN PyObject *_sized_binary_result(
PyObject *resultobj,
const char *cstr,
size_t cstrsz)
{
Py_XDECREF(resultobj);
return IDAPyBytes_FromMemAndSize(cstr, cstrsz);
}
SWIGINTERN PyObject *_maybe_sized_binary_result(
PyObject *resultobj,
const char *cstr,
size_t cstrsz,
int result)
{
Py_XDECREF(resultobj);
if ( result <= 0 )
Py_RETURN_NONE;
return IDAPyBytes_FromMemAndSize(cstr, cstrsz);
}
%}
#if defined(IDA_MODULE_NALT)
%{
#include <bytes.hpp>
#ifdef PY3
SWIGINTERN PyObject *_maybe_byte_array_or_none_result(
PyObject *resultobj,
bool result,
const uchar *bytes,
size_t nbytes)
{
Py_XDECREF(resultobj);
if ( !result )
Py_RETURN_NONE;
return IDAPyBytes_FromMemAndSize((const char *) bytes, nbytes);
}
#else
SWIGINTERN PyObject *_maybe_byte_array_as_hex_or_none_result(
PyObject *resultobj,
bool result,
const uchar *bytes,
size_t nbytes)
{
Py_XDECREF(resultobj);
if ( !result )
Py_RETURN_NONE;
qstring buf;
buf.resize(2*nbytes);
get_hex_string(buf.begin(), buf.size(), bytes, nbytes);
return IDAPyBytes_FromMemAndSize(buf.c_str(), buf.length());
}
#endif
%}
#endif
//---------------------------------------------------------------------
%define %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG)
%typemap(default) (BUFFER_ARG, SIZE_ARG) {
// %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG) %typemap(default) (BUFFER_ARG, SIZE_ARG)
$2 = MAXSTR;
}
%typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG) {
// %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG) %typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG)
$1 = ($1_ltype) qalloc(MAXSTR+1);
}
%typemap(argout) (BUFFER_ARG, SIZE_ARG) {
// %cstring_output_maxstr_none(BUFFER_ARG, SIZE_ARG) %typemap(argout) (BUFFER_ARG, SIZE_ARG)
resultobj = _maybe_cstring_result(resultobj, $1, int(result));
qfree($1);
}
%enddef
//---------------------------------------------------------------------
%define %binary_output_or_none(BUFFER_ARG, SIZE_ARG)
%typemap(default) (BUFFER_ARG, SIZE_ARG) {
// %binary_output_or_none(BUFFER_ARG, SIZE_ARG) %typemap(default) (BUFFER_ARG, SIZE_ARG)
$2 = MAXSPECSIZE;
}
%typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG) {
// %binary_output_or_none(BUFFER_ARG, SIZE_ARG) %typemap(in,numinputs=0) (BUFFER_ARG, SIZE_ARG)
$1 = (char *) qalloc(MAXSPECSIZE+1);
}
%typemap(argout) (BUFFER_ARG, SIZE_ARG) {
// %binary_output_or_none(BUFFER_ARG, SIZE_ARG) %typemap(argout) (BUFFER_ARG, SIZE_ARG)
resultobj = _maybe_binary_result(resultobj, $1, ssize_t(result));
qfree((void *)$1);
}
%enddef
//-------------------------------------------------------------------------
// and a helper for overriding the 'argout' of some of those functions,
// that return the input char* as return code; those build on recent
// versions of Xcode (>= 9.0), and need special care
%define %cstring_output_buf_and_size_returning_charptr(BUFIDX, ...)
%typemap(argout) (__VA_ARGS__) {
// cstring_output_buf_and_size_returning_charptr's argout
resultobj = _maybe_cstring_result_on_charptr_using_allocated_buf(resultobj, (const char *) result, $BUFIDX);
}
%enddef
//-------------------------------------------------------------------------
// see %cstring_output_buf_and_size_returning_charptr above
%define %cstring_output_qstring_returning_charptr(BUFIDX, ...)
%typemap(argout) (__VA_ARGS__)
{
// %cstring_output_qstring_returning_charptr typemap(argout) __VA_ARGS__
resultobj = _maybe_cstring_result_on_charptr_using_qbuf(resultobj, (const char *) result, *$BUFIDX);
}
%enddef
//-------------------------------------------------------------------------
// OUT qstrvec_t
//-------------------------------------------------------------------------
%typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp)
{
// %typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp)
$1 = &temp;
}
%typemap(argout) qstrvec_t *out
{
// %typemap(argout) qstrvec_t *out
Py_XDECREF(resultobj);
resultobj = qstrvec2pylist(*($1));
}
%typemap(freearg) qstrvec_t* out
{
// %typemap(freearg) qstrvec_t* out
// Nothing. We certainly don't want 'temp' to be deleted.
}
//-------------------------------------------------------------------------
// md5/sha256 hash retrieval (as hex representation)
//-------------------------------------------------------------------------
#ifdef PY3
%define %byte_array_or_none(PARAM_NAME)
%typemap(in, numinputs=0) uchar PARAM_NAME[ANY] (uchar temp[$1_dim0])
{ // byte_array_or_none typemap(in, numinputs=0) uchar PARAM_NAME[ANY] (uchar temp[$1_dim0])
$1 = temp;
}
%typemap(argout) uchar PARAM_NAME[ANY]
{ // byte_array_or_none typemap(argout) uchar PARAM_NAME[ANY]
resultobj = _maybe_byte_array_or_none_result(resultobj, result, $1, $1_dim0);
}
%enddef
%byte_array_or_none(hash);
#else
%define %byte_array_as_hex_or_none(PARAM_NAME)
%typemap(in, numinputs=0) uchar PARAM_NAME[ANY] (uchar temp[$1_dim0])
{ // byte_array_as_hex_or_none typemap(in, numinputs=0) uchar PARAM_NAME[ANY] (uchar temp[$1_dim0])
$1 = temp;
}
%typemap(argout) uchar PARAM_NAME[ANY]
{ // byte_array_as_hex_or_none typemap(argout) uchar PARAM_NAME[ANY]
resultobj = _maybe_byte_array_as_hex_or_none_result(resultobj, result, $1, $1_dim0);
}
%enddef
%byte_array_as_hex_or_none(hash);
#endif
// Check that the argument is a callable Python object
//---------------------------------------------------------------------
%typemap(in) PyObject *pyfunc {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Expected a callable object");
return NULL;
}
$1 = $input;
}
// Check that the argument is None or a callable Python object
//---------------------------------------------------------------------
%typemap(in) PyObject *pyfunc_or_none {
if ($input != Py_None && !PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Expected None or a callable object");
return NULL;
}
$1 = $input;
}
// Check that the argument is None or a tuple
//---------------------------------------------------------------------
%typemap(in) PyObject *tuple_or_none {
if ($input != Py_None && !PyTuple_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Expected None or a tuple");
return NULL;
}
$1 = $input;
}
%typemap(in) ea_t
{ // %typemap(in) ea_t
uint64 $1_temp;
if ( !PyW_GetNumber($input, &$1_temp) )
SWIG_exception_fail(
SWIG_TypeError,
"in method '" "$symname" "', argument " "$argnum"" of type 'ea_t'");
$1 = ea_t($1_temp);
}
%typemap(in) sval_t
{ // %typemap(in) sval_t
uint64 $1_temp;
if ( !PyW_GetNumber($input, &$1_temp) )
SWIG_exception_fail(
SWIG_TypeError,
"in method '" "$symname" "', argument " "$argnum"" of type 'sval_t'");
$1 = sval_t($1_temp);
}
// Use PyLong_FromUnsignedLongLong, because 'long' is 4 bytes on
// windows, and thus the ea_t would be truncated at the
// PyLong_FromUnsignedLong(unsigned int) call time.
%typemap(out) ea_t "$result = PyLong_FromUnsignedLongLong($1);"
%typemap(in) qtime64_t "$1 = PyLong_AsUnsignedLongLong($input);"
%typemap(out) qtime64_t "$result = PyLong_FromUnsignedLongLong($1);"
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) ea_t
{
// %typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) ea_t
uint64 $1_temp;
$1 = PyW_GetNumber($input, &$1_temp);
}
//---------------------------------------------------------------------
// IN/OUT qstring/bytevec_t
//---------------------------------------------------------------------
%define %bytes_container(
REFTYPE,
CONTAINER_TYPE,
START_ACCESSOR,
SIZE_ACCESSOR,
INSTANCE_CAST,
CHECKER,
IN_CONVERTER,
OUT_CONVERTER,
ARGOUT_CONVERTER,
ARGOUT_MAYBE_CONVERTER,
ELTYPE_TO_REPORT1,
ELTYPE_TO_REPORT2)
%typemap(typecheck) REFTYPE
{ // bytes_container REFTYPE typemap(typecheck)
$1 = CHECKER($input) ? 1 : 0;
}
%fragment("outarg_cvt_" #CONTAINER_TYPE, "header")
{
bool outarg_cvt_##CONTAINER_TYPE(
CONTAINER_TYPE *out,
PyObject *obj,
bool can_be_none=false)
{
bool ok = can_be_none && obj == Py_None;
if ( !ok )
{
ok = CHECKER(obj);
if ( ok )
IN_CONVERTER(out, obj);
}
return ok;
}
}
%fragment("cvt_" #CONTAINER_TYPE, "header")
{
CONTAINER_TYPE *cvt_##CONTAINER_TYPE(PyObject *obj, bool can_be_none=false)
{
CONTAINER_TYPE *out = NULL;
if ( can_be_none && obj == Py_None )
{
out = new CONTAINER_TYPE;
}
else if ( CHECKER(obj) )
{
// init properly, so ctor can't crash
out = new CONTAINER_TYPE;
IN_CONVERTER(out, obj);
}
return out;
}
}
%typemap(in, fragment="cvt_" #CONTAINER_TYPE) REFTYPE
{ // bytes_container REFTYPE, CONTAINER_TYPE typemap(in)
$1 = cvt_ ## CONTAINER_TYPE($input);
if ( $1 == NULL )
SWIG_exception_fail(
SWIG_ValueError,
"Expected " ELTYPE_TO_REPORT1 " " "in method '" "$symname" "', argument " "$argnum"" of type '" ELTYPE_TO_REPORT2 "'");
}
%typemap(in) const REFTYPE _type_or_none
{ // bytes_container REFTYPE _type_or_none, CONTAINER_TYPE typemap(in)
$1 = cvt_ ## CONTAINER_TYPE($input, /*can_be_none=*/ true);
if ( $1 == NULL )
SWIG_exception_fail(
SWIG_ValueError,
"Expected " ELTYPE_TO_REPORT1 " " "in method '" "$symname" "', argument " "$argnum"" of type '" ELTYPE_TO_REPORT2 "'");
}
%typemap(in) const REFTYPE _fields
{ // bytes_container REFTYPE _fields, CONTAINER_TYPE typemap(in)
$1 = cvt_ ## CONTAINER_TYPE($input, /*can_be_none=*/ true);
if ( $1 == NULL )
SWIG_exception_fail(
SWIG_ValueError,
"Expected " ELTYPE_TO_REPORT1 " " "in method '" "$symname" "', argument " "$argnum"" of type '" ELTYPE_TO_REPORT2 "'");
}
%typemap(freearg) REFTYPE
{ // bytes_container REFTYPE typemap(freearg)
delete $1;
}
%typemap(out) REFTYPE // e.g., %typemap(out) qstring*
{ // bytes_container typemap(out) REFTYPE
$result = OUT_CONVERTER((const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
%typemap(out) CONTAINER_TYPE // e.g., %typemap(out) qstring
{ // bytes_container typemap(out) CONTAINER_TYPE
$result = OUT_CONVERTER((const char *) $1.START_ACCESSOR(), $1.SIZE_ACCESSOR());
}
%typemap(varout) CONTAINER_TYPE // e.g., %typemap(varout) qstring
{ // bytes_container typemap(varout) CONTAINER_TYPE
$result = OUT_CONVERTER((const char *) $1.START_ACCESSOR(), $1.SIZE_ACCESSOR());
}
// the following is used to turn a '... *result' output parameter,
// into an actual return value.
%typemap(in,numinputs=0) CONTAINER_TYPE *result (CONTAINER_TYPE temp)
{
// bytes_container typemap(in,numinputs=0) CONTAINER_TYPE *result (CONTAINER_TYPE temp)
$1 = &temp;
}
%typemap(in,numinputs=0) CONTAINER_TYPE &result (CONTAINER_TYPE temp)
{
// bytes_container typemap(in,numinputs=0) CONTAINER_TYPE &result (CONTAINER_TYPE temp)
$1 = &temp;
}
%typemap(argout) CONTAINER_TYPE *result
{
// bytes_container typemap(argout) CONTAINER_TYPE *result
resultobj = ARGOUT_MAYBE_CONVERTER(resultobj, $1->START_ACCESSOR(), $1->SIZE_ACCESSOR(), int(result));
}
%typemap(argout) CONTAINER_TYPE &result
{
// bytes_container typemap(argout) CONTAINER_TYPE &result
resultobj = ARGOUT_MAYBE_CONVERTER(resultobj, $1->START_ACCESSOR(), $1->SIZE_ACCESSOR(), int(result));
}
%typemap(freearg) CONTAINER_TYPE* result
{
// bytes_container typemap(freearg) CONTAINER_TYPE *result
// Nothing. We certainly don't want 'temp' to be deleted.
}
%typemap(freearg) CONTAINER_TYPE& result
{
// bytes_container typemap(freearg) CONTAINER_TYPE &result
// Nothing. We certainly don't want 'temp' to be deleted.
}
// We determine that the following parameter: "CONTAINER_TYPE *vout" has the
// following characteristics:
// - the C function being called returns void
// - other than that, it's the same as for the "CONTAINER_TYPE *result" parameter
// (i.e., requires a temporary 'qstring', etc...)
//
// Re-use the 'CONTAINER_TYPE *result' typemaps, ...
%apply CONTAINER_TYPE *result { CONTAINER_TYPE *vout };
%apply CONTAINER_TYPE &result { CONTAINER_TYPE &vout };
// ...but override the argout one, so that it doesn't rely on a 'result'
%typemap(argout) (CONTAINER_TYPE *vout)
{
// bytes_container typemap(argout) (CONTAINER_TYPE *vout)
resultobj = ARGOUT_CONVERTER(resultobj, (const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
%typemap(argout) (CONTAINER_TYPE &vout)
{
// bytes_container typemap(argout) (CONTAINER_TYPE &vout)
resultobj = ARGOUT_CONVERTER(resultobj, (const char *) $1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
%typemap(directorin) CONTAINER_TYPE *
{ // bytes_container typemap(directorin) CONTAINER_TYPE *
if ( $1 != NULL )
{
$input = OUT_CONVERTER($1->START_ACCESSOR(), $1->SIZE_ACCESSOR());
}
else
{
Py_INCREF(Py_None);
$input = Py_None;
}
}
%typemap(directorin) REFTYPE
{ // bytes_container typemap(directorin) REFTYPE
$input = OUT_CONVERTER($1.START_ACCESSOR(), $1.SIZE_ACCESSOR());
}
%typemap(directorout) CONTAINER_TYPE
{ // bytes_container typemap(directorout) CONTAINER_TYPE
if ( CHECKER($1) )
IN_CONVERTER(&$result, $1);
else
Swig::DirectorTypeMismatchException::raise(
SWIG_ErrorType(SWIG_TypeError),
"in output value of type '" ELTYPE_TO_REPORT2 "' in method '$symname'");
}
%typemap(directorargout) CONTAINER_TYPE *vout
{ // bytes_container typemap(directorargout) CONTAINER_TYPE *vout
if ( CHECKER($result) )
{
CONTAINER_TYPE _buf;
if ( IN_CONVERTER(&_buf, $result) )
vout->insert(vout->SIZE_ACCESSOR(), _buf.START_ACCESSOR(), _buf.SIZE_ACCESSOR());
}
}
%enddef
%define %bytes_container_ptr_and_ref(
CONTAINER_TYPE,
START_ACCESSOR,
SIZE_ACCESSOR,
INSTANCE_CAST,
CHECKER,
IN_CONVERTER,
OUT_CONVERTER,
ARGOUT_CONVERTER,
ARGOUT_MAYBE_CONVERTER,
ELTYPE_TO_REPORT1,
ELTYPE_TO_REPORT2)
%bytes_container(
CONTAINER_TYPE *,
CONTAINER_TYPE,
START_ACCESSOR,
SIZE_ACCESSOR,
INSTANCE_CAST,
CHECKER,
IN_CONVERTER,
OUT_CONVERTER,
ARGOUT_CONVERTER,
ARGOUT_MAYBE_CONVERTER,
ELTYPE_TO_REPORT1,
ELTYPE_TO_REPORT2);
%bytes_container(
CONTAINER_TYPE &,
CONTAINER_TYPE,
START_ACCESSOR,
SIZE_ACCESSOR,
INSTANCE_CAST,
CHECKER,
IN_CONVERTER,
OUT_CONVERTER,
ARGOUT_CONVERTER,
ARGOUT_MAYBE_CONVERTER,
ELTYPE_TO_REPORT1,
ELTYPE_TO_REPORT2);
%enddef
#ifdef PY3
%bytes_container_ptr_and_ref(
qstring,
c_str,
length,
,
IDAPyStr_Check,
IDAPyStr_AsUTF8,
IDAPyStr_FromUTF8AndSize,
_sized_cstring_result,
_maybe_sized_cstring_result,
"string",
"str");
%bytes_container_ptr_and_ref(
bytevec_t,
begin,
size,
,
IDAPyBytes_Check,
IDAPyBytes_AsBytes,
IDAPyBytes_FromMemAndSize,
_sized_binary_result,
_maybe_sized_binary_result,
"bytes",
"bytes");
%bytes_container_ptr_and_ref(
qtype,
begin,
length,
(const uchar *),
IDAPyBytes_Check,
IDAPyBytes_as_qtype,
IDAPyBytes_FromMemAndSize,
_sized_binary_result,
_maybe_sized_binary_result,
"bytes",
"bytes");
#else
%bytes_container_ptr_and_ref(
qstring,
c_str,
length,
,
IDAPyStr_Check,
IDAPyStr_AsUTF8,
IDAPyStr_FromUTF8AndSize,
_sized_cstring_result,
_maybe_sized_cstring_result,
"string",
"str");
%bytes_container_ptr_and_ref(
bytevec_t,
begin,
size,
,
IDAPyBytes_Check,
IDAPyBytes_AsBytes,
IDAPyBytes_FromMemAndSize,
_sized_binary_result,
_maybe_sized_binary_result,
"string",
"str");
%bytes_container_ptr_and_ref(
qtype,
begin,
length,
(const uchar *),
IDAPyBytes_Check,
IDAPyBytes_as_qtype,
IDAPyBytes_FromMemAndSize,
_sized_binary_result,
_maybe_sized_binary_result,
"string",
"str");
#endif
//-------------------------------------------------------------------------
// insn_t
//-------------------------------------------------------------------------
%fragment("cvt_const_insn_t_ref", "header")
{
bool convert_const_insn_t_ref(insn_t *out, PyObject *in)
{
uint64 ea;
bool ok = PyW_GetNumber(in, &ea);
if ( ok )
{
insn_t tmp;
ok = decode_insn(&tmp, ea_t(ea));
if ( ok )
*out = tmp;
}
else
{
insn_t *p_insn = nullptr;
ok = SWIG_ConvertPtr(in, (void **) &p_insn, SWIGTYPE_p_insn_t, 0) >= 0 && p_insn != nullptr;
if ( ok )
*out = *p_insn;
}
return ok;
}
}
//-------------------------------------------------------------------------
%typemap(in, fragment="cvt_const_insn_t_ref") (const insn_t &) (insn_t lins)
{
// %typemap(in) (const insn_t &)
if ( !convert_const_insn_t_ref(&lins, $input) )
SWIG_exception_fail(SWIG_ValueError, "Expected either an address, or a non-null ida_ua.insn_t instance");
$1 = &lins;
}
%typemap(doc) (const insn_t &) "$1_name: an ida_ua.insn_t, or an address (C++: const insn_t &)"
//---------------------------------------------------------------------
// varargs (mostly kernwin.hpp)
//---------------------------------------------------------------------
// This is used for functions like warning(), info() and so on
%typemap(in) (const char *format, ...) (qstring buf)
{
$1 = "%s"; /* Fix format string to %s */
IDAPyStr_AsUTF8(&buf, $input); /* Get string argument */
$2 = (void *) buf.begin();
/* Note: we cannot rely on 'nonnul_argument_prototype' for */
/* these, since we fiddle with the arguments number */
if ( $2 == NULL )
SWIG_exception_fail(
SWIG_ValueError,
"invalid null pointer " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
};
//-------------------------------------------------------------------------
// for use with insn_t, op_t wrappers
%typemap(in) (size_t ptrval)
{
$1 = size_t(PyLong_AsUnsignedLongLong($input));
}
// Help SWIG to figure out the ulonglong type
#ifdef SWIGWIN
typedef unsigned __int64 ulonglong;
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif
#ifdef __EA64__
%apply longlong *INOUT { sval_t *value };
%apply longlong *INOUT { adiff_t *disp };
%apply ulonglong *INOUT { ea_t *addr };
%apply ulonglong *INPUT { ea_t *ea_ptr }; // get_debug_name
%apply ulonglong *INOUT { sel_t *sel };
%apply ulonglong *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_range_selection()
%apply ulonglong *OUTPUT { ea_t *from, ea_t *to, asize_t *size }; // get_mapping()
%apply ulonglong *OUTPUT { uval_t *value }; // get_name_value
#else
%apply int *INOUT { sval_t *value };
%apply int *INOUT { adiff_t *disp };
%apply unsigned int *INOUT { ea_t *addr };
%apply unsigned int *INPUT { ea_t *ea_ptr }; // get_debug_name
%apply unsigned int *INOUT { sel_t *sel };
%apply unsigned int *OUTPUT { ea_t *ea1, ea_t *ea2 }; // read_range_selection()
%apply unsigned int *OUTPUT { ea_t *from, ea_t *to, asize_t *size }; // get_mapping()
%apply unsigned int *OUTPUT { uval_t *value }; // get_name_value
#endif
%apply long long { qoff64_t };
%apply qstring *result { qstring *out };
%apply qstring *result { qstring *buf };
%apply qstring *result { qstring *errbuf };
%apply int *OUTPUT { int *icon };
%apply int *OUTPUT { action_state_t *state };
%apply bool *OUTPUT { bool *checkable };
%apply bool *OUTPUT { bool *checked };
%apply bool *OUTPUT { bool *visibility };
//-------------------------------------------------------------------------
// 'errbuf' output handling can go many ways. Let's provide common helpers.
%define %make_argout_errbuf_raise_exception_when_non_empty()
%typemap(argout) (qstring *errbuf)
{
// %typemap(argout) qstring *errbuf (from: %make_argout_errbuf_raise_exception_when_non_empty)
if ( !$1->empty() )
{
if ( $result != NULL )
Py_XDECREF($result);
SWIG_exception_fail(SWIG_RuntimeError, $1->c_str());
}
}
%enddef
%define %make_argout_errbuf_raise_when_null_result()
%typemap(argout) (qstring *errbuf)
{
// %typemap(argout) qstring *errbuf (from: %make_argout_errbuf_raise_when_null_result)
if ( result == NULL )
{
if ( $result != NULL )
Py_XDECREF($result);
SWIG_exception_fail(SWIG_RuntimeError, $1->c_str());
}
}
%enddef
//-------------------------------------------------------------------------
// The following is to be used to expose an array of items
// to IDAPython. This will not make a copy (on purpose!).
//-------------------------------------------------------------------------
//
// (Very) heavily inspired by:
// http://stackoverflow.com/questions/7713318/nested-structure-array-access-in-python-using-swig?rq=1
//
// NOTE: This should probably hold a (weak?) reference
// to the parent PyObject, because it is technically possible
// to end up with dangling pointers otherwise
// See also dynamic_wrapped_array_t
%immutable;
%inline %{
template <typename Type, size_t N>
struct wrapped_array_t {
Type (&data)[N];
wrapped_array_t(Type (&data)[N]) : data(data) { }
};
%}
%mutable;
%extend wrapped_array_t {
inline size_t __len__() const { qnotused($self); return N; }
inline const Type& __getitem__(size_t i) const {
if ( i >= N )
throw std::out_of_range("out of bounds access");
return $self->data[i];
}
inline void __setitem__(size_t i, const Type& v) {
if ( i >= N )
throw std::out_of_range("out of bounds access");
$self->data[i] = v;
}
inline bytevec_t _get_bytes() const {
bytevec_t bts;
bts.resize(N * sizeof(Type));
memmove(bts.begin(), $self->data, bts.size());
return bts;
}
inline void _set_bytes(const bytevec_t &bts) {
if ( bts.size() > N * sizeof(Type) )
throw std::out_of_range("out of bounds access");
memset($self->data, 0, sizeof($self->data));
memmove($self->data, bts.begin(), bts.size());
}
%pythoncode {
__iter__ = ida_idaapi._bounded_getitem_iterator
bytes = property(_get_bytes, _set_bytes)
}
}
//-------------------------------------------------------------------------
// NOTE: see note for wrapped_array_t
%immutable;
%inline %{
template <typename Type>
struct dynamic_wrapped_array_t {
Type *data;
size_t count;
dynamic_wrapped_array_t(Type *_data, size_t _count)
: data(_data), count(_count) { }
};
%}
%mutable;
%extend dynamic_wrapped_array_t {
inline size_t __len__() const { return $self->count; }
inline const Type& __getitem__(size_t i) const {
if ( i >= $self->count )
throw std::out_of_range("out of bounds access");
return $self->data[i];
}
inline void __setitem__(size_t i, const Type& v) {
if ( i >= $self->count )
throw std::out_of_range("out of bounds access");
$self->data[i] = v;
}
%pythoncode {
__iter__ = ida_idaapi._bounded_getitem_iterator
}
}
//-------------------------------------------------------------------------
#if SWIG_VERSION == 0x40000 || SWIG_VERSION == 0x40001
%typemap(out) tinfo_t {}
%typemap(ret) tinfo_t
{
// %typemap(ret) tinfo_t
tinfo_t *ni = new tinfo_t($1);
til_register_python_tinfo_t_instance(ni);
$result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0);
}
%typemap(check) tinfo_t *
{
// %typemap(check) tinfo_t *
if ( $1 == NULL )
SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
}
%typemap(out) tinfo_t *
{
// %typemap(out) tinfo_t *
tinfo_t *ni = new tinfo_t(*$1);
til_register_python_tinfo_t_instance(ni);
$result = SWIG_NewPointerObj(ni, $1_descriptor, SWIG_POINTER_OWN | 0);
}
%typemap(newfree) tinfo_t * {
// %typemap(newfree) tinfo_t *
delete $1;
}
#else
#error Ensure tinfo_t wrapping is compatible with this version of SWIG
#endif
// Convert all of these
%cstring_output_maxstr_none(char *buf, size_t bufsize);
%cstring_output_maxstr_none(char *buf, int bufsize);
%binary_output_or_none(void *buf, size_t bufsize);
// Accept single Python string for const void * + size input arguments
// For example: put_many_bytes() and patch_many_bytes()
%apply (char *STRING, int LENGTH) { (const void *buf, size_t size) };
%apply (char *STRING, int LENGTH) { (const void *buf, size_t bufsize) };
%apply (char *STRING, int LENGTH) { (const void *buf, size_t len) };
%apply (char *STRING, int LENGTH) { (const void *value, size_t length) };
%apply (char *STRING, int LENGTH) { (const void *dataptr,size_t len) };
#ifdef PY3
%define %const_pointer_and_size(PTRTYPE, BUFNAME, SIZENAME, STORAGE_TYPE, CONVERTER, LENGTH_GETTER)
%typemap(in) (const PTRTYPE *BUFNAME, size_t SIZENAME) (STORAGE_TYPE tmp)
{
// typemap(in) (const PTRTYPE *BUFNAME, size_t SIZENAME)
if ( !CONVERTER(&tmp, $input) ) {
%argument_fail(SWIG_ERROR, "$type", $symname, $argnum);
}
$1 = %reinterpret_cast(tmp.begin(), $1_ltype);
$2 = %numeric_cast(tmp.LENGTH_GETTER(), $2_ltype);
}
%typemap(freearg) (const PTRTYPE *BUFNAME, size_t SIZENAME)
{
// typemap(freearg) (const PTRTYPE *BUFNAME, size_t SIZENAME)
}
%enddef
%define %const_void_pointer_and_size(PTRTYPE, BUFNAME, SIZENAME)
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (const PTRTYPE *BUFNAME, size_t SIZENAME)
{ // %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (const PTRTYPE *BUFNAME, size_t SIZENAME)
$1 = PyBytes_Check($input) ? 1 : 0;
}
%const_pointer_and_size(PTRTYPE, BUFNAME, SIZENAME, bytevec_t, IDAPyBytes_AsBytes, size)
%enddef
%define %const_char_pointer_and_size(PTRTYPE, BUFNAME, SIZENAME)
%const_pointer_and_size(PTRTYPE, BUFNAME, SIZENAME, qstring, IDAPyStr_AsUTF8, length)
%enddef
%const_void_pointer_and_size(void, buf, size);
%const_void_pointer_and_size(void, buf, bufsize);
%const_void_pointer_and_size(void, buf, len);
%const_void_pointer_and_size(void, value, length);
%const_void_pointer_and_size(void, dataptr, len);
%const_char_pointer_and_size(char, value, length);
#endif
// Create wrapper classes for basic type arrays
%array_class(uchar, uchar_array);
%array_class(tid_t, tid_array);
%array_class(ea_t, ea_array);
%array_class(sel_t, sel_array);
%array_class(uval_t, uval_array);
%pointer_class(int, int_pointer);
%pointer_class(ea_t, ea_pointer);
%pointer_class(sval_t, sval_pointer);
%pointer_class(sel_t, sel_pointer);
%{
SWIGINTERN PyObject *qstrvec2pylist(const qstrvec_t &vec)
{
size_t n = vec.size();
PyObject *py_list = PyList_New(n);
for ( size_t i=0; i < n; ++i )
PyList_SetItem(py_list, i, IDAPyStr_FromUTF8AndSize(vec[i].c_str(), vec[i].length()));
return py_list;
}
%}
//-------------------------------------------------------------------------
// When it comes to uint64, we have been typically very tolerant and
// accept negative values as if were logical to perform C-like numbers
// 'wrapping' in Python. It's not, but bw-compat imposes that we do.
%fragment("cvt_uint64", "header")
{
int cvt_uint64(uint64 *out, PyObject *obj)
{
unsigned long long ull = PyLong_AsUnsignedLongLong(obj);
if ( PyErr_Occurred() )
{
PyErr_Clear();
long long ll = PyLong_AsLongLong(obj);
if ( PyErr_Occurred() )
{
PyErr_Clear();
return SWIG_OverflowError;
}
ull = (unsigned long long) ll;
}
*out = uint64(ull);
return SWIG_OK;
}
}
%typemap(in, fragment="cvt_uint64") uint64 (int ecode)
{
// %typemap(in) uint64
ecode = cvt_uint64(&$1, $input);
if ( !SWIG_IsOK(ecode) )
SWIG_exception_fail(SWIG_ArgError(ecode), "in method '$symname', argument $argnum of type $1_type");
}
//-------------------------------------------------------------------------
%define %_uint_result_as_output(TYPE, CONVFUNC, CHECK_EXPR)
%typemap(in,numinputs=0) TYPE *result (TYPE temp = 0)
{
// %_uint_result_as_output(TYPE, CONVFUNC, CHECK_EXPR) %typemap(in,numinputs=0) TYPE *result
$1 = &temp;
}
%typemap(argout) TYPE *result
{
// %_uint_result_as_output(TYPE, CONVFUNC) %typemap(argout) TYPE *result
Py_XDECREF(resultobj);
if ( CHECK_EXPR )
{
resultobj = CONVFUNC(*(TYPE *) $1);
}
else
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
}
%enddef
//-------------------------------------------------------------------------
%define %uint_result_as_output(TYPE, CONVFUNC)
%_uint_result_as_output(TYPE, CONVFUNC, int(result) > 0);
%enddef
%uint_result_as_output(uint32, PyLong_FromUnsignedLong);
%uint_result_as_output(uint64, PyLong_FromUnsignedLongLong);
%uint_result_as_output(int64, PyLong_FromLongLong);
%apply uint32 *result { uint32 *out };
%apply uint64 *result { uint64 *out };
%apply int64 *result { int64 *out };
#ifdef __EA64__
%apply uint64 *result { ea_t *result };
#else
%apply uint32 *result { ea_t *result };
#endif
// helpers to turn result into multiple values (just %apply, renaming 'appended_ea')
%typemap(argout) ea_t *appended_ea
{
// %typemap(argout) ea_t *appended_ea
#ifdef __EA64__
$result = SWIG_Python_AppendOutput($result, PyLong_FromUnsignedLongLong(*($1)));
#else
$result = SWIG_Python_AppendOutput($result, PyLong_FromUnsignedLong(*($1)));
#endif
}
//-------------------------------------------------------------------------
// Make get_any_cmt() work
%apply unsigned char *OUTPUT { color_t *cmttype };
// For get_enum_id()
%apply unsigned char *OUTPUT { uchar *serial };
// get_[first|last]_serial_enum_member() won't take serials as input; it'll be present as output
%apply unsigned char *OUTPUT { uchar *out_serial };
// get_[next|prev]_serial_enum_member() take serials as input, and have the result present as output
%apply unsigned char *INOUT { uchar *in_out_serial };
// This is meant only for the code that is defined in IDAPython,
// as SDK non-null pointers should be marked by NONNULL and handled
// automatically.
%define %pywraps_nonnul_argument_prototype(PROTO, ARGSIG)
/* first, define the typemap */
%typemap(check) (ARGSIG)
{
if ( $1 == NULL )
SWIG_exception_fail(SWIG_ValueError, "invalid null pointer " "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
}
/* Then, redeclare prototype. Note that we want this prototype _only_ seen */
/* by SWiG, but not by the later compile phase: because of the defines */
/* in pro.h, 'idaapi', 'ida_export', etc... will disappear, causing */
/* VisualStudio to exit with a "same prototype, different modifiers" error. */
%inline %{
#ifndef _MSC_VER
PROTO;
#endif
%}
%enddef
%define %numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, REFTYPE)
%typemap(arginit) VECTYPE REFTYPE "VECTYPE $1_local_storage; // %numbers_list_to_values_vec(VECTYPE) %typemap(arginit) VECTYPE REFTYPE" // *MUST NOT* be within '{}'s
%typemap(in) VECTYPE REFTYPE
{ // %numbers_list_to_values_vec(VECTYPE) %typemap(in) VECTYPE REFTYPE
if ( PySequence_Check($input) )
{
if ( PYLIST_CONVERTOR(&$1_local_storage, $input) < 0 )
SWIG_fail;
$1 = &$1_local_storage;
}
else
{
void *$1_vptr = 0;
int res$argnum = SWIG_ConvertPtr($input, &$1_vptr, SWIGTYPE, 0 | 0);
if ( !SWIG_IsOK(res$argnum) )
SWIG_exception_fail(SWIG_ArgError(res$argnum), "in method '$symname', argument $argnum of type $1_type");
$1 = reinterpret_cast<VECTYPE*>($1_vptr);
}
}
%typecheck(SWIG_TYPECHECK_POINTER) VECTYPE REFTYPE
{
// %numbers_list_to_values_vec(VECTYPE) %typecheck(SWIG_TYPECHECK_POINTER) VECTYPE REFTYPE
if ( PySequence_Check($input) > 0 )
{
$1 = 1;
}
else
{
int res = SWIG_ConvertPtr($input, 0, SWIGTYPE, 0);
$1 = SWIG_CheckState(res);
}
}
%enddef
//-------------------------------------------------------------------------
// For e.g., get_idainfo_by_type()
%apply uint32 * OUTPUT { flags_t *out_flags };
%apply size_t * OUTPUT { size_t *out_size };
%apply size_t * OUTPUT { size_t *out_alsize };
%typemap(check) size_t *out_size "*($1) = 0; // %typemap(check) size_t *out_size";
%typemap(check) size_t *out_alsize "*($1) = 0; // %typemap(check) size_t *out_alsize";
%typemap(check) flags_t *out_flags "*($1) = 0; // %typemap(check) flags_t *out_flags";
%typemap(in,numinputs=0) opinfo_t *out_mt (opinfo_t temp) {
// typemap(in,numinputs=0) opinfo_t *out_mt
$1 = &temp;
}
%typemap(argout) opinfo_t *out_mt
{
// typemap(argout) opinfo_t *out_mt
if ( result )
{
PyObject *py_opinfo = SWIG_NewPointerObj(SWIG_as_voidptr(new opinfo_t(*($1))), SWIGTYPE_p_opinfo_t, SWIG_POINTER_NEW );
$result = SWIG_Python_AppendOutput($result, py_opinfo);
}
else
{
Py_INCREF(Py_None);
$result = SWIG_Python_AppendOutput($result, Py_None);
}
}
%typemap(freearg) opinfo_t *out_mt
{
// typemap(freearg) opinfo_t *out_mt
// Nothing. We certainly don't want 'temp' to be deleted.
}
//-------------------------------------------------------------------------
%define %numbers_list_to_values_vec(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR)
%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, *);
%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, &);
%enddef
#ifdef __EA64__
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PyListToEaVec);
#else
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_int_t, PyW_PyListToEaVec);
#endif
//-------------------------------------------------------------------------
// Make sure the GIL is released, in case 'NAME' is calling execute_sync
// either directly, or indirectly
%define %calls_execute_sync(NAME)
%thread NAME;
%enddef
#ifdef TESTABLE_BUILD
# define HOOKS_DUMP_STATE() %ignore NAME##_Hooks::dump_state;
#else
# define HOOKS_DUMP_STATE()
#endif
%define %define_Hooks_class(NAME)
%ignore NAME##_Callback;
%ignore NAME##_Hooks::dispatch;
%ignore NAME##_Hooks::mappings;
%ignore NAME##_Hooks::mappings_size;
HOOKS_DUMP_STATE();
%enddef
%{
#include <expr.hpp>
#include <ieee.h>
#include "../../../pywraps.hpp"
%}
%{
#ifdef __EA64__
# define ea_t_SWIGTYPE_name SWIGTYPE_p_unsigned_long_long
#else
# define ea_t_SWIGTYPE_name SWIGTYPE_p_unsigned_int
#endif
SWIGINTERN void __raise_ba(const std::bad_alloc &SWIGUNUSEDPARM(ba))
{
PyErr_SetString(PyExc_MemoryError, "Out of memory (bad_alloc)");
}
SWIGINTERN void __raise_u()
{
PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
}
SWIGINTERN void __raise_e(const std::exception &e)
{
const char *what = e.what();
if ( what == NULL || what[0] == '\0' )
{
__raise_u();
}
else
{
PyErr_SetString(PyExc_RuntimeError, what);
}
}
SWIGINTERN void __raise_ie(const interr_exc_t &ie)
{
qstring emsg;
emsg.sprnt(INTERR_EXC_FMT, ie.code);
PyErr_SetString(PyExc_RuntimeError, emsg.begin());
}
SWIGINTERN void __raise_de(const Swig::DirectorException &e)
{
bool handled = false;
if ( PyErr_Occurred() != NULL )
{
// Add the new bits of info to the error
PyObject *exception, *v, *tb;
PyErr_Fetch(&exception, &v, &tb);
if ( exception != NULL )
{
PyErr_NormalizeException(&exception, &v, &tb);
if ( exception != NULL )
{
// FIXME: We retrieve the message, but not the context (i.e., the
// stack trace.) Ideally we should perhaps swoop in our own
// 'sys.stderr', call PyErr_Print(), retrieve the result, and
// append that to the new exception message.
newref_t as_str(PyObject_Str(v));
if ( as_str != NULL )
{
qstring buf;
IDAPyStr_AsUTF8(&buf, as_str.o);
buf.insert(" : ");
buf.insert(e.getMessage());
PyErr_SetString(PyExc_RuntimeError, buf.c_str());
handled = true;
}
}
}
}
if ( !handled )
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
}
SWIGINTERN void __raise_oor(const std::out_of_range &e)
{
PyErr_SetString(PyExc_IndexError, e.what());
}
SWIGINTERN bool __chkthr()
{
bool ok = is_main_thread();
if ( !ok )
PyErr_SetString(PyExc_RuntimeError, "Function can be called from the main thread only");
return ok;
}
SWIGINTERN bool __chkreqidb()
{
bool ok = netnode::inited();
if ( !ok )
PyErr_SetString(PyExc_RuntimeError, "Function requires a database");
return ok;
}
%}
%define %force_declare_SWiG_type(NAME)
// KLUDGE: I have no idea how to force SWiG to declare a type for a module,
// unless that type is indeed used. That's why this wrapper exists..
%inline %{
inline void _kludge_force_declare_##NAME(const NAME *) {}
%}
%enddef
%define %modal_dialog_triggering_function(NAME)
%thread NAME;
%pythonprepend NAME
%{
import ida_kernwin
# kludge: we can't use %feature("shadow") for top-level
# functions (see https://github.com/swig/swig/issues/980)
# Thus we'll %pythonprepend some code, and return from it,
# making the original code unreachable. Not pretty, but I
# don't have anything better at the moment.
with ida_kernwin.disabled_script_timeout_t():
return _ida_kernwin.NAME(*args)
%}
%enddef
%include <constraints.i>
// If the module is 'pro', don't import pro.h, or the %include
// at the beginning of pro.i won't have any effect. Same for all
// modules.
${ALL_IMPORTS}
// This is where all the collected NONNULL information coming
// from the SDK, will be injected in the form of 'check'
// typemaps.
${NONNULL_TYPEMAPS}
// gdl_graph_t & subclasses
%cstring_output_maxstr_none(char *iobuf, int iobufsize);
%typemap(argout) (char *iobuf, int iobufsize)
{
// %typemap(argout) (char *iobuf, int iobufsize)
qfree($1);
}
%typemap(directorout) char *get_node_label (qstring tmp)
{
// %typemap(directorout) char *get_node_label (qstring tmp)
if ( IDAPyStr_AsUTF8(&tmp, result) )
::qstrncpy(iobuf, tmp.c_str(), iobufsize);
else
Swig::DirectorTypeMismatchException::raise(
SWIG_ErrorType(SWIG_TypeError),
"in output value of type 'char *' in method '$symname'");
$result = iobuf;
}
%fragment("call_py_testf_t", "header")
{
bool call_py_testf_t(flags_t flags, void *ud)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
PyObject *py_callable = (PyObject *) ud;
QASSERT(0, PyCallable_Check(py_callable));
newref_t py_flags(PyLong_FromUnsignedLong(flags));
newref_t result(PyObject_CallFunctionObjArgs(py_callable, py_flags.o, nullptr));
return result != nullptr && PyObject_IsTrue(result.o);
}
}
%typemap(in, fragment="call_py_testf_t") (testf_t *func, void *ud)
{
// %typemap(in, fragment="call_py_testf_t") (testf_t *func, void *ud)
if ( !PyCallable_Check($input) )
SWIG_exception_fail(
SWIG_TypeError,
"in method '" "$symname" "', argument " "$argnum"" of type 'callable'");
$1 = call_py_testf_t;
$2 = $input;
}
#endif // __HEADER_I__
// END: auto-inserted header