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, " |
