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 | 289 |
1 files changed, 260 insertions, 29 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 10dd5fce082b..bc32e57d17be 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include "cpumap.h" | 48 | #include "cpumap.h" |
49 | #include "print_binary.h" | 49 | #include "print_binary.h" |
50 | #include "stat.h" | 50 | #include "stat.h" |
51 | #include "mem-events.h" | ||
51 | 52 | ||
52 | #if PY_MAJOR_VERSION < 3 | 53 | #if PY_MAJOR_VERSION < 3 |
53 | #define _PyUnicode_FromString(arg) \ | 54 | #define _PyUnicode_FromString(arg) \ |
@@ -372,6 +373,19 @@ static PyObject *get_field_numeric_entry(struct event_format *event, | |||
372 | return obj; | 373 | return obj; |
373 | } | 374 | } |
374 | 375 | ||
376 | static const char *get_dsoname(struct map *map) | ||
377 | { | ||
378 | const char *dsoname = "[unknown]"; | ||
379 | |||
380 | if (map && map->dso) { | ||
381 | if (symbol_conf.show_kernel_path && map->dso->long_name) | ||
382 | dsoname = map->dso->long_name; | ||
383 | else | ||
384 | dsoname = map->dso->name; | ||
385 | } | ||
386 | |||
387 | return dsoname; | ||
388 | } | ||
375 | 389 | ||
376 | static PyObject *python_process_callchain(struct perf_sample *sample, | 390 | static PyObject *python_process_callchain(struct perf_sample *sample, |
377 | struct perf_evsel *evsel, | 391 | struct perf_evsel *evsel, |
@@ -427,14 +441,8 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
427 | } | 441 | } |
428 | 442 | ||
429 | if (node->map) { | 443 | if (node->map) { |
430 | struct map *map = node->map; | 444 | const char *dsoname = get_dsoname(node->map); |
431 | const char *dsoname = "[unknown]"; | 445 | |
432 | if (map && map->dso) { | ||
433 | if (symbol_conf.show_kernel_path && map->dso->long_name) | ||
434 | dsoname = map->dso->long_name; | ||
435 | else | ||
436 | dsoname = map->dso->name; | ||
437 | } | ||
438 | pydict_set_item_string_decref(pyelem, "dso", | 446 | pydict_set_item_string_decref(pyelem, "dso", |
439 | _PyUnicode_FromString(dsoname)); | 447 | _PyUnicode_FromString(dsoname)); |
440 | } | 448 | } |
@@ -448,6 +456,166 @@ exit: | |||
448 | return pylist; | 456 | return pylist; |
449 | } | 457 | } |
450 | 458 | ||
459 | static PyObject *python_process_brstack(struct perf_sample *sample, | ||
460 | struct thread *thread) | ||
461 | { | ||
462 | struct branch_stack *br = sample->branch_stack; | ||
463 | PyObject *pylist; | ||
464 | u64 i; | ||
465 | |||
466 | pylist = PyList_New(0); | ||
467 | if (!pylist) | ||
468 | Py_FatalError("couldn't create Python list"); | ||
469 | |||
470 | if (!(br && br->nr)) | ||
471 | goto exit; | ||
472 | |||
473 | for (i = 0; i < br->nr; i++) { | ||
474 | PyObject *pyelem; | ||
475 | struct addr_location al; | ||
476 | const char *dsoname; | ||
477 | |||
478 | pyelem = PyDict_New(); | ||
479 | if (!pyelem) | ||
480 | Py_FatalError("couldn't create Python dictionary"); | ||
481 | |||
482 | pydict_set_item_string_decref(pyelem, "from", | ||
483 | PyLong_FromUnsignedLongLong(br->entries[i].from)); | ||
484 | pydict_set_item_string_decref(pyelem, "to", | ||
485 | PyLong_FromUnsignedLongLong(br->entries[i].to)); | ||
486 | pydict_set_item_string_decref(pyelem, "mispred", | ||
487 | PyBool_FromLong(br->entries[i].flags.mispred)); | ||
488 | pydict_set_item_string_decref(pyelem, "predicted", | ||
489 | PyBool_FromLong(br->entries[i].flags.predicted)); | ||
490 | pydict_set_item_string_decref(pyelem, "in_tx", | ||
491 | PyBool_FromLong(br->entries[i].flags.in_tx)); | ||
492 | pydict_set_item_string_decref(pyelem, "abort", | ||
493 | PyBool_FromLong(br->entries[i].flags.abort)); | ||
494 | pydict_set_item_string_decref(pyelem, "cycles", | ||
495 | PyLong_FromUnsignedLongLong(br->entries[i].flags.cycles)); | ||
496 | |||
497 | thread__find_map(thread, sample->cpumode, | ||
498 | br->entries[i].from, &al); | ||
499 | dsoname = get_dsoname(al.map); | ||
500 | pydict_set_item_string_decref(pyelem, "from_dsoname", | ||
501 | _PyUnicode_FromString(dsoname)); | ||
502 | |||
503 | thread__find_map(thread, sample->cpumode, | ||
504 | br->entries[i].to, &al); | ||
505 | dsoname = get_dsoname(al.map); | ||
506 | pydict_set_item_string_decref(pyelem, "to_dsoname", | ||
507 | _PyUnicode_FromString(dsoname)); | ||
508 | |||
509 | PyList_Append(pylist, pyelem); | ||
510 | Py_DECREF(pyelem); | ||
511 | } | ||
512 | |||
513 | exit: | ||
514 | return pylist; | ||
515 | } | ||
516 | |||
517 | static unsigned long get_offset(struct symbol *sym, struct addr_location *al) | ||
518 | { | ||
519 | unsigned long offset; | ||
520 | |||
521 | if (al->addr < sym->end) | ||
522 | offset = al->addr - sym->start; | ||
523 | else | ||
524 | offset = al->addr - al->map->start - sym->start; | ||
525 | |||
526 | return offset; | ||
527 | } | ||
528 | |||
529 | static int get_symoff(struct symbol *sym, struct addr_location *al, | ||
530 | bool print_off, char *bf, int size) | ||
531 | { | ||
532 | unsigned long offset; | ||
533 | |||
534 | if (!sym || !sym->name[0]) | ||
535 | return scnprintf(bf, size, "%s", "[unknown]"); | ||
536 | |||
537 | if (!print_off) | ||
538 | return scnprintf(bf, size, "%s", sym->name); | ||
539 | |||
540 | offset = get_offset(sym, al); | ||
541 | |||
542 | return scnprintf(bf, size, "%s+0x%x", sym->name, offset); | ||
543 | } | ||
544 | |||
545 | static int get_br_mspred(struct branch_flags *flags, char *bf, int size) | ||
546 | { | ||
547 | if (!flags->mispred && !flags->predicted) | ||
548 | return scnprintf(bf, size, "%s", "-"); | ||
549 | |||
550 | if (flags->mispred) | ||
551 | return scnprintf(bf, size, "%s", "M"); | ||
552 | |||
553 | return scnprintf(bf, size, "%s", "P"); | ||
554 | } | ||
555 | |||
556 | static PyObject *python_process_brstacksym(struct perf_sample *sample, | ||
557 | struct thread *thread) | ||
558 | { | ||
559 | struct branch_stack *br = sample->branch_stack; | ||
560 | PyObject *pylist; | ||
561 | u64 i; | ||
562 | char bf[512]; | ||
563 | struct addr_location al; | ||
564 | |||
565 | pylist = PyList_New(0); | ||
566 | if (!pylist) | ||
567 | Py_FatalError("couldn't create Python list"); | ||
568 | |||
569 | if (!(br && br->nr)) | ||
570 | goto exit; | ||
571 | |||
572 | for (i = 0; i < br->nr; i++) { | ||
573 | PyObject *pyelem; | ||
574 | |||
575 | pyelem = PyDict_New(); | ||
576 | if (!pyelem) | ||
577 | Py_FatalError("couldn't create Python dictionary"); | ||
578 | |||
579 | thread__find_symbol(thread, sample->cpumode, | ||
580 | br->entries[i].from, &al); | ||
581 | get_symoff(al.sym, &al, true, bf, sizeof(bf)); | ||
582 | pydict_set_item_string_decref(pyelem, "from", | ||
583 | _PyUnicode_FromString(bf)); | ||
584 | |||
585 | thread__find_symbol(thread, sample->cpumode, | ||
586 | br->entries[i].to, &al); | ||
587 | get_symoff(al.sym, &al, true, bf, sizeof(bf)); | ||
588 | pydict_set_item_string_decref(pyelem, "to", | ||
589 | _PyUnicode_FromString(bf)); | ||
590 | |||
591 | get_br_mspred(&br->entries[i].flags, bf, sizeof(bf)); | ||
592 | pydict_set_item_string_decref(pyelem, "pred", | ||
593 | _PyUnicode_FromString(bf)); | ||
594 | |||
595 | if (br->entries[i].flags.in_tx) { | ||
596 | pydict_set_item_string_decref(pyelem, "in_tx", | ||
597 | _PyUnicode_FromString("X")); | ||
598 | } else { | ||
599 | pydict_set_item_string_decref(pyelem, "in_tx", | ||
600 | _PyUnicode_FromString("-")); | ||
601 | } | ||
602 | |||
603 | if (br->entries[i].flags.abort) { | ||
604 | pydict_set_item_string_decref(pyelem, "abort", | ||
605 | _PyUnicode_FromString("A")); | ||
606 | } else { | ||
607 | pydict_set_item_string_decref(pyelem, "abort", | ||
608 | _PyUnicode_FromString("-")); | ||
609 | } | ||
610 | |||
611 | PyList_Append(pylist, pyelem); | ||
612 | Py_DECREF(pyelem); | ||
613 | } | ||
614 | |||
615 | exit: | ||
616 | return pylist; | ||
617 | } | ||
618 | |||
451 | static PyObject *get_sample_value_as_tuple(struct sample_read_value *value) | 619 | static PyObject *get_sample_value_as_tuple(struct sample_read_value *value) |
452 | { | 620 | { |
453 | PyObject *t; | 621 | PyObject *t; |
@@ -498,12 +666,63 @@ static void set_sample_read_in_dict(PyObject *dict_sample, | |||
498 | pydict_set_item_string_decref(dict_sample, "values", values); | 666 | pydict_set_item_string_decref(dict_sample, "values", values); |
499 | } | 667 | } |
500 | 668 | ||
669 | static void set_sample_datasrc_in_dict(PyObject *dict, | ||
670 | struct perf_sample *sample) | ||
671 | { | ||
672 | struct mem_info mi = { .data_src.val = sample->data_src }; | ||
673 | char decode[100]; | ||
674 | |||
675 | pydict_set_item_string_decref(dict, "datasrc", | ||
676 | PyLong_FromUnsignedLongLong(sample->data_src)); | ||
677 | |||
678 | perf_script__meminfo_scnprintf(decode, 100, &mi); | ||
679 | |||
680 | pydict_set_item_string_decref(dict, "datasrc_decode", | ||
681 | _PyUnicode_FromString(decode)); | ||
682 | } | ||
683 | |||
684 | static int regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size) | ||
685 | { | ||
686 | unsigned int i = 0, r; | ||
687 | int printed = 0; | ||
688 | |||
689 | bf[0] = 0; | ||
690 | |||
691 | for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { | ||
692 | u64 val = regs->regs[i++]; | ||
693 | |||
694 | printed += scnprintf(bf + printed, size - printed, | ||
695 | "%5s:0x%" PRIx64 " ", | ||
696 | perf_reg_name(r), val); | ||
697 | } | ||
698 | |||
699 | return printed; | ||
700 | } | ||
701 | |||
702 | static void set_regs_in_dict(PyObject *dict, | ||
703 | struct perf_sample *sample, | ||
704 | struct perf_evsel *evsel) | ||
705 | { | ||
706 | struct perf_event_attr *attr = &evsel->attr; | ||
707 | char bf[512]; | ||
708 | |||
709 | regs_map(&sample->intr_regs, attr->sample_regs_intr, bf, sizeof(bf)); | ||
710 | |||
711 | pydict_set_item_string_decref(dict, "iregs", | ||
712 | _PyUnicode_FromString(bf)); | ||
713 | |||
714 | regs_map(&sample->user_regs, attr->sample_regs_user, bf, sizeof(bf)); | ||
715 | |||
716 | pydict_set_item_string_decref(dict, "uregs", | ||
717 | _PyUnicode_FromString(bf)); | ||
718 | } | ||
719 | |||
501 | static PyObject *get_perf_sample_dict(struct perf_sample *sample, | 720 | static PyObject *get_perf_sample_dict(struct perf_sample *sample, |
502 | struct perf_evsel *evsel, | 721 | struct perf_evsel *evsel, |
503 | struct addr_location *al, | 722 | struct addr_location *al, |
504 | PyObject *callchain) | 723 | PyObject *callchain) |
505 | { | 724 | { |
506 | PyObject *dict, *dict_sample; | 725 | PyObject *dict, *dict_sample, *brstack, *brstacksym; |
507 | 726 | ||
508 | dict = PyDict_New(); | 727 | dict = PyDict_New(); |
509 | if (!dict) | 728 | if (!dict) |
@@ -531,7 +750,14 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, | |||
531 | PyLong_FromUnsignedLongLong(sample->period)); | 750 | PyLong_FromUnsignedLongLong(sample->period)); |
532 | pydict_set_item_string_decref(dict_sample, "phys_addr", | 751 | pydict_set_item_string_decref(dict_sample, "phys_addr", |
533 | PyLong_FromUnsignedLongLong(sample->phys_addr)); | 752 | PyLong_FromUnsignedLongLong(sample->phys_addr)); |
753 | pydict_set_item_string_decref(dict_sample, "addr", | ||
754 | PyLong_FromUnsignedLongLong(sample->addr)); | ||
534 | set_sample_read_in_dict(dict_sample, sample, evsel); | 755 | set_sample_read_in_dict(dict_sample, sample, evsel); |
756 | pydict_set_item_string_decref(dict_sample, "weight", | ||
757 | PyLong_FromUnsignedLongLong(sample->weight)); | ||
758 | pydict_set_item_string_decref(dict_sample, "transaction", | ||
759 | PyLong_FromUnsignedLongLong(sample->transaction)); | ||
760 | set_sample_datasrc_in_dict(dict_sample, sample); | ||
535 | pydict_set_item_string_decref(dict, "sample", dict_sample); | 761 | pydict_set_item_string_decref(dict, "sample", dict_sample); |
536 | 762 | ||
537 | pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( | 763 | pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( |
@@ -549,6 +775,14 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, | |||
549 | 775 | ||
550 | pydict_set_item_string_decref(dict, "callchain", callchain); | 776 | pydict_set_item_string_decref(dict, "callchain", callchain); |
551 | 777 | ||
778 | brstack = python_process_brstack(sample, al->thread); | ||
779 | pydict_set_item_string_decref(dict, "brstack", brstack); | ||
780 | |||
781 | brstacksym = python_process_brstacksym(sample, al->thread); | ||
782 | pydict_set_item_string_decref(dict, "brstacksym", brstacksym); | ||
783 | |||
784 | set_regs_in_dict(dict, sample, evsel); | ||
785 | |||
552 | return dict; | 786 | return dict; |
553 | } | 787 | } |
554 | 788 | ||
@@ -674,14 +908,11 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
674 | if (_PyTuple_Resize(&t, n) == -1) | 908 | if (_PyTuple_Resize(&t, n) == -1) |
675 | Py_FatalError("error resizing Python tuple"); | 909 | Py_FatalError("error resizing Python tuple"); |
676 | 910 | ||
677 | if (!dict) { | 911 | if (!dict) |
678 | call_object(handler, t, handler_name); | 912 | call_object(handler, t, handler_name); |
679 | } else { | 913 | else |
680 | call_object(handler, t, default_handler_name); | 914 | call_object(handler, t, default_handler_name); |
681 | Py_DECREF(dict); | ||
682 | } | ||
683 | 915 | ||
684 | Py_XDECREF(all_entries_dict); | ||
685 | Py_DECREF(t); | 916 | Py_DECREF(t); |
686 | } | 917 | } |
687 | 918 | ||
@@ -1001,7 +1232,6 @@ static void python_process_general_event(struct perf_sample *sample, | |||
1001 | 1232 | ||
1002 | call_object(handler, t, handler_name); | 1233 | call_object(handler, t, handler_name); |
1003 | 1234 | ||
1004 | Py_DECREF(dict); | ||
1005 | Py_DECREF(t); | 1235 | Py_DECREF(t); |
1006 | } | 1236 | } |
1007 | 1237 | ||
@@ -1393,6 +1623,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
1393 | fprintf(ofp, "# See the perf-script-python Documentation for the list " | 1623 | fprintf(ofp, "# See the perf-script-python Documentation for the list " |
1394 | "of available functions.\n\n"); | 1624 | "of available functions.\n\n"); |
1395 | 1625 | ||
1626 | fprintf(ofp, "from __future__ import print_function\n\n"); | ||
1396 | fprintf(ofp, "import os\n"); | 1627 | fprintf(ofp, "import os\n"); |
1397 | fprintf(ofp, "import sys\n\n"); | 1628 | fprintf(ofp, "import sys\n\n"); |
1398 | 1629 | ||
@@ -1402,10 +1633,10 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
1402 | fprintf(ofp, "from Core import *\n\n\n"); | 1633 | fprintf(ofp, "from Core import *\n\n\n"); |
1403 | 1634 | ||
1404 | fprintf(ofp, "def trace_begin():\n"); | 1635 | fprintf(ofp, "def trace_begin():\n"); |
1405 | fprintf(ofp, "\tprint \"in trace_begin\"\n\n"); | 1636 | fprintf(ofp, "\tprint(\"in trace_begin\")\n\n"); |
1406 | 1637 | ||
1407 | fprintf(ofp, "def trace_end():\n"); | 1638 | fprintf(ofp, "def trace_end():\n"); |
1408 | fprintf(ofp, "\tprint \"in trace_end\"\n\n"); | 1639 | fprintf(ofp, "\tprint(\"in trace_end\")\n\n"); |
1409 | 1640 | ||
1410 | while ((event = trace_find_next_event(pevent, event))) { | 1641 | while ((event = trace_find_next_event(pevent, event))) { |
1411 | fprintf(ofp, "def %s__%s(", event->system, event->name); | 1642 | fprintf(ofp, "def %s__%s(", event->system, event->name); |
@@ -1441,7 +1672,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
1441 | "common_secs, common_nsecs,\n\t\t\t" | 1672 | "common_secs, common_nsecs,\n\t\t\t" |
1442 | "common_pid, common_comm)\n\n"); | 1673 | "common_pid, common_comm)\n\n"); |
1443 | 1674 | ||
1444 | fprintf(ofp, "\t\tprint \""); | 1675 | fprintf(ofp, "\t\tprint(\""); |
1445 | 1676 | ||
1446 | not_first = 0; | 1677 | not_first = 0; |
1447 | count = 0; | 1678 | count = 0; |
@@ -1502,31 +1733,31 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
1502 | fprintf(ofp, "%s", f->name); | 1733 | fprintf(ofp, "%s", f->name); |
1503 | } | 1734 | } |
1504 | 1735 | ||
1505 | fprintf(ofp, ")\n\n"); | 1736 | fprintf(ofp, "))\n\n"); |
1506 | 1737 | ||
1507 | fprintf(ofp, "\t\tprint 'Sample: {'+" | 1738 | fprintf(ofp, "\t\tprint('Sample: {'+" |
1508 | "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n"); | 1739 | "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')\n\n"); |
1509 | 1740 | ||
1510 | fprintf(ofp, "\t\tfor node in common_callchain:"); | 1741 | fprintf(ofp, "\t\tfor node in common_callchain:"); |
1511 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | 1742 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); |
1512 | fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); | 1743 | fprintf(ofp, "\n\t\t\t\tprint(\"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name']))"); |
1513 | fprintf(ofp, "\n\t\t\telse:"); | 1744 | fprintf(ofp, "\n\t\t\telse:"); |
1514 | fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); | 1745 | fprintf(ofp, "\n\t\t\t\tprint(\"\t[%%x]\" %% (node['ip']))\n\n"); |
1515 | fprintf(ofp, "\t\tprint \"\\n\"\n\n"); | 1746 | fprintf(ofp, "\t\tprint()\n\n"); |
1516 | 1747 | ||
1517 | } | 1748 | } |
1518 | 1749 | ||
1519 | fprintf(ofp, "def trace_unhandled(event_name, context, " | 1750 | fprintf(ofp, "def trace_unhandled(event_name, context, " |
1520 | "event_fields_dict, perf_sample_dict):\n"); | 1751 | "event_fields_dict, perf_sample_dict):\n"); |
1521 | 1752 | ||
1522 | fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n"); | 1753 | fprintf(ofp, "\t\tprint(get_dict_as_string(event_fields_dict))\n"); |
1523 | fprintf(ofp, "\t\tprint 'Sample: {'+" | 1754 | fprintf(ofp, "\t\tprint('Sample: {'+" |
1524 | "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n"); | 1755 | "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')\n\n"); |
1525 | 1756 | ||
1526 | fprintf(ofp, "def print_header(" | 1757 | fprintf(ofp, "def print_header(" |
1527 | "event_name, cpu, secs, nsecs, pid, comm):\n" | 1758 | "event_name, cpu, secs, nsecs, pid, comm):\n" |
1528 | "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" | 1759 | "\tprint(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" |
1529 | "(event_name, cpu, secs, nsecs, pid, comm),\n\n"); | 1760 | "(event_name, cpu, secs, nsecs, pid, comm), end=\"\")\n\n"); |
1530 | 1761 | ||
1531 | fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n" | 1762 | fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n" |
1532 | "\treturn delimiter.join" | 1763 | "\treturn delimiter.join" |