Skip to content

Commit a3073c8

Browse files
tahiniacmel
authored andcommitted
perf data: Add callchain to CTF conversion
The field perf_callchain, if available, is added to the sampling events during the CTF conversion. It is an array of u64 values. The perf_callchain_size field contains the size of the array. It will allow the analysis of sampling data in trace visualization tools like Trace Compass. Possible analyses with those data: dynamic flamegraphs, correlation with other tracing data like a userspace trace. Here follows a babeltrace CTF output of a trace with callchain: $ babeltrace ./myctftrace [17:38:45.672760285] (+?.?????????) cycles:ppp: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF81063EE4, perf_tid = 25841, perf_pid = 25774, perf_period = 1, perf_callchain_size = 7, perf_callchain = [ [0] = 0xFFFFFFFFFFFFFF80, [1] = 0xFFFFFFFF81063EE4, [2] = 0xFFFFFFFF8100C770, [3] = 0xFFFFFFFF81006EC6, [4] = 0xFFFFFFFF8118245E, [5] = 0xFFFFFFFF810A9224, [6] = 0xFFFFFFFF8164A4C6 ] } [17:38:45.672777672] (+0.000017387) cycles:ppp: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF81063EE4, perf_tid = 25841, perf_pid = 25774, perf_period = 1, perf_callchain_size = 8, perf_callchain = [ [0] = 0xFFFFFFFFFFFFFF80, [1] = 0xFFFFFFFF81063EE4, [2] = 0xFFFFFFFF8100C770, [3] = 0xFFFFFFFF81006EC6, [4] = 0xFFFFFFFF8118245E, [5] = 0xFFFFFFFF810A9224, [6] = 0xFFFFFFFF8164A4C6, [7] = 0xFFFFFFFF8164ABAD ] } [17:38:45.672786700] (+0.000009028) cycles:ppp: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF81063EE4, perf_tid = 25841, perf_pid = 25774, perf_period = 70, perf_callchain_size = 3, perf_callchain = [ [0] = 0xFFFFFFFFFFFFFF80, [1] = 0xFFFFFFFF81063EE4, [2] = 0xFFFFFFFF8100C770 ] } Signed-off-by: Geneviève Bastien <[email protected]> Acked-by: Jiri Olsa <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Francis Deslauriers <[email protected]> Cc: Julien Desfossez <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/r/[email protected] [ Removed PERF_SAMPLE_CALLCHAIN from the TODO list, jolsa ] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 3861c4a commit a3073c8

File tree

1 file changed

+91
-1
lines changed

1 file changed

+91
-1
lines changed

tools/perf/util/data-convert-bt.c

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,81 @@ add_bpf_output_values(struct bt_ctf_event_class *event_class,
506506
return ret;
507507
}
508508

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+
509584
static int add_generic_values(struct ctf_writer *cw,
510585
struct bt_ctf_event *event,
511586
struct perf_evsel *evsel,
@@ -519,7 +594,6 @@ static int add_generic_values(struct ctf_writer *cw,
519594
* PERF_SAMPLE_TIME - not needed as we have it in
520595
* ctf event header
521596
* PERF_SAMPLE_READ - TODO
522-
* PERF_SAMPLE_CALLCHAIN - TODO
523597
* PERF_SAMPLE_RAW - tracepoint fields are handled separately
524598
* PERF_SAMPLE_BRANCH_STACK - TODO
525599
* PERF_SAMPLE_REGS_USER - TODO
@@ -720,6 +794,7 @@ static int process_sample_event(struct perf_tool *tool,
720794
struct bt_ctf_event_class *event_class;
721795
struct bt_ctf_event *event;
722796
int ret;
797+
unsigned long type = evsel->attr.sample_type;
723798

724799
if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
725800
return 0;
@@ -751,6 +826,13 @@ static int process_sample_event(struct perf_tool *tool,
751826
return -1;
752827
}
753828

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+
754836
if (perf_evsel__is_bpf_output(evsel)) {
755837
ret = add_bpf_output_values(event_class, event, sample);
756838
if (ret)
@@ -1043,6 +1125,14 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
10431125
if (type & PERF_SAMPLE_TRANSACTION)
10441126
ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
10451127

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+
10461136
#undef ADD_FIELD
10471137
return 0;
10481138
}

0 commit comments

Comments
 (0)