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 | 250 |
1 files changed, 241 insertions, 9 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 7f8afacd08ee..46e9e19ab1ac 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) |
@@ -534,6 +753,11 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, | |||
534 | pydict_set_item_string_decref(dict_sample, "addr", | 753 | pydict_set_item_string_decref(dict_sample, "addr", |
535 | PyLong_FromUnsignedLongLong(sample->addr)); | 754 | PyLong_FromUnsignedLongLong(sample->addr)); |
536 | 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); | ||
537 | pydict_set_item_string_decref(dict, "sample", dict_sample); | 761 | pydict_set_item_string_decref(dict, "sample", dict_sample); |
538 | 762 | ||
539 | pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( | 763 | pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( |
@@ -551,6 +775,14 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, | |||
551 | 775 | ||
552 | pydict_set_item_string_decref(dict, "callchain", callchain); | 776 | pydict_set_item_string_decref(dict, "callchain", callchain); |
553 | 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 | |||
554 | return dict; | 786 | return dict; |
555 | } | 787 | } |
556 | 788 | ||