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