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 <linux/compiler.h>
11 #include <babeltrace/ctf-writer/writer.h>
12 #include <babeltrace/ctf-writer/clock.h>
13 #include <babeltrace/ctf-writer/stream.h>
14 #include <babeltrace/ctf-writer/event.h>
15 #include <babeltrace/ctf-writer/event-types.h>
16 #include <babeltrace/ctf-writer/event-fields.h>
17 #include <babeltrace/ctf/events.h>
18 #include <traceevent/event-parse.h>
19 #include "asm/bug.h"
20 #include "data-convert-bt.h"
21 #include "session.h"
22 #include "util.h"
23 #include "debug.h"
24 #include "tool.h"
25 #include "evlist.h"
26 #include "evsel.h"
27 #include "machine.h"
28 
29 #define pr_N(n, fmt, ...) \
30 	eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
31 
32 #define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
33 #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
34 
35 #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
36 
37 struct evsel_priv {
38 	struct bt_ctf_event_class *event_class;
39 };
40 
41 struct ctf_writer {
42 	/* writer primitives */
43 	struct bt_ctf_writer		*writer;
44 	struct bt_ctf_stream		*stream;
45 	struct bt_ctf_stream_class	*stream_class;
46 	struct bt_ctf_clock		*clock;
47 
48 	/* data types */
49 	union {
50 		struct {
51 			struct bt_ctf_field_type	*s64;
52 			struct bt_ctf_field_type	*u64;
53 			struct bt_ctf_field_type	*s32;
54 			struct bt_ctf_field_type	*u32;
55 			struct bt_ctf_field_type	*string;
56 			struct bt_ctf_field_type	*u64_hex;
57 		};
58 		struct bt_ctf_field_type *array[6];
59 	} data;
60 };
61 
62 struct convert {
63 	struct perf_tool	tool;
64 	struct ctf_writer	writer;
65 
66 	u64			events_size;
67 	u64			events_count;
68 };
69 
70 static int value_set(struct bt_ctf_field_type *type,
71 		     struct bt_ctf_event *event,
72 		     const char *name, u64 val)
73 {
74 	struct bt_ctf_field *field;
75 	bool sign = bt_ctf_field_type_integer_get_signed(type);
76 	int ret;
77 
78 	field = bt_ctf_field_create(type);
79 	if (!field) {
80 		pr_err("failed to create a field %s\n", name);
81 		return -1;
82 	}
83 
84 	if (sign) {
85 		ret = bt_ctf_field_signed_integer_set_value(field, val);
86 		if (ret) {
87 			pr_err("failed to set field value %s\n", name);
88 			goto err;
89 		}
90 	} else {
91 		ret = bt_ctf_field_unsigned_integer_set_value(field, val);
92 		if (ret) {
93 			pr_err("failed to set field value %s\n", name);
94 			goto err;
95 		}
96 	}
97 
98 	ret = bt_ctf_event_set_payload(event, name, field);
99 	if (ret) {
100 		pr_err("failed to set payload %s\n", name);
101 		goto err;
102 	}
103 
104 	pr2("  SET [%s = %" PRIu64 "]\n", name, val);
105 
106 err:
107 	bt_ctf_field_put(field);
108 	return ret;
109 }
110 
111 #define __FUNC_VALUE_SET(_name, _val_type)				\
112 static __maybe_unused int value_set_##_name(struct ctf_writer *cw,	\
113 			     struct bt_ctf_event *event,		\
114 			     const char *name,				\
115 			     _val_type val)				\
116 {									\
117 	struct bt_ctf_field_type *type = cw->data._name;		\
118 	return value_set(type, event, name, (u64) val);			\
119 }
120 
121 #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
122 
123 FUNC_VALUE_SET(s32)
124 FUNC_VALUE_SET(u32)
125 FUNC_VALUE_SET(s64)
126 FUNC_VALUE_SET(u64)
127 __FUNC_VALUE_SET(u64_hex, u64)
128 
129 static struct bt_ctf_field_type*
130 get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
131 {
132 	unsigned long flags = field->flags;
133 
134 	if (flags & FIELD_IS_STRING)
135 		return cw->data.string;
136 
137 	if (!(flags & FIELD_IS_SIGNED)) {
138 		/* unsigned long are mostly pointers */
139 		if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
140 			return cw->data.u64_hex;
141 	}
142 
143 	if (flags & FIELD_IS_SIGNED) {
144 		if (field->size == 8)
145 			return cw->data.s64;
146 		else
147 			return cw->data.s32;
148 	}
149 
150 	if (field->size == 8)
151 		return cw->data.u64;
152 	else
153 		return cw->data.u32;
154 }
155 
156 static int add_tracepoint_field_value(struct ctf_writer *cw,
157 				      struct bt_ctf_event_class *event_class,
158 				      struct bt_ctf_event *event,
159 				      struct perf_sample *sample,
160 				      struct format_field *fmtf)
161 {
162 	struct bt_ctf_field_type *type;
163 	struct bt_ctf_field *array_field;
164 	struct bt_ctf_field *field;
165 	const char *name = fmtf->name;
166 	void *data = sample->raw_data;
167 	unsigned long long value_int;
168 	unsigned long flags = fmtf->flags;
169 	unsigned int n_items;
170 	unsigned int i;
171 	unsigned int offset;
172 	unsigned int len;
173 	int ret;
174 
175 	offset = fmtf->offset;
176 	len = fmtf->size;
177 	if (flags & FIELD_IS_STRING)
178 		flags &= ~FIELD_IS_ARRAY;
179 
180 	if (flags & FIELD_IS_DYNAMIC) {
181 		unsigned long long tmp_val;
182 
183 		tmp_val = pevent_read_number(fmtf->event->pevent,
184 				data + offset, len);
185 		offset = tmp_val;
186 		len = offset >> 16;
187 		offset &= 0xffff;
188 	}
189 
190 	if (flags & FIELD_IS_ARRAY) {
191 
192 		type = bt_ctf_event_class_get_field_by_name(
193 				event_class, name);
194 		array_field = bt_ctf_field_create(type);
195 		bt_ctf_field_type_put(type);
196 		if (!array_field) {
197 			pr_err("Failed to create array type %s\n", name);
198 			return -1;
199 		}
200 
201 		len = fmtf->size / fmtf->arraylen;
202 		n_items = fmtf->arraylen;
203 	} else {
204 		n_items = 1;
205 		array_field = NULL;
206 	}
207 
208 	type = get_tracepoint_field_type(cw, fmtf);
209 
210 	for (i = 0; i < n_items; i++) {
211 		if (!(flags & FIELD_IS_STRING))
212 			value_int = pevent_read_number(
213 					fmtf->event->pevent,
214 					data + offset + i * len, len);
215 
216 		if (flags & FIELD_IS_ARRAY)
217 			field = bt_ctf_field_array_get_field(array_field, i);
218 		else
219 			field = bt_ctf_field_create(type);
220 
221 		if (!field) {
222 			pr_err("failed to create a field %s\n", name);
223 			return -1;
224 		}
225 
226 		if (flags & FIELD_IS_STRING)
227 			ret = bt_ctf_field_string_set_value(field,
228 					data + offset + i * len);
229 		else if (!(flags & FIELD_IS_SIGNED))
230 			ret = bt_ctf_field_unsigned_integer_set_value(
231 					field, value_int);
232 		else
233 			ret = bt_ctf_field_signed_integer_set_value(
234 					field, value_int);
235 		if (ret) {
236 			pr_err("failed to set file value %s\n", name);
237 			goto err_put_field;
238 		}
239 		if (!(flags & FIELD_IS_ARRAY)) {
240 			ret = bt_ctf_event_set_payload(event, name, field);
241 			if (ret) {
242 				pr_err("failed to set payload %s\n", name);
243 				goto err_put_field;
244 			}
245 		}
246 		bt_ctf_field_put(field);
247 	}
248 	if (flags & FIELD_IS_ARRAY) {
249 		ret = bt_ctf_event_set_payload(event, name, array_field);
250 		if (ret) {
251 			pr_err("Failed add payload array %s\n", name);
252 			return -1;
253 		}
254 		bt_ctf_field_put(array_field);
255 	}
256 	return 0;
257 
258 err_put_field:
259 	bt_ctf_field_put(field);
260 	return -1;
261 }
262 
263 static int add_tracepoint_fields_values(struct ctf_writer *cw,
264 					struct bt_ctf_event_class *event_class,
265 					struct bt_ctf_event *event,
266 					struct format_field *fields,
267 					struct perf_sample *sample)
268 {
269 	struct format_field *field;
270 	int ret;
271 
272 	for (field = fields; field; field = field->next) {
273 		ret = add_tracepoint_field_value(cw, event_class, event, sample,
274 				field);
275 		if (ret)
276 			return -1;
277 	}
278 	return 0;
279 }
280 
281 static int add_tracepoint_values(struct ctf_writer *cw,
282 				 struct bt_ctf_event_class *event_class,
283 				 struct bt_ctf_event *event,
284 				 struct perf_evsel *evsel,
285 				 struct perf_sample *sample)
286 {
287 	struct format_field *common_fields = evsel->tp_format->format.common_fields;
288 	struct format_field *fields        = evsel->tp_format->format.fields;
289 	int ret;
290 
291 	ret = add_tracepoint_fields_values(cw, event_class, event,
292 					   common_fields, sample);
293 	if (!ret)
294 		ret = add_tracepoint_fields_values(cw, event_class, event,
295 						   fields, sample);
296 
297 	return ret;
298 }
299 
300 static int add_generic_values(struct ctf_writer *cw,
301 			      struct bt_ctf_event *event,
302 			      struct perf_evsel *evsel,
303 			      struct perf_sample *sample)
304 {
305 	u64 type = evsel->attr.sample_type;
306 	int ret;
307 
308 	/*
309 	 * missing:
310 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
311 	 *                              ctf event header
312 	 *   PERF_SAMPLE_READ         - TODO
313 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
314 	 *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
315 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
316 	 *   PERF_SAMPLE_REGS_USER    - TODO
317 	 *   PERF_SAMPLE_STACK_USER   - TODO
318 	 */
319 
320 	if (type & PERF_SAMPLE_IP) {
321 		ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
322 		if (ret)
323 			return -1;
324 	}
325 
326 	if (type & PERF_SAMPLE_TID) {
327 		ret = value_set_s32(cw, event, "perf_tid", sample->tid);
328 		if (ret)
329 			return -1;
330 
331 		ret = value_set_s32(cw, event, "perf_pid", sample->pid);
332 		if (ret)
333 			return -1;
334 	}
335 
336 	if ((type & PERF_SAMPLE_ID) ||
337 	    (type & PERF_SAMPLE_IDENTIFIER)) {
338 		ret = value_set_u64(cw, event, "perf_id", sample->id);
339 		if (ret)
340 			return -1;
341 	}
342 
343 	if (type & PERF_SAMPLE_STREAM_ID) {
344 		ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
345 		if (ret)
346 			return -1;
347 	}
348 
349 	if (type & PERF_SAMPLE_CPU) {
350 		ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
351 		if (ret)
352 			return -1;
353 	}
354 
355 	if (type & PERF_SAMPLE_PERIOD) {
356 		ret = value_set_u64(cw, event, "perf_period", sample->period);
357 		if (ret)
358 			return -1;
359 	}
360 
361 	if (type & PERF_SAMPLE_WEIGHT) {
362 		ret = value_set_u64(cw, event, "perf_weight", sample->weight);
363 		if (ret)
364 			return -1;
365 	}
366 
367 	if (type & PERF_SAMPLE_DATA_SRC) {
368 		ret = value_set_u64(cw, event, "perf_data_src",
369 				sample->data_src);
370 		if (ret)
371 			return -1;
372 	}
373 
374 	if (type & PERF_SAMPLE_TRANSACTION) {
375 		ret = value_set_u64(cw, event, "perf_transaction",
376 				sample->transaction);
377 		if (ret)
378 			return -1;
379 	}
380 
381 	return 0;
382 }
383 
384 static int process_sample_event(struct perf_tool *tool,
385 				union perf_event *_event __maybe_unused,
386 				struct perf_sample *sample,
387 				struct perf_evsel *evsel,
388 				struct machine *machine __maybe_unused)
389 {
390 	struct convert *c = container_of(tool, struct convert, tool);
391 	struct evsel_priv *priv = evsel->priv;
392 	struct ctf_writer *cw = &c->writer;
393 	struct bt_ctf_event_class *event_class;
394 	struct bt_ctf_event *event;
395 	int ret;
396 
397 	if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
398 		return 0;
399 
400 	event_class = priv->event_class;
401 
402 	/* update stats */
403 	c->events_count++;
404 	c->events_size += _event->header.size;
405 
406 	pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
407 
408 	event = bt_ctf_event_create(event_class);
409 	if (!event) {
410 		pr_err("Failed to create an CTF event\n");
411 		return -1;
412 	}
413 
414 	bt_ctf_clock_set_time(cw->clock, sample->time);
415 
416 	ret = add_generic_values(cw, event, evsel, sample);
417 	if (ret)
418 		return -1;
419 
420 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
421 		ret = add_tracepoint_values(cw, event_class, event,
422 					    evsel, sample);
423 		if (ret)
424 			return -1;
425 	}
426 
427 	bt_ctf_stream_append_event(cw->stream, event);
428 	bt_ctf_event_put(event);
429 	return 0;
430 }
431 
432 static int add_tracepoint_fields_types(struct ctf_writer *cw,
433 				       struct format_field *fields,
434 				       struct bt_ctf_event_class *event_class)
435 {
436 	struct format_field *field;
437 	int ret;
438 
439 	for (field = fields; field; field = field->next) {
440 		struct bt_ctf_field_type *type;
441 		unsigned long flags = field->flags;
442 
443 		pr2("  field '%s'\n", field->name);
444 
445 		type = get_tracepoint_field_type(cw, field);
446 		if (!type)
447 			return -1;
448 
449 		/*
450 		 * A string is an array of chars. For this we use the string
451 		 * type and don't care that it is an array. What we don't
452 		 * support is an array of strings.
453 		 */
454 		if (flags & FIELD_IS_STRING)
455 			flags &= ~FIELD_IS_ARRAY;
456 
457 		if (flags & FIELD_IS_ARRAY)
458 			type = bt_ctf_field_type_array_create(type, field->arraylen);
459 
460 		ret = bt_ctf_event_class_add_field(event_class, type,
461 				field->name);
462 
463 		if (flags & FIELD_IS_ARRAY)
464 			bt_ctf_field_type_put(type);
465 
466 		if (ret) {
467 			pr_err("Failed to add field '%s\n", field->name);
468 			return -1;
469 		}
470 	}
471 
472 	return 0;
473 }
474 
475 static int add_tracepoint_types(struct ctf_writer *cw,
476 				struct perf_evsel *evsel,
477 				struct bt_ctf_event_class *class)
478 {
479 	struct format_field *common_fields = evsel->tp_format->format.common_fields;
480 	struct format_field *fields        = evsel->tp_format->format.fields;
481 	int ret;
482 
483 	ret = add_tracepoint_fields_types(cw, common_fields, class);
484 	if (!ret)
485 		ret = add_tracepoint_fields_types(cw, fields, class);
486 
487 	return ret;
488 }
489 
490 static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
491 			     struct bt_ctf_event_class *event_class)
492 {
493 	u64 type = evsel->attr.sample_type;
494 
495 	/*
496 	 * missing:
497 	 *   PERF_SAMPLE_TIME         - not needed as we have it in
498 	 *                              ctf event header
499 	 *   PERF_SAMPLE_READ         - TODO
500 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
501 	 *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
502 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
503 	 *   PERF_SAMPLE_REGS_USER    - TODO
504 	 *   PERF_SAMPLE_STACK_USER   - TODO
505 	 */
506 
507 #define ADD_FIELD(cl, t, n)						\
508 	do {								\
509 		pr2("  field '%s'\n", n);				\
510 		if (bt_ctf_event_class_add_field(cl, t, n)) {		\
511 			pr_err("Failed to add field '%s;\n", n);	\
512 			return -1;					\
513 		}							\
514 	} while (0)
515 
516 	if (type & PERF_SAMPLE_IP)
517 		ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
518 
519 	if (type & PERF_SAMPLE_TID) {
520 		ADD_FIELD(event_class, cw->data.s32, "perf_tid");
521 		ADD_FIELD(event_class, cw->data.s32, "perf_pid");
522 	}
523 
524 	if ((type & PERF_SAMPLE_ID) ||
525 	    (type & PERF_SAMPLE_IDENTIFIER))
526 		ADD_FIELD(event_class, cw->data.u64, "perf_id");
527 
528 	if (type & PERF_SAMPLE_STREAM_ID)
529 		ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
530 
531 	if (type & PERF_SAMPLE_CPU)
532 		ADD_FIELD(event_class, cw->data.u32, "perf_cpu");
533 
534 	if (type & PERF_SAMPLE_PERIOD)
535 		ADD_FIELD(event_class, cw->data.u64, "perf_period");
536 
537 	if (type & PERF_SAMPLE_WEIGHT)
538 		ADD_FIELD(event_class, cw->data.u64, "perf_weight");
539 
540 	if (type & PERF_SAMPLE_DATA_SRC)
541 		ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
542 
543 	if (type & PERF_SAMPLE_TRANSACTION)
544 		ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
545 
546 #undef ADD_FIELD
547 	return 0;
548 }
549 
550 static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
551 {
552 	struct bt_ctf_event_class *event_class;
553 	struct evsel_priv *priv;
554 	const char *name = perf_evsel__name(evsel);
555 	int ret;
556 
557 	pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
558 
559 	event_class = bt_ctf_event_class_create(name);
560 	if (!event_class)
561 		return -1;
562 
563 	ret = add_generic_types(cw, evsel, event_class);
564 	if (ret)
565 		goto err;
566 
567 	if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
568 		ret = add_tracepoint_types(cw, evsel, event_class);
569 		if (ret)
570 			goto err;
571 	}
572 
573 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
574 	if (ret) {
575 		pr("Failed to add event class into stream.\n");
576 		goto err;
577 	}
578 
579 	priv = malloc(sizeof(*priv));
580 	if (!priv)
581 		goto err;
582 
583 	priv->event_class = event_class;
584 	evsel->priv       = priv;
585 	return 0;
586 
587 err:
588 	bt_ctf_event_class_put(event_class);
589 	pr_err("Failed to add event '%s'.\n", name);
590 	return -1;
591 }
592 
593 static int setup_events(struct ctf_writer *cw, struct perf_session *session)
594 {
595 	struct perf_evlist *evlist = session->evlist;
596 	struct perf_evsel *evsel;
597 	int ret;
598 
599 	evlist__for_each(evlist, evsel) {
600 		ret = add_event(cw, evsel);
601 		if (ret)
602 			return ret;
603 	}
604 	return 0;
605 }
606 
607 static int ctf_writer__setup_env(struct ctf_writer *cw,
608 				 struct perf_session *session)
609 {
610 	struct perf_header *header = &session->header;
611 	struct bt_ctf_writer *writer = cw->writer;
612 
613 #define ADD(__n, __v)							\
614 do {									\
615 	if (bt_ctf_writer_add_environment_field(writer, __n, __v))	\
616 		return -1;						\
617 } while (0)
618 
619 	ADD("host",    header->env.hostname);
620 	ADD("sysname", "Linux");
621 	ADD("release", header->env.os_release);
622 	ADD("version", header->env.version);
623 	ADD("machine", header->env.arch);
624 	ADD("domain", "kernel");
625 	ADD("tracer_name", "perf");
626 
627 #undef ADD
628 	return 0;
629 }
630 
631 static int ctf_writer__setup_clock(struct ctf_writer *cw)
632 {
633 	struct bt_ctf_clock *clock = cw->clock;
634 
635 	bt_ctf_clock_set_description(clock, "perf clock");
636 
637 #define SET(__n, __v)				\
638 do {						\
639 	if (bt_ctf_clock_set_##__n(clock, __v))	\
640 		return -1;			\
641 } while (0)
642 
643 	SET(frequency,   1000000000);
644 	SET(offset_s,    0);
645 	SET(offset,      0);
646 	SET(precision,   10);
647 	SET(is_absolute, 0);
648 
649 #undef SET
650 	return 0;
651 }
652 
653 static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
654 {
655 	struct bt_ctf_field_type *type;
656 
657 	type = bt_ctf_field_type_integer_create(size);
658 	if (!type)
659 		return NULL;
660 
661 	if (sign &&
662 	    bt_ctf_field_type_integer_set_signed(type, 1))
663 		goto err;
664 
665 	if (hex &&
666 	    bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
667 		goto err;
668 
669 	pr2("Created type: INTEGER %d-bit %ssigned %s\n",
670 	    size, sign ? "un" : "", hex ? "hex" : "");
671 	return type;
672 
673 err:
674 	bt_ctf_field_type_put(type);
675 	return NULL;
676 }
677 
678 static void ctf_writer__cleanup_data(struct ctf_writer *cw)
679 {
680 	unsigned int i;
681 
682 	for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
683 		bt_ctf_field_type_put(cw->data.array[i]);
684 }
685 
686 static int ctf_writer__init_data(struct ctf_writer *cw)
687 {
688 #define CREATE_INT_TYPE(type, size, sign, hex)		\
689 do {							\
690 	(type) = create_int_type(size, sign, hex);	\
691 	if (!(type))					\
692 		goto err;				\
693 } while (0)
694 
695 	CREATE_INT_TYPE(cw->data.s64, 64, true,  false);
696 	CREATE_INT_TYPE(cw->data.u64, 64, false, false);
697 	CREATE_INT_TYPE(cw->data.s32, 32, true,  false);
698 	CREATE_INT_TYPE(cw->data.u32, 32, false, false);
699 	CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
700 
701 	cw->data.string  = bt_ctf_field_type_string_create();
702 	if (cw->data.string)
703 		return 0;
704 
705 err:
706 	ctf_writer__cleanup_data(cw);
707 	pr_err("Failed to create data types.\n");
708 	return -1;
709 }
710 
711 static void ctf_writer__cleanup(struct ctf_writer *cw)
712 {
713 	ctf_writer__cleanup_data(cw);
714 
715 	bt_ctf_clock_put(cw->clock);
716 	bt_ctf_stream_put(cw->stream);
717 	bt_ctf_stream_class_put(cw->stream_class);
718 	bt_ctf_writer_put(cw->writer);
719 
720 	/* and NULL all the pointers */
721 	memset(cw, 0, sizeof(*cw));
722 }
723 
724 static int ctf_writer__init(struct ctf_writer *cw, const char *path)
725 {
726 	struct bt_ctf_writer		*writer;
727 	struct bt_ctf_stream_class	*stream_class;
728 	struct bt_ctf_stream		*stream;
729 	struct bt_ctf_clock		*clock;
730 
731 	/* CTF writer */
732 	writer = bt_ctf_writer_create(path);
733 	if (!writer)
734 		goto err;
735 
736 	cw->writer = writer;
737 
738 	/* CTF clock */
739 	clock = bt_ctf_clock_create("perf_clock");
740 	if (!clock) {
741 		pr("Failed to create CTF clock.\n");
742 		goto err_cleanup;
743 	}
744 
745 	cw->clock = clock;
746 
747 	if (ctf_writer__setup_clock(cw)) {
748 		pr("Failed to setup CTF clock.\n");
749 		goto err_cleanup;
750 	}
751 
752 	/* CTF stream class */
753 	stream_class = bt_ctf_stream_class_create("perf_stream");
754 	if (!stream_class) {
755 		pr("Failed to create CTF stream class.\n");
756 		goto err_cleanup;
757 	}
758 
759 	cw->stream_class = stream_class;
760 
761 	/* CTF clock stream setup */
762 	if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
763 		pr("Failed to assign CTF clock to stream class.\n");
764 		goto err_cleanup;
765 	}
766 
767 	if (ctf_writer__init_data(cw))
768 		goto err_cleanup;
769 
770 	/* CTF stream instance */
771 	stream = bt_ctf_writer_create_stream(writer, stream_class);
772 	if (!stream) {
773 		pr("Failed to create CTF stream.\n");
774 		goto err_cleanup;
775 	}
776 
777 	cw->stream = stream;
778 
779 	/* CTF clock writer setup */
780 	if (bt_ctf_writer_add_clock(writer, clock)) {
781 		pr("Failed to assign CTF clock to writer.\n");
782 		goto err_cleanup;
783 	}
784 
785 	return 0;
786 
787 err_cleanup:
788 	ctf_writer__cleanup(cw);
789 err:
790 	pr_err("Failed to setup CTF writer.\n");
791 	return -1;
792 }
793 
794 int bt_convert__perf2ctf(const char *input, const char *path, bool force)
795 {
796 	struct perf_session *session;
797 	struct perf_data_file file = {
798 		.path = input,
799 		.mode = PERF_DATA_MODE_READ,
800 		.force = force,
801 	};
802 	struct convert c = {
803 		.tool = {
804 			.sample          = process_sample_event,
805 			.mmap            = perf_event__process_mmap,
806 			.mmap2           = perf_event__process_mmap2,
807 			.comm            = perf_event__process_comm,
808 			.exit            = perf_event__process_exit,
809 			.fork            = perf_event__process_fork,
810 			.lost            = perf_event__process_lost,
811 			.tracing_data    = perf_event__process_tracing_data,
812 			.build_id        = perf_event__process_build_id,
813 			.ordered_events  = true,
814 			.ordering_requires_timestamps = true,
815 		},
816 	};
817 	struct ctf_writer *cw = &c.writer;
818 	int err = -1;
819 
820 	/* CTF writer */
821 	if (ctf_writer__init(cw, path))
822 		return -1;
823 
824 	/* perf.data session */
825 	session = perf_session__new(&file, 0, &c.tool);
826 	if (!session)
827 		goto free_writer;
828 
829 	/* CTF writer env/clock setup  */
830 	if (ctf_writer__setup_env(cw, session))
831 		goto free_session;
832 
833 	/* CTF events setup */
834 	if (setup_events(cw, session))
835 		goto free_session;
836 
837 	err = perf_session__process_events(session);
838 	if (!err)
839 		err = bt_ctf_stream_flush(cw->stream);
840 
841 	fprintf(stderr,
842 		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
843 		file.path, path);
844 
845 	fprintf(stderr,
846 		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
847 		(double) c.events_size / 1024.0 / 1024.0,
848 		c.events_count);
849 
850 	/* its all good */
851 free_session:
852 	perf_session__delete(session);
853 
854 free_writer:
855 	ctf_writer__cleanup(cw);
856 	return err;
857 }
858