@@ -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+
509584static 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