Linux Perf
data-convert-bt.c
Go to the documentation of this file.
1 /*
2  * CTF writing support via babeltrace.
3  *
4  * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
5  * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
6  *
7  * Released under the GPL v2. (and only v2, not any later version)
8  */
9 
10 #include <errno.h>
11 #include <inttypes.h>
12 #include <linux/compiler.h>
13 #include <linux/kernel.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 "util.h"
27 #include "debug.h"
28 #include "tool.h"
29 #include "evlist.h"
30 #include "evsel.h"
31 #include "machine.h"
32 #include "config.h"
33 #include "sane_ctype.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;
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;
86 
90 
91  /* Ordered events configured 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 format_field *field)
186 {
187  unsigned long flags = field->flags;
188 
189  if (flags & FIELD_IS_STRING)
190  return cw->data.string;
191 
192  if (!(flags & FIELD_IS_SIGNED)) {
193  /* unsigned long are mostly pointers */
194  if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
195  return cw->data.u64_hex;
196  }
197 
198  if (flags & 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  strncat(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 
287  struct bt_ctf_event_class *event_class,
288  struct bt_ctf_event *event,
289  struct perf_sample *sample,
290  struct 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 & FIELD_IS_STRING)
308  flags &= ~FIELD_IS_ARRAY;
309 
310  if (flags & FIELD_IS_DYNAMIC) {
311  unsigned long long tmp_val;
312 
313  tmp_val = pevent_read_number(fmtf->event->pevent,
314  data + offset, len);
315  offset = tmp_val;
316  len = offset >> 16;
317  offset &= 0xffff;
318  }
319 
320  if (flags & 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 & 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 & 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 = pevent_read_number(
357  fmtf->event->pevent,
358  data + offset + i * len, len);
359 
360  if (!(flags & 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 & 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 & 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 
397  struct bt_ctf_event_class *event_class,
398  struct bt_ctf_event *event,
399  struct format_field *fields,
400  struct perf_sample *sample)
401 {
402  struct 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 perf_evsel *evsel,
418  struct perf_sample *sample)
419 {
420  struct format_field *common_fields = evsel->tp_format->format.common_fields;
421  struct 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 perf_evsel *evsel,
589  struct perf_sample *sample)
590 {
591  u64 type = evsel->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 perf_evsel *evsel)
758 {
759  int cpu = 0;
760 
761  if (evsel->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 
787  union perf_event *_event,
788  struct perf_sample *sample,
789  struct perf_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->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->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 
902  __NON_SAMPLE_SET_FIELD(comm, u32, tid);
903  __NON_SAMPLE_SET_FIELD(comm, string, comm);
904 )
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 
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 )
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 )
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 )
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 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 
1012  struct format_field *fields,
1013  struct bt_ctf_event_class *event_class)
1014 {
1015  struct 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 & FIELD_IS_STRING)
1034  flags &= ~FIELD_IS_ARRAY;
1035 
1036  if (flags & 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 & 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 perf_evsel *evsel,
1056  struct bt_ctf_event_class *class)
1057 {
1058  struct format_field *common_fields = evsel->tp_format->format.common_fields;
1059  struct 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 perf_evsel *evsel,
1089  struct bt_ctf_event_class *event_class)
1090 {
1091  u64 type = evsel->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 perf_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->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->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 perf_evlist *evlist = session->evlist;
1206  struct perf_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 
1251  __NON_SAMPLE_ADD_FIELD(u32, tid);
1252  __NON_SAMPLE_ADD_FIELD(string, comm);
1253 )
1254 
1257  __NON_SAMPLE_ADD_FIELD(u32, ppid);
1258  __NON_SAMPLE_ADD_FIELD(u32, tid);
1259  __NON_SAMPLE_ADD_FIELD(u32, ptid);
1261 )
1262 
1265  __NON_SAMPLE_ADD_FIELD(u32, ppid);
1266  __NON_SAMPLE_ADD_FIELD(u32, tid);
1267  __NON_SAMPLE_ADD_FIELD(u32, ptid);
1269 )
1270 
1273  __NON_SAMPLE_ADD_FIELD(u32, tid);
1274  __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1276 )
1277 
1280  __NON_SAMPLE_ADD_FIELD(u32, tid);
1281  __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1283 )
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 
1311 {
1312  struct perf_evlist *evlist = session->evlist;
1313  struct perf_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  perf_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  free(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:
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 {
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 
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  .file.path = input,
1582  .mode = PERF_DATA_MODE_READ,
1583  .force = opts->force,
1584  };
1585  struct convert c = {
1586  .tool = {
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) {
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 (!session)
1624  goto free_writer;
1625 
1626  if (c.queue_size) {
1628  c.queue_size);
1629  }
1630 
1631  /* CTF writer env/clock setup */
1632  if (ctf_writer__setup_env(cw, session))
1633  goto free_session;
1634 
1635  /* CTF events setup */
1636  if (setup_events(cw, session))
1637  goto free_session;
1638 
1639  if (opts->all && setup_non_sample_events(cw, session))
1640  goto free_session;
1641 
1642  if (setup_streams(cw, session))
1643  goto free_session;
1644 
1645  err = perf_session__process_events(session);
1646  if (!err)
1647  err = ctf_writer__flush_streams(cw);
1648  else
1649  pr_err("Error during conversion.\n");
1650 
1651  fprintf(stderr,
1652  "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1653  data.file.path, path);
1654 
1655  fprintf(stderr,
1656  "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1657  (double) c.events_size / 1024.0 / 1024.0,
1658  c.events_count);
1659 
1660  if (!c.non_sample_count)
1661  fprintf(stderr, ") ]\n");
1662  else
1663  fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
1664 
1665  cleanup_events(session);
1666  perf_session__delete(session);
1667  ctf_writer__cleanup(cw);
1668 
1669  return err;
1670 
1671 free_session:
1672  perf_session__delete(session);
1673 free_writer:
1674  ctf_writer__cleanup(cw);
1675  pr_err("Error during conversion setup.\n");
1676  return err;
1677 }
event_op mmap2
Definition: tool.h:47
struct bt_ctf_event_class * comm_class
int value
Definition: python.c:1143
u64 queue_size
static void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
struct perf_evlist * evlist
Definition: session.h:25
static unsigned int hex(char c)
Definition: code-reading.c:33
u64 weight
Definition: event.h:199
struct ordered_events ordered_events
Definition: session.h:35
struct bt_ctf_stream * stream
static int convert__config(const char *var, const char *value, void *cb)
struct bt_ctf_writer * writer
u64 data_src
Definition: event.h:203
size_t size
Definition: evsel.c:60
#define MAX_CPUS
static int add_bpf_output_values(struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, struct perf_sample *sample)
static struct bt_ctf_field_type * get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
static struct ctf_stream * ctf_stream(struct ctf_writer *cw, int cpu)
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1385
struct bt_ctf_field_type * u64_hex
static unsigned long long adjust_signedness(unsigned long long value_int, int size)
const char * filename
Definition: hists_common.c:26
static bool perf_evsel__is_bpf_output(struct perf_evsel *evsel)
Definition: evsel.h:403
#define __NON_SAMPLE_ADD_FIELD(t, n)
dictionary data
Definition: stat-cpi.py:4
struct ip_callchain * callchain
Definition: event.h:211
int int err
Definition: 5sec.c:44
static bool is_flush_needed(struct ctf_stream *cs)
static int add_tracepoint_fields_types(struct ctf_writer *cw, struct format_field *fields, struct bt_ctf_event_class *event_class)
static int input(yyscan_t yyscanner)
static int add_bpf_output_types(struct ctf_writer *cw, struct bt_ctf_event_class *class)
struct perf_data_file file
Definition: data.h:18
struct perf_env env
Definition: header.h:82
void perf_evlist__delete(struct perf_evlist *evlist)
Definition: evlist.c:133
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1273
int perf_event__process_exit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1416
static void cleanup_events(struct perf_session *session)
static int process_exit_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
struct bt_ctf_event_class * event_class
static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, struct perf_evsel *evsel)
static int process_mmap_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
u64 ips[0]
Definition: event.h:137
int perf_event__process_fork(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1408
static void ctf_writer__cleanup(struct ctf_writer *cw)
char * hostname
Definition: env.h:37
int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session)
Definition: header.c:3922
u64 ip
Definition: event.h:192
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
#define pr_err(fmt,...)
Definition: json.h:21
static int ctf_writer__flush_streams(struct ctf_writer *cw)
void perf_session__delete(struct perf_session *session)
Definition: session.c:187
Definition: comm.h:11
static int ctf_stream__flush(struct ctf_stream *cs)
static int ctf_writer__init(struct ctf_writer *cw, const char *path)
static struct ctf_stream * ctf_stream__create(struct ctf_writer *cw, int cpu)
u64 events_count
char * arch
Definition: env.h:40
static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, struct bt_ctf_event_class *event_class)
u64 id
Definition: event.h:196
void * malloc(YYSIZE_T)
struct bt_ctf_event_class * exit_class
struct bt_ctf_field_type * string
#define __NON_SAMPLE_SET_FIELD(_name, _type, _field)
#define STREAM_FLUSH_COUNT
#define ADD_FIELD(cl, t, n)
const char * name
int nr_cpus_avail
Definition: env.h:42
static void ctf_writer__cleanup_data(struct ctf_writer *cw)
char * os_release
Definition: env.h:38
Definition: tool.h:44
static struct perf_session * session
Definition: builtin-lock.c:34
#define evlist__for_each_entry(evlist, evsel)
Definition: evlist.h:247
u64 nr
Definition: event.h:136
struct bt_ctf_field_type * s64
struct bt_ctf_event_class * mmap2_class
struct bt_ctf_event_class * mmap_class
#define SET(__n, __v)
struct bt_ctf_field_type * u32
static int process_sample_event(struct perf_tool *tool, union perf_event *_event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __maybe_unused)
event_op exit
Definition: tool.h:47
static int ctf_writer__setup_env(struct ctf_writer *cw, struct perf_session *session)
static struct perf_tool tool
Definition: builtin-diff.c:362
struct event_format * tp_format
Definition: evsel.h:105
struct ctf_writer writer
u64 period
Definition: event.h:198
u32 pid
Definition: event.h:193
u32 tid
Definition: event.h:193
struct bt_ctf_field_type * array[6]
u64 non_sample_count
Definition: jevents.c:169
int perf_config_u64(u64 *dest, const char *name, const char *value)
Definition: config.c:348
static void free_streams(struct ctf_writer *cw)
static int process_fork_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static int ctf_writer__setup_clock(struct ctf_writer *cw)
struct bt_ctf_field_type * u64
#define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body)
#define event
u32 raw_size
Definition: event.h:202
u32 cpu
Definition: event.h:201
static int process_comm_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: data.h:17
int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session)
Definition: header.c:3854
static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
#define array
#define zfree(ptr)
Definition: util.h:25
static int add_tracepoint_field_value(struct ctf_writer *cw, struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, struct perf_sample *sample, struct format_field *fmtf)
static struct bt_ctf_field_type * create_int_type(int size, bool sign, bool hex)
const char * perf_evsel__name(struct perf_evsel *evsel)
Definition: evsel.c:577
u64 fields
void * raw_data
Definition: event.h:210
struct bt_ctf_stream_class * stream_class
static int string_set_value(struct bt_ctf_field *field, const char *string)
struct perf_event_header header
Definition: event.h:624
u32 pid
Definition: hists_common.c:15
u64 start
Definition: hists_common.c:25
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
Definition: session.c:116
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1393
static int add_tracepoint_types(struct ctf_writer *cw, struct perf_evsel *evsel, struct bt_ctf_event_class *class)
static void ctf_stream__delete(struct ctf_stream *cs)
u64 transaction
Definition: event.h:200
union ctf_writer::@63 data
int perf_config(config_fn_t fn, void *data)
Definition: config.c:718
int perf_session__process_events(struct perf_session *session)
Definition: session.c:1945
static int event_class_add_field(struct bt_ctf_event_class *event_class, struct bt_ctf_field_type *type, struct format_field *field)
static __maybe_unused int value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event, const char *name, const char *string)
struct perf_tool tool
struct bt_ctf_field_type * u32_hex
static int process_mmap2_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
u64 time
Definition: event.h:194
u32 flags
struct bt_ctf_event_class * fork_class
int bt_convert__perf2ctf(const char *input, const char *path, struct perf_data_convert_opts *opts)
u64 events_size
static unsigned int ncpus
Definition: futex-wake.c:45
#define pr2(fmt,...)
struct perf_header header
Definition: session.h:23
static int setup_events(struct ctf_writer *cw, struct perf_session *session)
#define CREATE_INT_TYPE(type, size, sign, hex)
event_op comm
Definition: tool.h:47
struct ctf_stream ** stream
void * priv
Definition: evsel.h:108
void free(void *)
#define isprint(x)
Definition: sane_ctype.h:39
static int add_tracepoint_values(struct ctf_writer *cw, struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, struct perf_evsel *evsel, struct perf_sample *sample)
int perf_event__process_lost(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1289
#define __FUNC_PROCESS_NON_SAMPLE(_name, body)
static int add_generic_values(struct ctf_writer *cw, struct bt_ctf_event *event, struct perf_evsel *evsel, struct perf_sample *sample)
#define __FUNC_VALUE_SET(_name, _val_type)
static int ctf_writer__init_data(struct ctf_writer *cw)
#define pr_warning(fmt,...)
Definition: debug.h:25
static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
event_op fork
Definition: tool.h:47
#define FUNC_VALUE_SET(_name)
u64 stream_id
Definition: event.h:197
static int value_set(struct bt_ctf_field_type *type, struct bt_ctf_event *event, const char *name, u64 val)
event_op mmap
Definition: tool.h:47
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
Definition: event.c:1281
char * version
Definition: env.h:39
struct bt_ctf_clock * clock
struct bt_ctf_field_type * s32
static int add_tracepoint_fields_values(struct ctf_writer *cw, struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, struct format_field *fields, struct perf_sample *sample)
const char * path
Definition: data.h:13
#define pr_time2(t, fmt,...)
struct perf_event_attr attr
Definition: evsel.h:93
#define ADD(__n, __v)
#define pr(fmt,...)
event_sample sample
Definition: tool.h:45
void static void * zalloc(size_t size)
Definition: util.h:20
static int add_callchain_output_values(struct bt_ctf_event_class *event_class, struct bt_ctf_event *event, struct ip_callchain *callchain)