251 lines
5.3 KiB
OpenEdge ABL
251 lines
5.3 KiB
OpenEdge ABL
// tracecmd.i
|
|
%module ctracecmd
|
|
%include "typemaps.i"
|
|
%include "constraints.i"
|
|
|
|
%nodefaultctor record;
|
|
%nodefaultdtor record;
|
|
|
|
%apply Pointer NONNULL { struct tracecmd_input *handle };
|
|
%apply Pointer NONNULL { struct tep_handle *pevent };
|
|
%apply Pointer NONNULL { struct tep_format_field * };
|
|
%apply unsigned long long *OUTPUT {unsigned long long *}
|
|
%apply int *OUTPUT {int *}
|
|
|
|
|
|
%{
|
|
#include "trace-cmd.h"
|
|
#include "event-parse.h"
|
|
#include "event-utils.h"
|
|
#include <Python.h>
|
|
%}
|
|
|
|
|
|
%typemap(in) PyObject *pyfunc {
|
|
if (!PyCallable_Check($input)) {
|
|
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
|
|
return NULL;
|
|
}
|
|
$1 = $input;
|
|
}
|
|
|
|
%ignore python_callback;
|
|
|
|
%inline %{
|
|
static int python_callback(struct trace_seq *s,
|
|
struct tep_record *record,
|
|
struct tep_event *event,
|
|
void *context);
|
|
|
|
static int skip_output = 0;
|
|
|
|
static void py_supress_trace_output(void)
|
|
{
|
|
skip_output = 1;
|
|
}
|
|
|
|
void warning(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
if (skip_output)
|
|
return;
|
|
|
|
va_start(ap, fmt);
|
|
tep_vprint("tracecmd", TEP_LOG_WARNING, true, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
PyObject *convert_pevent(unsigned long pevent)
|
|
{
|
|
void *pev = (void *)pevent;
|
|
return SWIG_NewPointerObj(SWIG_as_voidptr(pev), SWIGTYPE_p_tep_handle, 0);
|
|
}
|
|
|
|
void py_pevent_register_event_handler(struct tep_handle *pevent, int id,
|
|
char *subsys, char *evname,
|
|
PyObject *pyfunc)
|
|
{
|
|
Py_INCREF(pyfunc);
|
|
tep_register_event_handler(pevent, id, subsys, evname,
|
|
python_callback, pyfunc);
|
|
}
|
|
|
|
static PyObject *py_field_get_stack(struct tep_handle *pevent,
|
|
struct tep_record *record,
|
|
struct tep_event *event,
|
|
int long_size)
|
|
{
|
|
PyObject *list;
|
|
struct tep_format_field *field;
|
|
void *data = record->data;
|
|
const char *func = NULL;
|
|
unsigned long addr;
|
|
|
|
field = tep_find_any_field(event, "caller");
|
|
if (!field) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"Event doesn't have caller field");
|
|
return NULL;
|
|
}
|
|
|
|
list = PyList_New(0);
|
|
|
|
for (data += field->offset; data < record->data + record->size;
|
|
data += long_size) {
|
|
addr = tep_read_number(event->tep, data, long_size);
|
|
|
|
if ((long_size == 8 && addr == (unsigned long long)-1) ||
|
|
((int)addr == -1))
|
|
break;
|
|
func = tep_find_function(event->tep, addr);
|
|
if (PyList_Append(list, PyUnicode_FromString(func))) {
|
|
Py_DECREF(list);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
static PyObject *fromMemory(void *buf, size_t len)
|
|
{
|
|
return PyMemoryView_FromMemory(buf, len, PyBUF_READ);
|
|
}
|
|
#define PY_INT_AS_LONG PyLong_AsLong
|
|
#else
|
|
static PyObject *fromMemory(void *buf, size_t len)
|
|
{
|
|
return PyBuffer_FromMemory(buf, len);
|
|
}
|
|
#define PY_INT_AS_LONG PyInt_AS_LONG
|
|
#endif
|
|
|
|
|
|
|
|
static PyObject *py_field_get_data(struct tep_format_field *f, struct tep_record *r)
|
|
{
|
|
if (!strncmp(f->type, "__data_loc ", 11)) {
|
|
unsigned long long val;
|
|
int len, offset;
|
|
|
|
if (tep_read_number_field(f, r->data, &val)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"Field is not a valid number");
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* The actual length of the dynamic array is stored
|
|
* in the top half of the field, and the offset
|
|
* is in the bottom half of the 32 bit field.
|
|
*/
|
|
offset = val & 0xffff;
|
|
len = val >> 16;
|
|
|
|
return fromMemory(r->data + offset, len);
|
|
}
|
|
|
|
return fromMemory(r->data + f->offset, f->size);
|
|
}
|
|
|
|
static PyObject *py_field_get_str(struct tep_format_field *f, struct tep_record *r)
|
|
{
|
|
if (!strncmp(f->type, "__data_loc ", 11)) {
|
|
unsigned long long val;
|
|
int offset;
|
|
|
|
if (tep_read_number_field(f, r->data, &val)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"Field is not a valid number");
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* The actual length of the dynamic array is stored
|
|
* in the top half of the field, and the offset
|
|
* is in the bottom half of the 32 bit field.
|
|
*/
|
|
offset = val & 0xffff;
|
|
|
|
return PyUnicode_FromString((char *)r->data + offset);
|
|
}
|
|
|
|
return PyUnicode_FromStringAndSize((char *)r->data + f->offset,
|
|
strnlen((char *)r->data + f->offset, f->size));
|
|
}
|
|
|
|
static PyObject *py_format_get_keys(struct tep_event *ef)
|
|
{
|
|
PyObject *list;
|
|
struct tep_format_field *f;
|
|
|
|
list = PyList_New(0);
|
|
|
|
for (f = ef->format.fields; f; f = f->next) {
|
|
if (PyList_Append(list, PyUnicode_FromString(f->name))) {
|
|
Py_DECREF(list);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
%}
|
|
|
|
|
|
%wrapper %{
|
|
static int python_callback(struct trace_seq *s,
|
|
struct tep_record *record,
|
|
struct tep_event *event,
|
|
void *context)
|
|
{
|
|
PyObject *arglist, *result;
|
|
int r = 0;
|
|
|
|
record->ref_count++;
|
|
|
|
arglist = Py_BuildValue("(OOO)",
|
|
SWIG_NewPointerObj(SWIG_as_voidptr(s),
|
|
SWIGTYPE_p_trace_seq, 0),
|
|
SWIG_NewPointerObj(SWIG_as_voidptr(record),
|
|
SWIGTYPE_p_tep_record, 0),
|
|
SWIG_NewPointerObj(SWIG_as_voidptr(event),
|
|
SWIGTYPE_p_tep_event, 0));
|
|
|
|
result = PyEval_CallObject(context, arglist);
|
|
Py_XDECREF(arglist);
|
|
if (result && result != Py_None) {
|
|
if (!PyInt_Check(result)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"callback must return int");
|
|
PyErr_Print();
|
|
Py_XDECREF(result);
|
|
return 0;
|
|
}
|
|
r = PY_INT_AS_LONG(result);
|
|
} else if (result == Py_None)
|
|
r = 0;
|
|
else
|
|
PyErr_Print();
|
|
|
|
Py_XDECREF(result);
|
|
|
|
return r;
|
|
}
|
|
%}
|
|
|
|
|
|
%ignore trace_seq_vprintf;
|
|
%ignore vpr_stat;
|
|
|
|
/* SWIG can't grok these, define them to nothing */
|
|
#define __trace
|
|
#define __attribute__(x)
|
|
#define __thread
|
|
|
|
%include "trace-cmd.h"
|
|
%include <trace-seq.h>
|
|
%include <event-parse.h>
|