aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/scripting-engines/trace-event-python.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c227
1 files changed, 185 insertions, 42 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 53c20e7fd900..cbce2545da45 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,11 +27,13 @@
27#include <errno.h> 27#include <errno.h>
28 28
29#include "../../perf.h" 29#include "../../perf.h"
30#include "../debug.h"
30#include "../evsel.h" 31#include "../evsel.h"
31#include "../util.h" 32#include "../util.h"
32#include "../event.h" 33#include "../event.h"
33#include "../thread.h" 34#include "../thread.h"
34#include "../trace-event.h" 35#include "../trace-event.h"
36#include "../machine.h"
35 37
36PyMODINIT_FUNC initperf_trace_context(void); 38PyMODINIT_FUNC initperf_trace_context(void);
37 39
@@ -50,10 +52,14 @@ static int zero_flag_atom;
50 52
51static PyObject *main_module, *main_dict; 53static PyObject *main_module, *main_dict;
52 54
55static void handler_call_die(const char *handler_name) NORETURN;
53static void handler_call_die(const char *handler_name) 56static void handler_call_die(const char *handler_name)
54{ 57{
55 PyErr_Print(); 58 PyErr_Print();
56 Py_FatalError("problem in Python trace event handler"); 59 Py_FatalError("problem in Python trace event handler");
60 // Py_FatalError does not return
61 // but we have to make the compiler happy
62 abort();
57} 63}
58 64
59/* 65/*
@@ -97,6 +103,7 @@ static void define_value(enum print_arg_type field_type,
97 retval = PyObject_CallObject(handler, t); 103 retval = PyObject_CallObject(handler, t);
98 if (retval == NULL) 104 if (retval == NULL)
99 handler_call_die(handler_name); 105 handler_call_die(handler_name);
106 Py_DECREF(retval);
100 } 107 }
101 108
102 Py_DECREF(t); 109 Py_DECREF(t);
@@ -143,6 +150,7 @@ static void define_field(enum print_arg_type field_type,
143 retval = PyObject_CallObject(handler, t); 150 retval = PyObject_CallObject(handler, t);
144 if (retval == NULL) 151 if (retval == NULL)
145 handler_call_die(handler_name); 152 handler_call_die(handler_name);
153 Py_DECREF(retval);
146 } 154 }
147 155
148 Py_DECREF(t); 156 Py_DECREF(t);
@@ -161,8 +169,7 @@ static void define_event_symbols(struct event_format *event,
161 zero_flag_atom = 0; 169 zero_flag_atom = 0;
162 break; 170 break;
163 case PRINT_FIELD: 171 case PRINT_FIELD:
164 if (cur_field_name) 172 free(cur_field_name);
165 free(cur_field_name);
166 cur_field_name = strdup(args->field.name); 173 cur_field_name = strdup(args->field.name);
167 break; 174 break;
168 case PRINT_FLAGS: 175 case PRINT_FLAGS:
@@ -198,6 +205,7 @@ static void define_event_symbols(struct event_format *event,
198 case PRINT_BSTRING: 205 case PRINT_BSTRING:
199 case PRINT_DYNAMIC_ARRAY: 206 case PRINT_DYNAMIC_ARRAY:
200 case PRINT_FUNC: 207 case PRINT_FUNC:
208 case PRINT_BITMASK:
201 /* we should warn... */ 209 /* we should warn... */
202 return; 210 return;
203 } 211 }
@@ -231,18 +239,133 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
231 return event; 239 return event;
232} 240}
233 241
234static void python_process_tracepoint(union perf_event *perf_event 242static PyObject *get_field_numeric_entry(struct event_format *event,
235 __maybe_unused, 243 struct format_field *field, void *data)
236 struct perf_sample *sample, 244{
237 struct perf_evsel *evsel, 245 bool is_array = field->flags & FIELD_IS_ARRAY;
238 struct machine *machine __maybe_unused, 246 PyObject *obj, *list = NULL;
239 struct thread *thread, 247 unsigned long long val;
240 struct addr_location *al) 248 unsigned int item_size, n_items, i;
249
250 if (is_array) {
251 list = PyList_New(field->arraylen);
252 item_size = field->size / field->arraylen;
253 n_items = field->arraylen;
254 } else {
255 item_size = field->size;
256 n_items = 1;
257 }
258
259 for (i = 0; i < n_items; i++) {
260
261 val = read_size(event, data + field->offset + i * item_size,
262 item_size);
263 if (field->flags & FIELD_IS_SIGNED) {
264 if ((long long)val >= LONG_MIN &&
265 (long long)val <= LONG_MAX)
266 obj = PyInt_FromLong(val);
267 else
268 obj = PyLong_FromLongLong(val);
269 } else {
270 if (val <= LONG_MAX)
271 obj = PyInt_FromLong(val);
272 else
273 obj = PyLong_FromUnsignedLongLong(val);
274 }
275 if (is_array)
276 PyList_SET_ITEM(list, i, obj);
277 }
278 if (is_array)
279 obj = list;
280 return obj;
281}
282
283
284static PyObject *python_process_callchain(struct perf_sample *sample,
285 struct perf_evsel *evsel,
286 struct addr_location *al)
287{
288 PyObject *pylist;
289
290 pylist = PyList_New(0);
291 if (!pylist)
292 Py_FatalError("couldn't create Python list");
293
294 if (!symbol_conf.use_callchain || !sample->callchain)
295 goto exit;
296
297 if (machine__resolve_callchain(al->machine, evsel, al->thread,
298 sample, NULL, NULL,
299 PERF_MAX_STACK_DEPTH) != 0) {
300 pr_err("Failed to resolve callchain. Skipping\n");
301 goto exit;
302 }
303 callchain_cursor_commit(&callchain_cursor);
304
305
306 while (1) {
307 PyObject *pyelem;
308 struct callchain_cursor_node *node;
309 node = callchain_cursor_current(&callchain_cursor);
310 if (!node)
311 break;
312
313 pyelem = PyDict_New();
314 if (!pyelem)
315 Py_FatalError("couldn't create Python dictionary");
316
317
318 pydict_set_item_string_decref(pyelem, "ip",
319 PyLong_FromUnsignedLongLong(node->ip));
320
321 if (node->sym) {
322 PyObject *pysym = PyDict_New();
323 if (!pysym)
324 Py_FatalError("couldn't create Python dictionary");
325 pydict_set_item_string_decref(pysym, "start",
326 PyLong_FromUnsignedLongLong(node->sym->start));
327 pydict_set_item_string_decref(pysym, "end",
328 PyLong_FromUnsignedLongLong(node->sym->end));
329 pydict_set_item_string_decref(pysym, "binding",
330 PyInt_FromLong(node->sym->binding));
331 pydict_set_item_string_decref(pysym, "name",
332 PyString_FromStringAndSize(node->sym->name,
333 node->sym->namelen));
334 pydict_set_item_string_decref(pyelem, "sym", pysym);
335 }
336
337 if (node->map) {
338 struct map *map = node->map;
339 const char *dsoname = "[unknown]";
340 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
341 if (symbol_conf.show_kernel_path && map->dso->long_name)
342 dsoname = map->dso->long_name;
343 else if (map->dso->name)
344 dsoname = map->dso->name;
345 }
346 pydict_set_item_string_decref(pyelem, "dso",
347 PyString_FromString(dsoname));
348 }
349
350 callchain_cursor_advance(&callchain_cursor);
351 PyList_Append(pylist, pyelem);
352 Py_DECREF(pyelem);
353 }
354
355exit:
356 return pylist;
357}
358
359
360static void python_process_tracepoint(struct perf_sample *sample,
361 struct perf_evsel *evsel,
362 struct thread *thread,
363 struct addr_location *al)
241{ 364{
242 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 365 PyObject *handler, *retval, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL;
243 static char handler_name[256]; 367 static char handler_name[256];
244 struct format_field *field; 368 struct format_field *field;
245 unsigned long long val;
246 unsigned long s, ns; 369 unsigned long s, ns;
247 struct event_format *event; 370 struct event_format *event;
248 unsigned n = 0; 371 unsigned n = 0;
@@ -283,18 +406,23 @@ static void python_process_tracepoint(union perf_event *perf_event
283 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 406 PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
284 PyTuple_SetItem(t, n++, context); 407 PyTuple_SetItem(t, n++, context);
285 408
409 /* ip unwinding */
410 callchain = python_process_callchain(sample, evsel, al);
411
286 if (handler) { 412 if (handler) {
287 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 413 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
288 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 414 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
289 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 415 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
290 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 416 PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
291 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 417 PyTuple_SetItem(t, n++, PyString_FromString(comm));
418 PyTuple_SetItem(t, n++, callchain);
292 } else { 419 } else {
293 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 420 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
294 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 421 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
295 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 422 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
296 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 423 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
297 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 424 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
425 pydict_set_item_string_decref(dict, "common_callchain", callchain);
298 } 426 }
299 for (field = event->format.fields; field; field = field->next) { 427 for (field = event->format.fields; field; field = field->next) {
300 if (field->flags & FIELD_IS_STRING) { 428 if (field->flags & FIELD_IS_STRING) {
@@ -306,20 +434,7 @@ static void python_process_tracepoint(union perf_event *perf_event
306 offset = field->offset; 434 offset = field->offset;
307 obj = PyString_FromString((char *)data + offset); 435 obj = PyString_FromString((char *)data + offset);
308 } else { /* FIELD_IS_NUMERIC */ 436 } else { /* FIELD_IS_NUMERIC */
309 val = read_size(event, data + field->offset, 437 obj = get_field_numeric_entry(event, field, data);
310 field->size);
311 if (field->flags & FIELD_IS_SIGNED) {
312 if ((long long)val >= LONG_MIN &&
313 (long long)val <= LONG_MAX)
314 obj = PyInt_FromLong(val);
315 else
316 obj = PyLong_FromLongLong(val);
317 } else {
318 if (val <= LONG_MAX)
319 obj = PyInt_FromLong(val);
320 else
321 obj = PyLong_FromUnsignedLongLong(val);
322 }
323 } 438 }
324 if (handler) 439 if (handler)
325 PyTuple_SetItem(t, n++, obj); 440 PyTuple_SetItem(t, n++, obj);
@@ -327,6 +442,7 @@ static void python_process_tracepoint(union perf_event *perf_event
327 pydict_set_item_string_decref(dict, field->name, obj); 442 pydict_set_item_string_decref(dict, field->name, obj);
328 443
329 } 444 }
445
330 if (!handler) 446 if (!handler)
331 PyTuple_SetItem(t, n++, dict); 447 PyTuple_SetItem(t, n++, dict);
332 448
@@ -337,6 +453,7 @@ static void python_process_tracepoint(union perf_event *perf_event
337 retval = PyObject_CallObject(handler, t); 453 retval = PyObject_CallObject(handler, t);
338 if (retval == NULL) 454 if (retval == NULL)
339 handler_call_die(handler_name); 455 handler_call_die(handler_name);
456 Py_DECREF(retval);
340 } else { 457 } else {
341 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 458 handler = PyDict_GetItemString(main_dict, "trace_unhandled");
342 if (handler && PyCallable_Check(handler)) { 459 if (handler && PyCallable_Check(handler)) {
@@ -344,6 +461,7 @@ static void python_process_tracepoint(union perf_event *perf_event
344 retval = PyObject_CallObject(handler, t); 461 retval = PyObject_CallObject(handler, t);
345 if (retval == NULL) 462 if (retval == NULL)
346 handler_call_die("trace_unhandled"); 463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
347 } 465 }
348 Py_DECREF(dict); 466 Py_DECREF(dict);
349 } 467 }
@@ -351,15 +469,12 @@ static void python_process_tracepoint(union perf_event *perf_event
351 Py_DECREF(t); 469 Py_DECREF(t);
352} 470}
353 471
354static void python_process_general_event(union perf_event *perf_event 472static void python_process_general_event(struct perf_sample *sample,
355 __maybe_unused,
356 struct perf_sample *sample,
357 struct perf_evsel *evsel, 473 struct perf_evsel *evsel,
358 struct machine *machine __maybe_unused,
359 struct thread *thread, 474 struct thread *thread,
360 struct addr_location *al) 475 struct addr_location *al)
361{ 476{
362 PyObject *handler, *retval, *t, *dict; 477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
363 static char handler_name[64]; 478 static char handler_name[64];
364 unsigned n = 0; 479 unsigned n = 0;
365 480
@@ -375,6 +490,10 @@ static void python_process_general_event(union perf_event *perf_event
375 if (!dict) 490 if (!dict)
376 Py_FatalError("couldn't create Python dictionary"); 491 Py_FatalError("couldn't create Python dictionary");
377 492
493 dict_sample = PyDict_New();
494 if (!dict_sample)
495 Py_FatalError("couldn't create Python dictionary");
496
378 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
379 498
380 handler = PyDict_GetItemString(main_dict, handler_name); 499 handler = PyDict_GetItemString(main_dict, handler_name);
@@ -384,8 +503,21 @@ static void python_process_general_event(union perf_event *perf_event
384 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
385 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 504 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
386 (const char *)&evsel->attr, sizeof(evsel->attr))); 505 (const char *)&evsel->attr, sizeof(evsel->attr)));
387 pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( 506
388 (const char *)sample, sizeof(*sample))); 507 pydict_set_item_string_decref(dict_sample, "pid",
508 PyInt_FromLong(sample->pid));
509 pydict_set_item_string_decref(dict_sample, "tid",
510 PyInt_FromLong(sample->tid));
511 pydict_set_item_string_decref(dict_sample, "cpu",
512 PyInt_FromLong(sample->cpu));
513 pydict_set_item_string_decref(dict_sample, "ip",
514 PyLong_FromUnsignedLongLong(sample->ip));
515 pydict_set_item_string_decref(dict_sample, "time",
516 PyLong_FromUnsignedLongLong(sample->time));
517 pydict_set_item_string_decref(dict_sample, "period",
518 PyLong_FromUnsignedLongLong(sample->period));
519 pydict_set_item_string_decref(dict, "sample", dict_sample);
520
389 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 521 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
390 (const char *)sample->raw_data, sample->raw_size)); 522 (const char *)sample->raw_data, sample->raw_size));
391 pydict_set_item_string_decref(dict, "comm", 523 pydict_set_item_string_decref(dict, "comm",
@@ -399,6 +531,10 @@ static void python_process_general_event(union perf_event *perf_event
399 PyString_FromString(al->sym->name)); 531 PyString_FromString(al->sym->name));
400 } 532 }
401 533
534 /* ip unwinding */
535 callchain = python_process_callchain(sample, evsel, al);
536 pydict_set_item_string_decref(dict, "callchain", callchain);
537
402 PyTuple_SetItem(t, n++, dict); 538 PyTuple_SetItem(t, n++, dict);
403 if (_PyTuple_Resize(&t, n) == -1) 539 if (_PyTuple_Resize(&t, n) == -1)
404 Py_FatalError("error resizing Python tuple"); 540 Py_FatalError("error resizing Python tuple");
@@ -406,27 +542,25 @@ static void python_process_general_event(union perf_event *perf_event
406 retval = PyObject_CallObject(handler, t); 542 retval = PyObject_CallObject(handler, t);
407 if (retval == NULL) 543 if (retval == NULL)
408 handler_call_die(handler_name); 544 handler_call_die(handler_name);
545 Py_DECREF(retval);
409exit: 546exit:
410 Py_DECREF(dict); 547 Py_DECREF(dict);
411 Py_DECREF(t); 548 Py_DECREF(t);
412} 549}
413 550
414static void python_process_event(union perf_event *perf_event, 551static void python_process_event(union perf_event *event __maybe_unused,
415 struct perf_sample *sample, 552 struct perf_sample *sample,
416 struct perf_evsel *evsel, 553 struct perf_evsel *evsel,
417 struct machine *machine,
418 struct thread *thread, 554 struct thread *thread,
419 struct addr_location *al) 555 struct addr_location *al)
420{ 556{
421 switch (evsel->attr.type) { 557 switch (evsel->attr.type) {
422 case PERF_TYPE_TRACEPOINT: 558 case PERF_TYPE_TRACEPOINT:
423 python_process_tracepoint(perf_event, sample, evsel, 559 python_process_tracepoint(sample, evsel, thread, al);
424 machine, thread, al);
425 break; 560 break;
426 /* Reserve for future process_hw/sw/raw APIs */ 561 /* Reserve for future process_hw/sw/raw APIs */
427 default: 562 default:
428 python_process_general_event(perf_event, sample, evsel, 563 python_process_general_event(sample, evsel, thread, al);
429 machine, thread, al);
430 } 564 }
431} 565}
432 566
@@ -530,8 +664,7 @@ static int python_stop_script(void)
530 retval = PyObject_CallObject(handler, NULL); 664 retval = PyObject_CallObject(handler, NULL);
531 if (retval == NULL) 665 if (retval == NULL)
532 handler_call_die("trace_end"); 666 handler_call_die("trace_end");
533 else 667 Py_DECREF(retval);
534 Py_DECREF(retval);
535out: 668out:
536 Py_XDECREF(main_dict); 669 Py_XDECREF(main_dict);
537 Py_XDECREF(main_module); 670 Py_XDECREF(main_module);
@@ -598,6 +731,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
598 fprintf(ofp, "common_nsecs, "); 731 fprintf(ofp, "common_nsecs, ");
599 fprintf(ofp, "common_pid, "); 732 fprintf(ofp, "common_pid, ");
600 fprintf(ofp, "common_comm,\n\t"); 733 fprintf(ofp, "common_comm,\n\t");
734 fprintf(ofp, "common_callchain, ");
601 735
602 not_first = 0; 736 not_first = 0;
603 count = 0; 737 count = 0;
@@ -632,6 +766,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
632 fprintf(ofp, "%s=", f->name); 766 fprintf(ofp, "%s=", f->name);
633 if (f->flags & FIELD_IS_STRING || 767 if (f->flags & FIELD_IS_STRING ||
634 f->flags & FIELD_IS_FLAG || 768 f->flags & FIELD_IS_FLAG ||
769 f->flags & FIELD_IS_ARRAY ||
635 f->flags & FIELD_IS_SYMBOLIC) 770 f->flags & FIELD_IS_SYMBOLIC)
636 fprintf(ofp, "%%s"); 771 fprintf(ofp, "%%s");
637 else if (f->flags & FIELD_IS_SIGNED) 772 else if (f->flags & FIELD_IS_SIGNED)
@@ -640,7 +775,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
640 fprintf(ofp, "%%u"); 775 fprintf(ofp, "%%u");
641 } 776 }
642 777
643 fprintf(ofp, "\\n\" %% \\\n\t\t("); 778 fprintf(ofp, "\" %% \\\n\t\t(");
644 779
645 not_first = 0; 780 not_first = 0;
646 count = 0; 781 count = 0;
@@ -676,7 +811,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
676 fprintf(ofp, "%s", f->name); 811 fprintf(ofp, "%s", f->name);
677 } 812 }
678 813
679 fprintf(ofp, "),\n\n"); 814 fprintf(ofp, ")\n\n");
815
816 fprintf(ofp, "\t\tfor node in common_callchain:");
817 fprintf(ofp, "\n\t\t\tif 'sym' in node:");
818 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
819 fprintf(ofp, "\n\t\t\telse:");
820 fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
821 fprintf(ofp, "\t\tprint \"\\n\"\n\n");
822
680 } 823 }
681 824
682 fprintf(ofp, "def trace_unhandled(event_name, context, " 825 fprintf(ofp, "def trace_unhandled(event_name, context, "