Commit | Line | Data |
---|---|---|
7e4b21b8 TZ |
1 | /* |
2 | * trace-event-python. Feed trace events to an embedded Python interpreter. | |
3 | * | |
4 | * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | * | |
20 | */ | |
21 | ||
22 | #include <Python.h> | |
23 | ||
fd20e811 | 24 | #include <inttypes.h> |
7e4b21b8 TZ |
25 | #include <stdio.h> |
26 | #include <stdlib.h> | |
27 | #include <string.h> | |
df919b40 | 28 | #include <stdbool.h> |
7e4b21b8 | 29 | #include <errno.h> |
adf5bcf3 | 30 | #include <linux/bitmap.h> |
6c346643 | 31 | #include <linux/compiler.h> |
bd48c63e | 32 | #include <linux/time64.h> |
80c3a7d9 | 33 | #ifdef HAVE_LIBTRACEEVENT |
35de42cd | 34 | #include <event-parse.h> |
80c3a7d9 | 35 | #endif |
7e4b21b8 | 36 | |
4a3cec84 | 37 | #include "../build-id.h" |
430482c2 | 38 | #include "../counts.h" |
84f5d36f | 39 | #include "../debug.h" |
4a3cec84 | 40 | #include "../dso.h" |
8f651eae | 41 | #include "../callchain.h" |
83869019 | 42 | #include "../env.h" |
fcf65bf1 | 43 | #include "../evsel.h" |
743eb868 ACM |
44 | #include "../event.h" |
45 | #include "../thread.h" | |
df919b40 AH |
46 | #include "../comm.h" |
47 | #include "../machine.h" | |
ad3003a6 | 48 | #include "../mem-info.h" |
df919b40 | 49 | #include "../db-export.h" |
6a70307d | 50 | #include "../thread-stack.h" |
7e4b21b8 | 51 | #include "../trace-event.h" |
451db126 | 52 | #include "../call-path.h" |
1101f69a | 53 | #include "map.h" |
daecf9e0 | 54 | #include "symbol.h" |
aef90263 | 55 | #include "thread_map.h" |
fea01392 | 56 | #include "print_binary.h" |
aef90263 | 57 | #include "stat.h" |
48a1f565 | 58 | #include "mem-events.h" |
06bf28cb | 59 | #include "util/perf_regs.h" |
7e4b21b8 | 60 | |
66dfdff0 JŠ |
61 | #define _PyUnicode_FromString(arg) \ |
62 | PyUnicode_FromString(arg) | |
63 | #define _PyUnicode_FromStringAndSize(arg1, arg2) \ | |
64 | PyUnicode_FromStringAndSize((arg1), (arg2)) | |
65 | #define _PyBytes_FromStringAndSize(arg1, arg2) \ | |
66 | PyBytes_FromStringAndSize((arg1), (arg2)) | |
67 | #define _PyLong_FromLong(arg) \ | |
68 | PyLong_FromLong(arg) | |
69 | #define _PyLong_AsLong(arg) \ | |
70 | PyLong_AsLong(arg) | |
71 | #define _PyCapsule_New(arg1, arg2, arg3) \ | |
72 | PyCapsule_New((arg1), (arg2), (arg3)) | |
73 | ||
74 | PyMODINIT_FUNC PyInit_perf_trace_context(void); | |
7e4b21b8 | 75 | |
80c3a7d9 | 76 | #ifdef HAVE_LIBTRACEEVENT |
609a7404 | 77 | #define TRACE_EVENT_TYPE_MAX \ |
7e4b21b8 TZ |
78 | ((1 << (sizeof(unsigned short) * 8)) - 1) |
79 | ||
7e4b21b8 TZ |
80 | #define N_COMMON_FIELDS 7 |
81 | ||
7e4b21b8 TZ |
82 | static char *cur_field_name; |
83 | static int zero_flag_atom; | |
80c3a7d9 AH |
84 | #endif |
85 | ||
86 | #define MAX_FIELDS 64 | |
87 | ||
88 | extern struct scripting_context *scripting_context; | |
7e4b21b8 TZ |
89 | |
90 | static PyObject *main_module, *main_dict; | |
91 | ||
df919b40 AH |
92 | struct tables { |
93 | struct db_export dbe; | |
94 | PyObject *evsel_handler; | |
95 | PyObject *machine_handler; | |
96 | PyObject *thread_handler; | |
97 | PyObject *comm_handler; | |
98 | PyObject *comm_thread_handler; | |
99 | PyObject *dso_handler; | |
100 | PyObject *symbol_handler; | |
c29414f5 | 101 | PyObject *branch_type_handler; |
df919b40 | 102 | PyObject *sample_handler; |
6a70307d AH |
103 | PyObject *call_path_handler; |
104 | PyObject *call_return_handler; | |
b9322cab | 105 | PyObject *synth_handler; |
abde8722 | 106 | PyObject *context_switch_handler; |
df919b40 AH |
107 | bool db_export_mode; |
108 | }; | |
109 | ||
110 | static struct tables tables_global; | |
111 | ||
6c346643 | 112 | static void handler_call_die(const char *handler_name) __noreturn; |
7e4b21b8 TZ |
113 | static void handler_call_die(const char *handler_name) |
114 | { | |
115 | PyErr_Print(); | |
116 | Py_FatalError("problem in Python trace event handler"); | |
05f832e3 JS |
117 | // Py_FatalError does not return |
118 | // but we have to make the compiler happy | |
119 | abort(); | |
7e4b21b8 TZ |
120 | } |
121 | ||
c0268e8d | 122 | /* |
0029e8ac | 123 | * Insert val into the dictionary and decrement the reference counter. |
48000a1a | 124 | * This is necessary for dictionaries since PyDict_SetItemString() does not |
c0268e8d JS |
125 | * steal a reference, as opposed to PyTuple_SetItem(). |
126 | */ | |
127 | static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val) | |
128 | { | |
129 | PyDict_SetItemString(dict, key, val); | |
130 | Py_DECREF(val); | |
131 | } | |
132 | ||
a5563edf AH |
133 | static PyObject *get_handler(const char *handler_name) |
134 | { | |
135 | PyObject *handler; | |
136 | ||
137 | handler = PyDict_GetItemString(main_dict, handler_name); | |
138 | if (handler && !PyCallable_Check(handler)) | |
139 | return NULL; | |
140 | return handler; | |
141 | } | |
142 | ||
80c3a7d9 AH |
143 | static void call_object(PyObject *handler, PyObject *args, const char *die_msg) |
144 | { | |
145 | PyObject *retval; | |
146 | ||
147 | retval = PyObject_CallObject(handler, args); | |
148 | if (retval == NULL) | |
149 | handler_call_die(die_msg); | |
150 | Py_DECREF(retval); | |
151 | } | |
152 | ||
153 | static void try_call_object(const char *handler_name, PyObject *args) | |
154 | { | |
155 | PyObject *handler; | |
156 | ||
157 | handler = get_handler(handler_name); | |
158 | if (handler) | |
159 | call_object(handler, args, handler_name); | |
160 | } | |
161 | ||
162 | #ifdef HAVE_LIBTRACEEVENT | |
f38d2816 AK |
163 | static int get_argument_count(PyObject *handler) |
164 | { | |
165 | int arg_count = 0; | |
166 | ||
e7e9943c | 167 | PyObject *code_obj = code_obj = PyObject_GetAttrString(handler, "__code__"); |
f38d2816 AK |
168 | PyErr_Clear(); |
169 | if (code_obj) { | |
170 | PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, | |
171 | "co_argcount"); | |
172 | if (arg_count_obj) { | |
66dfdff0 | 173 | arg_count = (int) _PyLong_AsLong(arg_count_obj); |
f38d2816 AK |
174 | Py_DECREF(arg_count_obj); |
175 | } | |
176 | Py_DECREF(code_obj); | |
177 | } | |
178 | return arg_count; | |
179 | } | |
180 | ||
1e97216f | 181 | static void define_value(enum tep_print_arg_type field_type, |
7e4b21b8 TZ |
182 | const char *ev_name, |
183 | const char *field_name, | |
184 | const char *field_value, | |
185 | const char *field_str) | |
186 | { | |
187 | const char *handler_name = "define_flag_value"; | |
a5563edf | 188 | PyObject *t; |
7e4b21b8 TZ |
189 | unsigned long long value; |
190 | unsigned n = 0; | |
191 | ||
1e97216f | 192 | if (field_type == TEP_PRINT_SYMBOL) |
7e4b21b8 TZ |
193 | handler_name = "define_symbolic_value"; |
194 | ||
44ad9cd8 | 195 | t = PyTuple_New(4); |
7e4b21b8 TZ |
196 | if (!t) |
197 | Py_FatalError("couldn't create Python tuple"); | |
198 | ||
199 | value = eval_flag(field_value); | |
200 | ||
66dfdff0 JŠ |
201 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); |
202 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); | |
203 | PyTuple_SetItem(t, n++, _PyLong_FromLong(value)); | |
204 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str)); | |
7e4b21b8 | 205 | |
a5563edf | 206 | try_call_object(handler_name, t); |
7e4b21b8 TZ |
207 | |
208 | Py_DECREF(t); | |
209 | } | |
210 | ||
1e97216f | 211 | static void define_values(enum tep_print_arg_type field_type, |
5647f94b | 212 | struct tep_print_flag_sym *field, |
7e4b21b8 TZ |
213 | const char *ev_name, |
214 | const char *field_name) | |
215 | { | |
216 | define_value(field_type, ev_name, field_name, field->value, | |
217 | field->str); | |
218 | ||
219 | if (field->next) | |
220 | define_values(field_type, field->next, ev_name, field_name); | |
221 | } | |
222 | ||
1e97216f | 223 | static void define_field(enum tep_print_arg_type field_type, |
7e4b21b8 TZ |
224 | const char *ev_name, |
225 | const char *field_name, | |
226 | const char *delim) | |
227 | { | |
228 | const char *handler_name = "define_flag_field"; | |
a5563edf | 229 | PyObject *t; |
7e4b21b8 TZ |
230 | unsigned n = 0; |
231 | ||
1e97216f | 232 | if (field_type == TEP_PRINT_SYMBOL) |
7e4b21b8 TZ |
233 | handler_name = "define_symbolic_field"; |
234 | ||
1e97216f | 235 | if (field_type == TEP_PRINT_FLAGS) |
44ad9cd8 TZ |
236 | t = PyTuple_New(3); |
237 | else | |
238 | t = PyTuple_New(2); | |
7e4b21b8 TZ |
239 | if (!t) |
240 | Py_FatalError("couldn't create Python tuple"); | |
241 | ||
66dfdff0 JŠ |
242 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); |
243 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); | |
1e97216f | 244 | if (field_type == TEP_PRINT_FLAGS) |
66dfdff0 | 245 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); |
7e4b21b8 | 246 | |
a5563edf | 247 | try_call_object(handler_name, t); |
7e4b21b8 TZ |
248 | |
249 | Py_DECREF(t); | |
250 | } | |
251 | ||
97fbf3f0 | 252 | static void define_event_symbols(struct tep_event *event, |
7e4b21b8 | 253 | const char *ev_name, |
5647f94b | 254 | struct tep_print_arg *args) |
7e4b21b8 | 255 | { |
8579aca3 TS |
256 | if (args == NULL) |
257 | return; | |
258 | ||
7e4b21b8 | 259 | switch (args->type) { |
1e97216f | 260 | case TEP_PRINT_NULL: |
7e4b21b8 | 261 | break; |
1e97216f TSV |
262 | case TEP_PRINT_ATOM: |
263 | define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0", | |
7e4b21b8 TZ |
264 | args->atom.atom); |
265 | zero_flag_atom = 0; | |
266 | break; | |
1e97216f | 267 | case TEP_PRINT_FIELD: |
f5385650 | 268 | free(cur_field_name); |
7e4b21b8 TZ |
269 | cur_field_name = strdup(args->field.name); |
270 | break; | |
1e97216f | 271 | case TEP_PRINT_FLAGS: |
7e4b21b8 | 272 | define_event_symbols(event, ev_name, args->flags.field); |
1e97216f | 273 | define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name, |
7e4b21b8 | 274 | args->flags.delim); |
1e97216f | 275 | define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name, |
7e4b21b8 TZ |
276 | cur_field_name); |
277 | break; | |
1e97216f | 278 | case TEP_PRINT_SYMBOL: |
7e4b21b8 | 279 | define_event_symbols(event, ev_name, args->symbol.field); |
1e97216f TSV |
280 | define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL); |
281 | define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name, | |
7e4b21b8 TZ |
282 | cur_field_name); |
283 | break; | |
1e97216f TSV |
284 | case TEP_PRINT_HEX: |
285 | case TEP_PRINT_HEX_STR: | |
e080e6f1 NK |
286 | define_event_symbols(event, ev_name, args->hex.field); |
287 | define_event_symbols(event, ev_name, args->hex.size); | |
288 | break; | |
1e97216f | 289 | case TEP_PRINT_INT_ARRAY: |
b839e1e8 JM |
290 | define_event_symbols(event, ev_name, args->int_array.field); |
291 | define_event_symbols(event, ev_name, args->int_array.count); | |
292 | define_event_symbols(event, ev_name, args->int_array.el_size); | |
293 | break; | |
1e97216f | 294 | case TEP_PRINT_STRING: |
7e4b21b8 | 295 | break; |
1e97216f | 296 | case TEP_PRINT_TYPE: |
7e4b21b8 TZ |
297 | define_event_symbols(event, ev_name, args->typecast.item); |
298 | break; | |
1e97216f | 299 | case TEP_PRINT_OP: |
7e4b21b8 TZ |
300 | if (strcmp(args->op.op, ":") == 0) |
301 | zero_flag_atom = 1; | |
302 | define_event_symbols(event, ev_name, args->op.left); | |
303 | define_event_symbols(event, ev_name, args->op.right); | |
304 | break; | |
305 | default: | |
aaf045f7 | 306 | /* gcc warns for these? */ |
1e97216f TSV |
307 | case TEP_PRINT_BSTRING: |
308 | case TEP_PRINT_DYNAMIC_ARRAY: | |
309 | case TEP_PRINT_DYNAMIC_ARRAY_LEN: | |
310 | case TEP_PRINT_FUNC: | |
311 | case TEP_PRINT_BITMASK: | |
7e4b21b8 TZ |
312 | /* we should warn... */ |
313 | return; | |
314 | } | |
315 | ||
316 | if (args->next) | |
317 | define_event_symbols(event, ev_name, args->next); | |
318 | } | |
319 | ||
97fbf3f0 | 320 | static PyObject *get_field_numeric_entry(struct tep_event *event, |
2c92f982 | 321 | struct tep_format_field *field, void *data) |
33058b94 | 322 | { |
bb39ccb2 | 323 | bool is_array = field->flags & TEP_FIELD_IS_ARRAY; |
39f54862 | 324 | PyObject *obj = NULL, *list = NULL; |
33058b94 | 325 | unsigned long long val; |
8ac631cd | 326 | unsigned int item_size, n_items, i; |
33058b94 | 327 | |
8ac631cd SAS |
328 | if (is_array) { |
329 | list = PyList_New(field->arraylen); | |
b457c526 PL |
330 | if (!list) |
331 | Py_FatalError("couldn't create Python list"); | |
8ac631cd SAS |
332 | item_size = field->size / field->arraylen; |
333 | n_items = field->arraylen; | |
33058b94 | 334 | } else { |
8ac631cd SAS |
335 | item_size = field->size; |
336 | n_items = 1; | |
33058b94 | 337 | } |
8ac631cd SAS |
338 | |
339 | for (i = 0; i < n_items; i++) { | |
340 | ||
341 | val = read_size(event, data + field->offset + i * item_size, | |
342 | item_size); | |
bb39ccb2 | 343 | if (field->flags & TEP_FIELD_IS_SIGNED) { |
8ac631cd SAS |
344 | if ((long long)val >= LONG_MIN && |
345 | (long long)val <= LONG_MAX) | |
66dfdff0 | 346 | obj = _PyLong_FromLong(val); |
8ac631cd SAS |
347 | else |
348 | obj = PyLong_FromLongLong(val); | |
349 | } else { | |
350 | if (val <= LONG_MAX) | |
66dfdff0 | 351 | obj = _PyLong_FromLong(val); |
8ac631cd SAS |
352 | else |
353 | obj = PyLong_FromUnsignedLongLong(val); | |
354 | } | |
355 | if (is_array) | |
356 | PyList_SET_ITEM(list, i, obj); | |
357 | } | |
358 | if (is_array) | |
359 | obj = list; | |
33058b94 SAS |
360 | return obj; |
361 | } | |
80c3a7d9 | 362 | #endif |
33058b94 | 363 | |
5f9e0f31 JY |
364 | static const char *get_dsoname(struct map *map) |
365 | { | |
366 | const char *dsoname = "[unknown]"; | |
63df0e4b | 367 | struct dso *dso = map ? map__dso(map) : NULL; |
5f9e0f31 | 368 | |
63df0e4b | 369 | if (dso) { |
ee756ef7 IR |
370 | if (symbol_conf.show_kernel_path && dso__long_name(dso)) |
371 | dsoname = dso__long_name(dso); | |
5f9e0f31 | 372 | else |
ee756ef7 | 373 | dsoname = dso__name(dso); |
5f9e0f31 JY |
374 | } |
375 | ||
376 | return dsoname; | |
377 | } | |
0f5f5bcd | 378 | |
ae24e9b5 EC |
379 | static unsigned long get_offset(struct symbol *sym, struct addr_location *al) |
380 | { | |
381 | unsigned long offset; | |
382 | ||
383 | if (al->addr < sym->end) | |
384 | offset = al->addr - sym->start; | |
385 | else | |
e5116f46 | 386 | offset = al->addr - map__start(al->map) - sym->start; |
ae24e9b5 EC |
387 | |
388 | return offset; | |
389 | } | |
390 | ||
0f5f5bcd | 391 | static PyObject *python_process_callchain(struct perf_sample *sample, |
32dcd021 | 392 | struct evsel *evsel, |
0f5f5bcd JS |
393 | struct addr_location *al) |
394 | { | |
395 | PyObject *pylist; | |
8ab12a20 | 396 | struct callchain_cursor *cursor; |
0f5f5bcd JS |
397 | |
398 | pylist = PyList_New(0); | |
399 | if (!pylist) | |
400 | Py_FatalError("couldn't create Python list"); | |
401 | ||
402 | if (!symbol_conf.use_callchain || !sample->callchain) | |
403 | goto exit; | |
404 | ||
8ab12a20 IR |
405 | cursor = get_tls_callchain_cursor(); |
406 | if (thread__resolve_callchain(al->thread, cursor, evsel, | |
cc8b7c2b | 407 | sample, NULL, NULL, |
44cbe729 | 408 | scripting_max_stack) != 0) { |
0f5f5bcd JS |
409 | pr_err("Failed to resolve callchain. Skipping\n"); |
410 | goto exit; | |
411 | } | |
8ab12a20 | 412 | callchain_cursor_commit(cursor); |
0f5f5bcd JS |
413 | |
414 | ||
415 | while (1) { | |
416 | PyObject *pyelem; | |
417 | struct callchain_cursor_node *node; | |
8ab12a20 | 418 | node = callchain_cursor_current(cursor); |
0f5f5bcd JS |
419 | if (!node) |
420 | break; | |
421 | ||
422 | pyelem = PyDict_New(); | |
423 | if (!pyelem) | |
424 | Py_FatalError("couldn't create Python dictionary"); | |
425 | ||
426 | ||
427 | pydict_set_item_string_decref(pyelem, "ip", | |
428 | PyLong_FromUnsignedLongLong(node->ip)); | |
429 | ||
5f0fef8a | 430 | if (node->ms.sym) { |
0f5f5bcd JS |
431 | PyObject *pysym = PyDict_New(); |
432 | if (!pysym) | |
433 | Py_FatalError("couldn't create Python dictionary"); | |
434 | pydict_set_item_string_decref(pysym, "start", | |
5f0fef8a | 435 | PyLong_FromUnsignedLongLong(node->ms.sym->start)); |
0f5f5bcd | 436 | pydict_set_item_string_decref(pysym, "end", |
5f0fef8a | 437 | PyLong_FromUnsignedLongLong(node->ms.sym->end)); |
0f5f5bcd | 438 | pydict_set_item_string_decref(pysym, "binding", |
5f0fef8a | 439 | _PyLong_FromLong(node->ms.sym->binding)); |
0f5f5bcd | 440 | pydict_set_item_string_decref(pysym, "name", |
5f0fef8a ACM |
441 | _PyUnicode_FromStringAndSize(node->ms.sym->name, |
442 | node->ms.sym->namelen)); | |
0f5f5bcd | 443 | pydict_set_item_string_decref(pyelem, "sym", pysym); |
ae24e9b5 EC |
444 | |
445 | if (node->ms.map) { | |
446 | struct map *map = node->ms.map; | |
447 | struct addr_location node_al; | |
448 | unsigned long offset; | |
449 | ||
0dd5041c | 450 | addr_location__init(&node_al); |
78a1f7cd | 451 | node_al.addr = map__map_ip(map, node->ip); |
0dd5041c | 452 | node_al.map = map__get(map); |
ae24e9b5 | 453 | offset = get_offset(node->ms.sym, &node_al); |
0dd5041c | 454 | addr_location__exit(&node_al); |
ae24e9b5 EC |
455 | |
456 | pydict_set_item_string_decref( | |
457 | pyelem, "sym_off", | |
458 | PyLong_FromUnsignedLongLong(offset)); | |
459 | } | |
460 | if (node->srcline && strcmp(":0", node->srcline)) { | |
461 | pydict_set_item_string_decref( | |
462 | pyelem, "sym_srcline", | |
463 | _PyUnicode_FromString(node->srcline)); | |
464 | } | |
0f5f5bcd JS |
465 | } |
466 | ||
5f0fef8a ACM |
467 | if (node->ms.map) { |
468 | const char *dsoname = get_dsoname(node->ms.map); | |
5f9e0f31 | 469 | |
0f5f5bcd | 470 | pydict_set_item_string_decref(pyelem, "dso", |
66dfdff0 | 471 | _PyUnicode_FromString(dsoname)); |
0f5f5bcd JS |
472 | } |
473 | ||
8ab12a20 | 474 | callchain_cursor_advance(cursor); |
0f5f5bcd JS |
475 | PyList_Append(pylist, pyelem); |
476 | Py_DECREF(pyelem); | |
477 | } | |
478 | ||
479 | exit: | |
480 | return pylist; | |
481 | } | |
482 | ||
48a1f565 JY |
483 | static PyObject *python_process_brstack(struct perf_sample *sample, |
484 | struct thread *thread) | |
485 | { | |
486 | struct branch_stack *br = sample->branch_stack; | |
42bbabed | 487 | struct branch_entry *entries = perf_sample__branch_entries(sample); |
48a1f565 JY |
488 | PyObject *pylist; |
489 | u64 i; | |
490 | ||
491 | pylist = PyList_New(0); | |
492 | if (!pylist) | |
493 | Py_FatalError("couldn't create Python list"); | |
494 | ||
495 | if (!(br && br->nr)) | |
496 | goto exit; | |
497 | ||
498 | for (i = 0; i < br->nr; i++) { | |
499 | PyObject *pyelem; | |
500 | struct addr_location al; | |
501 | const char *dsoname; | |
502 | ||
503 | pyelem = PyDict_New(); | |
504 | if (!pyelem) | |
505 | Py_FatalError("couldn't create Python dictionary"); | |
506 | ||
507 | pydict_set_item_string_decref(pyelem, "from", | |
42bbabed | 508 | PyLong_FromUnsignedLongLong(entries[i].from)); |
48a1f565 | 509 | pydict_set_item_string_decref(pyelem, "to", |
42bbabed | 510 | PyLong_FromUnsignedLongLong(entries[i].to)); |
48a1f565 | 511 | pydict_set_item_string_decref(pyelem, "mispred", |
42bbabed | 512 | PyBool_FromLong(entries[i].flags.mispred)); |
48a1f565 | 513 | pydict_set_item_string_decref(pyelem, "predicted", |
42bbabed | 514 | PyBool_FromLong(entries[i].flags.predicted)); |
48a1f565 | 515 | pydict_set_item_string_decref(pyelem, "in_tx", |
42bbabed | 516 | PyBool_FromLong(entries[i].flags.in_tx)); |
48a1f565 | 517 | pydict_set_item_string_decref(pyelem, "abort", |
42bbabed | 518 | PyBool_FromLong(entries[i].flags.abort)); |
48a1f565 | 519 | pydict_set_item_string_decref(pyelem, "cycles", |
42bbabed | 520 | PyLong_FromUnsignedLongLong(entries[i].flags.cycles)); |
48a1f565 | 521 | |
0dd5041c | 522 | addr_location__init(&al); |
692d0e63 | 523 | thread__find_map_fb(thread, sample->cpumode, |
42bbabed | 524 | entries[i].from, &al); |
48a1f565 JY |
525 | dsoname = get_dsoname(al.map); |
526 | pydict_set_item_string_decref(pyelem, "from_dsoname", | |
527 | _PyUnicode_FromString(dsoname)); | |
528 | ||
692d0e63 | 529 | thread__find_map_fb(thread, sample->cpumode, |
42bbabed | 530 | entries[i].to, &al); |
48a1f565 JY |
531 | dsoname = get_dsoname(al.map); |
532 | pydict_set_item_string_decref(pyelem, "to_dsoname", | |
533 | _PyUnicode_FromString(dsoname)); | |
534 | ||
0dd5041c | 535 | addr_location__exit(&al); |
48a1f565 JY |
536 | PyList_Append(pylist, pyelem); |
537 | Py_DECREF(pyelem); | |
538 | } | |
539 | ||
540 | exit: | |
541 | return pylist; | |
542 | } | |
543 | ||
48a1f565 JY |
544 | static int get_symoff(struct symbol *sym, struct addr_location *al, |
545 | bool print_off, char *bf, int size) | |
546 | { | |
547 | unsigned long offset; | |
548 | ||
549 | if (!sym || !sym->name[0]) | |
550 | return scnprintf(bf, size, "%s", "[unknown]"); | |
551 | ||
552 | if (!print_off) | |
553 | return scnprintf(bf, size, "%s", sym->name); | |
554 | ||
555 | offset = get_offset(sym, al); | |
556 | ||
557 | return scnprintf(bf, size, "%s+0x%x", sym->name, offset); | |
558 | } | |
559 | ||
560 | static int get_br_mspred(struct branch_flags *flags, char *bf, int size) | |
561 | { | |
562 | if (!flags->mispred && !flags->predicted) | |
563 | return scnprintf(bf, size, "%s", "-"); | |
564 | ||
565 | if (flags->mispred) | |
566 | return scnprintf(bf, size, "%s", "M"); | |
567 | ||
568 | return scnprintf(bf, size, "%s", "P"); | |
569 | } | |
570 | ||
571 | static PyObject *python_process_brstacksym(struct perf_sample *sample, | |
572 | struct thread *thread) | |
573 | { | |
574 | struct branch_stack *br = sample->branch_stack; | |
42bbabed | 575 | struct branch_entry *entries = perf_sample__branch_entries(sample); |
48a1f565 JY |
576 | PyObject *pylist; |
577 | u64 i; | |
578 | char bf[512]; | |
48a1f565 JY |
579 | |
580 | pylist = PyList_New(0); | |
581 | if (!pylist) | |
582 | Py_FatalError("couldn't create Python list"); | |
583 | ||
584 | if (!(br && br->nr)) | |
585 | goto exit; | |
586 | ||
587 | for (i = 0; i < br->nr; i++) { | |
588 | PyObject *pyelem; | |
0dd5041c | 589 | struct addr_location al; |
48a1f565 | 590 | |
0dd5041c | 591 | addr_location__init(&al); |
48a1f565 JY |
592 | pyelem = PyDict_New(); |
593 | if (!pyelem) | |
594 | Py_FatalError("couldn't create Python dictionary"); | |
595 | ||
692d0e63 | 596 | thread__find_symbol_fb(thread, sample->cpumode, |
42bbabed | 597 | entries[i].from, &al); |
48a1f565 JY |
598 | get_symoff(al.sym, &al, true, bf, sizeof(bf)); |
599 | pydict_set_item_string_decref(pyelem, "from", | |
600 | _PyUnicode_FromString(bf)); | |
601 | ||
692d0e63 | 602 | thread__find_symbol_fb(thread, sample->cpumode, |
42bbabed | 603 | entries[i].to, &al); |
48a1f565 JY |
604 | get_symoff(al.sym, &al, true, bf, sizeof(bf)); |
605 | pydict_set_item_string_decref(pyelem, "to", | |
606 | _PyUnicode_FromString(bf)); | |
607 | ||
42bbabed | 608 | get_br_mspred(&entries[i].flags, bf, sizeof(bf)); |
48a1f565 JY |
609 | pydict_set_item_string_decref(pyelem, "pred", |
610 | _PyUnicode_FromString(bf)); | |
611 | ||
42bbabed | 612 | if (entries[i].flags.in_tx) { |
48a1f565 JY |
613 | pydict_set_item_string_decref(pyelem, "in_tx", |
614 | _PyUnicode_FromString("X")); | |
615 | } else { | |
616 | pydict_set_item_string_decref(pyelem, "in_tx", | |
617 | _PyUnicode_FromString("-")); | |
618 | } | |
619 | ||
42bbabed | 620 | if (entries[i].flags.abort) { |
48a1f565 JY |
621 | pydict_set_item_string_decref(pyelem, "abort", |
622 | _PyUnicode_FromString("A")); | |
623 | } else { | |
624 | pydict_set_item_string_decref(pyelem, "abort", | |
625 | _PyUnicode_FromString("-")); | |
626 | } | |
627 | ||
628 | PyList_Append(pylist, pyelem); | |
629 | Py_DECREF(pyelem); | |
0dd5041c | 630 | addr_location__exit(&al); |
48a1f565 JY |
631 | } |
632 | ||
633 | exit: | |
634 | return pylist; | |
635 | } | |
636 | ||
f52679b7 NK |
637 | static PyObject *get_sample_value_as_tuple(struct sample_read_value *value, |
638 | u64 read_format) | |
74ec14f3 AK |
639 | { |
640 | PyObject *t; | |
641 | ||
f52679b7 | 642 | t = PyTuple_New(3); |
74ec14f3 AK |
643 | if (!t) |
644 | Py_FatalError("couldn't create Python tuple"); | |
645 | PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id)); | |
646 | PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value)); | |
f52679b7 NK |
647 | if (read_format & PERF_FORMAT_LOST) |
648 | PyTuple_SetItem(t, 2, PyLong_FromUnsignedLongLong(value->lost)); | |
649 | ||
74ec14f3 AK |
650 | return t; |
651 | } | |
652 | ||
653 | static void set_sample_read_in_dict(PyObject *dict_sample, | |
654 | struct perf_sample *sample, | |
32dcd021 | 655 | struct evsel *evsel) |
74ec14f3 | 656 | { |
1fc632ce | 657 | u64 read_format = evsel->core.attr.read_format; |
74ec14f3 AK |
658 | PyObject *values; |
659 | unsigned int i; | |
660 | ||
661 | if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { | |
662 | pydict_set_item_string_decref(dict_sample, "time_enabled", | |
663 | PyLong_FromUnsignedLongLong(sample->read.time_enabled)); | |
664 | } | |
665 | ||
666 | if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { | |
667 | pydict_set_item_string_decref(dict_sample, "time_running", | |
668 | PyLong_FromUnsignedLongLong(sample->read.time_running)); | |
669 | } | |
670 | ||
671 | if (read_format & PERF_FORMAT_GROUP) | |
672 | values = PyList_New(sample->read.group.nr); | |
673 | else | |
674 | values = PyList_New(1); | |
675 | ||
676 | if (!values) | |
677 | Py_FatalError("couldn't create Python list"); | |
678 | ||
679 | if (read_format & PERF_FORMAT_GROUP) { | |
f52679b7 NK |
680 | struct sample_read_value *v = sample->read.group.values; |
681 | ||
682 | i = 0; | |
683 | sample_read_group__for_each(v, sample->read.group.nr, read_format) { | |
684 | PyObject *t = get_sample_value_as_tuple(v, read_format); | |
74ec14f3 | 685 | PyList_SET_ITEM(values, i, t); |
f52679b7 | 686 | i++; |
74ec14f3 AK |
687 | } |
688 | } else { | |
f52679b7 NK |
689 | PyObject *t = get_sample_value_as_tuple(&sample->read.one, |
690 | read_format); | |
74ec14f3 AK |
691 | PyList_SET_ITEM(values, 0, t); |
692 | } | |
693 | pydict_set_item_string_decref(dict_sample, "values", values); | |
694 | } | |
695 | ||
48a1f565 | 696 | static void set_sample_datasrc_in_dict(PyObject *dict, |
1a8c2e01 | 697 | struct perf_sample *sample) |
48a1f565 | 698 | { |
1a8c2e01 | 699 | struct mem_info *mi = mem_info__new(); |
48a1f565 JY |
700 | char decode[100]; |
701 | ||
1a8c2e01 IR |
702 | if (!mi) |
703 | Py_FatalError("couldn't create mem-info"); | |
704 | ||
48a1f565 JY |
705 | pydict_set_item_string_decref(dict, "datasrc", |
706 | PyLong_FromUnsignedLongLong(sample->data_src)); | |
707 | ||
1a8c2e01 IR |
708 | mem_info__data_src(mi)->val = sample->data_src; |
709 | perf_script__meminfo_scnprintf(decode, 100, mi); | |
710 | mem_info__put(mi); | |
48a1f565 JY |
711 | |
712 | pydict_set_item_string_decref(dict, "datasrc_decode", | |
713 | _PyUnicode_FromString(decode)); | |
714 | } | |
715 | ||
83869019 | 716 | static void regs_map(struct regs_dump *regs, uint64_t mask, const char *arch, char *bf, int size) |
48a1f565 JY |
717 | { |
718 | unsigned int i = 0, r; | |
719 | int printed = 0; | |
720 | ||
2d7f5540 NK |
721 | bf[0] = 0; |
722 | ||
51cfe7a3 IR |
723 | if (size <= 0) |
724 | return; | |
725 | ||
1a4025f0 | 726 | if (!regs || !regs->regs) |
dea8cfcc | 727 | return; |
1a4025f0 | 728 | |
48a1f565 JY |
729 | for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { |
730 | u64 val = regs->regs[i++]; | |
731 | ||
732 | printed += scnprintf(bf + printed, size - printed, | |
733 | "%5s:0x%" PRIx64 " ", | |
83869019 | 734 | perf_reg_name(r, arch), val); |
48a1f565 | 735 | } |
48a1f565 JY |
736 | } |
737 | ||
4bef6168 AK |
738 | #define MAX_REG_SIZE 128 |
739 | ||
b457c526 | 740 | static int set_regs_in_dict(PyObject *dict, |
48a1f565 | 741 | struct perf_sample *sample, |
32dcd021 | 742 | struct evsel *evsel) |
48a1f565 | 743 | { |
1fc632ce | 744 | struct perf_event_attr *attr = &evsel->core.attr; |
83869019 | 745 | const char *arch = perf_env__arch(evsel__env(evsel)); |
dea8cfcc | 746 | |
4bef6168 | 747 | int size = (__sw_hweight64(attr->sample_regs_intr) * MAX_REG_SIZE) + 1; |
dc6d2bc2 | 748 | char *bf = NULL; |
48a1f565 | 749 | |
dc6d2bc2 IR |
750 | if (sample->intr_regs) { |
751 | bf = malloc(size); | |
752 | if (!bf) | |
753 | return -1; | |
48a1f565 | 754 | |
dc6d2bc2 | 755 | regs_map(sample->intr_regs, attr->sample_regs_intr, arch, bf, size); |
48a1f565 | 756 | |
dc6d2bc2 IR |
757 | pydict_set_item_string_decref(dict, "iregs", |
758 | _PyUnicode_FromString(bf)); | |
759 | } | |
760 | ||
761 | if (sample->user_regs) { | |
762 | if (!bf) { | |
763 | bf = malloc(size); | |
764 | if (!bf) | |
765 | return -1; | |
766 | } | |
767 | regs_map(sample->user_regs, attr->sample_regs_user, arch, bf, size); | |
48a1f565 | 768 | |
dc6d2bc2 IR |
769 | pydict_set_item_string_decref(dict, "uregs", |
770 | _PyUnicode_FromString(bf)); | |
771 | } | |
51cfe7a3 | 772 | free(bf); |
b457c526 PL |
773 | |
774 | return 0; | |
48a1f565 JY |
775 | } |
776 | ||
8271b509 | 777 | static void set_sym_in_dict(PyObject *dict, struct addr_location *al, |
c4f46223 LY |
778 | const char *dso_field, const char *dso_bid_field, |
779 | const char *dso_map_start, const char *dso_map_end, | |
26ec3d7c SC |
780 | const char *sym_field, const char *symoff_field, |
781 | const char *map_pgoff) | |
8271b509 | 782 | { |
c4f46223 LY |
783 | char sbuild_id[SBUILD_ID_SIZE]; |
784 | ||
8271b509 | 785 | if (al->map) { |
63df0e4b IR |
786 | struct dso *dso = map__dso(al->map); |
787 | ||
ee756ef7 IR |
788 | pydict_set_item_string_decref(dict, dso_field, |
789 | _PyUnicode_FromString(dso__name(dso))); | |
790 | build_id__sprintf(dso__bid(dso), sbuild_id); | |
c4f46223 LY |
791 | pydict_set_item_string_decref(dict, dso_bid_field, |
792 | _PyUnicode_FromString(sbuild_id)); | |
793 | pydict_set_item_string_decref(dict, dso_map_start, | |
e5116f46 | 794 | PyLong_FromUnsignedLong(map__start(al->map))); |
c4f46223 | 795 | pydict_set_item_string_decref(dict, dso_map_end, |
e5116f46 | 796 | PyLong_FromUnsignedLong(map__end(al->map))); |
26ec3d7c SC |
797 | pydict_set_item_string_decref(dict, map_pgoff, |
798 | PyLong_FromUnsignedLongLong(map__pgoff(al->map))); | |
8271b509 AH |
799 | } |
800 | if (al->sym) { | |
801 | pydict_set_item_string_decref(dict, sym_field, | |
802 | _PyUnicode_FromString(al->sym->name)); | |
803 | pydict_set_item_string_decref(dict, symoff_field, | |
804 | PyLong_FromUnsignedLong(get_offset(al->sym, al))); | |
805 | } | |
806 | } | |
807 | ||
bee272af AH |
808 | static void set_sample_flags(PyObject *dict, u32 flags) |
809 | { | |
810 | const char *ch = PERF_IP_FLAG_CHARS; | |
811 | char *p, str[33]; | |
812 | ||
813 | for (p = str; *ch; ch++, flags >>= 1) { | |
814 | if (flags & 1) | |
815 | *p++ = *ch; | |
816 | } | |
817 | *p = 0; | |
818 | pydict_set_item_string_decref(dict, "flags", _PyUnicode_FromString(str)); | |
819 | } | |
820 | ||
821 | static void python_process_sample_flags(struct perf_sample *sample, PyObject *dict_sample) | |
822 | { | |
823 | char flags_disp[SAMPLE_FLAGS_BUF_SIZE]; | |
824 | ||
825 | set_sample_flags(dict_sample, sample->flags); | |
826 | perf_sample__sprintf_flags(sample->flags, flags_disp, sizeof(flags_disp)); | |
827 | pydict_set_item_string_decref(dict_sample, "flags_disp", | |
828 | _PyUnicode_FromString(flags_disp)); | |
829 | } | |
830 | ||
892e76b2 | 831 | static PyObject *get_perf_sample_dict(struct perf_sample *sample, |
32dcd021 | 832 | struct evsel *evsel, |
892e76b2 | 833 | struct addr_location *al, |
3f8e009e | 834 | struct addr_location *addr_al, |
892e76b2 AK |
835 | PyObject *callchain) |
836 | { | |
48a1f565 | 837 | PyObject *dict, *dict_sample, *brstack, *brstacksym; |
892e76b2 AK |
838 | |
839 | dict = PyDict_New(); | |
840 | if (!dict) | |
841 | Py_FatalError("couldn't create Python dictionary"); | |
842 | ||
843 | dict_sample = PyDict_New(); | |
844 | if (!dict_sample) | |
845 | Py_FatalError("couldn't create Python dictionary"); | |
846 | ||
8ab2e96d | 847 | pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(evsel__name(evsel))); |
1fc632ce | 848 | pydict_set_item_string_decref(dict, "attr", _PyBytes_FromStringAndSize((const char *)&evsel->core.attr, sizeof(evsel->core.attr))); |
892e76b2 | 849 | |
acfd65c8 BG |
850 | pydict_set_item_string_decref(dict_sample, "id", |
851 | PyLong_FromUnsignedLongLong(sample->id)); | |
852 | pydict_set_item_string_decref(dict_sample, "stream_id", | |
853 | PyLong_FromUnsignedLongLong(sample->stream_id)); | |
892e76b2 | 854 | pydict_set_item_string_decref(dict_sample, "pid", |
66dfdff0 | 855 | _PyLong_FromLong(sample->pid)); |
892e76b2 | 856 | pydict_set_item_string_decref(dict_sample, "tid", |
66dfdff0 | 857 | _PyLong_FromLong(sample->tid)); |
892e76b2 | 858 | pydict_set_item_string_decref(dict_sample, "cpu", |
66dfdff0 | 859 | _PyLong_FromLong(sample->cpu)); |
892e76b2 AK |
860 | pydict_set_item_string_decref(dict_sample, "ip", |
861 | PyLong_FromUnsignedLongLong(sample->ip)); | |
862 | pydict_set_item_string_decref(dict_sample, "time", | |
863 | PyLong_FromUnsignedLongLong(sample->time)); | |
864 | pydict_set_item_string_decref(dict_sample, "period", | |
865 | PyLong_FromUnsignedLongLong(sample->period)); | |
41013f0c KL |
866 | pydict_set_item_string_decref(dict_sample, "phys_addr", |
867 | PyLong_FromUnsignedLongLong(sample->phys_addr)); | |
943f32a0 LY |
868 | pydict_set_item_string_decref(dict_sample, "addr", |
869 | PyLong_FromUnsignedLongLong(sample->addr)); | |
74ec14f3 | 870 | set_sample_read_in_dict(dict_sample, sample, evsel); |
48a1f565 JY |
871 | pydict_set_item_string_decref(dict_sample, "weight", |
872 | PyLong_FromUnsignedLongLong(sample->weight)); | |
05673c42 ZC |
873 | pydict_set_item_string_decref(dict_sample, "ins_lat", |
874 | PyLong_FromUnsignedLong(sample->ins_lat)); | |
48a1f565 JY |
875 | pydict_set_item_string_decref(dict_sample, "transaction", |
876 | PyLong_FromUnsignedLongLong(sample->transaction)); | |
877 | set_sample_datasrc_in_dict(dict_sample, sample); | |
892e76b2 AK |
878 | pydict_set_item_string_decref(dict, "sample", dict_sample); |
879 | ||
66dfdff0 | 880 | pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( |
892e76b2 AK |
881 | (const char *)sample->raw_data, sample->raw_size)); |
882 | pydict_set_item_string_decref(dict, "comm", | |
66dfdff0 | 883 | _PyUnicode_FromString(thread__comm_str(al->thread))); |
c4f46223 | 884 | set_sym_in_dict(dict, al, "dso", "dso_bid", "dso_map_start", "dso_map_end", |
26ec3d7c | 885 | "symbol", "symoff", "map_pgoff"); |
892e76b2 AK |
886 | |
887 | pydict_set_item_string_decref(dict, "callchain", callchain); | |
888 | ||
48a1f565 JY |
889 | brstack = python_process_brstack(sample, al->thread); |
890 | pydict_set_item_string_decref(dict, "brstack", brstack); | |
891 | ||
892 | brstacksym = python_process_brstacksym(sample, al->thread); | |
893 | pydict_set_item_string_decref(dict, "brstacksym", brstacksym); | |
894 | ||
6de306b7 AH |
895 | if (sample->machine_pid) { |
896 | pydict_set_item_string_decref(dict_sample, "machine_pid", | |
897 | _PyLong_FromLong(sample->machine_pid)); | |
898 | pydict_set_item_string_decref(dict_sample, "vcpu", | |
899 | _PyLong_FromLong(sample->vcpu)); | |
900 | } | |
901 | ||
22cc2f74 AH |
902 | pydict_set_item_string_decref(dict_sample, "cpumode", |
903 | _PyLong_FromLong((unsigned long)sample->cpumode)); | |
904 | ||
3f8e009e AH |
905 | if (addr_al) { |
906 | pydict_set_item_string_decref(dict_sample, "addr_correlates_sym", | |
907 | PyBool_FromLong(1)); | |
c4f46223 LY |
908 | set_sym_in_dict(dict_sample, addr_al, "addr_dso", "addr_dso_bid", |
909 | "addr_dso_map_start", "addr_dso_map_end", | |
26ec3d7c | 910 | "addr_symbol", "addr_symoff", "addr_map_pgoff"); |
3f8e009e AH |
911 | } |
912 | ||
bee272af AH |
913 | if (sample->flags) |
914 | python_process_sample_flags(sample, dict_sample); | |
915 | ||
142b0518 AH |
916 | /* Instructions per cycle (IPC) */ |
917 | if (sample->insn_cnt && sample->cyc_cnt) { | |
918 | pydict_set_item_string_decref(dict_sample, "insn_cnt", | |
919 | PyLong_FromUnsignedLongLong(sample->insn_cnt)); | |
920 | pydict_set_item_string_decref(dict_sample, "cyc_cnt", | |
921 | PyLong_FromUnsignedLongLong(sample->cyc_cnt)); | |
922 | } | |
923 | ||
b457c526 PL |
924 | if (set_regs_in_dict(dict, sample, evsel)) |
925 | Py_FatalError("Failed to setting regs in dict"); | |
48a1f565 | 926 | |
892e76b2 AK |
927 | return dict; |
928 | } | |
929 | ||
80c3a7d9 | 930 | #ifdef HAVE_LIBTRACEEVENT |
b7fff6b5 | 931 | static void python_process_tracepoint(struct perf_sample *sample, |
32dcd021 | 932 | struct evsel *evsel, |
3f8e009e AH |
933 | struct addr_location *al, |
934 | struct addr_location *addr_al) | |
7e4b21b8 | 935 | { |
c46d634a | 936 | struct tep_event *event; |
39f54862 | 937 | PyObject *handler, *context, *t, *obj = NULL, *callchain; |
f38d2816 | 938 | PyObject *dict = NULL, *all_entries_dict = NULL; |
7e4b21b8 | 939 | static char handler_name[256]; |
2c92f982 | 940 | struct tep_format_field *field; |
7e4b21b8 | 941 | unsigned long s, ns; |
7e4b21b8 | 942 | unsigned n = 0; |
7e4b21b8 | 943 | int pid; |
be6d842a DA |
944 | int cpu = sample->cpu; |
945 | void *data = sample->raw_data; | |
946 | unsigned long long nsecs = sample->time; | |
f9d5d549 | 947 | const char *comm = thread__comm_str(al->thread); |
e9f9a9ca | 948 | const char *default_handler_name = "trace_unhandled"; |
d9c26d45 IR |
949 | DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX); |
950 | ||
951 | bitmap_zero(events_defined, TRACE_EVENT_TYPE_MAX); | |
7e4b21b8 | 952 | |
c46d634a | 953 | event = evsel__tp_format(evsel); |
62665dff ACM |
954 | if (!event) { |
955 | snprintf(handler_name, sizeof(handler_name), | |
1fc632ce | 956 | "ug! no event found for type %" PRIu64, (u64)evsel->core.attr.config); |
62665dff ACM |
957 | Py_FatalError(handler_name); |
958 | } | |
7e4b21b8 | 959 | |
97822433 | 960 | pid = raw_field_value(event, "common_pid", data); |
7e4b21b8 TZ |
961 | |
962 | sprintf(handler_name, "%s__%s", event->system, event->name); | |
963 | ||
49bd97c2 | 964 | if (!__test_and_set_bit(event->id, events_defined)) |
adf5bcf3 JO |
965 | define_event_symbols(event, handler_name, event->print_fmt.args); |
966 | ||
a5563edf | 967 | handler = get_handler(handler_name); |
c0251485 | 968 | if (!handler) { |
e9f9a9ca AK |
969 | handler = get_handler(default_handler_name); |
970 | if (!handler) | |
971 | return; | |
c0251485 PT |
972 | dict = PyDict_New(); |
973 | if (!dict) | |
974 | Py_FatalError("couldn't create Python dict"); | |
975 | } | |
e9f9a9ca AK |
976 | |
977 | t = PyTuple_New(MAX_FIELDS); | |
978 | if (!t) | |
979 | Py_FatalError("couldn't create Python tuple"); | |
980 | ||
981 | ||
bd48c63e ACM |
982 | s = nsecs / NSEC_PER_SEC; |
983 | ns = nsecs - s * NSEC_PER_SEC; | |
7e4b21b8 | 984 | |
66dfdff0 | 985 | context = _PyCapsule_New(scripting_context, NULL, NULL); |
7e4b21b8 | 986 | |
66dfdff0 | 987 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name)); |
fb7d0b3c | 988 | PyTuple_SetItem(t, n++, context); |
7e4b21b8 | 989 | |
0f5f5bcd JS |
990 | /* ip unwinding */ |
991 | callchain = python_process_callchain(sample, evsel, al); | |
f38d2816 AK |
992 | /* Need an additional reference for the perf_sample dict */ |
993 | Py_INCREF(callchain); | |
0f5f5bcd | 994 | |
e9f9a9ca | 995 | if (!dict) { |
66dfdff0 JŠ |
996 | PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); |
997 | PyTuple_SetItem(t, n++, _PyLong_FromLong(s)); | |
998 | PyTuple_SetItem(t, n++, _PyLong_FromLong(ns)); | |
999 | PyTuple_SetItem(t, n++, _PyLong_FromLong(pid)); | |
1000 | PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm)); | |
0f5f5bcd | 1001 | PyTuple_SetItem(t, n++, callchain); |
c0251485 | 1002 | } else { |
66dfdff0 JŠ |
1003 | pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu)); |
1004 | pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s)); | |
1005 | pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns)); | |
1006 | pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid)); | |
1007 | pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm)); | |
0f5f5bcd | 1008 | pydict_set_item_string_decref(dict, "common_callchain", callchain); |
c0251485 | 1009 | } |
7e4b21b8 | 1010 | for (field = event->format.fields; field; field = field->next) { |
249de6e0 JO |
1011 | unsigned int offset, len; |
1012 | unsigned long long val; | |
1013 | ||
bb39ccb2 | 1014 | if (field->flags & TEP_FIELD_IS_ARRAY) { |
249de6e0 JO |
1015 | offset = field->offset; |
1016 | len = field->size; | |
bb39ccb2 | 1017 | if (field->flags & TEP_FIELD_IS_DYNAMIC) { |
59c1baee TSV |
1018 | val = tep_read_number(scripting_context->pevent, |
1019 | data + offset, len); | |
249de6e0 JO |
1020 | offset = val; |
1021 | len = offset >> 16; | |
7e4b21b8 | 1022 | offset &= 0xffff; |
1634bad3 | 1023 | if (tep_field_is_relative(field->flags)) |
7c689c83 | 1024 | offset += field->offset + field->size; |
249de6e0 | 1025 | } |
bb39ccb2 | 1026 | if (field->flags & TEP_FIELD_IS_STRING && |
249de6e0 | 1027 | is_printable_array(data + offset, len)) { |
66dfdff0 | 1028 | obj = _PyUnicode_FromString((char *) data + offset); |
249de6e0 JO |
1029 | } else { |
1030 | obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); | |
bb39ccb2 | 1031 | field->flags &= ~TEP_FIELD_IS_STRING; |
249de6e0 | 1032 | } |
7e4b21b8 | 1033 | } else { /* FIELD_IS_NUMERIC */ |
33058b94 | 1034 | obj = get_field_numeric_entry(event, field, data); |
7e4b21b8 | 1035 | } |
e9f9a9ca | 1036 | if (!dict) |
c0251485 PT |
1037 | PyTuple_SetItem(t, n++, obj); |
1038 | else | |
c0268e8d | 1039 | pydict_set_item_string_decref(dict, field->name, obj); |
c0251485 | 1040 | |
7e4b21b8 | 1041 | } |
0f5f5bcd | 1042 | |
e9f9a9ca | 1043 | if (dict) |
c0251485 | 1044 | PyTuple_SetItem(t, n++, dict); |
7e4b21b8 | 1045 | |
f38d2816 | 1046 | if (get_argument_count(handler) == (int) n + 1) { |
3f8e009e | 1047 | all_entries_dict = get_perf_sample_dict(sample, evsel, al, addr_al, |
f38d2816 AK |
1048 | callchain); |
1049 | PyTuple_SetItem(t, n++, all_entries_dict); | |
1050 | } else { | |
1051 | Py_DECREF(callchain); | |
1052 | } | |
1053 | ||
7e4b21b8 TZ |
1054 | if (_PyTuple_Resize(&t, n) == -1) |
1055 | Py_FatalError("error resizing Python tuple"); | |
1056 | ||
db0ba84c | 1057 | if (!dict) |
a5563edf | 1058 | call_object(handler, t, handler_name); |
db0ba84c | 1059 | else |
e9f9a9ca | 1060 | call_object(handler, t, default_handler_name); |
7e4b21b8 TZ |
1061 | |
1062 | Py_DECREF(t); | |
1063 | } | |
80c3a7d9 AH |
1064 | #else |
1065 | static void python_process_tracepoint(struct perf_sample *sample __maybe_unused, | |
1066 | struct evsel *evsel __maybe_unused, | |
1067 | struct addr_location *al __maybe_unused, | |
1068 | struct addr_location *addr_al __maybe_unused) | |
1069 | { | |
1070 | fprintf(stderr, "Tracepoint events are not supported because " | |
1071 | "perf is not linked with libtraceevent.\n"); | |
1072 | } | |
1073 | #endif | |
7e4b21b8 | 1074 | |
df919b40 AH |
1075 | static PyObject *tuple_new(unsigned int sz) |
1076 | { | |
1077 | PyObject *t; | |
1078 | ||
1079 | t = PyTuple_New(sz); | |
1080 | if (!t) | |
1081 | Py_FatalError("couldn't create Python tuple"); | |
1082 | return t; | |
1083 | } | |
1084 | ||
d04c1ff0 | 1085 | static int tuple_set_s64(PyObject *t, unsigned int pos, s64 val) |
df919b40 AH |
1086 | { |
1087 | #if BITS_PER_LONG == 64 | |
66dfdff0 | 1088 | return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); |
df919b40 AH |
1089 | #endif |
1090 | #if BITS_PER_LONG == 32 | |
1091 | return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); | |
1092 | #endif | |
1093 | } | |
1094 | ||
d04c1ff0 AH |
1095 | /* |
1096 | * Databases support only signed 64-bit numbers, so even though we are | |
1097 | * exporting a u64, it must be as s64. | |
1098 | */ | |
1099 | #define tuple_set_d64 tuple_set_s64 | |
1100 | ||
1101 | static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) | |
1102 | { | |
1103 | #if BITS_PER_LONG == 64 | |
1104 | return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLong(val)); | |
1105 | #endif | |
1106 | #if BITS_PER_LONG == 32 | |
1107 | return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLongLong(val)); | |
1108 | #endif | |
1109 | } | |
1110 | ||
2ede9217 AH |
1111 | static int tuple_set_u32(PyObject *t, unsigned int pos, u32 val) |
1112 | { | |
1113 | return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLong(val)); | |
1114 | } | |
1115 | ||
df919b40 AH |
1116 | static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) |
1117 | { | |
66dfdff0 | 1118 | return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); |
df919b40 AH |
1119 | } |
1120 | ||
0db21340 AH |
1121 | static int tuple_set_bool(PyObject *t, unsigned int pos, bool val) |
1122 | { | |
1123 | return PyTuple_SetItem(t, pos, PyBool_FromLong(val)); | |
1124 | } | |
1125 | ||
df919b40 AH |
1126 | static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) |
1127 | { | |
66dfdff0 | 1128 | return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s)); |
df919b40 AH |
1129 | } |
1130 | ||
b9322cab AH |
1131 | static int tuple_set_bytes(PyObject *t, unsigned int pos, void *bytes, |
1132 | unsigned int sz) | |
1133 | { | |
1134 | return PyTuple_SetItem(t, pos, _PyBytes_FromStringAndSize(bytes, sz)); | |
1135 | } | |
1136 | ||
32dcd021 | 1137 | static int python_export_evsel(struct db_export *dbe, struct evsel *evsel) |
df919b40 AH |
1138 | { |
1139 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1140 | PyObject *t; | |
1141 | ||
1142 | t = tuple_new(2); | |
1143 | ||
d04c1ff0 | 1144 | tuple_set_d64(t, 0, evsel->db_id); |
8ab2e96d | 1145 | tuple_set_string(t, 1, evsel__name(evsel)); |
df919b40 AH |
1146 | |
1147 | call_object(tables->evsel_handler, t, "evsel_table"); | |
1148 | ||
1149 | Py_DECREF(t); | |
1150 | ||
1151 | return 0; | |
1152 | } | |
1153 | ||
1154 | static int python_export_machine(struct db_export *dbe, | |
1155 | struct machine *machine) | |
1156 | { | |
1157 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1158 | PyObject *t; | |
1159 | ||
1160 | t = tuple_new(3); | |
1161 | ||
d04c1ff0 | 1162 | tuple_set_d64(t, 0, machine->db_id); |
df919b40 AH |
1163 | tuple_set_s32(t, 1, machine->pid); |
1164 | tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : ""); | |
1165 | ||
1166 | call_object(tables->machine_handler, t, "machine_table"); | |
1167 | ||
1168 | Py_DECREF(t); | |
1169 | ||
1170 | return 0; | |
1171 | } | |
1172 | ||
1173 | static int python_export_thread(struct db_export *dbe, struct thread *thread, | |
1174 | u64 main_thread_db_id, struct machine *machine) | |
1175 | { | |
1176 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1177 | PyObject *t; | |
1178 | ||
1179 | t = tuple_new(5); | |
1180 | ||
ee84a303 | 1181 | tuple_set_d64(t, 0, thread__db_id(thread)); |
d04c1ff0 AH |
1182 | tuple_set_d64(t, 1, machine->db_id); |
1183 | tuple_set_d64(t, 2, main_thread_db_id); | |
ee84a303 IR |
1184 | tuple_set_s32(t, 3, thread__pid(thread)); |
1185 | tuple_set_s32(t, 4, thread__tid(thread)); | |
df919b40 AH |
1186 | |
1187 | call_object(tables->thread_handler, t, "thread_table"); | |
1188 | ||
1189 | Py_DECREF(t); | |
1190 | ||
1191 | return 0; | |
1192 | } | |
1193 | ||
8ebf5cc0 AH |
1194 | static int python_export_comm(struct db_export *dbe, struct comm *comm, |
1195 | struct thread *thread) | |
df919b40 AH |
1196 | { |
1197 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1198 | PyObject *t; | |
1199 | ||
8ebf5cc0 | 1200 | t = tuple_new(5); |
df919b40 | 1201 | |
d04c1ff0 | 1202 | tuple_set_d64(t, 0, comm->db_id); |
df919b40 | 1203 | tuple_set_string(t, 1, comm__str(comm)); |
ee84a303 | 1204 | tuple_set_d64(t, 2, thread__db_id(thread)); |
d04c1ff0 | 1205 | tuple_set_d64(t, 3, comm->start); |
8ebf5cc0 | 1206 | tuple_set_s32(t, 4, comm->exec); |
df919b40 AH |
1207 | |
1208 | call_object(tables->comm_handler, t, "comm_table"); | |
1209 | ||
1210 | Py_DECREF(t); | |
1211 | ||
1212 | return 0; | |
1213 | } | |
1214 | ||
1215 | static int python_export_comm_thread(struct db_export *dbe, u64 db_id, | |
1216 | struct comm *comm, struct thread *thread) | |
1217 | { | |
1218 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1219 | PyObject *t; | |
1220 | ||
1221 | t = tuple_new(3); | |
1222 | ||
d04c1ff0 AH |
1223 | tuple_set_d64(t, 0, db_id); |
1224 | tuple_set_d64(t, 1, comm->db_id); | |
ee84a303 | 1225 | tuple_set_d64(t, 2, thread__db_id(thread)); |
df919b40 AH |
1226 | |
1227 | call_object(tables->comm_thread_handler, t, "comm_thread_table"); | |
1228 | ||
1229 | Py_DECREF(t); | |
1230 | ||
1231 | return 0; | |
1232 | } | |
1233 | ||
1234 | static int python_export_dso(struct db_export *dbe, struct dso *dso, | |
1235 | struct machine *machine) | |
1236 | { | |
1237 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
b5d8bbe8 | 1238 | char sbuild_id[SBUILD_ID_SIZE]; |
df919b40 AH |
1239 | PyObject *t; |
1240 | ||
ee756ef7 | 1241 | build_id__sprintf(dso__bid(dso), sbuild_id); |
df919b40 AH |
1242 | |
1243 | t = tuple_new(5); | |
1244 | ||
ee756ef7 | 1245 | tuple_set_d64(t, 0, dso__db_id(dso)); |
d04c1ff0 | 1246 | tuple_set_d64(t, 1, machine->db_id); |
ee756ef7 IR |
1247 | tuple_set_string(t, 2, dso__short_name(dso)); |
1248 | tuple_set_string(t, 3, dso__long_name(dso)); | |
df919b40 AH |
1249 | tuple_set_string(t, 4, sbuild_id); |
1250 | ||
1251 | call_object(tables->dso_handler, t, "dso_table"); | |
1252 | ||
1253 | Py_DECREF(t); | |
1254 | ||
1255 | return 0; | |
1256 | } | |
1257 | ||
1258 | static int python_export_symbol(struct db_export *dbe, struct symbol *sym, | |
1259 | struct dso *dso) | |
1260 | { | |
1261 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1262 | u64 *sym_db_id = symbol__priv(sym); | |
1263 | PyObject *t; | |
1264 | ||
1265 | t = tuple_new(6); | |
1266 | ||
d04c1ff0 | 1267 | tuple_set_d64(t, 0, *sym_db_id); |
ee756ef7 | 1268 | tuple_set_d64(t, 1, dso__db_id(dso)); |
d04c1ff0 AH |
1269 | tuple_set_d64(t, 2, sym->start); |
1270 | tuple_set_d64(t, 3, sym->end); | |
df919b40 AH |
1271 | tuple_set_s32(t, 4, sym->binding); |
1272 | tuple_set_string(t, 5, sym->name); | |
1273 | ||
1274 | call_object(tables->symbol_handler, t, "symbol_table"); | |
1275 | ||
1276 | Py_DECREF(t); | |
1277 | ||
1278 | return 0; | |
1279 | } | |
1280 | ||
c29414f5 AH |
1281 | static int python_export_branch_type(struct db_export *dbe, u32 branch_type, |
1282 | const char *name) | |
1283 | { | |
1284 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1285 | PyObject *t; | |
1286 | ||
1287 | t = tuple_new(2); | |
1288 | ||
1289 | tuple_set_s32(t, 0, branch_type); | |
1290 | tuple_set_string(t, 1, name); | |
1291 | ||
1292 | call_object(tables->branch_type_handler, t, "branch_type_table"); | |
1293 | ||
1294 | Py_DECREF(t); | |
1295 | ||
1296 | return 0; | |
1297 | } | |
1298 | ||
b9322cab AH |
1299 | static void python_export_sample_table(struct db_export *dbe, |
1300 | struct export_sample *es) | |
df919b40 AH |
1301 | { |
1302 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1303 | PyObject *t; | |
1304 | ||
05673c42 | 1305 | t = tuple_new(28); |
df919b40 | 1306 | |
d04c1ff0 AH |
1307 | tuple_set_d64(t, 0, es->db_id); |
1308 | tuple_set_d64(t, 1, es->evsel->db_id); | |
5ab6d715 | 1309 | tuple_set_d64(t, 2, maps__machine(es->al->maps)->db_id); |
ee84a303 | 1310 | tuple_set_d64(t, 3, thread__db_id(es->al->thread)); |
d04c1ff0 AH |
1311 | tuple_set_d64(t, 4, es->comm_db_id); |
1312 | tuple_set_d64(t, 5, es->dso_db_id); | |
1313 | tuple_set_d64(t, 6, es->sym_db_id); | |
1314 | tuple_set_d64(t, 7, es->offset); | |
1315 | tuple_set_d64(t, 8, es->sample->ip); | |
1316 | tuple_set_d64(t, 9, es->sample->time); | |
df919b40 | 1317 | tuple_set_s32(t, 10, es->sample->cpu); |
d04c1ff0 AH |
1318 | tuple_set_d64(t, 11, es->addr_dso_db_id); |
1319 | tuple_set_d64(t, 12, es->addr_sym_db_id); | |
1320 | tuple_set_d64(t, 13, es->addr_offset); | |
1321 | tuple_set_d64(t, 14, es->sample->addr); | |
1322 | tuple_set_d64(t, 15, es->sample->period); | |
1323 | tuple_set_d64(t, 16, es->sample->weight); | |
1324 | tuple_set_d64(t, 17, es->sample->transaction); | |
1325 | tuple_set_d64(t, 18, es->sample->data_src); | |
c29414f5 AH |
1326 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); |
1327 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | |
d04c1ff0 AH |
1328 | tuple_set_d64(t, 21, es->call_path_id); |
1329 | tuple_set_d64(t, 22, es->sample->insn_cnt); | |
1330 | tuple_set_d64(t, 23, es->sample->cyc_cnt); | |
c096fff6 | 1331 | tuple_set_s32(t, 24, es->sample->flags); |
acfd65c8 BG |
1332 | tuple_set_d64(t, 25, es->sample->id); |
1333 | tuple_set_d64(t, 26, es->sample->stream_id); | |
05673c42 | 1334 | tuple_set_u32(t, 27, es->sample->ins_lat); |
df919b40 AH |
1335 | |
1336 | call_object(tables->sample_handler, t, "sample_table"); | |
1337 | ||
1338 | Py_DECREF(t); | |
b9322cab AH |
1339 | } |
1340 | ||
1341 | static void python_export_synth(struct db_export *dbe, struct export_sample *es) | |
1342 | { | |
1343 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1344 | PyObject *t; | |
1345 | ||
1346 | t = tuple_new(3); | |
1347 | ||
d04c1ff0 AH |
1348 | tuple_set_d64(t, 0, es->db_id); |
1349 | tuple_set_d64(t, 1, es->evsel->core.attr.config); | |
b9322cab AH |
1350 | tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size); |
1351 | ||
1352 | call_object(tables->synth_handler, t, "synth_data"); | |
1353 | ||
1354 | Py_DECREF(t); | |
1355 | } | |
1356 | ||
1357 | static int python_export_sample(struct db_export *dbe, | |
1358 | struct export_sample *es) | |
1359 | { | |
1360 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1361 | ||
1362 | python_export_sample_table(dbe, es); | |
1363 | ||
1fc632ce | 1364 | if (es->evsel->core.attr.type == PERF_TYPE_SYNTH && tables->synth_handler) |
b9322cab | 1365 | python_export_synth(dbe, es); |
df919b40 AH |
1366 | |
1367 | return 0; | |
1368 | } | |
1369 | ||
6a70307d AH |
1370 | static int python_export_call_path(struct db_export *dbe, struct call_path *cp) |
1371 | { | |
1372 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1373 | PyObject *t; | |
1374 | u64 parent_db_id, sym_db_id; | |
1375 | ||
1376 | parent_db_id = cp->parent ? cp->parent->db_id : 0; | |
1377 | sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0; | |
1378 | ||
1379 | t = tuple_new(4); | |
1380 | ||
d04c1ff0 AH |
1381 | tuple_set_d64(t, 0, cp->db_id); |
1382 | tuple_set_d64(t, 1, parent_db_id); | |
1383 | tuple_set_d64(t, 2, sym_db_id); | |
1384 | tuple_set_d64(t, 3, cp->ip); | |
6a70307d AH |
1385 | |
1386 | call_object(tables->call_path_handler, t, "call_path_table"); | |
1387 | ||
1388 | Py_DECREF(t); | |
1389 | ||
1390 | return 0; | |
1391 | } | |
1392 | ||
1393 | static int python_export_call_return(struct db_export *dbe, | |
1394 | struct call_return *cr) | |
1395 | { | |
1396 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1397 | u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; | |
1398 | PyObject *t; | |
1399 | ||
52a2ab6f | 1400 | t = tuple_new(14); |
6a70307d | 1401 | |
d04c1ff0 | 1402 | tuple_set_d64(t, 0, cr->db_id); |
ee84a303 | 1403 | tuple_set_d64(t, 1, thread__db_id(cr->thread)); |
d04c1ff0 AH |
1404 | tuple_set_d64(t, 2, comm_db_id); |
1405 | tuple_set_d64(t, 3, cr->cp->db_id); | |
1406 | tuple_set_d64(t, 4, cr->call_time); | |
1407 | tuple_set_d64(t, 5, cr->return_time); | |
1408 | tuple_set_d64(t, 6, cr->branch_count); | |
1409 | tuple_set_d64(t, 7, cr->call_ref); | |
1410 | tuple_set_d64(t, 8, cr->return_ref); | |
1411 | tuple_set_d64(t, 9, cr->cp->parent->db_id); | |
6a70307d | 1412 | tuple_set_s32(t, 10, cr->flags); |
d04c1ff0 AH |
1413 | tuple_set_d64(t, 11, cr->parent_db_id); |
1414 | tuple_set_d64(t, 12, cr->insn_count); | |
1415 | tuple_set_d64(t, 13, cr->cyc_count); | |
6a70307d AH |
1416 | |
1417 | call_object(tables->call_return_handler, t, "call_return_table"); | |
1418 | ||
1419 | Py_DECREF(t); | |
1420 | ||
1421 | return 0; | |
1422 | } | |
1423 | ||
abde8722 AH |
1424 | static int python_export_context_switch(struct db_export *dbe, u64 db_id, |
1425 | struct machine *machine, | |
1426 | struct perf_sample *sample, | |
1427 | u64 th_out_id, u64 comm_out_id, | |
1428 | u64 th_in_id, u64 comm_in_id, int flags) | |
1429 | { | |
1430 | struct tables *tables = container_of(dbe, struct tables, dbe); | |
1431 | PyObject *t; | |
1432 | ||
1433 | t = tuple_new(9); | |
1434 | ||
d04c1ff0 AH |
1435 | tuple_set_d64(t, 0, db_id); |
1436 | tuple_set_d64(t, 1, machine->db_id); | |
1437 | tuple_set_d64(t, 2, sample->time); | |
abde8722 | 1438 | tuple_set_s32(t, 3, sample->cpu); |
d04c1ff0 AH |
1439 | tuple_set_d64(t, 4, th_out_id); |
1440 | tuple_set_d64(t, 5, comm_out_id); | |
1441 | tuple_set_d64(t, 6, th_in_id); | |
1442 | tuple_set_d64(t, 7, comm_in_id); | |
abde8722 AH |
1443 | tuple_set_s32(t, 8, flags); |
1444 | ||
1445 | call_object(tables->context_switch_handler, t, "context_switch"); | |
1446 | ||
1447 | Py_DECREF(t); | |
1448 | ||
1449 | return 0; | |
1450 | } | |
1451 | ||
f435887e AH |
1452 | static int python_process_call_return(struct call_return *cr, u64 *parent_db_id, |
1453 | void *data) | |
6a70307d AH |
1454 | { |
1455 | struct db_export *dbe = data; | |
1456 | ||
f435887e | 1457 | return db_export__call_return(dbe, cr, parent_db_id); |
6a70307d AH |
1458 | } |
1459 | ||
b7fff6b5 | 1460 | static void python_process_general_event(struct perf_sample *sample, |
32dcd021 | 1461 | struct evsel *evsel, |
3f8e009e AH |
1462 | struct addr_location *al, |
1463 | struct addr_location *addr_al) | |
6a6daec2 | 1464 | { |
892e76b2 | 1465 | PyObject *handler, *t, *dict, *callchain; |
6a6daec2 FT |
1466 | static char handler_name[64]; |
1467 | unsigned n = 0; | |
6a6daec2 | 1468 | |
e9f9a9ca AK |
1469 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); |
1470 | ||
1471 | handler = get_handler(handler_name); | |
1472 | if (!handler) | |
1473 | return; | |
1474 | ||
fd6b858a FT |
1475 | /* |
1476 | * Use the MAX_FIELDS to make the function expandable, though | |
87b6a3ad | 1477 | * currently there is only one item for the tuple. |
fd6b858a | 1478 | */ |
6a6daec2 FT |
1479 | t = PyTuple_New(MAX_FIELDS); |
1480 | if (!t) | |
1481 | Py_FatalError("couldn't create Python tuple"); | |
1482 | ||
0f5f5bcd JS |
1483 | /* ip unwinding */ |
1484 | callchain = python_process_callchain(sample, evsel, al); | |
3f8e009e | 1485 | dict = get_perf_sample_dict(sample, evsel, al, addr_al, callchain); |
0f5f5bcd | 1486 | |
fd6b858a | 1487 | PyTuple_SetItem(t, n++, dict); |
6a6daec2 FT |
1488 | if (_PyTuple_Resize(&t, n) == -1) |
1489 | Py_FatalError("error resizing Python tuple"); | |
1490 | ||
a5563edf | 1491 | call_object(handler, t, handler_name); |
e9f9a9ca | 1492 | |
6a6daec2 FT |
1493 | Py_DECREF(t); |
1494 | } | |
1495 | ||
df919b40 | 1496 | static void python_process_event(union perf_event *event, |
6a6daec2 | 1497 | struct perf_sample *sample, |
32dcd021 | 1498 | struct evsel *evsel, |
3f8e009e AH |
1499 | struct addr_location *al, |
1500 | struct addr_location *addr_al) | |
6a6daec2 | 1501 | { |
df919b40 AH |
1502 | struct tables *tables = &tables_global; |
1503 | ||
cac30400 AH |
1504 | scripting_context__update(scripting_context, event, sample, evsel, al, addr_al); |
1505 | ||
1fc632ce | 1506 | switch (evsel->core.attr.type) { |
6a6daec2 | 1507 | case PERF_TYPE_TRACEPOINT: |
3f8e009e | 1508 | python_process_tracepoint(sample, evsel, al, addr_al); |
6a6daec2 FT |
1509 | break; |
1510 | /* Reserve for future process_hw/sw/raw APIs */ | |
1511 | default: | |
df919b40 | 1512 | if (tables->db_export_mode) |
3f8e009e | 1513 | db_export__sample(&tables->dbe, event, sample, evsel, al, addr_al); |
df919b40 | 1514 | else |
3f8e009e | 1515 | python_process_general_event(sample, evsel, al, addr_al); |
6a6daec2 FT |
1516 | } |
1517 | } | |
1518 | ||
538d9c18 SB |
1519 | static void python_process_throttle(union perf_event *event, |
1520 | struct perf_sample *sample, | |
1521 | struct machine *machine) | |
1522 | { | |
1523 | const char *handler_name; | |
1524 | PyObject *handler, *t; | |
1525 | ||
1526 | if (event->header.type == PERF_RECORD_THROTTLE) | |
1527 | handler_name = "throttle"; | |
1528 | else | |
1529 | handler_name = "unthrottle"; | |
1530 | handler = get_handler(handler_name); | |
1531 | if (!handler) | |
1532 | return; | |
1533 | ||
1534 | t = tuple_new(6); | |
1535 | if (!t) | |
1536 | return; | |
1537 | ||
1538 | tuple_set_u64(t, 0, event->throttle.time); | |
1539 | tuple_set_u64(t, 1, event->throttle.id); | |
1540 | tuple_set_u64(t, 2, event->throttle.stream_id); | |
1541 | tuple_set_s32(t, 3, sample->cpu); | |
1542 | tuple_set_s32(t, 4, sample->pid); | |
1543 | tuple_set_s32(t, 5, sample->tid); | |
1544 | ||
1545 | call_object(handler, t, handler_name); | |
1546 | ||
1547 | Py_DECREF(t); | |
1548 | } | |
1549 | ||
0db21340 AH |
1550 | static void python_do_process_switch(union perf_event *event, |
1551 | struct perf_sample *sample, | |
1552 | struct machine *machine) | |
1553 | { | |
1554 | const char *handler_name = "context_switch"; | |
1555 | bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT; | |
1556 | bool out_preempt = out && (event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT); | |
1557 | pid_t np_pid = -1, np_tid = -1; | |
1558 | PyObject *handler, *t; | |
1559 | ||
1560 | handler = get_handler(handler_name); | |
1561 | if (!handler) | |
1562 | return; | |
1563 | ||
1564 | if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) { | |
1565 | np_pid = event->context_switch.next_prev_pid; | |
1566 | np_tid = event->context_switch.next_prev_tid; | |
1567 | } | |
1568 | ||
6de306b7 | 1569 | t = tuple_new(11); |
0db21340 AH |
1570 | if (!t) |
1571 | return; | |
1572 | ||
1573 | tuple_set_u64(t, 0, sample->time); | |
1574 | tuple_set_s32(t, 1, sample->cpu); | |
1575 | tuple_set_s32(t, 2, sample->pid); | |
1576 | tuple_set_s32(t, 3, sample->tid); | |
1577 | tuple_set_s32(t, 4, np_pid); | |
1578 | tuple_set_s32(t, 5, np_tid); | |
1579 | tuple_set_s32(t, 6, machine->pid); | |
1580 | tuple_set_bool(t, 7, out); | |
1581 | tuple_set_bool(t, 8, out_preempt); | |
6de306b7 AH |
1582 | tuple_set_s32(t, 9, sample->machine_pid); |
1583 | tuple_set_s32(t, 10, sample->vcpu); | |
0db21340 AH |
1584 | |
1585 | call_object(handler, t, handler_name); | |
1586 | ||
1587 | Py_DECREF(t); | |
1588 | } | |
1589 | ||
abde8722 AH |
1590 | static void python_process_switch(union perf_event *event, |
1591 | struct perf_sample *sample, | |
1592 | struct machine *machine) | |
1593 | { | |
1594 | struct tables *tables = &tables_global; | |
1595 | ||
1596 | if (tables->db_export_mode) | |
1597 | db_export__switch(&tables->dbe, event, sample, machine); | |
0db21340 AH |
1598 | else |
1599 | python_do_process_switch(event, sample, machine); | |
abde8722 AH |
1600 | } |
1601 | ||
2ede9217 AH |
1602 | static void python_process_auxtrace_error(struct perf_session *session __maybe_unused, |
1603 | union perf_event *event) | |
1604 | { | |
1605 | struct perf_record_auxtrace_error *e = &event->auxtrace_error; | |
1606 | u8 cpumode = e->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | |
1607 | const char *handler_name = "auxtrace_error"; | |
1608 | unsigned long long tm = e->time; | |
1609 | const char *msg = e->msg; | |
1610 | PyObject *handler, *t; | |
1611 | ||
1612 | handler = get_handler(handler_name); | |
1613 | if (!handler) | |
1614 | return; | |
1615 | ||
1616 | if (!e->fmt) { | |
1617 | tm = 0; | |
1618 | msg = (const char *)&e->time; | |
1619 | } | |
1620 | ||
7151c1d1 | 1621 | t = tuple_new(11); |
2ede9217 AH |
1622 | |
1623 | tuple_set_u32(t, 0, e->type); | |
1624 | tuple_set_u32(t, 1, e->code); | |
1625 | tuple_set_s32(t, 2, e->cpu); | |
1626 | tuple_set_s32(t, 3, e->pid); | |
1627 | tuple_set_s32(t, 4, e->tid); | |
1628 | tuple_set_u64(t, 5, e->ip); | |
1629 | tuple_set_u64(t, 6, tm); | |
1630 | tuple_set_string(t, 7, msg); | |
1631 | tuple_set_u32(t, 8, cpumode); | |
7151c1d1 AH |
1632 | tuple_set_s32(t, 9, e->machine_pid); |
1633 | tuple_set_s32(t, 10, e->vcpu); | |
2ede9217 AH |
1634 | |
1635 | call_object(handler, t, handler_name); | |
1636 | ||
1637 | Py_DECREF(t); | |
1638 | } | |
1639 | ||
aef90263 | 1640 | static void get_handler_name(char *str, size_t size, |
32dcd021 | 1641 | struct evsel *evsel) |
aef90263 JO |
1642 | { |
1643 | char *p = str; | |
1644 | ||
8ab2e96d | 1645 | scnprintf(str, size, "stat__%s", evsel__name(evsel)); |
aef90263 JO |
1646 | |
1647 | while ((p = strchr(p, ':'))) { | |
1648 | *p = '_'; | |
1649 | p++; | |
1650 | } | |
1651 | } | |
1652 | ||
1653 | static void | |
6d18804b | 1654 | process_stat(struct evsel *counter, struct perf_cpu cpu, int thread, u64 tstamp, |
aef90263 JO |
1655 | struct perf_counts_values *count) |
1656 | { | |
1657 | PyObject *handler, *t; | |
1658 | static char handler_name[256]; | |
1659 | int n = 0; | |
1660 | ||
1661 | t = PyTuple_New(MAX_FIELDS); | |
1662 | if (!t) | |
1663 | Py_FatalError("couldn't create Python tuple"); | |
1664 | ||
1665 | get_handler_name(handler_name, sizeof(handler_name), | |
1666 | counter); | |
1667 | ||
1668 | handler = get_handler(handler_name); | |
1669 | if (!handler) { | |
1670 | pr_debug("can't find python handler %s\n", handler_name); | |
1671 | return; | |
1672 | } | |
1673 | ||
6d18804b | 1674 | PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu.cpu)); |
66dfdff0 | 1675 | PyTuple_SetItem(t, n++, _PyLong_FromLong(thread)); |
aef90263 JO |
1676 | |
1677 | tuple_set_u64(t, n++, tstamp); | |
1678 | tuple_set_u64(t, n++, count->val); | |
1679 | tuple_set_u64(t, n++, count->ena); | |
1680 | tuple_set_u64(t, n++, count->run); | |
1681 | ||
1682 | if (_PyTuple_Resize(&t, n) == -1) | |
1683 | Py_FatalError("error resizing Python tuple"); | |
1684 | ||
1685 | call_object(handler, t, handler_name); | |
1686 | ||
1687 | Py_DECREF(t); | |
1688 | } | |
1689 | ||
1690 | static void python_process_stat(struct perf_stat_config *config, | |
32dcd021 | 1691 | struct evsel *counter, u64 tstamp) |
aef90263 | 1692 | { |
af663bd0 | 1693 | struct perf_thread_map *threads = counter->core.threads; |
d400bd3a | 1694 | struct perf_cpu_map *cpus = counter->core.cpus; |
aef90263 | 1695 | |
71bc3ac8 IR |
1696 | for (int thread = 0; thread < perf_thread_map__nr(threads); thread++) { |
1697 | int idx; | |
1698 | struct perf_cpu cpu; | |
1699 | ||
1700 | perf_cpu_map__for_each_cpu(cpu, idx, cpus) { | |
1701 | process_stat(counter, cpu, | |
a2f354e3 | 1702 | perf_thread_map__pid(threads, thread), tstamp, |
71bc3ac8 | 1703 | perf_counts(counter->counts, idx, thread)); |
aef90263 JO |
1704 | } |
1705 | } | |
1706 | } | |
1707 | ||
1708 | static void python_process_stat_interval(u64 tstamp) | |
1709 | { | |
1710 | PyObject *handler, *t; | |
1711 | static const char handler_name[] = "stat__interval"; | |
1712 | int n = 0; | |
1713 | ||
1714 | t = PyTuple_New(MAX_FIELDS); | |
1715 | if (!t) | |
1716 | Py_FatalError("couldn't create Python tuple"); | |
1717 | ||
1718 | handler = get_handler(handler_name); | |
1719 | if (!handler) { | |
1720 | pr_debug("can't find python handler %s\n", handler_name); | |
1721 | return; | |
1722 | } | |
1723 | ||
1724 | tuple_set_u64(t, n++, tstamp); | |
1725 | ||
1726 | if (_PyTuple_Resize(&t, n) == -1) | |
1727 | Py_FatalError("error resizing Python tuple"); | |
1728 | ||
1729 | call_object(handler, t, handler_name); | |
1730 | ||
1731 | Py_DECREF(t); | |
1732 | } | |
1733 | ||
cf9bfa6c AH |
1734 | static int perf_script_context_init(void) |
1735 | { | |
1736 | PyObject *perf_script_context; | |
1737 | PyObject *perf_trace_context; | |
1738 | PyObject *dict; | |
1739 | int ret; | |
1740 | ||
1741 | perf_trace_context = PyImport_AddModule("perf_trace_context"); | |
1742 | if (!perf_trace_context) | |
1743 | return -1; | |
1744 | dict = PyModule_GetDict(perf_trace_context); | |
1745 | if (!dict) | |
1746 | return -1; | |
1747 | ||
1748 | perf_script_context = _PyCapsule_New(scripting_context, NULL, NULL); | |
1749 | if (!perf_script_context) | |
1750 | return -1; | |
1751 | ||
1752 | ret = PyDict_SetItemString(dict, "perf_script_context", perf_script_context); | |
1753 | if (!ret) | |
1754 | ret = PyDict_SetItemString(main_dict, "perf_script_context", perf_script_context); | |
1755 | Py_DECREF(perf_script_context); | |
1756 | return ret; | |
1757 | } | |
1758 | ||
7e4b21b8 TZ |
1759 | static int run_start_sub(void) |
1760 | { | |
7e4b21b8 TZ |
1761 | main_module = PyImport_AddModule("__main__"); |
1762 | if (main_module == NULL) | |
1763 | return -1; | |
1764 | Py_INCREF(main_module); | |
1765 | ||
1766 | main_dict = PyModule_GetDict(main_module); | |
a5563edf | 1767 | if (main_dict == NULL) |
7e4b21b8 | 1768 | goto error; |
7e4b21b8 TZ |
1769 | Py_INCREF(main_dict); |
1770 | ||
cf9bfa6c AH |
1771 | if (perf_script_context_init()) |
1772 | goto error; | |
1773 | ||
a5563edf | 1774 | try_call_object("trace_begin", NULL); |
7e4b21b8 | 1775 | |
a5563edf | 1776 | return 0; |
7e4b21b8 | 1777 | |
7e4b21b8 TZ |
1778 | error: |
1779 | Py_XDECREF(main_dict); | |
1780 | Py_XDECREF(main_module); | |
a5563edf | 1781 | return -1; |
7e4b21b8 TZ |
1782 | } |
1783 | ||
df919b40 AH |
1784 | #define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \ |
1785 | tables->handler_name = get_handler(#table_name); \ | |
1786 | if (tables->handler_name) \ | |
1787 | tables->dbe.export_ ## name = python_export_ ## name; \ | |
1788 | } while (0) | |
1789 | ||
1790 | #define SET_TABLE_HANDLER(name) \ | |
1791 | SET_TABLE_HANDLER_(name, name ## _handler, name ## _table) | |
1792 | ||
1793 | static void set_table_handlers(struct tables *tables) | |
1794 | { | |
1795 | const char *perf_db_export_mode = "perf_db_export_mode"; | |
6a70307d | 1796 | const char *perf_db_export_calls = "perf_db_export_calls"; |
2c15f5eb CP |
1797 | const char *perf_db_export_callchains = "perf_db_export_callchains"; |
1798 | PyObject *db_export_mode, *db_export_calls, *db_export_callchains; | |
6a70307d | 1799 | bool export_calls = false; |
2c15f5eb | 1800 | bool export_callchains = false; |
df919b40 AH |
1801 | int ret; |
1802 | ||
1803 | memset(tables, 0, sizeof(struct tables)); | |
1804 | if (db_export__init(&tables->dbe)) | |
1805 | Py_FatalError("failed to initialize export"); | |
1806 | ||
1807 | db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode); | |
1808 | if (!db_export_mode) | |
1809 | return; | |
1810 | ||
1811 | ret = PyObject_IsTrue(db_export_mode); | |
1812 | if (ret == -1) | |
1813 | handler_call_die(perf_db_export_mode); | |
1814 | if (!ret) | |
1815 | return; | |
1816 | ||
2c15f5eb | 1817 | /* handle export calls */ |
6a70307d AH |
1818 | tables->dbe.crp = NULL; |
1819 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | |
1820 | if (db_export_calls) { | |
1821 | ret = PyObject_IsTrue(db_export_calls); | |
1822 | if (ret == -1) | |
1823 | handler_call_die(perf_db_export_calls); | |
1824 | export_calls = !!ret; | |
1825 | } | |
1826 | ||
1827 | if (export_calls) { | |
1828 | tables->dbe.crp = | |
1829 | call_return_processor__new(python_process_call_return, | |
1830 | &tables->dbe); | |
1831 | if (!tables->dbe.crp) | |
1832 | Py_FatalError("failed to create calls processor"); | |
1833 | } | |
1834 | ||
2c15f5eb CP |
1835 | /* handle export callchains */ |
1836 | tables->dbe.cpr = NULL; | |
1837 | db_export_callchains = PyDict_GetItemString(main_dict, | |
1838 | perf_db_export_callchains); | |
1839 | if (db_export_callchains) { | |
1840 | ret = PyObject_IsTrue(db_export_callchains); | |
1841 | if (ret == -1) | |
1842 | handler_call_die(perf_db_export_callchains); | |
1843 | export_callchains = !!ret; | |
1844 | } | |
1845 | ||
1846 | if (export_callchains) { | |
1847 | /* | |
1848 | * Attempt to use the call path root from the call return | |
1849 | * processor, if the call return processor is in use. Otherwise, | |
1850 | * we allocate a new call path root. This prevents exporting | |
4d39c89f | 1851 | * duplicate call path ids when both are in use simultaneously. |
2c15f5eb CP |
1852 | */ |
1853 | if (tables->dbe.crp) | |
1854 | tables->dbe.cpr = tables->dbe.crp->cpr; | |
1855 | else | |
1856 | tables->dbe.cpr = call_path_root__new(); | |
1857 | ||
1858 | if (!tables->dbe.cpr) | |
aff63340 | 1859 | Py_FatalError("failed to create call path root"); |
2c15f5eb CP |
1860 | } |
1861 | ||
df919b40 AH |
1862 | tables->db_export_mode = true; |
1863 | /* | |
1864 | * Reserve per symbol space for symbol->db_id via symbol__priv() | |
1865 | */ | |
1866 | symbol_conf.priv_size = sizeof(u64); | |
1867 | ||
1868 | SET_TABLE_HANDLER(evsel); | |
1869 | SET_TABLE_HANDLER(machine); | |
1870 | SET_TABLE_HANDLER(thread); | |
1871 | SET_TABLE_HANDLER(comm); | |
1872 | SET_TABLE_HANDLER(comm_thread); | |
1873 | SET_TABLE_HANDLER(dso); | |
1874 | SET_TABLE_HANDLER(symbol); | |
c29414f5 | 1875 | SET_TABLE_HANDLER(branch_type); |
df919b40 | 1876 | SET_TABLE_HANDLER(sample); |
6a70307d AH |
1877 | SET_TABLE_HANDLER(call_path); |
1878 | SET_TABLE_HANDLER(call_return); | |
abde8722 | 1879 | SET_TABLE_HANDLER(context_switch); |
b9322cab AH |
1880 | |
1881 | /* | |
1882 | * Synthesized events are samples but with architecture-specific data | |
1883 | * stored in sample->raw_data. They are exported via | |
1884 | * python_export_sample() and consequently do not need a separate export | |
1885 | * callback. | |
1886 | */ | |
1887 | tables->synth_handler = get_handler("synth_data"); | |
df919b40 AH |
1888 | } |
1889 | ||
66dfdff0 JŠ |
1890 | static void _free_command_line(wchar_t **command_line, int num) |
1891 | { | |
1892 | int i; | |
1893 | for (i = 0; i < num; i++) | |
1894 | PyMem_RawFree(command_line[i]); | |
1895 | free(command_line); | |
1896 | } | |
66dfdff0 JŠ |
1897 | |
1898 | ||
7e4b21b8 TZ |
1899 | /* |
1900 | * Start trace script | |
1901 | */ | |
67e50ce0 AH |
1902 | static int python_start_script(const char *script, int argc, const char **argv, |
1903 | struct perf_session *session) | |
7e4b21b8 | 1904 | { |
df919b40 | 1905 | struct tables *tables = &tables_global; |
66dfdff0 | 1906 | wchar_t **command_line; |
e7e9943c | 1907 | char buf[PATH_MAX]; |
7e4b21b8 TZ |
1908 | int i, err = 0; |
1909 | FILE *fp; | |
1910 | ||
67e50ce0 | 1911 | scripting_context->session = session; |
66dfdff0 | 1912 | command_line = malloc((argc + 1) * sizeof(wchar_t *)); |
b457c526 PL |
1913 | if (!command_line) |
1914 | return -1; | |
1915 | ||
66dfdff0 JŠ |
1916 | command_line[0] = Py_DecodeLocale(script, NULL); |
1917 | for (i = 1; i < argc + 1; i++) | |
1918 | command_line[i] = Py_DecodeLocale(argv[i - 1], NULL); | |
e7e9943c | 1919 | PyImport_AppendInittab("perf_trace_context", PyInit_perf_trace_context); |
7e4b21b8 TZ |
1920 | Py_Initialize(); |
1921 | ||
66dfdff0 | 1922 | PySys_SetArgv(argc + 1, command_line); |
7e4b21b8 TZ |
1923 | |
1924 | fp = fopen(script, "r"); | |
1925 | if (!fp) { | |
1926 | sprintf(buf, "Can't open python script \"%s\"", script); | |
1927 | perror(buf); | |
1928 | err = -1; | |
1929 | goto error; | |
1930 | } | |
1931 | ||
1932 | err = PyRun_SimpleFile(fp, script); | |
1933 | if (err) { | |
1934 | fprintf(stderr, "Error running python script %s\n", script); | |
1935 | goto error; | |
1936 | } | |
1937 | ||
1938 | err = run_start_sub(); | |
1939 | if (err) { | |
1940 | fprintf(stderr, "Error starting python script %s\n", script); | |
1941 | goto error; | |
1942 | } | |
1943 | ||
df919b40 AH |
1944 | set_table_handlers(tables); |
1945 | ||
c29414f5 AH |
1946 | if (tables->db_export_mode) { |
1947 | err = db_export__branch_types(&tables->dbe); | |
1948 | if (err) | |
1949 | goto error; | |
1950 | } | |
1951 | ||
66dfdff0 | 1952 | _free_command_line(command_line, argc + 1); |
979ac257 | 1953 | |
7e4b21b8 TZ |
1954 | return err; |
1955 | error: | |
1956 | Py_Finalize(); | |
66dfdff0 | 1957 | _free_command_line(command_line, argc + 1); |
7e4b21b8 TZ |
1958 | |
1959 | return err; | |
1960 | } | |
1961 | ||
d445dd2a AH |
1962 | static int python_flush_script(void) |
1963 | { | |
fead24e5 | 1964 | return 0; |
d445dd2a AH |
1965 | } |
1966 | ||
7e4b21b8 TZ |
1967 | /* |
1968 | * Stop trace script | |
1969 | */ | |
1970 | static int python_stop_script(void) | |
1971 | { | |
df919b40 AH |
1972 | struct tables *tables = &tables_global; |
1973 | ||
a5563edf | 1974 | try_call_object("trace_end", NULL); |
7e4b21b8 | 1975 | |
df919b40 AH |
1976 | db_export__exit(&tables->dbe); |
1977 | ||
7e4b21b8 TZ |
1978 | Py_XDECREF(main_dict); |
1979 | Py_XDECREF(main_module); | |
1980 | Py_Finalize(); | |
1981 | ||
a5563edf | 1982 | return 0; |
7e4b21b8 TZ |
1983 | } |
1984 | ||
80c3a7d9 | 1985 | #ifdef HAVE_LIBTRACEEVENT |
096177a8 | 1986 | static int python_generate_script(struct tep_handle *pevent, const char *outfile) |
7e4b21b8 | 1987 | { |
a5e05abc SRV |
1988 | int i, not_first, count, nr_events; |
1989 | struct tep_event **all_events; | |
97fbf3f0 | 1990 | struct tep_event *event = NULL; |
2c92f982 | 1991 | struct tep_format_field *f; |
7e4b21b8 | 1992 | char fname[PATH_MAX]; |
7e4b21b8 TZ |
1993 | FILE *ofp; |
1994 | ||
1995 | sprintf(fname, "%s.py", outfile); | |
1996 | ofp = fopen(fname, "w"); | |
1997 | if (ofp == NULL) { | |
1998 | fprintf(stderr, "couldn't open %s\n", fname); | |
1999 | return -1; | |
2000 | } | |
133dc4c3 IM |
2001 | fprintf(ofp, "# perf script event handlers, " |
2002 | "generated by perf script -g python\n"); | |
7e4b21b8 TZ |
2003 | |
2004 | fprintf(ofp, "# Licensed under the terms of the GNU GPL" | |
2005 | " License version 2\n\n"); | |
2006 | ||
2007 | fprintf(ofp, "# The common_* event handler fields are the most useful " | |
2008 | "fields common to\n"); | |
2009 | ||
2010 | fprintf(ofp, "# all events. They don't necessarily correspond to " | |
2011 | "the 'common_*' fields\n"); | |
2012 | ||
2013 | fprintf(ofp, "# in the format files. Those fields not available as " | |
2014 | "handler params can\n"); | |
2015 | ||
2016 | fprintf(ofp, "# be retrieved using Python functions of the form " | |
2017 | "common_*(context).\n"); | |
2018 | ||
c76132dc | 2019 | fprintf(ofp, "# See the perf-script-python Documentation for the list " |
7e4b21b8 TZ |
2020 | "of available functions.\n\n"); |
2021 | ||
877cc639 | 2022 | fprintf(ofp, "from __future__ import print_function\n\n"); |
7e4b21b8 TZ |
2023 | fprintf(ofp, "import os\n"); |
2024 | fprintf(ofp, "import sys\n\n"); | |
2025 | ||
2026 | fprintf(ofp, "sys.path.append(os.environ['PERF_EXEC_PATH'] + \\\n"); | |
2027 | fprintf(ofp, "\t'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')\n"); | |
2028 | fprintf(ofp, "\nfrom perf_trace_context import *\n"); | |
2029 | fprintf(ofp, "from Core import *\n\n\n"); | |
2030 | ||
2031 | fprintf(ofp, "def trace_begin():\n"); | |
877cc639 | 2032 | fprintf(ofp, "\tprint(\"in trace_begin\")\n\n"); |
7e4b21b8 TZ |
2033 | |
2034 | fprintf(ofp, "def trace_end():\n"); | |
877cc639 | 2035 | fprintf(ofp, "\tprint(\"in trace_end\")\n\n"); |
7e4b21b8 | 2036 | |
a5e05abc SRV |
2037 | nr_events = tep_get_events_count(pevent); |
2038 | all_events = tep_list_events(pevent, TEP_EVENT_SORT_ID); | |
2039 | ||
2040 | for (i = 0; all_events && i < nr_events; i++) { | |
2041 | event = all_events[i]; | |
7e4b21b8 TZ |
2042 | fprintf(ofp, "def %s__%s(", event->system, event->name); |
2043 | fprintf(ofp, "event_name, "); | |
2044 | fprintf(ofp, "context, "); | |
2045 | fprintf(ofp, "common_cpu,\n"); | |
2046 | fprintf(ofp, "\tcommon_secs, "); | |
2047 | fprintf(ofp, "common_nsecs, "); | |
2048 | fprintf(ofp, "common_pid, "); | |
2049 | fprintf(ofp, "common_comm,\n\t"); | |
0f5f5bcd | 2050 | fprintf(ofp, "common_callchain, "); |
7e4b21b8 TZ |
2051 | |
2052 | not_first = 0; | |
2053 | count = 0; | |
2054 | ||
2055 | for (f = event->format.fields; f; f = f->next) { | |
2056 | if (not_first++) | |
2057 | fprintf(ofp, ", "); | |
2058 | if (++count % 5 == 0) | |
2059 | fprintf(ofp, "\n\t"); | |
2060 | ||
2061 | fprintf(ofp, "%s", f->name); | |
2062 | } | |
a6418605 AK |
2063 | if (not_first++) |
2064 | fprintf(ofp, ", "); | |
2065 | if (++count % 5 == 0) | |
2066 | fprintf(ofp, "\n\t\t"); | |
2067 | fprintf(ofp, "perf_sample_dict"); | |
2068 | ||
7e4b21b8 TZ |
2069 | fprintf(ofp, "):\n"); |
2070 | ||
2071 | fprintf(ofp, "\t\tprint_header(event_name, common_cpu, " | |
2072 | "common_secs, common_nsecs,\n\t\t\t" | |
2073 | "common_pid, common_comm)\n\n"); | |
2074 | ||
877cc639 | 2075 | fprintf(ofp, "\t\tprint(\""); |
7e4b21b8 TZ |
2076 | |
2077 | not_first = 0; | |
2078 | count = 0; | |
2079 | ||
2080 | for (f = event->format.fields; f; f = f->next) { | |
2081 | if (not_first++) | |
2082 | fprintf(ofp, ", "); | |
2083 | if (count && count % 3 == 0) { | |
2084 | fprintf(ofp, "\" \\\n\t\t\""); | |
2085 | } | |
2086 | count++; | |
2087 | ||
2088 | fprintf(ofp, "%s=", f->name); | |
bb39ccb2 TSV |
2089 | if (f->flags & TEP_FIELD_IS_STRING || |
2090 | f->flags & TEP_FIELD_IS_FLAG || | |
2091 | f->flags & TEP_FIELD_IS_ARRAY || | |
2092 | f->flags & TEP_FIELD_IS_SYMBOLIC) | |
7e4b21b8 | 2093 | fprintf(ofp, "%%s"); |
bb39ccb2 | 2094 | else if (f->flags & TEP_FIELD_IS_SIGNED) |
7e4b21b8 TZ |
2095 | fprintf(ofp, "%%d"); |
2096 | else | |
2097 | fprintf(ofp, "%%u"); | |
2098 | } | |
2099 | ||
0f5f5bcd | 2100 | fprintf(ofp, "\" %% \\\n\t\t("); |
7e4b21b8 TZ |
2101 | |
2102 | not_first = 0; | |
2103 | count = 0; | |
2104 | ||
2105 | for (f = event->format.fields; f; f = f->next) { | |
2106 | if (not_first++) | |
2107 | fprintf(ofp, ", "); | |
2108 | ||
2109 | if (++count % 5 == 0) | |
2110 | fprintf(ofp, "\n\t\t"); | |
2111 | ||
bb39ccb2 | 2112 | if (f->flags & TEP_FIELD_IS_FLAG) { |
7e4b21b8 TZ |
2113 | if ((count - 1) % 5 != 0) { |
2114 | fprintf(ofp, "\n\t\t"); | |
2115 | count = 4; | |
2116 | } | |
2117 | fprintf(ofp, "flag_str(\""); | |
2118 | fprintf(ofp, "%s__%s\", ", event->system, | |
2119 | event->name); | |
2120 | fprintf(ofp, "\"%s\", %s)", f->name, | |
2121 | f->name); | |
bb39ccb2 | 2122 | } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) { |
7e4b21b8 TZ |
2123 | if ((count - 1) % 5 != 0) { |
2124 | fprintf(ofp, "\n\t\t"); | |
2125 | count = 4; | |
2126 | } | |
2127 | fprintf(ofp, "symbol_str(\""); | |
2128 | fprintf(ofp, "%s__%s\", ", event->system, | |
2129 | event->name); | |
2130 | fprintf(ofp, "\"%s\", %s)", f->name, | |
2131 | f->name); | |
2132 | } else | |
2133 | fprintf(ofp, "%s", f->name); | |
2134 | } | |
2135 | ||
877cc639 | 2136 | fprintf(ofp, "))\n\n"); |
0f5f5bcd | 2137 | |
877cc639 JC |
2138 | fprintf(ofp, "\t\tprint('Sample: {'+" |
2139 | "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')\n\n"); | |
a6418605 | 2140 | |
0f5f5bcd JS |
2141 | fprintf(ofp, "\t\tfor node in common_callchain:"); |
2142 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | |
ae24e9b5 EC |
2143 | fprintf(ofp, "\n\t\t\t\tprint(\"\t[%%x] %%s%%s%%s%%s\" %% ("); |
2144 | fprintf(ofp, "\n\t\t\t\t\tnode['ip'], node['sym']['name'],"); | |
2145 | fprintf(ofp, "\n\t\t\t\t\t\"+0x{:x}\".format(node['sym_off']) if 'sym_off' in node else \"\","); | |
2146 | fprintf(ofp, "\n\t\t\t\t\t\" ({})\".format(node['dso']) if 'dso' in node else \"\","); | |
2147 | fprintf(ofp, "\n\t\t\t\t\t\" \" + node['sym_srcline'] if 'sym_srcline' in node else \"\"))"); | |
0f5f5bcd | 2148 | fprintf(ofp, "\n\t\t\telse:"); |
877cc639 JC |
2149 | fprintf(ofp, "\n\t\t\t\tprint(\"\t[%%x]\" %% (node['ip']))\n\n"); |
2150 | fprintf(ofp, "\t\tprint()\n\n"); | |
0f5f5bcd | 2151 | |
7e4b21b8 TZ |
2152 | } |
2153 | ||
2154 | fprintf(ofp, "def trace_unhandled(event_name, context, " | |
a6418605 | 2155 | "event_fields_dict, perf_sample_dict):\n"); |
7e4b21b8 | 2156 | |
877cc639 JC |
2157 | fprintf(ofp, "\t\tprint(get_dict_as_string(event_fields_dict))\n"); |
2158 | fprintf(ofp, "\t\tprint('Sample: {'+" | |
2159 | "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')\n\n"); | |
7e4b21b8 TZ |
2160 | |
2161 | fprintf(ofp, "def print_header(" | |
2162 | "event_name, cpu, secs, nsecs, pid, comm):\n" | |
877cc639 JC |
2163 | "\tprint(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" |
2164 | "(event_name, cpu, secs, nsecs, pid, comm), end=\"\")\n\n"); | |
a6418605 AK |
2165 | |
2166 | fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n" | |
2167 | "\treturn delimiter.join" | |
2168 | "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n"); | |
7e4b21b8 TZ |
2169 | |
2170 | fclose(ofp); | |
2171 | ||
2172 | fprintf(stderr, "generated Python script: %s\n", fname); | |
2173 | ||
2174 | return 0; | |
2175 | } | |
80c3a7d9 AH |
2176 | #else |
2177 | static int python_generate_script(struct tep_handle *pevent __maybe_unused, | |
2178 | const char *outfile __maybe_unused) | |
2179 | { | |
2180 | fprintf(stderr, "Generating Python perf-script is not supported." | |
2181 | " Install libtraceevent and rebuild perf to enable it.\n" | |
2182 | "For example:\n # apt install libtraceevent-dev (ubuntu)" | |
2183 | "\n # yum install libtraceevent-devel (Fedora)" | |
2184 | "\n etc.\n"); | |
2185 | return -1; | |
2186 | } | |
2187 | #endif | |
7e4b21b8 TZ |
2188 | |
2189 | struct scripting_ops python_scripting_ops = { | |
aef90263 | 2190 | .name = "Python", |
6ea4b5db | 2191 | .dirname = "python", |
aef90263 JO |
2192 | .start_script = python_start_script, |
2193 | .flush_script = python_flush_script, | |
2194 | .stop_script = python_stop_script, | |
2195 | .process_event = python_process_event, | |
abde8722 | 2196 | .process_switch = python_process_switch, |
2ede9217 | 2197 | .process_auxtrace_error = python_process_auxtrace_error, |
aef90263 JO |
2198 | .process_stat = python_process_stat, |
2199 | .process_stat_interval = python_process_stat_interval, | |
538d9c18 | 2200 | .process_throttle = python_process_throttle, |
aef90263 | 2201 | .generate_script = python_generate_script, |
7e4b21b8 | 2202 | }; |