aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/data-convert-bt.c92
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
509static int
510add_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
573put_seq_field:
574 bt_ctf_field_put(seq_field);
575put_seq_type:
576 bt_ctf_field_type_put(seq_type);
577put_len_field:
578 bt_ctf_field_put(len_field);
579put_len_type:
580 bt_ctf_field_type_put(len_type);
581 return ret;
582}
583
509static int add_generic_values(struct ctf_writer *cw, 584static 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}