diff options
-rw-r--r-- | tools/perf/util/data-convert-bt.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 3149b70799fd..eeb2590a3ddf 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -506,6 +506,81 @@ put_len_type: | |||
506 | return ret; | 506 | return ret; |
507 | } | 507 | } |
508 | 508 | ||
509 | static int | ||
510 | add_callchain_output_values(struct bt_ctf_event_class *event_class, | ||
511 | struct bt_ctf_event *event, | ||
512 | struct ip_callchain *callchain) | ||
513 | { | ||
514 | struct bt_ctf_field_type *len_type, *seq_type; | ||
515 | struct bt_ctf_field *len_field, *seq_field; | ||
516 | unsigned int nr_elements = callchain->nr; | ||
517 | unsigned int i; | ||
518 | int ret; | ||
519 | |||
520 | len_type = bt_ctf_event_class_get_field_by_name( | ||
521 | event_class, "perf_callchain_size"); | ||
522 | len_field = bt_ctf_field_create(len_type); | ||
523 | if (!len_field) { | ||
524 | pr_err("failed to create 'perf_callchain_size' for callchain output event\n"); | ||
525 | ret = -1; | ||
526 | goto put_len_type; | ||
527 | } | ||
528 | |||
529 | ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements); | ||
530 | if (ret) { | ||
531 | pr_err("failed to set field value for perf_callchain_size\n"); | ||
532 | goto put_len_field; | ||
533 | } | ||
534 | ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field); | ||
535 | if (ret) { | ||
536 | pr_err("failed to set payload to perf_callchain_size\n"); | ||
537 | goto put_len_field; | ||
538 | } | ||
539 | |||
540 | seq_type = bt_ctf_event_class_get_field_by_name( | ||
541 | event_class, "perf_callchain"); | ||
542 | seq_field = bt_ctf_field_create(seq_type); | ||
543 | if (!seq_field) { | ||
544 | pr_err("failed to create 'perf_callchain' for callchain output event\n"); | ||
545 | ret = -1; | ||
546 | goto put_seq_type; | ||
547 | } | ||
548 | |||
549 | ret = bt_ctf_field_sequence_set_length(seq_field, len_field); | ||
550 | if (ret) { | ||
551 | pr_err("failed to set length of 'perf_callchain'\n"); | ||
552 | goto put_seq_field; | ||
553 | } | ||
554 | |||
555 | for (i = 0; i < nr_elements; i++) { | ||
556 | struct bt_ctf_field *elem_field = | ||
557 | bt_ctf_field_sequence_get_field(seq_field, i); | ||
558 | |||
559 | ret = bt_ctf_field_unsigned_integer_set_value(elem_field, | ||
560 | ((u64 *)(callchain->ips))[i]); | ||
561 | |||
562 | bt_ctf_field_put(elem_field); | ||
563 | if (ret) { | ||
564 | pr_err("failed to set callchain[%d]\n", i); | ||
565 | goto put_seq_field; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field); | ||
570 | if (ret) | ||
571 | pr_err("failed to set payload for raw_data\n"); | ||
572 | |||
573 | put_seq_field: | ||
574 | bt_ctf_field_put(seq_field); | ||
575 | put_seq_type: | ||
576 | bt_ctf_field_type_put(seq_type); | ||
577 | put_len_field: | ||
578 | bt_ctf_field_put(len_field); | ||
579 | put_len_type: | ||
580 | bt_ctf_field_type_put(len_type); | ||
581 | return ret; | ||
582 | } | ||
583 | |||
509 | static int add_generic_values(struct ctf_writer *cw, | 584 | static int add_generic_values(struct ctf_writer *cw, |
510 | struct bt_ctf_event *event, | 585 | struct bt_ctf_event *event, |
511 | struct perf_evsel *evsel, | 586 | struct perf_evsel *evsel, |
@@ -519,7 +594,6 @@ static int add_generic_values(struct ctf_writer *cw, | |||
519 | * PERF_SAMPLE_TIME - not needed as we have it in | 594 | * PERF_SAMPLE_TIME - not needed as we have it in |
520 | * ctf event header | 595 | * ctf event header |
521 | * PERF_SAMPLE_READ - TODO | 596 | * PERF_SAMPLE_READ - TODO |
522 | * PERF_SAMPLE_CALLCHAIN - TODO | ||
523 | * PERF_SAMPLE_RAW - tracepoint fields are handled separately | 597 | * PERF_SAMPLE_RAW - tracepoint fields are handled separately |
524 | * PERF_SAMPLE_BRANCH_STACK - TODO | 598 | * PERF_SAMPLE_BRANCH_STACK - TODO |
525 | * PERF_SAMPLE_REGS_USER - TODO | 599 | * PERF_SAMPLE_REGS_USER - TODO |
@@ -720,6 +794,7 @@ static int process_sample_event(struct perf_tool *tool, | |||
720 | struct bt_ctf_event_class *event_class; | 794 | struct bt_ctf_event_class *event_class; |
721 | struct bt_ctf_event *event; | 795 | struct bt_ctf_event *event; |
722 | int ret; | 796 | int ret; |
797 | unsigned long type = evsel->attr.sample_type; | ||
723 | 798 | ||
724 | if (WARN_ONCE(!priv, "Failed to setup all events.\n")) | 799 | if (WARN_ONCE(!priv, "Failed to setup all events.\n")) |
725 | return 0; | 800 | return 0; |
@@ -751,6 +826,13 @@ static int process_sample_event(struct perf_tool *tool, | |||
751 | return -1; | 826 | return -1; |
752 | } | 827 | } |
753 | 828 | ||
829 | if (type & PERF_SAMPLE_CALLCHAIN) { | ||
830 | ret = add_callchain_output_values(event_class, | ||
831 | event, sample->callchain); | ||
832 | if (ret) | ||
833 | return -1; | ||
834 | } | ||
835 | |||
754 | if (perf_evsel__is_bpf_output(evsel)) { | 836 | if (perf_evsel__is_bpf_output(evsel)) { |
755 | ret = add_bpf_output_values(event_class, event, sample); | 837 | ret = add_bpf_output_values(event_class, event, sample); |
756 | if (ret) | 838 | if (ret) |
@@ -1043,6 +1125,14 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, | |||
1043 | if (type & PERF_SAMPLE_TRANSACTION) | 1125 | if (type & PERF_SAMPLE_TRANSACTION) |
1044 | ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); | 1126 | ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); |
1045 | 1127 | ||
1128 | if (type & PERF_SAMPLE_CALLCHAIN) { | ||
1129 | ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size"); | ||
1130 | ADD_FIELD(event_class, | ||
1131 | bt_ctf_field_type_sequence_create( | ||
1132 | cw->data.u64_hex, "perf_callchain_size"), | ||
1133 | "perf_callchain"); | ||
1134 | } | ||
1135 | |||
1046 | #undef ADD_FIELD | 1136 | #undef ADD_FIELD |
1047 | return 0; | 1137 | return 0; |
1048 | } | 1138 | } |