Common Trace Format 2 generation
[deliverable/lttng-modules.git] / src / ctf1-8.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * src/ctf1-8.c
4 *
5 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com>
7 */
8
9 #include <linux/dmi.h>
10 #include <linux/utsname.h>
11 #include <linux/ktime.h>
12 #include <linux/timekeeping.h>
13
14 #include <lttng/events.h>
15 #include <lttng/events-internal.h>
16
17 #include "metadata-printer.h"
18 #include "clock-utils.h"
19
20 static
21 int _lttng_field_statedump(struct lttng_kernel_session *session,
22 const struct lttng_kernel_event_field *field,
23 size_t nesting, const char **prev_field_name_p);
24
25 static
26 int _lttng_type_statedump(struct lttng_kernel_session *session,
27 const struct lttng_kernel_type_common *type,
28 enum lttng_kernel_string_encoding parent_encoding,
29 size_t nesting);
30
31 static
32 int print_tabs(struct lttng_kernel_session *session, size_t nesting)
33 {
34 size_t i;
35
36 for (i = 0; i < nesting; i++) {
37 int ret;
38
39 ret = lttng_metadata_printf(session, " ");
40 if (ret) {
41 return ret;
42 }
43 }
44 return 0;
45 }
46
47 static
48 int lttng_field_name_statedump(struct lttng_kernel_session *session,
49 const struct lttng_kernel_event_field *field,
50 size_t nesting)
51 {
52 return lttng_metadata_printf(session, " _%s;\n", field->name);
53 }
54
55 static
56 int _lttng_integer_type_statedump(struct lttng_kernel_session *session,
57 const struct lttng_kernel_type_integer *type,
58 enum lttng_kernel_string_encoding parent_encoding,
59 size_t nesting)
60 {
61 int ret;
62
63 ret = print_tabs(session, nesting);
64 if (ret)
65 return ret;
66 ret = lttng_metadata_printf(session,
67 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s }",
68 type->size,
69 type->alignment,
70 type->signedness,
71 (parent_encoding == lttng_kernel_string_encoding_none)
72 ? "none"
73 : (parent_encoding == lttng_kernel_string_encoding_UTF8)
74 ? "UTF8"
75 : "ASCII",
76 type->base,
77 #if __BYTE_ORDER == __BIG_ENDIAN
78 type->reverse_byte_order ? " byte_order = le;" : ""
79 #else
80 type->reverse_byte_order ? " byte_order = be;" : ""
81 #endif
82 );
83 return ret;
84 }
85
86 /*
87 * Must be called with sessions_mutex held.
88 */
89 static
90 int _lttng_struct_type_statedump(struct lttng_kernel_session *session,
91 const struct lttng_kernel_type_struct *type,
92 size_t nesting)
93 {
94 const char *prev_field_name = NULL;
95 int ret;
96 uint32_t i, nr_fields;
97 unsigned int alignment;
98
99 ret = print_tabs(session, nesting);
100 if (ret)
101 return ret;
102 ret = lttng_metadata_printf(session,
103 "struct {\n");
104 if (ret)
105 return ret;
106 nr_fields = type->nr_fields;
107 for (i = 0; i < nr_fields; i++) {
108 const struct lttng_kernel_event_field *iter_field;
109
110 iter_field = type->fields[i];
111 ret = _lttng_field_statedump(session, iter_field, nesting + 1, &prev_field_name);
112 if (ret)
113 return ret;
114 }
115 ret = print_tabs(session, nesting);
116 if (ret)
117 return ret;
118 alignment = type->alignment;
119 if (alignment) {
120 ret = lttng_metadata_printf(session,
121 "} align(%u)",
122 alignment);
123 } else {
124 ret = lttng_metadata_printf(session,
125 "}");
126 }
127 return ret;
128 }
129
130 /*
131 * Must be called with sessions_mutex held.
132 */
133 static
134 int _lttng_struct_field_statedump(struct lttng_kernel_session *session,
135 const struct lttng_kernel_event_field *field,
136 size_t nesting)
137 {
138 int ret;
139
140 ret = _lttng_struct_type_statedump(session,
141 lttng_kernel_get_type_struct(field->type), nesting);
142 if (ret)
143 return ret;
144 return lttng_field_name_statedump(session, field, nesting);
145 }
146
147 /*
148 * Must be called with sessions_mutex held.
149 */
150 static
151 int _lttng_variant_type_statedump(struct lttng_kernel_session *session,
152 const struct lttng_kernel_type_variant *type,
153 size_t nesting,
154 const char *prev_field_name)
155 {
156 const char *tag_name;
157 int ret;
158 uint32_t i, nr_choices;
159
160 tag_name = type->tag_name;
161 if (!tag_name)
162 tag_name = prev_field_name;
163 if (!tag_name)
164 return -EINVAL;
165 /*
166 * CTF 1.8 does not allow expressing nonzero variant alignment in a nestable way.
167 */
168 if (type->alignment != 0)
169 return -EINVAL;
170 ret = print_tabs(session, nesting);
171 if (ret)
172 return ret;
173 ret = lttng_metadata_printf(session,
174 "variant <_%s> {\n",
175 tag_name);
176 if (ret)
177 return ret;
178 nr_choices = type->nr_choices;
179 for (i = 0; i < nr_choices; i++) {
180 const struct lttng_kernel_event_field *iter_field;
181
182 iter_field = type->choices[i];
183 ret = _lttng_field_statedump(session, iter_field, nesting + 1, NULL);
184 if (ret)
185 return ret;
186 }
187 ret = print_tabs(session, nesting);
188 if (ret)
189 return ret;
190 ret = lttng_metadata_printf(session,
191 "}");
192 return ret;
193 }
194
195 /*
196 * Must be called with sessions_mutex held.
197 */
198 static
199 int _lttng_variant_field_statedump(struct lttng_kernel_session *session,
200 const struct lttng_kernel_event_field *field,
201 size_t nesting,
202 const char *prev_field_name)
203 {
204 int ret;
205
206 ret = _lttng_variant_type_statedump(session,
207 lttng_kernel_get_type_variant(field->type), nesting,
208 prev_field_name);
209 if (ret)
210 return ret;
211 return lttng_field_name_statedump(session, field, nesting);
212 }
213
214 /*
215 * Must be called with sessions_mutex held.
216 */
217 static
218 int _lttng_array_field_statedump(struct lttng_kernel_session *session,
219 const struct lttng_kernel_event_field *field,
220 size_t nesting)
221 {
222 int ret;
223 const struct lttng_kernel_type_array *array_type;
224 const struct lttng_kernel_type_common *elem_type;
225
226 array_type = lttng_kernel_get_type_array(field->type);
227 WARN_ON_ONCE(!array_type);
228
229 if (array_type->alignment) {
230 ret = print_tabs(session, nesting);
231 if (ret)
232 return ret;
233 ret = lttng_metadata_printf(session,
234 "struct { } align(%u) _%s_padding;\n",
235 array_type->alignment * CHAR_BIT,
236 field->name);
237 if (ret)
238 return ret;
239 }
240 /*
241 * Nested compound types: Only array of structures and variants are
242 * currently supported.
243 */
244 elem_type = array_type->elem_type;
245 switch (elem_type->type) {
246 case lttng_kernel_type_integer:
247 case lttng_kernel_type_struct:
248 case lttng_kernel_type_variant:
249 ret = _lttng_type_statedump(session, elem_type,
250 array_type->encoding, nesting);
251 if (ret)
252 return ret;
253 break;
254
255 default:
256 return -EINVAL;
257 }
258 ret = lttng_metadata_printf(session,
259 " _%s[%u];\n",
260 field->name,
261 array_type->length);
262 return ret;
263 }
264
265 /*
266 * Must be called with sessions_mutex held.
267 */
268 static
269 int _lttng_sequence_field_statedump(struct lttng_kernel_session *session,
270 const struct lttng_kernel_event_field *field,
271 size_t nesting,
272 const char *prev_field_name)
273 {
274 int ret;
275 const char *length_name;
276 const struct lttng_kernel_type_sequence *sequence_type;
277 const struct lttng_kernel_type_common *elem_type;
278
279 sequence_type = lttng_kernel_get_type_sequence(field->type);
280 WARN_ON_ONCE(!sequence_type);
281
282 length_name = sequence_type->length_name;
283 if (!length_name)
284 length_name = prev_field_name;
285 if (!length_name)
286 return -EINVAL;
287
288 if (sequence_type->alignment) {
289 ret = print_tabs(session, nesting);
290 if (ret)
291 return ret;
292 ret = lttng_metadata_printf(session,
293 "struct { } align(%u) _%s_padding;\n",
294 sequence_type->alignment * CHAR_BIT,
295 field->name);
296 if (ret)
297 return ret;
298 }
299
300 /*
301 * Nested compound types: Only array of structures and variants are
302 * currently supported.
303 */
304 elem_type = sequence_type->elem_type;
305 switch (elem_type->type) {
306 case lttng_kernel_type_integer:
307 case lttng_kernel_type_struct:
308 case lttng_kernel_type_variant:
309 ret = _lttng_type_statedump(session, elem_type,
310 sequence_type->encoding, nesting);
311 if (ret)
312 return ret;
313 break;
314
315 default:
316 return -EINVAL;
317 }
318 ret = lttng_metadata_printf(session,
319 " _%s[ _%s ];\n",
320 field->name,
321 length_name);
322 return ret;
323 }
324
325 /*
326 * Must be called with sessions_mutex held.
327 */
328 static
329 int _lttng_enum_type_statedump(struct lttng_kernel_session *session,
330 const struct lttng_kernel_type_enum *type,
331 size_t nesting)
332 {
333 const struct lttng_kernel_enum_desc *enum_desc;
334 const struct lttng_kernel_type_common *container_type;
335 int ret;
336 unsigned int i, nr_entries;
337
338 container_type = type->container_type;
339 if (container_type->type != lttng_kernel_type_integer) {
340 ret = -EINVAL;
341 goto end;
342 }
343 enum_desc = type->desc;
344 nr_entries = enum_desc->nr_entries;
345
346 ret = print_tabs(session, nesting);
347 if (ret)
348 goto end;
349 ret = lttng_metadata_printf(session, "enum : ");
350 if (ret)
351 goto end;
352 ret = _lttng_integer_type_statedump(session, lttng_kernel_get_type_integer(container_type),
353 lttng_kernel_string_encoding_none, 0);
354 if (ret)
355 goto end;
356 ret = lttng_metadata_printf(session, " {\n");
357 if (ret)
358 goto end;
359 /* Dump all entries */
360 for (i = 0; i < nr_entries; i++) {
361 const struct lttng_kernel_enum_entry *entry = enum_desc->entries[i];
362 int j, len;
363
364 ret = print_tabs(session, nesting + 1);
365 if (ret)
366 goto end;
367 ret = lttng_metadata_printf(session,
368 "\"");
369 if (ret)
370 goto end;
371 len = strlen(entry->string);
372 /* Escape the character '"' */
373 for (j = 0; j < len; j++) {
374 char c = entry->string[j];
375
376 switch (c) {
377 case '"':
378 ret = lttng_metadata_printf(session,
379 "\\\"");
380 break;
381 case '\\':
382 ret = lttng_metadata_printf(session,
383 "\\\\");
384 break;
385 default:
386 ret = lttng_metadata_printf(session,
387 "%c", c);
388 break;
389 }
390 if (ret)
391 goto end;
392 }
393 ret = lttng_metadata_printf(session, "\"");
394 if (ret)
395 goto end;
396
397 if (entry->options.is_auto) {
398 ret = lttng_metadata_printf(session, ",\n");
399 if (ret)
400 goto end;
401 } else {
402 ret = lttng_metadata_printf(session,
403 " = ");
404 if (ret)
405 goto end;
406 if (entry->start.signedness)
407 ret = lttng_metadata_printf(session,
408 "%lld", (long long) entry->start.value);
409 else
410 ret = lttng_metadata_printf(session,
411 "%llu", entry->start.value);
412 if (ret)
413 goto end;
414 if (entry->start.signedness == entry->end.signedness &&
415 entry->start.value
416 == entry->end.value) {
417 ret = lttng_metadata_printf(session,
418 ",\n");
419 } else {
420 if (entry->end.signedness) {
421 ret = lttng_metadata_printf(session,
422 " ... %lld,\n",
423 (long long) entry->end.value);
424 } else {
425 ret = lttng_metadata_printf(session,
426 " ... %llu,\n",
427 entry->end.value);
428 }
429 }
430 if (ret)
431 goto end;
432 }
433 }
434 ret = print_tabs(session, nesting);
435 if (ret)
436 goto end;
437 ret = lttng_metadata_printf(session, "}");
438 end:
439 return ret;
440 }
441
442 /*
443 * Must be called with sessions_mutex held.
444 */
445 static
446 int _lttng_enum_field_statedump(struct lttng_kernel_session *session,
447 const struct lttng_kernel_event_field *field,
448 size_t nesting)
449 {
450 int ret;
451 const struct lttng_kernel_type_enum *enum_type;
452
453 enum_type = lttng_kernel_get_type_enum(field->type);
454 WARN_ON_ONCE(!enum_type);
455 ret = _lttng_enum_type_statedump(session, enum_type, nesting);
456 if (ret)
457 return ret;
458 return lttng_field_name_statedump(session, field, nesting);
459 }
460
461 static
462 int _lttng_integer_field_statedump(struct lttng_kernel_session *session,
463 const struct lttng_kernel_event_field *field,
464 size_t nesting)
465 {
466 int ret;
467
468 ret = _lttng_integer_type_statedump(session, lttng_kernel_get_type_integer(field->type),
469 lttng_kernel_string_encoding_none, nesting);
470 if (ret)
471 return ret;
472 return lttng_field_name_statedump(session, field, nesting);
473 }
474
475 static
476 int _lttng_string_type_statedump(struct lttng_kernel_session *session,
477 const struct lttng_kernel_type_string *type,
478 size_t nesting)
479 {
480 int ret;
481
482 /* Default encoding is UTF8 */
483 ret = print_tabs(session, nesting);
484 if (ret)
485 return ret;
486 ret = lttng_metadata_printf(session,
487 "string%s",
488 type->encoding == lttng_kernel_string_encoding_ASCII ?
489 " { encoding = ASCII; }" : "");
490 return ret;
491 }
492
493 static
494 int _lttng_string_field_statedump(struct lttng_kernel_session *session,
495 const struct lttng_kernel_event_field *field,
496 size_t nesting)
497 {
498 const struct lttng_kernel_type_string *string_type;
499 int ret;
500
501 string_type = lttng_kernel_get_type_string(field->type);
502 WARN_ON_ONCE(!string_type);
503 ret = _lttng_string_type_statedump(session, string_type, nesting);
504 if (ret)
505 return ret;
506 return lttng_field_name_statedump(session, field, nesting);
507 }
508
509 /*
510 * Must be called with sessions_mutex held.
511 */
512 static
513 int _lttng_type_statedump(struct lttng_kernel_session *session,
514 const struct lttng_kernel_type_common *type,
515 enum lttng_kernel_string_encoding parent_encoding,
516 size_t nesting)
517 {
518 int ret = 0;
519
520 switch (type->type) {
521 case lttng_kernel_type_integer:
522 ret = _lttng_integer_type_statedump(session,
523 lttng_kernel_get_type_integer(type),
524 parent_encoding, nesting);
525 break;
526 case lttng_kernel_type_enum:
527 ret = _lttng_enum_type_statedump(session,
528 lttng_kernel_get_type_enum(type),
529 nesting);
530 break;
531 case lttng_kernel_type_string:
532 ret = _lttng_string_type_statedump(session,
533 lttng_kernel_get_type_string(type),
534 nesting);
535 break;
536 case lttng_kernel_type_struct:
537 ret = _lttng_struct_type_statedump(session,
538 lttng_kernel_get_type_struct(type),
539 nesting);
540 break;
541 case lttng_kernel_type_variant:
542 ret = _lttng_variant_type_statedump(session,
543 lttng_kernel_get_type_variant(type),
544 nesting, NULL);
545 break;
546
547 /* Nested arrays and sequences are not supported yet. */
548 case lttng_kernel_type_array:
549 case lttng_kernel_type_sequence:
550 default:
551 WARN_ON_ONCE(1);
552 return -EINVAL;
553 }
554 return ret;
555 }
556
557 /*
558 * Must be called with sessions_mutex held.
559 */
560 static
561 int _lttng_field_statedump(struct lttng_kernel_session *session,
562 const struct lttng_kernel_event_field *field,
563 size_t nesting,
564 const char **prev_field_name_p)
565 {
566 const char *prev_field_name = NULL;
567 int ret = 0;
568
569 if (prev_field_name_p)
570 prev_field_name = *prev_field_name_p;
571 switch (field->type->type) {
572 case lttng_kernel_type_integer:
573 ret = _lttng_integer_field_statedump(session, field, nesting);
574 break;
575 case lttng_kernel_type_enum:
576 ret = _lttng_enum_field_statedump(session, field, nesting);
577 break;
578 case lttng_kernel_type_string:
579 ret = _lttng_string_field_statedump(session, field, nesting);
580 break;
581 case lttng_kernel_type_struct:
582 ret = _lttng_struct_field_statedump(session, field, nesting);
583 break;
584 case lttng_kernel_type_array:
585 ret = _lttng_array_field_statedump(session, field, nesting);
586 break;
587 case lttng_kernel_type_sequence:
588 ret = _lttng_sequence_field_statedump(session, field, nesting, prev_field_name);
589 break;
590 case lttng_kernel_type_variant:
591 ret = _lttng_variant_field_statedump(session, field, nesting, prev_field_name);
592 break;
593
594 default:
595 WARN_ON_ONCE(1);
596 return -EINVAL;
597 }
598 if (prev_field_name_p)
599 *prev_field_name_p = field->name;
600 return ret;
601 }
602
603 static
604 int _lttng_context_metadata_statedump(struct lttng_kernel_session *session,
605 struct lttng_kernel_ctx *ctx)
606 {
607 const char *prev_field_name = NULL;
608 int ret = 0;
609 int i;
610
611 if (!ctx)
612 return 0;
613 for (i = 0; i < ctx->nr_fields; i++) {
614 const struct lttng_kernel_ctx_field *field = &ctx->fields[i];
615
616 ret = _lttng_field_statedump(session, field->event_field, 2, &prev_field_name);
617 if (ret)
618 return ret;
619 }
620 return ret;
621 }
622
623 static
624 int _lttng_fields_metadata_statedump(struct lttng_kernel_session *session,
625 struct lttng_kernel_event_recorder *event_recorder)
626 {
627 const char *prev_field_name = NULL;
628 const struct lttng_kernel_event_desc *desc = event_recorder->priv->parent.desc;
629 int ret = 0;
630 int i;
631
632 for (i = 0; i < desc->tp_class->nr_fields; i++) {
633 const struct lttng_kernel_event_field *field = desc->tp_class->fields[i];
634
635 ret = _lttng_field_statedump(session, field, 2, &prev_field_name);
636 if (ret)
637 return ret;
638 }
639 return ret;
640 }
641
642 /*
643 * Must be called with sessions_mutex held.
644 * The entire event metadata is printed as a single atomic metadata
645 * transaction.
646 */
647 int _lttng_event_recorder_metadata_statedump(struct lttng_kernel_event_common *event)
648 {
649 struct lttng_kernel_event_recorder *event_recorder;
650 struct lttng_kernel_channel_buffer *chan;
651 struct lttng_kernel_session *session;
652 int ret = 0;
653
654 if (event->type != LTTNG_KERNEL_EVENT_TYPE_RECORDER)
655 return 0;
656 event_recorder = container_of(event, struct lttng_kernel_event_recorder, parent);
657 chan = event_recorder->chan;
658 session = chan->parent.session;
659
660 if (event_recorder->priv->metadata_dumped || !LTTNG_READ_ONCE(session->active))
661 return 0;
662 if (chan->priv->channel_type == METADATA_CHANNEL)
663 return 0;
664
665 lttng_metadata_begin(session);
666
667 ret = lttng_metadata_printf(session,
668 "event {\n"
669 " name = \"%s\";\n"
670 " id = %u;\n"
671 " stream_id = %u;\n",
672 event_recorder->priv->parent.desc->event_name,
673 event_recorder->priv->id,
674 event_recorder->chan->priv->id);
675 if (ret)
676 goto end;
677
678 ret = lttng_metadata_printf(session,
679 " fields := struct {\n"
680 );
681 if (ret)
682 goto end;
683
684 ret = _lttng_fields_metadata_statedump(session, event_recorder);
685 if (ret)
686 goto end;
687
688 /*
689 * LTTng space reservation can only reserve multiples of the
690 * byte size.
691 */
692 ret = lttng_metadata_printf(session,
693 " };\n"
694 "};\n\n");
695 if (ret)
696 goto end;
697
698 event_recorder->priv->metadata_dumped = 1;
699 end:
700 lttng_metadata_end(session);
701 return ret;
702
703 }
704
705 /*
706 * Must be called with sessions_mutex held.
707 * The entire channel metadata is printed as a single atomic metadata
708 * transaction.
709 */
710 static
711 int lttng_channel_metadata_statedump(struct lttng_kernel_session *session,
712 struct lttng_kernel_channel_buffer *chan)
713 {
714 int ret = 0;
715
716 if (chan->priv->metadata_dumped || !LTTNG_READ_ONCE(session->active))
717 return 0;
718
719 if (chan->priv->channel_type == METADATA_CHANNEL)
720 return 0;
721
722 lttng_metadata_begin(session);
723
724 WARN_ON_ONCE(!chan->priv->header_type);
725 ret = lttng_metadata_printf(session,
726 "stream {\n"
727 " id = %u;\n"
728 " event.header := %s;\n"
729 " packet.context := struct packet_context;\n",
730 chan->priv->id,
731 chan->priv->header_type == 1 ? "struct event_header_compact" :
732 "struct event_header_large");
733 if (ret)
734 goto end;
735
736 if (chan->priv->ctx) {
737 ret = lttng_metadata_printf(session,
738 " event.context := struct {\n");
739 if (ret)
740 goto end;
741 }
742 ret = _lttng_context_metadata_statedump(session, chan->priv->ctx);
743 if (ret)
744 goto end;
745 if (chan->priv->ctx) {
746 ret = lttng_metadata_printf(session,
747 " };\n");
748 if (ret)
749 goto end;
750 }
751
752 ret = lttng_metadata_printf(session,
753 "};\n\n");
754
755 chan->priv->metadata_dumped = 1;
756 end:
757 lttng_metadata_end(session);
758 return ret;
759 }
760
761 /*
762 * Must be called with sessions_mutex held.
763 */
764 static
765 int _lttng_stream_packet_context_declare(struct lttng_kernel_session *session)
766 {
767 return lttng_metadata_printf(session,
768 "struct packet_context {\n"
769 " uint64_clock_monotonic_t timestamp_begin;\n"
770 " uint64_clock_monotonic_t timestamp_end;\n"
771 " uint64_t content_size;\n"
772 " uint64_t packet_size;\n"
773 " uint64_t packet_seq_num;\n"
774 " unsigned long events_discarded;\n"
775 " uint32_t cpu_id;\n"
776 "};\n\n"
777 );
778 }
779
780 /*
781 * Compact header:
782 * id: range: 0 - 30.
783 * id 31 is reserved to indicate an extended header.
784 *
785 * Large header:
786 * id: range: 0 - 65534.
787 * id 65535 is reserved to indicate an extended header.
788 *
789 * Must be called with sessions_mutex held.
790 */
791 static
792 int _lttng_event_header_declare(struct lttng_kernel_session *session)
793 {
794 return lttng_metadata_printf(session,
795 "struct event_header_compact {\n"
796 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
797 " variant <id> {\n"
798 " struct {\n"
799 " uint27_clock_monotonic_t timestamp;\n"
800 " } compact;\n"
801 " struct {\n"
802 " uint32_t id;\n"
803 " uint64_clock_monotonic_t timestamp;\n"
804 " } extended;\n"
805 " } v;\n"
806 "} align(%u);\n"
807 "\n"
808 "struct event_header_large {\n"
809 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
810 " variant <id> {\n"
811 " struct {\n"
812 " uint32_clock_monotonic_t timestamp;\n"
813 " } compact;\n"
814 " struct {\n"
815 " uint32_t id;\n"
816 " uint64_clock_monotonic_t timestamp;\n"
817 " } extended;\n"
818 " } v;\n"
819 "} align(%u);\n\n",
820 lttng_alignof(uint32_t) * CHAR_BIT,
821 lttng_alignof(uint16_t) * CHAR_BIT
822 );
823 }
824
825 static
826 int print_escaped_ctf_string(struct lttng_kernel_session *session, const char *string)
827 {
828 int ret = 0;
829 size_t i;
830 char cur;
831
832 i = 0;
833 cur = string[i];
834 while (cur != '\0') {
835 switch (cur) {
836 case '\n':
837 ret = lttng_metadata_printf(session, "%s", "\\n");
838 break;
839 case '\\':
840 case '"':
841 ret = lttng_metadata_printf(session, "%c", '\\');
842 if (ret)
843 goto error;
844 /* We still print the current char */
845 lttng_fallthrough;
846 default:
847 ret = lttng_metadata_printf(session, "%c", cur);
848 break;
849 }
850
851 if (ret)
852 goto error;
853
854 cur = string[++i];
855 }
856 error:
857 return ret;
858 }
859
860 static
861 int print_metadata_escaped_field(struct lttng_kernel_session *session, const char *field,
862 const char *field_value)
863 {
864 int ret;
865
866 ret = lttng_metadata_printf(session, " %s = \"", field);
867 if (ret)
868 goto error;
869
870 ret = print_escaped_ctf_string(session, field_value);
871 if (ret)
872 goto error;
873
874 ret = lttng_metadata_printf(session, "\";\n");
875
876 error:
877 return ret;
878 }
879
880 /*
881 * Output metadata into this session's metadata buffers.
882 * Must be called with sessions_mutex held.
883 */
884 int _lttng_session_metadata_statedump(struct lttng_kernel_session *session)
885 {
886 unsigned char *uuid_c = session->priv->uuid.b;
887 unsigned char uuid_s[37], clock_uuid_s[BOOT_ID_LEN];
888 const char *product_uuid;
889 struct lttng_kernel_channel_buffer_private *chan_priv;
890 struct lttng_kernel_event_recorder_private *event_recorder_priv;
891 int ret = 0;
892
893 if (!LTTNG_READ_ONCE(session->active))
894 return 0;
895
896 lttng_metadata_begin(session);
897
898 if (session->priv->metadata_dumped)
899 goto skip_session;
900
901 snprintf(uuid_s, sizeof(uuid_s),
902 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
903 uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3],
904 uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7],
905 uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11],
906 uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]);
907
908 ret = lttng_metadata_printf(session,
909 "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
910 "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
911 "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
912 "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
913 "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n"
914 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
915 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
916 "\n"
917 "trace {\n"
918 " major = %u;\n"
919 " minor = %u;\n"
920 " uuid = \"%s\";\n"
921 " byte_order = %s;\n"
922 " packet.header := struct {\n"
923 " uint32_t magic;\n"
924 " uint8_t uuid[16];\n"
925 " uint32_t stream_id;\n"
926 " uint64_t stream_instance_id;\n"
927 " };\n"
928 "};\n\n",
929 lttng_alignof(uint8_t) * CHAR_BIT,
930 lttng_alignof(uint16_t) * CHAR_BIT,
931 lttng_alignof(uint32_t) * CHAR_BIT,
932 lttng_alignof(uint64_t) * CHAR_BIT,
933 sizeof(unsigned long) * CHAR_BIT,
934 lttng_alignof(unsigned long) * CHAR_BIT,
935 CTF_SPEC_MAJOR,
936 CTF_SPEC_MINOR,
937 uuid_s,
938 #if __BYTE_ORDER == __BIG_ENDIAN
939 "be"
940 #else
941 "le"
942 #endif
943 );
944 if (ret)
945 goto end;
946
947 ret = lttng_metadata_printf(session,
948 "env {\n"
949 " hostname = \"%s\";\n"
950 " domain = \"kernel\";\n"
951 " sysname = \"%s\";\n"
952 " kernel_release = \"%s\";\n"
953 " kernel_version = \"%s\";\n"
954 " tracer_name = \"lttng-modules\";\n"
955 " tracer_major = %d;\n"
956 " tracer_minor = %d;\n"
957 " tracer_patchlevel = %d;\n"
958 " trace_buffering_scheme = \"global\";\n",
959 current->nsproxy->uts_ns->name.nodename,
960 utsname()->sysname,
961 utsname()->release,
962 utsname()->version,
963 LTTNG_MODULES_MAJOR_VERSION,
964 LTTNG_MODULES_MINOR_VERSION,
965 LTTNG_MODULES_PATCHLEVEL_VERSION
966 );
967 if (ret)
968 goto end;
969
970 ret = print_metadata_escaped_field(session, "trace_name", session->priv->name);
971 if (ret)
972 goto end;
973 ret = print_metadata_escaped_field(session, "trace_creation_datetime",
974 session->priv->creation_time);
975 if (ret)
976 goto end;
977
978 /* Add the product UUID to the 'env' section */
979 product_uuid = dmi_get_system_info(DMI_PRODUCT_UUID);
980 if (product_uuid) {
981 ret = lttng_metadata_printf(session,
982 " product_uuid = \"%s\";\n",
983 product_uuid
984 );
985 if (ret)
986 goto end;
987 }
988
989 /* Close the 'env' section */
990 ret = lttng_metadata_printf(session, "};\n\n");
991 if (ret)
992 goto end;
993
994 ret = lttng_metadata_printf(session,
995 "clock {\n"
996 " name = \"%s\";\n",
997 trace_clock_name()
998 );
999 if (ret)
1000 goto end;
1001
1002 if (!trace_clock_uuid(clock_uuid_s)) {
1003 ret = lttng_metadata_printf(session,
1004 " uuid = \"%s\";\n",
1005 clock_uuid_s
1006 );
1007 if (ret)
1008 goto end;
1009 }
1010
1011 ret = lttng_metadata_printf(session,
1012 " description = \"%s\";\n"
1013 " freq = %llu; /* Frequency, in Hz */\n"
1014 " /* clock value offset from Epoch is: offset * (1/freq) */\n"
1015 " offset = %lld;\n"
1016 "};\n\n",
1017 trace_clock_description(),
1018 (unsigned long long) trace_clock_freq(),
1019 (long long) trace_clock_offset()
1020 );
1021 if (ret)
1022 goto end;
1023
1024 ret = lttng_metadata_printf(session,
1025 "typealias integer {\n"
1026 " size = 27; align = 1; signed = false;\n"
1027 " map = clock.%s.value;\n"
1028 "} := uint27_clock_monotonic_t;\n"
1029 "\n"
1030 "typealias integer {\n"
1031 " size = 32; align = %u; signed = false;\n"
1032 " map = clock.%s.value;\n"
1033 "} := uint32_clock_monotonic_t;\n"
1034 "\n"
1035 "typealias integer {\n"
1036 " size = 64; align = %u; signed = false;\n"
1037 " map = clock.%s.value;\n"
1038 "} := uint64_clock_monotonic_t;\n\n",
1039 trace_clock_name(),
1040 lttng_alignof(uint32_t) * CHAR_BIT,
1041 trace_clock_name(),
1042 lttng_alignof(uint64_t) * CHAR_BIT,
1043 trace_clock_name()
1044 );
1045 if (ret)
1046 goto end;
1047
1048 ret = _lttng_stream_packet_context_declare(session);
1049 if (ret)
1050 goto end;
1051
1052 ret = _lttng_event_header_declare(session);
1053 if (ret)
1054 goto end;
1055
1056 skip_session:
1057 list_for_each_entry(chan_priv, &session->priv->chan, node) {
1058 ret = lttng_channel_metadata_statedump(session, chan_priv->pub);
1059 if (ret)
1060 goto end;
1061 }
1062
1063 list_for_each_entry(event_recorder_priv, &session->priv->events, parent.node) {
1064 ret = _lttng_event_recorder_metadata_statedump(&event_recorder_priv->pub->parent);
1065 if (ret)
1066 goto end;
1067 }
1068 session->priv->metadata_dumped = 1;
1069 end:
1070 lttng_metadata_end(session);
1071 return ret;
1072 }
This page took 0.051626 seconds and 5 git commands to generate.