diff options
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 106 |
1 files changed, 102 insertions, 4 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index b6c1a69f2b18..cf65404472cb 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "../event.h" | 32 | #include "../event.h" |
33 | #include "../thread.h" | 33 | #include "../thread.h" |
34 | #include "../trace-event.h" | 34 | #include "../trace-event.h" |
35 | #include "../machine.h" | ||
35 | 36 | ||
36 | PyMODINIT_FUNC initperf_trace_context(void); | 37 | PyMODINIT_FUNC initperf_trace_context(void); |
37 | 38 | ||
@@ -278,12 +279,90 @@ static PyObject *get_field_numeric_entry(struct event_format *event, | |||
278 | return obj; | 279 | return obj; |
279 | } | 280 | } |
280 | 281 | ||
282 | |||
283 | static PyObject *python_process_callchain(struct perf_sample *sample, | ||
284 | struct perf_evsel *evsel, | ||
285 | struct addr_location *al) | ||
286 | { | ||
287 | PyObject *pylist; | ||
288 | |||
289 | pylist = PyList_New(0); | ||
290 | if (!pylist) | ||
291 | Py_FatalError("couldn't create Python list"); | ||
292 | |||
293 | if (!symbol_conf.use_callchain || !sample->callchain) | ||
294 | goto exit; | ||
295 | |||
296 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | ||
297 | sample, NULL, NULL, | ||
298 | PERF_MAX_STACK_DEPTH) != 0) { | ||
299 | pr_err("Failed to resolve callchain. Skipping\n"); | ||
300 | goto exit; | ||
301 | } | ||
302 | callchain_cursor_commit(&callchain_cursor); | ||
303 | |||
304 | |||
305 | while (1) { | ||
306 | PyObject *pyelem; | ||
307 | struct callchain_cursor_node *node; | ||
308 | node = callchain_cursor_current(&callchain_cursor); | ||
309 | if (!node) | ||
310 | break; | ||
311 | |||
312 | pyelem = PyDict_New(); | ||
313 | if (!pyelem) | ||
314 | Py_FatalError("couldn't create Python dictionary"); | ||
315 | |||
316 | |||
317 | pydict_set_item_string_decref(pyelem, "ip", | ||
318 | PyLong_FromUnsignedLongLong(node->ip)); | ||
319 | |||
320 | if (node->sym) { | ||
321 | PyObject *pysym = PyDict_New(); | ||
322 | if (!pysym) | ||
323 | Py_FatalError("couldn't create Python dictionary"); | ||
324 | pydict_set_item_string_decref(pysym, "start", | ||
325 | PyLong_FromUnsignedLongLong(node->sym->start)); | ||
326 | pydict_set_item_string_decref(pysym, "end", | ||
327 | PyLong_FromUnsignedLongLong(node->sym->end)); | ||
328 | pydict_set_item_string_decref(pysym, "binding", | ||
329 | PyInt_FromLong(node->sym->binding)); | ||
330 | pydict_set_item_string_decref(pysym, "name", | ||
331 | PyString_FromStringAndSize(node->sym->name, | ||
332 | node->sym->namelen)); | ||
333 | pydict_set_item_string_decref(pyelem, "sym", pysym); | ||
334 | } | ||
335 | |||
336 | if (node->map) { | ||
337 | struct map *map = node->map; | ||
338 | const char *dsoname = "[unknown]"; | ||
339 | if (map && map->dso && (map->dso->name || map->dso->long_name)) { | ||
340 | if (symbol_conf.show_kernel_path && map->dso->long_name) | ||
341 | dsoname = map->dso->long_name; | ||
342 | else if (map->dso->name) | ||
343 | dsoname = map->dso->name; | ||
344 | } | ||
345 | pydict_set_item_string_decref(pyelem, "dso", | ||
346 | PyString_FromString(dsoname)); | ||
347 | } | ||
348 | |||
349 | callchain_cursor_advance(&callchain_cursor); | ||
350 | PyList_Append(pylist, pyelem); | ||
351 | Py_DECREF(pyelem); | ||
352 | } | ||
353 | |||
354 | exit: | ||
355 | return pylist; | ||
356 | } | ||
357 | |||
358 | |||
281 | static void python_process_tracepoint(struct perf_sample *sample, | 359 | static void python_process_tracepoint(struct perf_sample *sample, |
282 | struct perf_evsel *evsel, | 360 | struct perf_evsel *evsel, |
283 | struct thread *thread, | 361 | struct thread *thread, |
284 | struct addr_location *al) | 362 | struct addr_location *al) |
285 | { | 363 | { |
286 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 364 | PyObject *handler, *retval, *context, *t, *obj, *callchain; |
365 | PyObject *dict = NULL; | ||
287 | static char handler_name[256]; | 366 | static char handler_name[256]; |
288 | struct format_field *field; | 367 | struct format_field *field; |
289 | unsigned long s, ns; | 368 | unsigned long s, ns; |
@@ -326,18 +405,23 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
326 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); | 405 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); |
327 | PyTuple_SetItem(t, n++, context); | 406 | PyTuple_SetItem(t, n++, context); |
328 | 407 | ||
408 | /* ip unwinding */ | ||
409 | callchain = python_process_callchain(sample, evsel, al); | ||
410 | |||
329 | if (handler) { | 411 | if (handler) { |
330 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | 412 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); |
331 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); | 413 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); |
332 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); | 414 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); |
333 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); | 415 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); |
334 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); | 416 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); |
417 | PyTuple_SetItem(t, n++, callchain); | ||
335 | } else { | 418 | } else { |
336 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); | 419 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); |
337 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); | 420 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); |
338 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); | 421 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); |
339 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); | 422 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); |
340 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); | 423 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); |
424 | pydict_set_item_string_decref(dict, "common_callchain", callchain); | ||
341 | } | 425 | } |
342 | for (field = event->format.fields; field; field = field->next) { | 426 | for (field = event->format.fields; field; field = field->next) { |
343 | if (field->flags & FIELD_IS_STRING) { | 427 | if (field->flags & FIELD_IS_STRING) { |
@@ -357,6 +441,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
357 | pydict_set_item_string_decref(dict, field->name, obj); | 441 | pydict_set_item_string_decref(dict, field->name, obj); |
358 | 442 | ||
359 | } | 443 | } |
444 | |||
360 | if (!handler) | 445 | if (!handler) |
361 | PyTuple_SetItem(t, n++, dict); | 446 | PyTuple_SetItem(t, n++, dict); |
362 | 447 | ||
@@ -388,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
388 | struct thread *thread, | 473 | struct thread *thread, |
389 | struct addr_location *al) | 474 | struct addr_location *al) |
390 | { | 475 | { |
391 | PyObject *handler, *retval, *t, *dict; | 476 | PyObject *handler, *retval, *t, *dict, *callchain; |
392 | static char handler_name[64]; | 477 | static char handler_name[64]; |
393 | unsigned n = 0; | 478 | unsigned n = 0; |
394 | 479 | ||
@@ -428,6 +513,10 @@ static void python_process_general_event(struct perf_sample *sample, | |||
428 | PyString_FromString(al->sym->name)); | 513 | PyString_FromString(al->sym->name)); |
429 | } | 514 | } |
430 | 515 | ||
516 | /* ip unwinding */ | ||
517 | callchain = python_process_callchain(sample, evsel, al); | ||
518 | pydict_set_item_string_decref(dict, "callchain", callchain); | ||
519 | |||
431 | PyTuple_SetItem(t, n++, dict); | 520 | PyTuple_SetItem(t, n++, dict); |
432 | if (_PyTuple_Resize(&t, n) == -1) | 521 | if (_PyTuple_Resize(&t, n) == -1) |
433 | Py_FatalError("error resizing Python tuple"); | 522 | Py_FatalError("error resizing Python tuple"); |
@@ -624,6 +713,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
624 | fprintf(ofp, "common_nsecs, "); | 713 | fprintf(ofp, "common_nsecs, "); |
625 | fprintf(ofp, "common_pid, "); | 714 | fprintf(ofp, "common_pid, "); |
626 | fprintf(ofp, "common_comm,\n\t"); | 715 | fprintf(ofp, "common_comm,\n\t"); |
716 | fprintf(ofp, "common_callchain, "); | ||
627 | 717 | ||
628 | not_first = 0; | 718 | not_first = 0; |
629 | count = 0; | 719 | count = 0; |
@@ -667,7 +757,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
667 | fprintf(ofp, "%%u"); | 757 | fprintf(ofp, "%%u"); |
668 | } | 758 | } |
669 | 759 | ||
670 | fprintf(ofp, "\\n\" %% \\\n\t\t("); | 760 | fprintf(ofp, "\" %% \\\n\t\t("); |
671 | 761 | ||
672 | not_first = 0; | 762 | not_first = 0; |
673 | count = 0; | 763 | count = 0; |
@@ -703,7 +793,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
703 | fprintf(ofp, "%s", f->name); | 793 | fprintf(ofp, "%s", f->name); |
704 | } | 794 | } |
705 | 795 | ||
706 | fprintf(ofp, "),\n\n"); | 796 | fprintf(ofp, ")\n\n"); |
797 | |||
798 | fprintf(ofp, "\t\tfor node in common_callchain:"); | ||
799 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | ||
800 | fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); | ||
801 | fprintf(ofp, "\n\t\t\telse:"); | ||
802 | fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); | ||
803 | fprintf(ofp, "\t\tprint \"\\n\"\n\n"); | ||
804 | |||
707 | } | 805 | } |
708 | 806 | ||
709 | fprintf(ofp, "def trace_unhandled(event_name, context, " | 807 | fprintf(ofp, "def trace_unhandled(event_name, context, " |