~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/data-convert-bt.c

Version: ~ [ linux-5.12 ] ~ [ linux-5.11.16 ] ~ [ linux-5.10.32 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.114 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.188 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.231 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.267 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.267 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * CTF writing support via babeltrace.
  4  *
  5  * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
  6  * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  7  */
  8 
  9 #include <errno.h>
 10 #include <inttypes.h>
 11 #include <linux/compiler.h>
 12 #include <linux/kernel.h>
 13 #include <linux/zalloc.h>
 14 #include <babeltrace/ctf-writer/writer.h>
 15 #include <babeltrace/ctf-writer/clock.h>
 16 #include <babeltrace/ctf-writer/stream.h>
 17 #include <babeltrace/ctf-writer/event.h>
 18 #include <babeltrace/ctf-writer/event-types.h>
 19 #include <babeltrace/ctf-writer/event-fields.h>
 20 #include <babeltrace/ctf-ir/utils.h>
 21 #include <babeltrace/ctf/events.h>
 22 #include <traceevent/event-parse.h>
 23 #include "asm/bug.h"
 24 #include "data-convert-bt.h"
 25 #include "session.h"
 26 #include "debug.h"
 27 #include "tool.h"
 28 #include "evlist.h"
 29 #include "evsel.h"
 30 #include "machine.h"
 31 #include "config.h"
 32 #include <linux/ctype.h>
 33 #include <linux/err.h>
 34 
 35 #define pr_N(n, fmt, ...) \
 36         eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
 37 
 38 #define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
 39 #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
 40 
 41 #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
 42 
 43 struct evsel_priv {
 44         struct bt_ctf_event_class *event_class;
 45 };
 46 
 47 #define MAX_CPUS        4096
 48 
 49 struct ctf_stream {
 50         struct bt_ctf_stream *stream;
 51         int cpu;
 52         u32 count;
 53 };
 54 
 55 struct ctf_writer {
 56         /* writer primitives */
 57         struct bt_ctf_writer             *writer;
 58         struct ctf_stream               **stream;
 59         int                               stream_cnt;
 60         struct bt_ctf_stream_class       *stream_class;
 61         struct bt_ctf_clock              *clock;
 62 
 63         /* data types */
 64         union {
 65                 struct {
 66                         struct bt_ctf_field_type        *s64;
 67                         struct bt_ctf_field_type        *u64;
 68                         struct bt_ctf_field_type        *s32;
 69                         struct bt_ctf_field_type        *u32;
 70                         struct bt_ctf_field_type        *string;
 71                         struct bt_ctf_field_type        *u32_hex;
 72                         struct bt_ctf_field_type        *u64_hex;
 73                 };
 74                 struct bt_ctf_field_type *array[6];
 75         } data;
 76         struct bt_ctf_event_class       *comm_class;
 77         struct bt_ctf_event_class       *exit_class;
 78         struct bt_ctf_event_class       *fork_class;
 79         struct bt_ctf_event_class       *mmap_class;
 80         struct bt_ctf_event_class       *mmap2_class;
 81 };
 82 
 83 struct convert {
 84         struct perf_tool        tool;
 85         struct ctf_writer       writer;
 86 
 87         u64                     events_size;
 88         u64                     events_count;
 89         u64                     non_sample_count;
 90 
 91         /* Ordered events configured queue size. */
 92         u64                     queue_size;
 93 };
 94 
 95 static int value_set(struct bt_ctf_field_type *type,
 96                      struct bt_ctf_event *event,
 97                      const char *name, u64 val)
 98 {
 99         struct bt_ctf_field *field;
100         bool sign = bt_ctf_field_type_integer_get_signed(type);
101         int ret;
102 
103         field = bt_ctf_field_create(type);
104         if (!field) {
105                 pr_err("failed to create a field %s\n", name);
106                 return -1;
107         }
108 
109         if (sign) {
110                 ret = bt_ctf_field_signed_integer_set_value(field, val);
111                 if (ret) {
112                         pr_err("failed to set field value %s\n", name);
113                         goto err;
114                 }
115         } else {
116                 ret = bt_ctf_field_unsigned_integer_set_value(field, val);
117                 if (ret) {
118                         pr_err("failed to set field value %s\n", name);
119                         goto err;
120                 }
121         }
122 
123         ret = bt_ctf_event_set_payload(event, name, field);
124         if (ret) {
125                 pr_err("failed to set payload %s\n", name);
126                 goto err;
127         }
128 
129         pr2("  SET [%s = %" PRIu64 "]\n", name, val);
130 
131 err:
132         bt_ctf_field_put(field);
133         return ret;
134 }
135 
136 #define __FUNC_VALUE_SET(_name, _val_type)                              \
137 static __maybe_unused int value_set_##_name(struct ctf_writer *cw,      \
138                              struct bt_ctf_event *event,                \
139                              const char *name,                          \
140                              _val_type val)                             \
141 {                                                                       \
142         struct bt_ctf_field_type *type = cw->data._name;                \
143         return value_set(type, event, name, (u64) val);                 \
144 }
145 
146 #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
147 
148 FUNC_VALUE_SET(s32)
149 FUNC_VALUE_SET(u32)
150 FUNC_VALUE_SET(s64)
151 FUNC_VALUE_SET(u64)
152 __FUNC_VALUE_SET(u64_hex, u64)
153 
154 static int string_set_value(struct bt_ctf_field *field, const char *string);
155 static __maybe_unused int
156 value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
157                  const char *name, const char *string)
158 {
159         struct bt_ctf_field_type *type = cw->data.string;
160         struct bt_ctf_field *field;
161         int ret = 0;
162 
163         field = bt_ctf_field_create(type);
164         if (!field) {
165                 pr_err("failed to create a field %s\n", name);
166                 return -1;
167         }
168 
169         ret = string_set_value(field, string);
170         if (ret) {
171                 pr_err("failed to set value %s\n", name);
172                 goto err_put_field;
173         }
174 
175         ret = bt_ctf_event_set_payload(event, name, field);
176         if (ret)
177                 pr_err("failed to set payload %s\n", name);
178 
179 err_put_field:
180         bt_ctf_field_put(field);
181         return ret;
182 }
183 
184 static struct bt_ctf_field_type*
185 get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field)
186 {
187         unsigned long flags = field->flags;
188 
189         if (flags & TEP_FIELD_IS_STRING)
190                 return cw->data.string;
191 
192         if (!(flags & TEP_FIELD_IS_SIGNED)) {
193                 /* unsigned long are mostly pointers */
194                 if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER)
195                         return cw->data.u64_hex;
196         }
197 
198         if (flags & TEP_FIELD_IS_SIGNED) {
199                 if (field->size == 8)
200                         return cw->data.s64;
201                 else
202                         return cw->data.s32;
203         }
204 
205         if (field->size == 8)
206                 return cw->data.u64;
207         else
208                 return cw->data.u32;
209 }
210 
211 static unsigned long long adjust_signedness(unsigned long long value_int, int size)
212 {
213         unsigned long long value_mask;
214 
215         /*
216          * value_mask = (1 << (size * 8 - 1)) - 1.
217          * Directly set value_mask for code readers.
218          */
219         switch (size) {
220         case 1:
221                 value_mask = 0x7fULL;
222                 break;
223         case 2:
224                 value_mask = 0x7fffULL;
225                 break;
226         case 4:
227                 value_mask = 0x7fffffffULL;
228                 break;
229         case 8:
230                 /*
231                  * For 64 bit value, return it self. There is no need
232                  * to fill high bit.
233                  */
234                 /* Fall through */
235         default:
236                 /* BUG! */
237                 return value_int;
238         }
239 
240         /* If it is a positive value, don't adjust. */
241         if ((value_int & (~0ULL - value_mask)) == 0)
242                 return value_int;
243 
244         /* Fill upper part of value_int with 1 to make it a negative long long. */
245         return (value_int & value_mask) | ~value_mask;
246 }
247 
248 static int string_set_value(struct bt_ctf_field *field, const char *string)
249 {
250         char *buffer = NULL;
251         size_t len = strlen(string), i, p;
252         int err;
253 
254         for (i = p = 0; i < len; i++, p++) {
255                 if (isprint(string[i])) {
256                         if (!buffer)
257                                 continue;
258                         buffer[p] = string[i];
259                 } else {
260                         char numstr[5];
261 
262                         snprintf(numstr, sizeof(numstr), "\\x%02x",
263                                  (unsigned int)(string[i]) & 0xff);
264 
265                         if (!buffer) {
266                                 buffer = zalloc(i + (len - i) * 4 + 2);
267                                 if (!buffer) {
268                                         pr_err("failed to set unprintable string '%s'\n", string);
269                                         return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
270                                 }
271                                 if (i > 0)
272                                         strncpy(buffer, string, i);
273                         }
274                         memcpy(buffer + p, numstr, 4);
275                         p += 3;
276                 }
277         }
278 
279         if (!buffer)
280                 return bt_ctf_field_string_set_value(field, string);
281         err = bt_ctf_field_string_set_value(field, buffer);
282         free(buffer);
283         return err;
284 }
285 
286 static int add_tracepoint_field_value(struct ctf_writer *cw,
287                                       struct bt_ctf_event_class *event_class,
288                                       struct bt_ctf_event *event,
289                                       struct perf_sample *sample,
290                                       struct tep_format_field *fmtf)
291 {
292         struct bt_ctf_field_type *type;
293         struct bt_ctf_field *array_field;
294         struct bt_ctf_field *field;
295         const char *name = fmtf->name;
296         void *data = sample->raw_data;
297         unsigned long flags = fmtf->flags;
298         unsigned int n_items;
299         unsigned int i;
300         unsigned int offset;
301         unsigned int len;
302         int ret;
303 
304         name = fmtf->alias;
305         offset = fmtf->offset;
306         len = fmtf->size;
307         if (flags & TEP_FIELD_IS_STRING)
308                 flags &= ~TEP_FIELD_IS_ARRAY;
309 
310         if (flags & TEP_FIELD_IS_DYNAMIC) {
311                 unsigned long long tmp_val;
312 
313                 tmp_val = tep_read_number(fmtf->event->tep,
314                                           data + offset, len);
315                 offset = tmp_val;
316                 len = offset >> 16;
317                 offset &= 0xffff;
318         }
319 
320         if (flags & TEP_FIELD_IS_ARRAY) {
321 
322                 type = bt_ctf_event_class_get_field_by_name(
323                                 event_class, name);
324                 array_field = bt_ctf_field_create(type);
325                 bt_ctf_field_type_put(type);
326                 if (!array_field) {
327                         pr_err("Failed to create array type %s\n", name);
328                         return -1;
329                 }
330 
331                 len = fmtf->size / fmtf->arraylen;
332                 n_items = fmtf->arraylen;
333         } else {
334                 n_items = 1;
335                 array_field = NULL;
336         }
337 
338         type = get_tracepoint_field_type(cw, fmtf);
339 
340         for (i = 0; i < n_items; i++) {
341                 if (flags & TEP_FIELD_IS_ARRAY)
342                         field = bt_ctf_field_array_get_field(array_field, i);
343                 else
344                         field = bt_ctf_field_create(type);
345 
346                 if (!field) {
347                         pr_err("failed to create a field %s\n", name);
348                         return -1;
349                 }
350 
351                 if (flags & TEP_FIELD_IS_STRING)
352                         ret = string_set_value(field, data + offset + i * len);
353                 else {
354                         unsigned long long value_int;
355 
356                         value_int = tep_read_number(
357                                         fmtf->event->tep,
358                                         data + offset + i * len, len);
359 
360                         if (!(flags & TEP_FIELD_IS_SIGNED))
361                                 ret = bt_ctf_field_unsigned_integer_set_value(
362                                                 field, value_int);
363                         else
364                                 ret = bt_ctf_field_signed_integer_set_value(
365                                                 field, adjust_signedness(value_int, len));
366                 }
367 
368                 if (ret) {
369                         pr_err("failed to set file value %s\n", name);
370                         goto err_put_field;
371                 }
372                 if (!(flags & TEP_FIELD_IS_ARRAY)) {
373                         ret = bt_ctf_event_set_payload(event, name, field);
374                         if (ret) {
375                                 pr_err("failed to set payload %s\n", name);
376                                 goto err_put_field;
377                         }
378                 }
379                 bt_ctf_field_put(field);
380         }
381         if (flags & TEP_FIELD_IS_ARRAY) {
382                 ret = bt_ctf_event_set_payload(event, name, array_field);
383                 if (ret) {
384                         pr_err("Failed add payload array %s\n", name);
385                         return -1;
386                 }
387                 bt_ctf_field_put(array_field);
388         }
389         return 0;
390 
391 err_put_field:
392         bt_ctf_field_put(field);
393         return -1;
394 }
395 
396 static int add_tracepoint_fields_values(struct ctf_writer *cw,
397                                         struct bt_ctf_event_class *event_class,
398                                         struct bt_ctf_event *event,
399                                         struct tep_format_field *fields,
400                                         struct perf_sample *sample)
401 {
402         struct tep_format_field *field;
403         int ret;
404 
405         for (field = fields; field; field = field->next) {
406                 ret = add_tracepoint_field_value(cw, event_class, event, sample,
407                                 field);
408                 if (ret)
409                         return -1;
410         }
411         return 0;
412 }
413 
414 static int add_tracepoint_values(struct ctf_writer *cw,
415                                  struct bt_ctf_event_class *event_class,
416                                  struct bt_ctf_event *event,
417                                  struct evsel *evsel,
418                                  struct perf_sample *sample)
419 {
420         struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
421         struct tep_format_field *fields        = evsel->tp_format->format.fields;
422         int ret;
423 
424         ret = add_tracepoint_fields_values(cw, event_class, event,
425                                            common_fields, sample);
426         if (!ret)
427                 ret = add_tracepoint_fields_values(cw, event_class, event,
428                                                    fields, sample);
429 
430         return ret;
431 }
432 
433 static int
434 add_bpf_output_values(struct bt_ctf_event_class *event_class,
435                       struct bt_ctf_event *event,
436                       struct perf_sample *sample)
437 {
438         struct bt_ctf_field_type *len_type, *seq_type;
439         struct bt_ctf_field *len_field, *seq_field;
440         unsigned int raw_size = sample->raw_size;
441         unsigned int nr_elements = raw_size / sizeof(u32);
442         unsigned int i;
443         int ret;
444 
445         if (nr_elements * sizeof(u32) != raw_size)
446                 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %zu bytes\n",
447                            raw_size, nr_elements * sizeof(u32) - raw_size);
448 
449         len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
450         len_field = bt_ctf_field_create(len_type);
451         if (!len_field) {
452                 pr_err("failed to create 'raw_len' for bpf output event\n");
453                 ret = -1;
454                 goto put_len_type;
455         }
456 
457         ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
458         if (ret) {
459                 pr_err("failed to set field value for raw_len\n");
460                 goto put_len_field;
461         }
462         ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
463         if (ret) {
464                 pr_err("failed to set payload to raw_len\n");
465                 goto put_len_field;
466         }
467 
468         seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
469         seq_field = bt_ctf_field_create(seq_type);
470         if (!seq_field) {
471                 pr_err("failed to create 'raw_data' for bpf output event\n");
472                 ret = -1;
473                 goto put_seq_type;
474         }
475 
476         ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
477         if (ret) {
478                 pr_err("failed to set length of 'raw_data'\n");
479                 goto put_seq_field;
480         }
481 
482         for (i = 0; i < nr_elements; i++) {
483                 struct bt_ctf_field *elem_field =
484                         bt_ctf_field_sequence_get_field(seq_field, i);
485 
486                 ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
487                                 ((u32 *)(sample->raw_data))[i]);
488 
489                 bt_ctf_field_put(elem_field);
490                 if (ret) {
491                         pr_err("failed to set raw_data[%d]\n", i);
492                         goto put_seq_field;
493                 }
494         }
495 
496         ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
497         if (ret)
498                 pr_err("failed to set payload for raw_data\n");
499 
500 put_seq_field:
501         bt_ctf_field_put(seq_field);
502 put_seq_type:
503         bt_ctf_field_type_put(seq_type);
504 put_len_field:
505         bt_ctf_field_put(len_field);
506 put_len_type:
507         bt_ctf_field_type_put(len_type);
508         return ret;
509 }
510 
511 static int
512 add_callchain_output_values(struct bt_ctf_event_class *event_class,
513                       struct bt_ctf_event *event,
514                       struct ip_callchain *callchain)
515 {
516         struct bt_ctf_field_type *len_type, *seq_type;
517         struct bt_ctf_field *len_field, *seq_field;
518         unsigned int nr_elements = callchain->nr;
519         unsigned int i;
520         int ret;
521 
522         len_type = bt_ctf_event_class_get_field_by_name(
523                         event_class, "perf_callchain_size");
524         len_field = bt_ctf_field_create(len_type);
525         if (!len_field) {
526                 pr_err("failed to create 'perf_callchain_size' for callchain output event\n");
527                 ret = -1;
528                 goto put_len_type;
529         }
530 
531         ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
532         if (ret) {
533                 pr_err("failed to set field value for perf_callchain_size\n");
534                 goto put_len_field;
535         }
536         ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field);
537         if (ret) {
538                 pr_err("failed to set payload to perf_callchain_size\n");
539                 goto put_len_field;
540         }
541 
542         seq_type = bt_ctf_event_class_get_field_by_name(
543                         event_class, "perf_callchain");
544         seq_field = bt_ctf_field_create(seq_type);
545         if (!seq_field) {
546                 pr_err("failed to create 'perf_callchain' for callchain output event\n");
547                 ret = -1;
548                 goto put_seq_type;
549         }
550 
551         ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
552         if (ret) {
553                 pr_err("failed to set length of 'perf_callchain'\n");
554                 goto put_seq_field;
555         }
556 
557         for (i = 0; i < nr_elements; i++) {
558                 struct bt_ctf_field *elem_field =
559                         bt_ctf_field_sequence_get_field(seq_field, i);
560 
561                 ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
562                                 ((u64 *)(callchain->ips))[i]);
563 
564                 bt_ctf_field_put(elem_field);
565                 if (ret) {
566                         pr_err("failed to set callchain[%d]\n", i);
567                         goto put_seq_field;
568                 }
569         }
570 
571         ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field);
572         if (ret)
573                 pr_err("failed to set payload for raw_data\n");
574 
575 put_seq_field:
576         bt_ctf_field_put(seq_field);
577 put_seq_type:
578         bt_ctf_field_type_put(seq_type);
579 put_len_field:
580         bt_ctf_field_put(len_field);
581 put_len_type:
582         bt_ctf_field_type_put(len_type);
583         return ret;
584 }
585 
586 static int add_generic_values(struct ctf_writer *cw,
587                               struct bt_ctf_event *event,
588                               struct evsel *evsel,
589                               struct perf_sample *sample)
590 {
591         u64 type = evsel->core.attr.sample_type;
592         int ret;
593 
594         /*
595          * missing:
596          *   PERF_SAMPLE_TIME         - not needed as we have it in
597          *                              ctf event header
598          *   PERF_SAMPLE_READ         - TODO
599          *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
600          *   PERF_SAMPLE_BRANCH_STACK - TODO
601          *   PERF_SAMPLE_REGS_USER    - TODO
602          *   PERF_SAMPLE_STACK_USER   - TODO
603          */
604 
605         if (type & PERF_SAMPLE_IP) {
606                 ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
607                 if (ret)
608                         return -1;
609         }
610 
611         if (type & PERF_SAMPLE_TID) {
612                 ret = value_set_s32(cw, event, "perf_tid", sample->tid);
613                 if (ret)
614                         return -1;
615 
616                 ret = value_set_s32(cw, event, "perf_pid", sample->pid);
617                 if (ret)
618                         return -1;
619         }
620 
621         if ((type & PERF_SAMPLE_ID) ||
622             (type & PERF_SAMPLE_IDENTIFIER)) {
623                 ret = value_set_u64(cw, event, "perf_id", sample->id);
624                 if (ret)
625                         return -1;
626         }
627 
628         if (type & PERF_SAMPLE_STREAM_ID) {
629                 ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
630                 if (ret)
631                         return -1;
632         }
633 
634         if (type & PERF_SAMPLE_PERIOD) {
635                 ret = value_set_u64(cw, event, "perf_period", sample->period);
636                 if (ret)
637                         return -1;
638         }
639 
640         if (type & PERF_SAMPLE_WEIGHT) {
641                 ret = value_set_u64(cw, event, "perf_weight", sample->weight);
642                 if (ret)
643                         return -1;
644         }
645 
646         if (type & PERF_SAMPLE_DATA_SRC) {
647                 ret = value_set_u64(cw, event, "perf_data_src",
648                                 sample->data_src);
649                 if (ret)
650                         return -1;
651         }
652 
653         if (type & PERF_SAMPLE_TRANSACTION) {
654                 ret = value_set_u64(cw, event, "perf_transaction",
655                                 sample->transaction);
656                 if (ret)
657                         return -1;
658         }
659 
660         return 0;
661 }
662 
663 static int ctf_stream__flush(struct ctf_stream *cs)
664 {
665         int err = 0;
666 
667         if (cs) {
668                 err = bt_ctf_stream_flush(cs->stream);
669                 if (err)
670                         pr_err("CTF stream %d flush failed\n", cs->cpu);
671 
672                 pr("Flush stream for cpu %d (%u samples)\n",
673                    cs->cpu, cs->count);
674 
675                 cs->count = 0;
676         }
677 
678         return err;
679 }
680 
681 static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
682 {
683         struct ctf_stream *cs;
684         struct bt_ctf_field *pkt_ctx   = NULL;
685         struct bt_ctf_field *cpu_field = NULL;
686         struct bt_ctf_stream *stream   = NULL;
687         int ret;
688 
689         cs = zalloc(sizeof(*cs));
690         if (!cs) {
691                 pr_err("Failed to allocate ctf stream\n");
692                 return NULL;
693         }
694 
695         stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
696         if (!stream) {
697                 pr_err("Failed to create CTF stream\n");
698                 goto out;
699         }
700 
701         pkt_ctx = bt_ctf_stream_get_packet_context(stream);
702         if (!pkt_ctx) {
703                 pr_err("Failed to obtain packet context\n");
704                 goto out;
705         }
706 
707         cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
708         bt_ctf_field_put(pkt_ctx);
709         if (!cpu_field) {
710                 pr_err("Failed to obtain cpu field\n");
711                 goto out;
712         }
713 
714         ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
715         if (ret) {
716                 pr_err("Failed to update CPU number\n");
717                 goto out;
718         }
719 
720         bt_ctf_field_put(cpu_field);
721 
722         cs->cpu    = cpu;
723         cs->stream = stream;
724         return cs;
725 
726 out:
727         if (cpu_field)
728                 bt_ctf_field_put(cpu_field);
729         if (stream)
730                 bt_ctf_stream_put(stream);
731 
732         free(cs);
733         return NULL;
734 }
735 
736 static void ctf_stream__delete(struct ctf_stream *cs)
737 {
738         if (cs) {
739                 bt_ctf_stream_put(cs->stream);
740                 free(cs);
741         }
742 }
743 
744 static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
745 {
746         struct ctf_stream *cs = cw->stream[cpu];
747 
748         if (!cs) {
749                 cs = ctf_stream__create(cw, cpu);
750                 cw->stream[cpu] = cs;
751         }
752 
753         return cs;
754 }
755 
756 static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
757                           struct evsel *evsel)
758 {
759         int cpu = 0;
760 
761         if (evsel->core.attr.sample_type & PERF_SAMPLE_CPU)
762                 cpu = sample->cpu;
763 
764         if (cpu > cw->stream_cnt) {
765                 pr_err("Event was recorded for CPU %d, limit is at %d.\n",
766                         cpu, cw->stream_cnt);
767                 cpu = 0;
768         }
769 
770         return cpu;
771 }
772 
773 #define STREAM_FLUSH_COUNT 100000
774 
775 /*
776  * Currently we have no other way to determine the
777  * time for the stream flush other than keep track
778  * of the number of events and check it against
779  * threshold.
780  */
781 static bool is_flush_needed(struct ctf_stream *cs)
782 {
783         return cs->count >= STREAM_FLUSH_COUNT;
784 }
785 
786 static int process_sample_event(struct perf_tool *tool,
787                                 union perf_event *_event,
788                                 struct perf_sample *sample,
789                                 struct evsel *evsel,
790                                 struct machine *machine __maybe_unused)
791 {
792         struct convert *c = container_of(tool, struct convert, tool);
793         struct evsel_priv *priv = evsel->priv;
794         struct ctf_writer *cw = &c->writer;
795         struct ctf_stream *cs;
796         struct bt_ctf_event_class *event_class;
797         struct bt_ctf_event *event;
798         int ret;
799         unsigned long type = evsel->core.attr.sample_type;
800 
801         if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
802                 return 0;
803 
804         event_class = priv->event_class;
805 
806         /* update stats */
807         c->events_count++;
808         c->events_size += _event->header.size;
809 
810         pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
811 
812         event = bt_ctf_event_create(event_class);
813         if (!event) {
814                 pr_err("Failed to create an CTF event\n");
815                 return -1;
816         }
817 
818         bt_ctf_clock_set_time(cw->clock, sample->time);
819 
820         ret = add_generic_values(cw, event, evsel, sample);
821         if (ret)
822                 return -1;
823 
824         if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
825                 ret = add_tracepoint_values(cw, event_class, event,
826                                             evsel, sample);
827                 if (ret)
828                         return -1;
829         }
830 
831         if (type & PERF_SAMPLE_CALLCHAIN) {
832                 ret = add_callchain_output_values(event_class,
833                                 event, sample->callchain);
834                 if (ret)
835                         return -1;
836         }
837 
838         if (perf_evsel__is_bpf_output(evsel)) {
839                 ret = add_bpf_output_values(event_class, event, sample);
840                 if (ret)
841                         return -1;
842         }
843 
844         cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
845         if (cs) {
846                 if (is_flush_needed(cs))
847                         ctf_stream__flush(cs);
848 
849                 cs->count++;
850                 bt_ctf_stream_append_event(cs->stream, event);
851         }
852 
853         bt_ctf_event_put(event);
854         return cs ? 0 : -1;
855 }
856 
857 #define __NON_SAMPLE_SET_FIELD(_name, _type, _field)    \
858 do {                                                    \
859         ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
860         if (ret)                                        \
861                 return -1;                              \
862 } while(0)
863 
864 #define __FUNC_PROCESS_NON_SAMPLE(_name, body)  \
865 static int process_##_name##_event(struct perf_tool *tool,      \
866                                    union perf_event *_event,    \
867                                    struct perf_sample *sample,  \
868                                    struct machine *machine)     \
869 {                                                               \
870         struct convert *c = container_of(tool, struct convert, tool);\
871         struct ctf_writer *cw = &c->writer;                     \
872         struct bt_ctf_event_class *event_class = cw->_name##_class;\
873         struct bt_ctf_event *event;                             \
874         struct ctf_stream *cs;                                  \
875         int ret;                                                \
876                                                                 \
877         c->non_sample_count++;                                  \
878         c->events_size += _event->header.size;                  \
879         event = bt_ctf_event_create(event_class);               \
880         if (!event) {                                           \
881                 pr_err("Failed to create an CTF event\n");      \
882                 return -1;                                      \
883         }                                                       \
884                                                                 \
885         bt_ctf_clock_set_time(cw->clock, sample->time);         \
886         body                                                    \
887         cs = ctf_stream(cw, 0);                                 \
888         if (cs) {                                               \
889                 if (is_flush_needed(cs))                        \
890                         ctf_stream__flush(cs);                  \
891                                                                 \
892                 cs->count++;                                    \
893                 bt_ctf_stream_append_event(cs->stream, event);  \
894         }                                                       \
895         bt_ctf_event_put(event);                                \
896                                                                 \
897         return perf_event__process_##_name(tool, _event, sample, machine);\
898 }
899 
900 __FUNC_PROCESS_NON_SAMPLE(comm,
901         __NON_SAMPLE_SET_FIELD(comm, u32, pid);
902         __NON_SAMPLE_SET_FIELD(comm, u32, tid);
903         __NON_SAMPLE_SET_FIELD(comm, string, comm);
904 )
905 __FUNC_PROCESS_NON_SAMPLE(fork,
906         __NON_SAMPLE_SET_FIELD(fork, u32, pid);
907         __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
908         __NON_SAMPLE_SET_FIELD(fork, u32, tid);
909         __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
910         __NON_SAMPLE_SET_FIELD(fork, u64, time);
911 )
912 
913 __FUNC_PROCESS_NON_SAMPLE(exit,
914         __NON_SAMPLE_SET_FIELD(fork, u32, pid);
915         __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
916         __NON_SAMPLE_SET_FIELD(fork, u32, tid);
917         __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
918         __NON_SAMPLE_SET_FIELD(fork, u64, time);
919 )
920 __FUNC_PROCESS_NON_SAMPLE(mmap,
921         __NON_SAMPLE_SET_FIELD(mmap, u32, pid);
922         __NON_SAMPLE_SET_FIELD(mmap, u32, tid);
923         __NON_SAMPLE_SET_FIELD(mmap, u64_hex, start);
924         __NON_SAMPLE_SET_FIELD(mmap, string, filename);
925 )
926 __FUNC_PROCESS_NON_SAMPLE(mmap2,
927         __NON_SAMPLE_SET_FIELD(mmap2, u32, pid);
928         __NON_SAMPLE_SET_FIELD(mmap2, u32, tid);
929         __NON_SAMPLE_SET_FIELD(mmap2, u64_hex, start);
930         __NON_SAMPLE_SET_FIELD(mmap2, string, filename);
931 )
932 #undef __NON_SAMPLE_SET_FIELD
933 #undef __FUNC_PROCESS_NON_SAMPLE
934 
935 /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
936 static char *change_name(char *name, char *orig_name, int dup)
937 {
938         char *new_name = NULL;
939         size_t len;
940 
941         if (!name)
942                 name = orig_name;
943 
944         if (dup >= 10)
945                 goto out;
946         /*
947          * Add '_' prefix to potential keywork.  According to
948          * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
949          * futher CTF spec updating may require us to use '$'.
950          */
951         if (dup < 0)
952                 len = strlen(name) + sizeof("_");
953         else
954                 len = strlen(orig_name) + sizeof("_dupl_X");
955 
956         new_name = malloc(len);
957         if (!new_name)
958                 goto out;
959 
960         if (dup < 0)
961                 snprintf(new_name, len, "_%s", name);
962         else
963                 snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
964 
965 out:
966         if (name != orig_name)
967                 free(name);
968         return new_name;
969 }
970 
971 static int event_class_add_field(struct bt_ctf_event_class *event_class,
972                 struct bt_ctf_field_type *type,
973                 struct tep_format_field *field)
974 {
975         struct bt_ctf_field_type *t = NULL;
976         char *name;
977         int dup = 1;
978         int ret;
979 
980         /* alias was already assigned */
981         if (field->alias != field->name)
982                 return bt_ctf_event_class_add_field(event_class, type,
983                                 (char *)field->alias);
984 
985         name = field->name;
986 
987         /* If 'name' is a keywork, add prefix. */
988         if (bt_ctf_validate_identifier(name))
989                 name = change_name(name, field->name, -1);
990 
991         if (!name) {
992                 pr_err("Failed to fix invalid identifier.");
993                 return -1;
994         }
995         while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
996                 bt_ctf_field_type_put(t);
997                 name = change_name(name, field->name, dup++);
998                 if (!name) {
999                         pr_err("Failed to create dup name for '%s'\n", field->name);
1000                         return -1;
1001                 }
1002         }
1003 
1004         ret = bt_ctf_event_class_add_field(event_class, type, name);
1005         if (!ret)
1006                 field->alias = name;
1007 
1008         return ret;
1009 }
1010 
1011 static int add_tracepoint_fields_types(struct ctf_writer *cw,
1012                                        struct tep_format_field *fields,
1013                                        struct bt_ctf_event_class *event_class)
1014 {
1015         struct tep_format_field *field;
1016         int ret;
1017 
1018         for (field = fields; field; field = field->next) {
1019                 struct bt_ctf_field_type *type;
1020                 unsigned long flags = field->flags;
1021 
1022                 pr2("  field '%s'\n", field->name);
1023 
1024                 type = get_tracepoint_field_type(cw, field);
1025                 if (!type)
1026                         return -1;
1027 
1028                 /*
1029                  * A string is an array of chars. For this we use the string
1030                  * type and don't care that it is an array. What we don't
1031                  * support is an array of strings.
1032                  */
1033                 if (flags & TEP_FIELD_IS_STRING)
1034                         flags &= ~TEP_FIELD_IS_ARRAY;
1035 
1036                 if (flags & TEP_FIELD_IS_ARRAY)
1037                         type = bt_ctf_field_type_array_create(type, field->arraylen);
1038 
1039                 ret = event_class_add_field(event_class, type, field);
1040 
1041                 if (flags & TEP_FIELD_IS_ARRAY)
1042                         bt_ctf_field_type_put(type);
1043 
1044                 if (ret) {
1045                         pr_err("Failed to add field '%s': %d\n",
1046                                         field->name, ret);
1047                         return -1;
1048                 }
1049         }
1050 
1051         return 0;
1052 }
1053 
1054 static int add_tracepoint_types(struct ctf_writer *cw,
1055                                 struct evsel *evsel,
1056                                 struct bt_ctf_event_class *class)
1057 {
1058         struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
1059         struct tep_format_field *fields        = evsel->tp_format->format.fields;
1060         int ret;
1061 
1062         ret = add_tracepoint_fields_types(cw, common_fields, class);
1063         if (!ret)
1064                 ret = add_tracepoint_fields_types(cw, fields, class);
1065 
1066         return ret;
1067 }
1068 
1069 static int add_bpf_output_types(struct ctf_writer *cw,
1070                                 struct bt_ctf_event_class *class)
1071 {
1072         struct bt_ctf_field_type *len_type = cw->data.u32;
1073         struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
1074         struct bt_ctf_field_type *seq_type;
1075         int ret;
1076 
1077         ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
1078         if (ret)
1079                 return ret;
1080 
1081         seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
1082         if (!seq_type)
1083                 return -1;
1084 
1085         return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
1086 }
1087 
1088 static int add_generic_types(struct ctf_writer *cw, struct evsel *evsel,
1089                              struct bt_ctf_event_class *event_class)
1090 {
1091         u64 type = evsel->core.attr.sample_type;
1092 
1093         /*
1094          * missing:
1095          *   PERF_SAMPLE_TIME         - not needed as we have it in
1096          *                              ctf event header
1097          *   PERF_SAMPLE_READ         - TODO
1098          *   PERF_SAMPLE_CALLCHAIN    - TODO
1099          *   PERF_SAMPLE_RAW          - tracepoint fields and BPF output
1100          *                              are handled separately
1101          *   PERF_SAMPLE_BRANCH_STACK - TODO
1102          *   PERF_SAMPLE_REGS_USER    - TODO
1103          *   PERF_SAMPLE_STACK_USER   - TODO
1104          */
1105 
1106 #define ADD_FIELD(cl, t, n)                                             \
1107         do {                                                            \
1108                 pr2("  field '%s'\n", n);                               \
1109                 if (bt_ctf_event_class_add_field(cl, t, n)) {           \
1110                         pr_err("Failed to add field '%s';\n", n);       \
1111                         return -1;                                      \
1112                 }                                                       \
1113         } while (0)
1114 
1115         if (type & PERF_SAMPLE_IP)
1116                 ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
1117 
1118         if (type & PERF_SAMPLE_TID) {
1119                 ADD_FIELD(event_class, cw->data.s32, "perf_tid");
1120                 ADD_FIELD(event_class, cw->data.s32, "perf_pid");
1121         }
1122 
1123         if ((type & PERF_SAMPLE_ID) ||
1124             (type & PERF_SAMPLE_IDENTIFIER))
1125                 ADD_FIELD(event_class, cw->data.u64, "perf_id");
1126 
1127         if (type & PERF_SAMPLE_STREAM_ID)
1128                 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
1129 
1130         if (type & PERF_SAMPLE_PERIOD)
1131                 ADD_FIELD(event_class, cw->data.u64, "perf_period");
1132 
1133         if (type & PERF_SAMPLE_WEIGHT)
1134                 ADD_FIELD(event_class, cw->data.u64, "perf_weight");
1135 
1136         if (type & PERF_SAMPLE_DATA_SRC)
1137                 ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
1138 
1139         if (type & PERF_SAMPLE_TRANSACTION)
1140                 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
1141 
1142         if (type & PERF_SAMPLE_CALLCHAIN) {
1143                 ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size");
1144                 ADD_FIELD(event_class,
1145                         bt_ctf_field_type_sequence_create(
1146                                 cw->data.u64_hex, "perf_callchain_size"),
1147                         "perf_callchain");
1148         }
1149 
1150 #undef ADD_FIELD
1151         return 0;
1152 }
1153 
1154 static int add_event(struct ctf_writer *cw, struct evsel *evsel)
1155 {
1156         struct bt_ctf_event_class *event_class;
1157         struct evsel_priv *priv;
1158         const char *name = perf_evsel__name(evsel);
1159         int ret;
1160 
1161         pr("Adding event '%s' (type %d)\n", name, evsel->core.attr.type);
1162 
1163         event_class = bt_ctf_event_class_create(name);
1164         if (!event_class)
1165                 return -1;
1166 
1167         ret = add_generic_types(cw, evsel, event_class);
1168         if (ret)
1169                 goto err;
1170 
1171         if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
1172                 ret = add_tracepoint_types(cw, evsel, event_class);
1173                 if (ret)
1174                         goto err;
1175         }
1176 
1177         if (perf_evsel__is_bpf_output(evsel)) {
1178                 ret = add_bpf_output_types(cw, event_class);
1179                 if (ret)
1180                         goto err;
1181         }
1182 
1183         ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
1184         if (ret) {
1185                 pr("Failed to add event class into stream.\n");
1186                 goto err;
1187         }
1188 
1189         priv = malloc(sizeof(*priv));
1190         if (!priv)
1191                 goto err;
1192 
1193         priv->event_class = event_class;
1194         evsel->priv       = priv;
1195         return 0;
1196 
1197 err:
1198         bt_ctf_event_class_put(event_class);
1199         pr_err("Failed to add event '%s'.\n", name);
1200         return -1;
1201 }
1202 
1203 static int setup_events(struct ctf_writer *cw, struct perf_session *session)
1204 {
1205         struct evlist *evlist = session->evlist;
1206         struct evsel *evsel;
1207         int ret;
1208 
1209         evlist__for_each_entry(evlist, evsel) {
1210                 ret = add_event(cw, evsel);
1211                 if (ret)
1212                         return ret;
1213         }
1214         return 0;
1215 }
1216 
1217 #define __NON_SAMPLE_ADD_FIELD(t, n)                                            \
1218         do {                                                    \
1219                 pr2("  field '%s'\n", #n);                      \
1220                 if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
1221                         pr_err("Failed to add field '%s';\n", #n);\
1222                         return -1;                              \
1223                 }                                               \
1224         } while(0)
1225 
1226 #define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body)          \
1227 static int add_##_name##_event(struct ctf_writer *cw)           \
1228 {                                                               \
1229         struct bt_ctf_event_class *event_class;                 \
1230         int ret;                                                \
1231                                                                 \
1232         pr("Adding "#_name" event\n");                          \
1233         event_class = bt_ctf_event_class_create("perf_" #_name);\
1234         if (!event_class)                                       \
1235                 return -1;                                      \
1236         body                                                    \
1237                                                                 \
1238         ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
1239         if (ret) {                                              \
1240                 pr("Failed to add event class '"#_name"' into stream.\n");\
1241                 return ret;                                     \
1242         }                                                       \
1243                                                                 \
1244         cw->_name##_class = event_class;                        \
1245         bt_ctf_event_class_put(event_class);                    \
1246         return 0;                                               \
1247 }
1248 
1249 __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
1250         __NON_SAMPLE_ADD_FIELD(u32, pid);
1251         __NON_SAMPLE_ADD_FIELD(u32, tid);
1252         __NON_SAMPLE_ADD_FIELD(string, comm);
1253 )
1254 
1255 __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork,
1256         __NON_SAMPLE_ADD_FIELD(u32, pid);
1257         __NON_SAMPLE_ADD_FIELD(u32, ppid);
1258         __NON_SAMPLE_ADD_FIELD(u32, tid);
1259         __NON_SAMPLE_ADD_FIELD(u32, ptid);
1260         __NON_SAMPLE_ADD_FIELD(u64, time);
1261 )
1262 
1263 __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1264         __NON_SAMPLE_ADD_FIELD(u32, pid);
1265         __NON_SAMPLE_ADD_FIELD(u32, ppid);
1266         __NON_SAMPLE_ADD_FIELD(u32, tid);
1267         __NON_SAMPLE_ADD_FIELD(u32, ptid);
1268         __NON_SAMPLE_ADD_FIELD(u64, time);
1269 )
1270 
1271 __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap,
1272         __NON_SAMPLE_ADD_FIELD(u32, pid);
1273         __NON_SAMPLE_ADD_FIELD(u32, tid);
1274         __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1275         __NON_SAMPLE_ADD_FIELD(string, filename);
1276 )
1277 
1278 __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap2,
1279         __NON_SAMPLE_ADD_FIELD(u32, pid);
1280         __NON_SAMPLE_ADD_FIELD(u32, tid);
1281         __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1282         __NON_SAMPLE_ADD_FIELD(string, filename);
1283 )
1284 #undef __NON_SAMPLE_ADD_FIELD
1285 #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1286 
1287 static int setup_non_sample_events(struct ctf_writer *cw,
1288                                    struct perf_session *session __maybe_unused)
1289 {
1290         int ret;
1291 
1292         ret = add_comm_event(cw);
1293         if (ret)
1294                 return ret;
1295         ret = add_exit_event(cw);
1296         if (ret)
1297                 return ret;
1298         ret = add_fork_event(cw);
1299         if (ret)
1300                 return ret;
1301         ret = add_mmap_event(cw);
1302         if (ret)
1303                 return ret;
1304         ret = add_mmap2_event(cw);
1305         if (ret)
1306                 return ret;
1307         return 0;
1308 }
1309 
1310 static void cleanup_events(struct perf_session *session)
1311 {
1312         struct evlist *evlist = session->evlist;
1313         struct evsel *evsel;
1314 
1315         evlist__for_each_entry(evlist, evsel) {
1316                 struct evsel_priv *priv;
1317 
1318                 priv = evsel->priv;
1319                 bt_ctf_event_class_put(priv->event_class);
1320                 zfree(&evsel->priv);
1321         }
1322 
1323         evlist__delete(evlist);
1324         session->evlist = NULL;
1325 }
1326 
1327 static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
1328 {
1329         struct ctf_stream **stream;
1330         struct perf_header *ph = &session->header;
1331         int ncpus;
1332 
1333         /*
1334          * Try to get the number of cpus used in the data file,
1335          * if not present fallback to the MAX_CPUS.
1336          */
1337         ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
1338 
1339         stream = zalloc(sizeof(*stream) * ncpus);
1340         if (!stream) {
1341                 pr_err("Failed to allocate streams.\n");
1342                 return -ENOMEM;
1343         }
1344 
1345         cw->stream     = stream;
1346         cw->stream_cnt = ncpus;
1347         return 0;
1348 }
1349 
1350 static void free_streams(struct ctf_writer *cw)
1351 {
1352         int cpu;
1353 
1354         for (cpu = 0; cpu < cw->stream_cnt; cpu++)
1355                 ctf_stream__delete(cw->stream[cpu]);
1356 
1357         zfree(&cw->stream);
1358 }
1359 
1360 static int ctf_writer__setup_env(struct ctf_writer *cw,
1361                                  struct perf_session *session)
1362 {
1363         struct perf_header *header = &session->header;
1364         struct bt_ctf_writer *writer = cw->writer;
1365 
1366 #define ADD(__n, __v)                                                   \
1367 do {                                                                    \
1368         if (bt_ctf_writer_add_environment_field(writer, __n, __v))      \
1369                 return -1;                                              \
1370 } while (0)
1371 
1372         ADD("host",    header->env.hostname);
1373         ADD("sysname", "Linux");
1374         ADD("release", header->env.os_release);
1375         ADD("version", header->env.version);
1376         ADD("machine", header->env.arch);
1377         ADD("domain", "kernel");
1378         ADD("tracer_name", "perf");
1379 
1380 #undef ADD
1381         return 0;
1382 }
1383 
1384 static int ctf_writer__setup_clock(struct ctf_writer *cw)
1385 {
1386         struct bt_ctf_clock *clock = cw->clock;
1387 
1388         bt_ctf_clock_set_description(clock, "perf clock");
1389 
1390 #define SET(__n, __v)                           \
1391 do {                                            \
1392         if (bt_ctf_clock_set_##__n(clock, __v)) \
1393                 return -1;                      \
1394 } while (0)
1395 
1396         SET(frequency,   1000000000);
1397         SET(offset_s,    0);
1398         SET(offset,      0);
1399         SET(precision,   10);
1400         SET(is_absolute, 0);
1401 
1402 #undef SET
1403         return 0;
1404 }
1405 
1406 static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
1407 {
1408         struct bt_ctf_field_type *type;
1409 
1410         type = bt_ctf_field_type_integer_create(size);
1411         if (!type)
1412                 return NULL;
1413 
1414         if (sign &&
1415             bt_ctf_field_type_integer_set_signed(type, 1))
1416                 goto err;
1417 
1418         if (hex &&
1419             bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
1420                 goto err;
1421 
1422 #if __BYTE_ORDER == __BIG_ENDIAN
1423         bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
1424 #else
1425         bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
1426 #endif
1427 
1428         pr2("Created type: INTEGER %d-bit %ssigned %s\n",
1429             size, sign ? "un" : "", hex ? "hex" : "");
1430         return type;
1431 
1432 err:
1433         bt_ctf_field_type_put(type);
1434         return NULL;
1435 }
1436 
1437 static void ctf_writer__cleanup_data(struct ctf_writer *cw)
1438 {
1439         unsigned int i;
1440 
1441         for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
1442                 bt_ctf_field_type_put(cw->data.array[i]);
1443 }
1444 
1445 static int ctf_writer__init_data(struct ctf_writer *cw)
1446 {
1447 #define CREATE_INT_TYPE(type, size, sign, hex)          \
1448 do {                                                    \
1449         (type) = create_int_type(size, sign, hex);      \
1450         if (!(type))                                    \
1451                 goto err;                               \
1452 } while (0)
1453 
1454         CREATE_INT_TYPE(cw->data.s64, 64, true,  false);
1455         CREATE_INT_TYPE(cw->data.u64, 64, false, false);
1456         CREATE_INT_TYPE(cw->data.s32, 32, true,  false);
1457         CREATE_INT_TYPE(cw->data.u32, 32, false, false);
1458         CREATE_INT_TYPE(cw->data.u32_hex, 32, false, true);
1459         CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
1460 
1461         cw->data.string  = bt_ctf_field_type_string_create();
1462         if (cw->data.string)
1463                 return 0;
1464 
1465 err:
1466         ctf_writer__cleanup_data(cw);
1467         pr_err("Failed to create data types.\n");
1468         return -1;
1469 }
1470 
1471 static void ctf_writer__cleanup(struct ctf_writer *cw)
1472 {
1473         ctf_writer__cleanup_data(cw);
1474 
1475         bt_ctf_clock_put(cw->clock);
1476         free_streams(cw);
1477         bt_ctf_stream_class_put(cw->stream_class);
1478         bt_ctf_writer_put(cw->writer);
1479 
1480         /* and NULL all the pointers */
1481         memset(cw, 0, sizeof(*cw));
1482 }
1483 
1484 static int ctf_writer__init(struct ctf_writer *cw, const char *path)
1485 {
1486         struct bt_ctf_writer            *writer;
1487         struct bt_ctf_stream_class      *stream_class;
1488         struct bt_ctf_clock             *clock;
1489         struct bt_ctf_field_type        *pkt_ctx_type;
1490         int                             ret;
1491 
1492         /* CTF writer */
1493         writer = bt_ctf_writer_create(path);
1494         if (!writer)
1495                 goto err;
1496 
1497         cw->writer = writer;
1498 
1499         /* CTF clock */
1500         clock = bt_ctf_clock_create("perf_clock");
1501         if (!clock) {
1502                 pr("Failed to create CTF clock.\n");
1503                 goto err_cleanup;
1504         }
1505 
1506         cw->clock = clock;
1507 
1508         if (ctf_writer__setup_clock(cw)) {
1509                 pr("Failed to setup CTF clock.\n");
1510                 goto err_cleanup;
1511         }
1512 
1513         /* CTF stream class */
1514         stream_class = bt_ctf_stream_class_create("perf_stream");
1515         if (!stream_class) {
1516                 pr("Failed to create CTF stream class.\n");
1517                 goto err_cleanup;
1518         }
1519 
1520         cw->stream_class = stream_class;
1521 
1522         /* CTF clock stream setup */
1523         if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
1524                 pr("Failed to assign CTF clock to stream class.\n");
1525                 goto err_cleanup;
1526         }
1527 
1528         if (ctf_writer__init_data(cw))
1529                 goto err_cleanup;
1530 
1531         /* Add cpu_id for packet context */
1532         pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
1533         if (!pkt_ctx_type)
1534                 goto err_cleanup;
1535 
1536         ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
1537         bt_ctf_field_type_put(pkt_ctx_type);
1538         if (ret)
1539                 goto err_cleanup;
1540 
1541         /* CTF clock writer setup */
1542         if (bt_ctf_writer_add_clock(writer, clock)) {
1543                 pr("Failed to assign CTF clock to writer.\n");
1544                 goto err_cleanup;
1545         }
1546 
1547         return 0;
1548 
1549 err_cleanup:
1550         ctf_writer__cleanup(cw);
1551 err:
1552         pr_err("Failed to setup CTF writer.\n");
1553         return -1;
1554 }
1555 
1556 static int ctf_writer__flush_streams(struct ctf_writer *cw)
1557 {
1558         int cpu, ret = 0;
1559 
1560         for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
1561                 ret = ctf_stream__flush(cw->stream[cpu]);
1562 
1563         return ret;
1564 }
1565 
1566 static int convert__config(const char *var, const char *value, void *cb)
1567 {
1568         struct convert *c = cb;
1569 
1570         if (!strcmp(var, "convert.queue-size"))
1571                 return perf_config_u64(&c->queue_size, var, value);
1572 
1573         return 0;
1574 }
1575 
1576 int bt_convert__perf2ctf(const char *input, const char *path,
1577                          struct perf_data_convert_opts *opts)
1578 {
1579         struct perf_session *session;
1580         struct perf_data data = {
1581                 .path      = input,
1582                 .mode      = PERF_DATA_MODE_READ,
1583                 .force     = opts->force,
1584         };
1585         struct convert c = {
1586                 .tool = {
1587                         .sample          = process_sample_event,
1588                         .mmap            = perf_event__process_mmap,
1589                         .mmap2           = perf_event__process_mmap2,
1590                         .comm            = perf_event__process_comm,
1591                         .exit            = perf_event__process_exit,
1592                         .fork            = perf_event__process_fork,
1593                         .lost            = perf_event__process_lost,
1594                         .tracing_data    = perf_event__process_tracing_data,
1595                         .build_id        = perf_event__process_build_id,
1596                         .namespaces      = perf_event__process_namespaces,
1597                         .ordered_events  = true,
1598                         .ordering_requires_timestamps = true,
1599                 },
1600         };
1601         struct ctf_writer *cw = &c.writer;
1602         int err;
1603 
1604         if (opts->all) {
1605                 c.tool.comm = process_comm_event;
1606                 c.tool.exit = process_exit_event;
1607                 c.tool.fork = process_fork_event;
1608                 c.tool.mmap = process_mmap_event;
1609                 c.tool.mmap2 = process_mmap2_event;
1610         }
1611 
1612         err = perf_config(convert__config, &c);
1613         if (err)
1614                 return err;
1615 
1616         /* CTF writer */
1617         if (ctf_writer__init(cw, path))
1618                 return -1;
1619 
1620         err = -1;
1621         /* perf.data session */
1622         session = perf_session__new(&data, 0, &c.tool);
1623         if (IS_ERR(session)) {
1624                 err = PTR_ERR(session);
1625                 goto free_writer;
1626         }
1627 
1628         if (c.queue_size) {
1629                 ordered_events__set_alloc_size(&session->ordered_events,
1630                                                c.queue_size);
1631         }
1632 
1633         /* CTF writer env/clock setup  */
1634         if (ctf_writer__setup_env(cw, session))
1635                 goto free_session;
1636 
1637         /* CTF events setup */
1638         if (setup_events(cw, session))
1639                 goto free_session;
1640 
1641         if (opts->all && setup_non_sample_events(cw, session))
1642                 goto free_session;
1643 
1644         if (setup_streams(cw, session))
1645                 goto free_session;
1646 
1647         err = perf_session__process_events(session);
1648         if (!err)
1649                 err = ctf_writer__flush_streams(cw);
1650         else
1651                 pr_err("Error during conversion.\n");
1652 
1653         fprintf(stderr,
1654                 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1655                 data.path, path);
1656 
1657         fprintf(stderr,
1658                 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1659                 (double) c.events_size / 1024.0 / 1024.0,
1660                 c.events_count);
1661 
1662         if (!c.non_sample_count)
1663                 fprintf(stderr, ") ]\n");
1664         else
1665                 fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
1666 
1667         cleanup_events(session);
1668         perf_session__delete(session);
1669         ctf_writer__cleanup(cw);
1670 
1671         return err;
1672 
1673 free_session:
1674         perf_session__delete(session);
1675 free_writer:
1676         ctf_writer__cleanup(cw);
1677         pr_err("Error during conversion setup.\n");
1678         return err;
1679 }
1680 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp