xref: /aosp_15_r20/external/trace-cmd/python/ctracecmd.i (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1*58e6ee5fSAndroid Build Coastguard Worker // tracecmd.i
2*58e6ee5fSAndroid Build Coastguard Worker %module ctracecmd
3*58e6ee5fSAndroid Build Coastguard Worker %include "typemaps.i"
4*58e6ee5fSAndroid Build Coastguard Worker %include "constraints.i"
5*58e6ee5fSAndroid Build Coastguard Worker 
6*58e6ee5fSAndroid Build Coastguard Worker %nodefaultctor record;
7*58e6ee5fSAndroid Build Coastguard Worker %nodefaultdtor record;
8*58e6ee5fSAndroid Build Coastguard Worker 
9*58e6ee5fSAndroid Build Coastguard Worker %apply Pointer NONNULL { struct tracecmd_input *handle };
10*58e6ee5fSAndroid Build Coastguard Worker %apply Pointer NONNULL { struct tep_handle *pevent };
11*58e6ee5fSAndroid Build Coastguard Worker %apply Pointer NONNULL { struct tep_format_field * };
12*58e6ee5fSAndroid Build Coastguard Worker %apply unsigned long long *OUTPUT {unsigned long long *}
13*58e6ee5fSAndroid Build Coastguard Worker %apply int *OUTPUT {int *}
14*58e6ee5fSAndroid Build Coastguard Worker 
15*58e6ee5fSAndroid Build Coastguard Worker 
16*58e6ee5fSAndroid Build Coastguard Worker %{
17*58e6ee5fSAndroid Build Coastguard Worker #include "trace-cmd.h"
18*58e6ee5fSAndroid Build Coastguard Worker #include "event-parse.h"
19*58e6ee5fSAndroid Build Coastguard Worker #include "event-utils.h"
20*58e6ee5fSAndroid Build Coastguard Worker #include <Python.h>
21*58e6ee5fSAndroid Build Coastguard Worker %}
22*58e6ee5fSAndroid Build Coastguard Worker 
23*58e6ee5fSAndroid Build Coastguard Worker 
24*58e6ee5fSAndroid Build Coastguard Worker %typemap(in) PyObject *pyfunc {
25*58e6ee5fSAndroid Build Coastguard Worker 	if (!PyCallable_Check($input)) {
26*58e6ee5fSAndroid Build Coastguard Worker 		PyErr_SetString(PyExc_TypeError, "Need a callable object!");
27*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
28*58e6ee5fSAndroid Build Coastguard Worker 	}
29*58e6ee5fSAndroid Build Coastguard Worker 	$1 = $input;
30*58e6ee5fSAndroid Build Coastguard Worker }
31*58e6ee5fSAndroid Build Coastguard Worker 
32*58e6ee5fSAndroid Build Coastguard Worker %ignore python_callback;
33*58e6ee5fSAndroid Build Coastguard Worker 
34*58e6ee5fSAndroid Build Coastguard Worker %inline %{
35*58e6ee5fSAndroid Build Coastguard Worker static int python_callback(struct trace_seq *s,
36*58e6ee5fSAndroid Build Coastguard Worker 			   struct tep_record *record,
37*58e6ee5fSAndroid Build Coastguard Worker 			   struct tep_event *event,
38*58e6ee5fSAndroid Build Coastguard Worker 			   void *context);
39*58e6ee5fSAndroid Build Coastguard Worker 
40*58e6ee5fSAndroid Build Coastguard Worker static int skip_output = 0;
41*58e6ee5fSAndroid Build Coastguard Worker 
42*58e6ee5fSAndroid Build Coastguard Worker static void py_supress_trace_output(void)
43*58e6ee5fSAndroid Build Coastguard Worker {
44*58e6ee5fSAndroid Build Coastguard Worker 	skip_output = 1;
45*58e6ee5fSAndroid Build Coastguard Worker }
46*58e6ee5fSAndroid Build Coastguard Worker 
47*58e6ee5fSAndroid Build Coastguard Worker void warning(const char *fmt, ...)
48*58e6ee5fSAndroid Build Coastguard Worker {
49*58e6ee5fSAndroid Build Coastguard Worker 	va_list ap;
50*58e6ee5fSAndroid Build Coastguard Worker 
51*58e6ee5fSAndroid Build Coastguard Worker 	if (skip_output)
52*58e6ee5fSAndroid Build Coastguard Worker 		return;
53*58e6ee5fSAndroid Build Coastguard Worker 
54*58e6ee5fSAndroid Build Coastguard Worker 	va_start(ap, fmt);
55*58e6ee5fSAndroid Build Coastguard Worker 	tep_vprint("tracecmd", TEP_LOG_WARNING, true, fmt, ap);
56*58e6ee5fSAndroid Build Coastguard Worker 	va_end(ap);
57*58e6ee5fSAndroid Build Coastguard Worker }
58*58e6ee5fSAndroid Build Coastguard Worker 
59*58e6ee5fSAndroid Build Coastguard Worker PyObject *convert_pevent(unsigned long pevent)
60*58e6ee5fSAndroid Build Coastguard Worker {
61*58e6ee5fSAndroid Build Coastguard Worker 	void *pev = (void *)pevent;
62*58e6ee5fSAndroid Build Coastguard Worker 	return SWIG_NewPointerObj(SWIG_as_voidptr(pev), SWIGTYPE_p_tep_handle, 0);
63*58e6ee5fSAndroid Build Coastguard Worker }
64*58e6ee5fSAndroid Build Coastguard Worker 
65*58e6ee5fSAndroid Build Coastguard Worker void py_pevent_register_event_handler(struct tep_handle *pevent, int id,
66*58e6ee5fSAndroid Build Coastguard Worker 				      char *subsys, char *evname,
67*58e6ee5fSAndroid Build Coastguard Worker 				      PyObject *pyfunc)
68*58e6ee5fSAndroid Build Coastguard Worker {
69*58e6ee5fSAndroid Build Coastguard Worker 	Py_INCREF(pyfunc);
70*58e6ee5fSAndroid Build Coastguard Worker 	tep_register_event_handler(pevent, id, subsys, evname,
71*58e6ee5fSAndroid Build Coastguard Worker 				   python_callback, pyfunc);
72*58e6ee5fSAndroid Build Coastguard Worker }
73*58e6ee5fSAndroid Build Coastguard Worker 
74*58e6ee5fSAndroid Build Coastguard Worker static PyObject *py_field_get_stack(struct tep_handle *pevent,
75*58e6ee5fSAndroid Build Coastguard Worker 				    struct tep_record *record,
76*58e6ee5fSAndroid Build Coastguard Worker 				    struct tep_event *event,
77*58e6ee5fSAndroid Build Coastguard Worker 				    int long_size)
78*58e6ee5fSAndroid Build Coastguard Worker {
79*58e6ee5fSAndroid Build Coastguard Worker 	PyObject *list;
80*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field *field;
81*58e6ee5fSAndroid Build Coastguard Worker 	void *data = record->data;
82*58e6ee5fSAndroid Build Coastguard Worker 	const char *func = NULL;
83*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long addr;
84*58e6ee5fSAndroid Build Coastguard Worker 
85*58e6ee5fSAndroid Build Coastguard Worker 	field = tep_find_any_field(event, "caller");
86*58e6ee5fSAndroid Build Coastguard Worker 	if (!field) {
87*58e6ee5fSAndroid Build Coastguard Worker 		PyErr_SetString(PyExc_TypeError,
88*58e6ee5fSAndroid Build Coastguard Worker 				"Event doesn't have caller field");
89*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
90*58e6ee5fSAndroid Build Coastguard Worker 	}
91*58e6ee5fSAndroid Build Coastguard Worker 
92*58e6ee5fSAndroid Build Coastguard Worker 	list = PyList_New(0);
93*58e6ee5fSAndroid Build Coastguard Worker 
94*58e6ee5fSAndroid Build Coastguard Worker 	for (data += field->offset; data < record->data + record->size;
95*58e6ee5fSAndroid Build Coastguard Worker 	     data += long_size) {
96*58e6ee5fSAndroid Build Coastguard Worker 		addr = tep_read_number(event->tep, data, long_size);
97*58e6ee5fSAndroid Build Coastguard Worker 
98*58e6ee5fSAndroid Build Coastguard Worker 		if ((long_size == 8 && addr == (unsigned long long)-1) ||
99*58e6ee5fSAndroid Build Coastguard Worker 		    ((int)addr == -1))
100*58e6ee5fSAndroid Build Coastguard Worker 			break;
101*58e6ee5fSAndroid Build Coastguard Worker 		func = tep_find_function(event->tep, addr);
102*58e6ee5fSAndroid Build Coastguard Worker 		if (PyList_Append(list, PyUnicode_FromString(func))) {
103*58e6ee5fSAndroid Build Coastguard Worker 			Py_DECREF(list);
104*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
105*58e6ee5fSAndroid Build Coastguard Worker 		}
106*58e6ee5fSAndroid Build Coastguard Worker 	}
107*58e6ee5fSAndroid Build Coastguard Worker 
108*58e6ee5fSAndroid Build Coastguard Worker 	return list;
109*58e6ee5fSAndroid Build Coastguard Worker }
110*58e6ee5fSAndroid Build Coastguard Worker 
111*58e6ee5fSAndroid Build Coastguard Worker #if PY_MAJOR_VERSION >= 3
112*58e6ee5fSAndroid Build Coastguard Worker static PyObject *fromMemory(void *buf, size_t len)
113*58e6ee5fSAndroid Build Coastguard Worker {
114*58e6ee5fSAndroid Build Coastguard Worker 		return PyMemoryView_FromMemory(buf, len, PyBUF_READ);
115*58e6ee5fSAndroid Build Coastguard Worker }
116*58e6ee5fSAndroid Build Coastguard Worker #define PY_INT_AS_LONG PyLong_AsLong
117*58e6ee5fSAndroid Build Coastguard Worker #else
118*58e6ee5fSAndroid Build Coastguard Worker static PyObject *fromMemory(void *buf, size_t len)
119*58e6ee5fSAndroid Build Coastguard Worker {
120*58e6ee5fSAndroid Build Coastguard Worker 		return PyBuffer_FromMemory(buf, len);
121*58e6ee5fSAndroid Build Coastguard Worker }
122*58e6ee5fSAndroid Build Coastguard Worker #define PY_INT_AS_LONG PyInt_AS_LONG
123*58e6ee5fSAndroid Build Coastguard Worker #endif
124*58e6ee5fSAndroid Build Coastguard Worker 
125*58e6ee5fSAndroid Build Coastguard Worker 
126*58e6ee5fSAndroid Build Coastguard Worker 
127*58e6ee5fSAndroid Build Coastguard Worker static PyObject *py_field_get_data(struct tep_format_field *f, struct tep_record *r)
128*58e6ee5fSAndroid Build Coastguard Worker {
129*58e6ee5fSAndroid Build Coastguard Worker 	if (!strncmp(f->type, "__data_loc ", 11)) {
130*58e6ee5fSAndroid Build Coastguard Worker 		unsigned long long val;
131*58e6ee5fSAndroid Build Coastguard Worker 		int len, offset;
132*58e6ee5fSAndroid Build Coastguard Worker 
133*58e6ee5fSAndroid Build Coastguard Worker 		if (tep_read_number_field(f, r->data, &val)) {
134*58e6ee5fSAndroid Build Coastguard Worker 			PyErr_SetString(PyExc_TypeError,
135*58e6ee5fSAndroid Build Coastguard Worker 					"Field is not a valid number");
136*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
137*58e6ee5fSAndroid Build Coastguard Worker 		}
138*58e6ee5fSAndroid Build Coastguard Worker 
139*58e6ee5fSAndroid Build Coastguard Worker 		/*
140*58e6ee5fSAndroid Build Coastguard Worker 		 * The actual length of the dynamic array is stored
141*58e6ee5fSAndroid Build Coastguard Worker 		 * in the top half of the field, and the offset
142*58e6ee5fSAndroid Build Coastguard Worker 		 * is in the bottom half of the 32 bit field.
143*58e6ee5fSAndroid Build Coastguard Worker 		 */
144*58e6ee5fSAndroid Build Coastguard Worker 		offset = val & 0xffff;
145*58e6ee5fSAndroid Build Coastguard Worker 		len = val >> 16;
146*58e6ee5fSAndroid Build Coastguard Worker 
147*58e6ee5fSAndroid Build Coastguard Worker 		return fromMemory(r->data + offset, len);
148*58e6ee5fSAndroid Build Coastguard Worker 	}
149*58e6ee5fSAndroid Build Coastguard Worker 
150*58e6ee5fSAndroid Build Coastguard Worker 	return fromMemory(r->data + f->offset, f->size);
151*58e6ee5fSAndroid Build Coastguard Worker }
152*58e6ee5fSAndroid Build Coastguard Worker 
153*58e6ee5fSAndroid Build Coastguard Worker static PyObject *py_field_get_str(struct tep_format_field *f, struct tep_record *r)
154*58e6ee5fSAndroid Build Coastguard Worker {
155*58e6ee5fSAndroid Build Coastguard Worker 	if (!strncmp(f->type, "__data_loc ", 11)) {
156*58e6ee5fSAndroid Build Coastguard Worker 		unsigned long long val;
157*58e6ee5fSAndroid Build Coastguard Worker 		int offset;
158*58e6ee5fSAndroid Build Coastguard Worker 
159*58e6ee5fSAndroid Build Coastguard Worker 		if (tep_read_number_field(f, r->data, &val)) {
160*58e6ee5fSAndroid Build Coastguard Worker 			PyErr_SetString(PyExc_TypeError,
161*58e6ee5fSAndroid Build Coastguard Worker 					"Field is not a valid number");
162*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
163*58e6ee5fSAndroid Build Coastguard Worker 		}
164*58e6ee5fSAndroid Build Coastguard Worker 
165*58e6ee5fSAndroid Build Coastguard Worker 		/*
166*58e6ee5fSAndroid Build Coastguard Worker 		 * The actual length of the dynamic array is stored
167*58e6ee5fSAndroid Build Coastguard Worker 		 * in the top half of the field, and the offset
168*58e6ee5fSAndroid Build Coastguard Worker 		 * is in the bottom half of the 32 bit field.
169*58e6ee5fSAndroid Build Coastguard Worker 		 */
170*58e6ee5fSAndroid Build Coastguard Worker 		offset = val & 0xffff;
171*58e6ee5fSAndroid Build Coastguard Worker 
172*58e6ee5fSAndroid Build Coastguard Worker 		return PyUnicode_FromString((char *)r->data + offset);
173*58e6ee5fSAndroid Build Coastguard Worker 	}
174*58e6ee5fSAndroid Build Coastguard Worker 
175*58e6ee5fSAndroid Build Coastguard Worker 	return PyUnicode_FromStringAndSize((char *)r->data + f->offset,
176*58e6ee5fSAndroid Build Coastguard Worker 				strnlen((char *)r->data + f->offset, f->size));
177*58e6ee5fSAndroid Build Coastguard Worker }
178*58e6ee5fSAndroid Build Coastguard Worker 
179*58e6ee5fSAndroid Build Coastguard Worker static PyObject *py_format_get_keys(struct tep_event *ef)
180*58e6ee5fSAndroid Build Coastguard Worker {
181*58e6ee5fSAndroid Build Coastguard Worker 	PyObject *list;
182*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field *f;
183*58e6ee5fSAndroid Build Coastguard Worker 
184*58e6ee5fSAndroid Build Coastguard Worker 	list = PyList_New(0);
185*58e6ee5fSAndroid Build Coastguard Worker 
186*58e6ee5fSAndroid Build Coastguard Worker 	for (f = ef->format.fields; f; f = f->next) {
187*58e6ee5fSAndroid Build Coastguard Worker 		if (PyList_Append(list, PyUnicode_FromString(f->name))) {
188*58e6ee5fSAndroid Build Coastguard Worker 			Py_DECREF(list);
189*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
190*58e6ee5fSAndroid Build Coastguard Worker 		}
191*58e6ee5fSAndroid Build Coastguard Worker 	}
192*58e6ee5fSAndroid Build Coastguard Worker 
193*58e6ee5fSAndroid Build Coastguard Worker 	return list;
194*58e6ee5fSAndroid Build Coastguard Worker }
195*58e6ee5fSAndroid Build Coastguard Worker %}
196*58e6ee5fSAndroid Build Coastguard Worker 
197*58e6ee5fSAndroid Build Coastguard Worker 
198*58e6ee5fSAndroid Build Coastguard Worker %wrapper %{
199*58e6ee5fSAndroid Build Coastguard Worker static int python_callback(struct trace_seq *s,
200*58e6ee5fSAndroid Build Coastguard Worker 			   struct tep_record *record,
201*58e6ee5fSAndroid Build Coastguard Worker 			   struct tep_event *event,
202*58e6ee5fSAndroid Build Coastguard Worker 			   void *context)
203*58e6ee5fSAndroid Build Coastguard Worker {
204*58e6ee5fSAndroid Build Coastguard Worker 	PyObject *arglist, *result;
205*58e6ee5fSAndroid Build Coastguard Worker 	int r = 0;
206*58e6ee5fSAndroid Build Coastguard Worker 
207*58e6ee5fSAndroid Build Coastguard Worker 	record->ref_count++;
208*58e6ee5fSAndroid Build Coastguard Worker 
209*58e6ee5fSAndroid Build Coastguard Worker 	arglist = Py_BuildValue("(OOO)",
210*58e6ee5fSAndroid Build Coastguard Worker 		SWIG_NewPointerObj(SWIG_as_voidptr(s),
211*58e6ee5fSAndroid Build Coastguard Worker 				   SWIGTYPE_p_trace_seq, 0),
212*58e6ee5fSAndroid Build Coastguard Worker 		SWIG_NewPointerObj(SWIG_as_voidptr(record),
213*58e6ee5fSAndroid Build Coastguard Worker 				   SWIGTYPE_p_tep_record, 0),
214*58e6ee5fSAndroid Build Coastguard Worker 		SWIG_NewPointerObj(SWIG_as_voidptr(event),
215*58e6ee5fSAndroid Build Coastguard Worker 				   SWIGTYPE_p_tep_event, 0));
216*58e6ee5fSAndroid Build Coastguard Worker 
217*58e6ee5fSAndroid Build Coastguard Worker 	result = PyEval_CallObject(context, arglist);
218*58e6ee5fSAndroid Build Coastguard Worker 	Py_XDECREF(arglist);
219*58e6ee5fSAndroid Build Coastguard Worker 	if (result && result != Py_None) {
220*58e6ee5fSAndroid Build Coastguard Worker 		if (!PyInt_Check(result)) {
221*58e6ee5fSAndroid Build Coastguard Worker 			PyErr_SetString(PyExc_TypeError,
222*58e6ee5fSAndroid Build Coastguard Worker 					"callback must return int");
223*58e6ee5fSAndroid Build Coastguard Worker 			PyErr_Print();
224*58e6ee5fSAndroid Build Coastguard Worker 			Py_XDECREF(result);
225*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
226*58e6ee5fSAndroid Build Coastguard Worker 		}
227*58e6ee5fSAndroid Build Coastguard Worker 		r = PY_INT_AS_LONG(result);
228*58e6ee5fSAndroid Build Coastguard Worker 	} else if (result == Py_None)
229*58e6ee5fSAndroid Build Coastguard Worker 		r = 0;
230*58e6ee5fSAndroid Build Coastguard Worker 	else
231*58e6ee5fSAndroid Build Coastguard Worker 		PyErr_Print();
232*58e6ee5fSAndroid Build Coastguard Worker 
233*58e6ee5fSAndroid Build Coastguard Worker 	Py_XDECREF(result);
234*58e6ee5fSAndroid Build Coastguard Worker 
235*58e6ee5fSAndroid Build Coastguard Worker 	return r;
236*58e6ee5fSAndroid Build Coastguard Worker }
237*58e6ee5fSAndroid Build Coastguard Worker %}
238*58e6ee5fSAndroid Build Coastguard Worker 
239*58e6ee5fSAndroid Build Coastguard Worker 
240*58e6ee5fSAndroid Build Coastguard Worker %ignore trace_seq_vprintf;
241*58e6ee5fSAndroid Build Coastguard Worker %ignore vpr_stat;
242*58e6ee5fSAndroid Build Coastguard Worker 
243*58e6ee5fSAndroid Build Coastguard Worker /* SWIG can't grok these, define them to nothing */
244*58e6ee5fSAndroid Build Coastguard Worker #define __trace
245*58e6ee5fSAndroid Build Coastguard Worker #define __attribute__(x)
246*58e6ee5fSAndroid Build Coastguard Worker #define __thread
247*58e6ee5fSAndroid Build Coastguard Worker 
248*58e6ee5fSAndroid Build Coastguard Worker %include "trace-cmd.h"
249*58e6ee5fSAndroid Build Coastguard Worker %include <trace-seq.h>
250*58e6ee5fSAndroid Build Coastguard Worker %include <event-parse.h>
251