1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
5 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com>
10 #include <linux/ktime.h>
11 #include <linux/list.h>
12 #include <linux/math64.h>
13 #include <linux/slab.h>
14 #include <linux/timekeeping.h>
15 #include <linux/utsname.h>
17 #include <lttng/events.h>
18 #include <lttng/events-internal.h>
19 #include <lttng/uuid.h>
21 #include <wrapper/time.h>
23 #include "clock-utils.h"
24 #include "field-path-resolving.h"
25 #include "metadata-printer.h"
27 #if __BYTE_ORDER == __BIG_ENDIAN
28 #define NATIVE_BYTEORDER "\"big-endian\""
29 #define REVERSE_BYTEORDER "\"little-endian\""
31 #define NATIVE_BYTEORDER "\"little-endian\""
32 #define REVERSE_BYTEORDER "\"big-endian\""
35 struct ctf2_enum_mapping_range
{
36 struct list_head node
;
37 struct lttng_kernel_enum_value start
;
38 struct lttng_kernel_enum_value end
;
41 struct ctf2_enum_mapping
{
42 struct list_head node
;
44 struct list_head ranges
;
45 unsigned int nr_ranges
;
49 struct list_head mappings
;
50 unsigned int nr_mappings
;
54 ctf2_metadata_write_field(struct lttng_kernel_session
*session
,
55 const struct lttng_kernel_event_field
*field
,
56 struct field_location_ctx
*field_location_ctx
);
58 ctf2_metadata_write_field_class(struct lttng_kernel_session
*session
,
59 const struct lttng_kernel_type_common
*type
,
60 struct field_location_ctx
*field_location_ctx
);
63 ctf2_metadata_write_record_separator(struct lttng_kernel_session
*session
)
65 return lttng_metadata_printf(session
, "%c\n", 0x1E);
68 static int ctf2_metadata_write_uuid(struct lttng_kernel_session
*session
,
71 unsigned int i
, uuid_len
= 16;
74 ret
= lttng_metadata_printf(session
, "[");
78 for (i
= 0; i
< uuid_len
; i
++) {
79 ret
= lttng_metadata_printf(session
, "%hhu", uuid
[i
]);
83 if (i
< uuid_len
- 1) {
84 ret
= lttng_metadata_printf(session
, ",");
90 ret
= lttng_metadata_printf(session
, "]");
97 ctf2_metadata_write_preamble_fragment(struct lttng_kernel_session
*session
)
99 unsigned char *session_uuid
= session
->priv
->uuid
.b
;
102 ret
= ctf2_metadata_write_record_separator(session
);
106 /* Write the preamble */
107 ret
= lttng_metadata_printf(session
, "{\n\"type\":\"preamble\",\n"
113 ret
= ctf2_metadata_write_uuid(session
, session_uuid
);
116 "LTTng: CTF2: error producing metadata trace class UUID\n");
120 ret
= lttng_metadata_printf(session
, "}\n");
126 ctf2_metadata_write_clock_class_fragment(struct lttng_kernel_session
*session
)
128 unsigned char clock_uuid_str
[37] = { 0 };
129 const char *clock_name
, *clock_desc
;
130 long long offset
, offset_seconds
;
131 unsigned long long freq
;
132 int offset_cycles
, ret
;
134 ret
= ctf2_metadata_write_record_separator(session
);
138 clock_name
= trace_clock_name();
139 clock_desc
= trace_clock_description();
140 freq
= trace_clock_freq();
141 offset
= trace_clock_measure_offset();
142 offset_seconds
= div_s64_rem(offset
, freq
, &offset_cycles
);
144 ret
= lttng_metadata_printf(
147 "\"type\":\"clock-class\",\n"
149 "\"description\" : \"%s\",\n"
150 "\"frequency\" : %llu,\n"
151 "\"offset\" : { \"seconds\": %llu, \"cycles\":%lu}\n",
152 clock_name
, clock_desc
, freq
, offset_seconds
, offset_cycles
);
156 if (!trace_clock_uuid(clock_uuid_str
)) {
157 lttng_uuid clock_uuid
;
159 ret
= lttng_metadata_printf(session
, ",\n\"uuid\": ");
163 ret
= lttng_uuid_from_str(clock_uuid_str
, clock_uuid
);
166 "LTTng: CTF2: error creating UUID from string\n");
170 ret
= ctf2_metadata_write_uuid(session
, clock_uuid
);
174 ret
= lttng_metadata_printf(session
, "}\n");
181 static int ctf2_metadata_write_packet_header_field_class(
182 struct lttng_kernel_session
*session
)
186 ret
= lttng_metadata_printf(
189 " \"type\": \"structure\","
190 " \"member-classes\": ["
192 " \"name\": \"magic\","
193 " \"field-class\": {"
194 " \"type\": \"fixed-length-unsigned-integer\","
195 " \"alignment\": %u,"
197 " \"byte-order\": " NATIVE_BYTEORDER
","
198 " \"preferred-display-base\": 16,"
199 " \"roles\": [\"packet-magic-number\"]"
203 " \"name\": \"uuid\","
204 " \"field-class\": {"
205 " \"type\": \"static-length-blob\","
207 " \"roles\": [\"metadata-stream-uuid\"]"
211 " \"name\": \"stream_id\","
212 " \"field-class\": {"
213 " \"type\": \"fixed-length-unsigned-integer\","
214 " \"alignment\": %u,"
216 " \"byte-order\": " NATIVE_BYTEORDER
","
217 " \"roles\": [\"data-stream-class-id\"]"
221 " \"name\": \"stream_instance_id\","
222 " \"field-class\": {"
223 " \"type\": \"fixed-length-unsigned-integer\","
224 " \"alignment\": %u,"
226 " \"byte-order\": " NATIVE_BYTEORDER
","
227 " \"roles\": [\"data-stream-id\"]"
232 lttng_alignof(uint32_t) * CHAR_BIT
,
233 lttng_alignof(uint32_t) * CHAR_BIT
,
234 lttng_alignof(uint64_t) * CHAR_BIT
);
239 static int ctf2_metadata_write_environment(struct lttng_kernel_session
*session
)
243 ret
= lttng_metadata_printf(
246 " \"hostname\": \"%s\",\n"
247 " \"domain\": \"kernel\",\n"
248 " \"sysname\": \"%s\",\n"
249 " \"kernel_release\": \"%s\",\n"
250 " \"kernel_version\": \"%s\",\n"
251 " \"tracer_name\": \"lttng-modules\",\n"
252 " \"tracer_major\": %d,\n"
253 " \"tracer_minor\": %d,\n"
254 " \"tracer_patchlevel\": %d,\n"
255 " \"trace_buffering_scheme\": \"global\"\n"
257 current
->nsproxy
->uts_ns
->name
.nodename
, utsname()->sysname
,
258 utsname()->release
, utsname()->version
,
259 LTTNG_MODULES_MAJOR_VERSION
, LTTNG_MODULES_MINOR_VERSION
,
260 LTTNG_MODULES_PATCHLEVEL_VERSION
);
266 ctf2_metadata_write_trace_class_fragment(struct lttng_kernel_session
*session
)
270 ret
= ctf2_metadata_write_record_separator(session
);
274 ret
= lttng_metadata_printf(session
, "{\n\"type\":\"trace-class\"");
278 ret
= lttng_metadata_printf(session
, ",\n\"environment\":");
282 ret
= ctf2_metadata_write_environment(session
);
286 ret
= lttng_metadata_printf(session
, ",\n\"packet-header-field-class\":");
290 ret
= ctf2_metadata_write_packet_header_field_class(session
);
293 "LTTng: CTF2: error producing metadata trace class packet header field class\n");
297 ret
= lttng_metadata_printf(session
, "}\n");
302 static int ctf2_metadata_write_packet_context_field_class(
303 struct lttng_kernel_session
*session
,
304 struct lttng_kernel_channel_buffer
*chan
)
307 ret
= lttng_metadata_printf(
310 " \"type\": \"structure\","
311 " \"member-classes\": ["
313 " \"name\": \"timestamp_begin\","
314 " \"field-class\": {"
315 " \"type\": \"fixed-length-unsigned-integer\","
316 " \"alignment\": %u,"
318 " \"byte-order\": " NATIVE_BYTEORDER
","
319 " \"roles\": [\"default-clock-timestamp\"]"
323 " \"name\": \"timestamp_end\","
324 " \"field-class\": {"
325 " \"type\": \"fixed-length-unsigned-integer\","
326 " \"alignment\": %u,"
328 " \"byte-order\": " NATIVE_BYTEORDER
","
329 " \"roles\": [\"packet-end-default-clock-timestamp\"]"
333 " \"name\": \"content_size\","
334 " \"field-class\": {"
335 " \"type\": \"fixed-length-unsigned-integer\","
336 " \"alignment\": %u,"
338 " \"byte-order\": " NATIVE_BYTEORDER
","
339 " \"roles\": [\"packet-content-length\"]"
343 " \"name\": \"packet_size\","
344 " \"field-class\": {"
345 " \"type\": \"fixed-length-unsigned-integer\","
346 " \"alignment\": %u,"
348 " \"byte-order\": " NATIVE_BYTEORDER
","
349 " \"roles\": [\"packet-total-length\"]"
353 " \"name\": \"packet_seq_num\","
354 " \"field-class\": {"
355 " \"type\": \"fixed-length-unsigned-integer\","
356 " \"alignment\": %u,"
358 " \"byte-order\": " NATIVE_BYTEORDER
","
359 " \"roles\": [\"packet-sequence-number\" ]"
363 " \"name\": \"events_discarded\","
364 " \"field-class\": {"
365 " \"type\": \"fixed-length-unsigned-integer\","
366 " \"alignment\": %u,"
367 " \"byte-order\": " NATIVE_BYTEORDER
","
369 " \"roles\": [\"discarded-event-record-counter-snapshot\"]"
373 " \"name\": \"cpu_id\","
374 " \"field-class\": {"
375 " \"type\": \"fixed-length-unsigned-integer\","
377 " \"byte-order\": " NATIVE_BYTEORDER
","
383 lttng_alignof(uint64_t) * CHAR_BIT
,
384 lttng_alignof(uint64_t) * CHAR_BIT
,
385 lttng_alignof(uint64_t) * CHAR_BIT
,
386 lttng_alignof(uint64_t) * CHAR_BIT
,
387 lttng_alignof(uint64_t) * CHAR_BIT
,
388 lttng_alignof(unsigned long) * CHAR_BIT
,
389 sizeof(unsigned long) * CHAR_BIT
);
393 static int ctf2_metadata_write_common_context_field_class(
394 struct lttng_kernel_session
*session
, struct lttng_kernel_ctx
*ctx
)
396 struct field_location_ctx
*field_location_ctx
;
402 ret
= lttng_metadata_printf(session
, "{\n"
403 "\"type\": \"structure\",\n"
404 "\"member-classes\": [");
408 field_location_ctx
= field_location_ctx_create();
409 if (!field_location_ctx
) {
412 "LTTng: CTF2: error allocating field location context\n");
416 ret
= field_location_stack_push(field_location_ctx
,
417 SCOPE_STACK_NODE_TYPE_SCOPE
,
418 "event-record-common-context", NULL
);
421 "LTTng: CTF2: error pushing new scope on scope stack\n");
422 goto destroy_field_loc
;
425 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
426 const struct lttng_kernel_ctx_field
*iter_field
=
429 ret
= ctf2_metadata_write_field(
430 session
, iter_field
->event_field
, field_location_ctx
);
432 goto destroy_field_loc
;
434 ret
= field_location_stack_push(field_location_ctx
,
435 SCOPE_STACK_NODE_TYPE_FIELD
,
436 iter_field
->event_field
->name
,
437 iter_field
->event_field
);
440 "LTTng: CTF2: error pushing new field on scope stack\n");
441 goto destroy_field_loc
;
444 if (i
< ctx
->nr_fields
- 1) {
445 ret
= lttng_metadata_printf(session
, ", ");
447 goto destroy_field_loc
;
451 field_location_stack_pop_n_elem(field_location_ctx
, ctx
->nr_fields
+ 1);
453 ret
= lttng_metadata_printf(session
, "]\n}\n");
456 field_location_ctx_destroy(field_location_ctx
);
461 static int ctf2_metadata_write_compact_event_header_field_class(
462 struct lttng_kernel_session
*session
)
465 ret
= lttng_metadata_printf(
468 " \"type\": \"structure\","
469 " \"minimum-alignment\": 8,"
470 " \"member-classes\": ["
473 " \"field-class\": {"
474 " \"type\": \"fixed-length-unsigned-enumeration\","
476 " \"byte-order\": " NATIVE_BYTEORDER
","
478 " \"compact\": [[0,30]],"
479 " \"extended\": [[31,31]]"
481 " \"roles\": [\"event-record-class-id\"]"
486 " \"field-class\": {"
487 " \"type\": \"variant\","
488 " \"selector-field-location\": ["
489 " \"event-record-header\","
494 " \"selector-field-ranges\": [[0, 30]],"
495 " \"field-class\": {"
496 " \"type\": \"structure\","
497 " \"member-classes\": ["
499 " \"name\": \"timestamp\","
501 " \"type\": \"fixed-length-unsigned-integer\","
502 " \"byte-order\": " NATIVE_BYTEORDER
","
504 " \"roles\": [\"default-clock-timestamp\"]"
511 " \"selector-field-ranges\": [[31, 31]],"
512 " \"field-class\": {"
513 " \"type\": \"structure\","
514 " \"member-classes\": ["
517 " \"field-class\": {"
518 " \"type\": \"fixed-length-unsigned-integer\","
520 " \"alignment\": %u,"
521 " \"byte-order\": " NATIVE_BYTEORDER
","
522 " \"roles\": [\"event-record-class-id\" ]"
526 " \"name\": \"timestamp\","
527 " \"field-class\": {"
528 " \"type\": \"fixed-length-unsigned-integer\","
529 " \"alignment\": %u,"
531 " \"byte-order\": " NATIVE_BYTEORDER
","
532 " \"roles\": [\"default-clock-timestamp\"]"
543 lttng_alignof(uint32_t) * CHAR_BIT
,
544 lttng_alignof(uint64_t) * CHAR_BIT
);
548 static int ctf2_metadata_write_large_event_header_field_class(
549 struct lttng_kernel_session
*session
)
552 ret
= lttng_metadata_printf(
555 " \"type\": \"structure\","
556 " \"minimum-alignment\": 8,"
557 " \"member-classes\": ["
560 " \"field-class\": {"
561 " \"type\": \"fixed-length-unsigned-enumeration\","
563 " \"alignment\": %u,"
564 " \"byte-order\": " NATIVE_BYTEORDER
","
566 " \"compact\": [[0,65534]],"
567 " \"extended\": [[65535,65535]]"
569 " \"roles\": [\"event-record-class-id\"]"
574 " \"field-class\": {"
575 " \"type\": \"variant\","
576 " \"selector-field-location\": ["
577 " \"event-record-header\","
582 " \"selector-field-ranges\": [[0,65534]],"
583 " \"field-class\": {"
584 " \"type\": \"structure\","
585 " \"member-classes\": ["
587 " \"name\": \"timestamp\","
588 " \"field-class\": {"
589 " \"type\": \"fixed-length-unsigned-integer\","
590 " \"alignment\": %u,"
591 " \"byte-order\": " NATIVE_BYTEORDER
","
593 " \"roles\": [\"default-clock-timestamp\"]"
600 " \"selector-field-ranges\": [ [65525,65535] ],"
601 " \"field-class\": {"
602 " \"type\": \"structure\","
603 " \"member-classes\": ["
606 " \"field-class\": {"
607 " \"type\": \"fixed-length-unsigned-integer\","
609 " \"alignment\": %u,"
610 " \"byte-order\": " NATIVE_BYTEORDER
","
611 " \"roles\": [\"event-record-class-id\" ]"
615 " \"name\": \"timestamp\","
616 " \"field-class\": {"
617 " \"type\": \"fixed-length-unsigned-integer\","
619 " \"alignment\": %u,"
620 " \"byte-order\": " NATIVE_BYTEORDER
","
621 " \"roles\": [\"default-clock-timestamp\"]"
632 lttng_alignof(uint16_t) * CHAR_BIT
,
633 lttng_alignof(uint32_t) * CHAR_BIT
,
634 lttng_alignof(uint32_t) * CHAR_BIT
,
635 lttng_alignof(uint64_t) * CHAR_BIT
);
639 static int ctf2_metadata_write_integer_field_class(
640 struct lttng_kernel_session
*session
,
641 const struct lttng_kernel_type_integer
*type
)
643 char *enum_type_name
, *byte_order
;
646 if (type
->signedness
) {
647 enum_type_name
= "fixed-length-signed-integer";
649 enum_type_name
= "fixed-length-unsigned-integer";
653 type
->reverse_byte_order
? REVERSE_BYTEORDER
: NATIVE_BYTEORDER
;
655 ret
= lttng_metadata_printf(session
,
657 "\n\"type\": \"%s\","
659 "\n\"byte-order\": %s",
660 enum_type_name
, type
->size
, byte_order
);
664 if (type
->alignment
!= 1) {
665 ret
= lttng_metadata_printf(session
, ",\n\"alignment\": %u",
671 if (type
->base
!= 10) {
672 ret
= lttng_metadata_printf(session
,
673 ",\n\"preferred-display-base\": %u",
679 ret
= lttng_metadata_printf(session
, "\n}");
687 ctf2_enum_mapping_destroy(struct ctf2_enum_mapping
*ctf2_enum_mapping
)
689 struct ctf2_enum_mapping_range
*range
, *tmp
;
691 if (!ctf2_enum_mapping
) {
695 list_for_each_entry_safe (range
, tmp
, &ctf2_enum_mapping
->ranges
,
700 kfree(ctf2_enum_mapping
->name
);
701 kfree(ctf2_enum_mapping
);
704 static void ctf2_enum_destroy(struct ctf2_enum
*ctf2_enum
)
706 struct ctf2_enum_mapping
*mapping
, *tmp
;
712 list_for_each_entry_safe (mapping
, tmp
, &ctf2_enum
->mappings
, node
) {
713 ctf2_enum_mapping_destroy(mapping
);
719 static struct ctf2_enum
*
720 ctf2_enum_create_from_type_enum(const struct lttng_kernel_type_enum
*cur_enum
)
722 struct ctf2_enum
*ctf2_enum
;
723 const struct lttng_kernel_enum_desc
*enum_desc
;
724 unsigned int i
, nr_entries
;
725 struct ctf2_enum_mapping
*mapping
;
726 struct lttng_kernel_enum_value next_value
= { .value
= 0,
727 .signedness
= false };
729 nr_entries
= cur_enum
->desc
->nr_entries
;
730 enum_desc
= cur_enum
->desc
;
732 ctf2_enum
= kzalloc(sizeof(*ctf2_enum
), GFP_KERNEL
);
736 INIT_LIST_HEAD(&ctf2_enum
->mappings
);
738 for (i
= 0; i
< nr_entries
; i
++) {
739 const struct lttng_kernel_enum_entry
*entry
=
740 enum_desc
->entries
[i
];
741 struct ctf2_enum_mapping_range
*mapping_range
;
744 list_for_each_entry (mapping
, &ctf2_enum
->mappings
, node
) {
745 if (strcmp(mapping
->name
, entry
->string
) == 0) {
751 mapping_range
= kzalloc(sizeof(*mapping_range
), GFP_KERNEL
);
753 goto destroy_ctf2_enum
;
755 if (entry
->options
.is_auto
) {
756 mapping_range
->start
.value
= next_value
.value
;
757 mapping_range
->start
.signedness
= next_value
.signedness
;
758 mapping_range
->end
.value
= next_value
.value
;
759 mapping_range
->end
.signedness
= next_value
.signedness
;
763 mapping_range
->start
.value
= entry
->start
.value
;
764 mapping_range
->start
.signedness
=
765 entry
->start
.signedness
;
766 mapping_range
->end
.value
= entry
->end
.value
;
767 mapping_range
->end
.signedness
= entry
->end
.signedness
;
769 next_value
.value
= entry
->end
.value
+ 1;
770 next_value
.signedness
= entry
->end
.signedness
;
775 * We already have a mapping with that name, add the
776 * new range to the range list.
778 list_add_tail(&mapping_range
->node
, &mapping
->ranges
);
781 * Allocate the new mapping, add its range to the range
782 * list, and add the mapping to the mapping list
784 mapping
= kzalloc(sizeof(*mapping
), GFP_KERNEL
);
786 kfree(mapping_range
);
787 goto destroy_ctf2_enum
;
790 mapping
->name
= kstrdup(entry
->string
, GFP_KERNEL
);
792 INIT_LIST_HEAD(&mapping
->ranges
);
794 list_add_tail(&mapping
->node
, &ctf2_enum
->mappings
);
795 ctf2_enum
->nr_mappings
++;
797 list_add_tail(&mapping_range
->node
, &mapping
->ranges
);
800 mapping
->nr_ranges
++;
806 ctf2_enum_destroy(ctf2_enum
);
813 ctf2_metadata_write_enum_mapping_ranges(struct lttng_kernel_session
*session
,
814 struct ctf2_enum_mapping
*mapping
)
816 unsigned int range_idx
;
817 struct ctf2_enum_mapping_range
*mapping_range
;
822 list_for_each_entry (mapping_range
, &mapping
->ranges
, node
) {
823 if (mapping_range
->start
.signedness
)
824 ret
= lttng_metadata_printf(
826 (long long)mapping_range
->start
.value
);
828 ret
= lttng_metadata_printf(session
, "[%llu, ",
829 mapping_range
->start
.value
);
833 if (mapping_range
->end
.signedness
)
834 ret
= lttng_metadata_printf(
836 (long long)mapping_range
->end
.value
);
838 ret
= lttng_metadata_printf(session
, "%llu]",
839 mapping_range
->end
.value
);
843 if (range_idx
< mapping
->nr_ranges
- 1) {
844 ret
= lttng_metadata_printf(session
, ",\n");
856 static int ctf2_metadata_write_enum_field_class(
857 struct lttng_kernel_session
*session
,
858 const struct lttng_kernel_type_enum
*enum_type
)
860 const struct lttng_kernel_enum_desc
*enum_desc
;
861 const struct lttng_kernel_type_common
*container_type
;
862 const struct lttng_kernel_type_integer
*base_type
;
863 struct ctf2_enum
*ctf2_enum
;
864 struct ctf2_enum_mapping
*mapping
;
865 unsigned int mapping_idx
, nr_entries
;
866 const char *byte_order
;
867 char *enum_type_name
;
870 enum_desc
= enum_type
->desc
;
871 container_type
= enum_type
->container_type
;
872 nr_entries
= enum_desc
->nr_entries
;
874 if (container_type
->type
!= lttng_kernel_type_integer
) {
879 base_type
= lttng_kernel_get_type_integer(container_type
);
881 if (base_type
->signedness
) {
882 enum_type_name
= "fixed-length-signed-enumeration";
884 enum_type_name
= "fixed-length-unsigned-enumeration";
887 byte_order
= base_type
->reverse_byte_order
? REVERSE_BYTEORDER
:
890 ret
= lttng_metadata_printf(session
,
894 " \"byte-order\": %s",
895 enum_type_name
, base_type
->size
,
900 if (base_type
->alignment
!= 1) {
901 ret
= lttng_metadata_printf(session
, ", \"alignment\": %u",
902 base_type
->alignment
);
907 if (base_type
->base
!= 10) {
908 ret
= lttng_metadata_printf(session
,
909 ", \"preferred-display-base\": %u",
915 ret
= lttng_metadata_printf(session
, ", \"mappings\": {");
919 ctf2_enum
= ctf2_enum_create_from_type_enum(enum_type
);
921 list_for_each_entry (mapping
, &ctf2_enum
->mappings
, node
) {
922 ret
= lttng_metadata_printf(session
, " \"%s\": [",
927 ret
= ctf2_metadata_write_enum_mapping_ranges(session
, mapping
);
931 ret
= lttng_metadata_printf(session
, " ]");
935 if (mapping_idx
< ctf2_enum
->nr_mappings
- 1) {
936 ret
= lttng_metadata_printf(session
, ",\n");
943 ret
= lttng_metadata_printf(session
, "}}");
946 ctf2_enum_destroy(ctf2_enum
);
950 static int ctf2_metadata_write_string_field_class(
951 struct lttng_kernel_session
*session
,
952 const struct lttng_kernel_type_string
*type
)
956 ret
= lttng_metadata_printf(session
,
957 "{\"type\": \"null-terminated-string\"}");
961 static int ctf2_metadata_write_struct_field_class(
962 struct lttng_kernel_session
*session
,
963 const struct lttng_kernel_type_struct
*type
,
964 struct field_location_ctx
*field_location_ctx
)
966 unsigned int nr_fields
;
969 ret
= lttng_metadata_printf(session
, "{\"type\": \"structure\"");
973 if (type
->alignment
!= 0 && type
->alignment
!= 1) {
974 ret
= lttng_metadata_printf(session
,
975 ", \"minimum-alignment\": %u",
981 nr_fields
= type
->nr_fields
;
986 ret
= lttng_metadata_printf(session
, ", \"member-classes\":[ ");
988 for (i
= 0; i
< nr_fields
; i
++) {
989 const struct lttng_kernel_event_field
*iter_field
;
991 iter_field
= type
->fields
[i
];
993 ret
= ctf2_metadata_write_field(session
, iter_field
,
998 if (field_location_ctx
) {
999 ret
= field_location_stack_push(
1001 SCOPE_STACK_NODE_TYPE_FIELD
,
1002 iter_field
->name
, iter_field
);
1007 if (i
< nr_fields
- 1) {
1008 ret
= lttng_metadata_printf(session
, ", ");
1015 * We are done visiting the struct field class. Remove all the
1016 * concrete fields of that scope.
1018 if (field_location_ctx
) {
1019 field_location_stack_pop_n_elem(field_location_ctx
,
1023 ret
= lttng_metadata_printf(session
, "]");
1027 ret
= lttng_metadata_printf(session
, "}");
1032 static int ctf2_metadata_write_static_length_array_field_class(
1033 struct lttng_kernel_session
*session
,
1034 const struct lttng_kernel_type_array
*type
)
1037 const struct lttng_kernel_type_common
*elem_type
= type
->elem_type
;
1040 * If it's an array of integer encoded as characters, we translate it
1041 * as a static-length-string.
1043 if (elem_type
->type
== lttng_kernel_type_integer
&&
1044 (type
->encoding
== lttng_kernel_string_encoding_ASCII
||
1045 type
->encoding
== lttng_kernel_string_encoding_UTF8
)) {
1046 ret
= lttng_metadata_printf(
1049 " \"type\": \"static-length-string\","
1050 " \"length\": %u }",
1053 ret
= lttng_metadata_printf(
1056 " \"type\": \"static-length-array\","
1062 if (type
->alignment
!= 0 && type
->alignment
!= 1) {
1063 ret
= lttng_metadata_printf(
1064 session
, ", \"minimum-alignment\": %u",
1065 type
->alignment
* CHAR_BIT
);
1070 ret
= lttng_metadata_printf(session
,
1071 ", \"element-field-class\":");
1076 * Nested compound types: Only array of integers, structures,
1077 * and variants are currently supported.
1079 switch (elem_type
->type
) {
1080 case lttng_kernel_type_integer
:
1081 case lttng_kernel_type_struct
:
1082 case lttng_kernel_type_variant
:
1083 ret
= ctf2_metadata_write_field_class(session
,
1094 ret
= lttng_metadata_printf(session
, "}");
1101 static int print_field_location(struct lttng_kernel_session
*session
,
1102 struct field_path
*field_path
)
1104 struct field_path_node
*field_path_node
;
1105 unsigned int entry_idx
= 0;
1108 ret
= lttng_metadata_printf(session
, "[");
1112 list_for_each_entry (field_path_node
, &(field_path
->path
), node
) {
1113 ret
= lttng_metadata_printf(session
, "\"%s\"",
1114 field_path_node
->name
);
1118 if (entry_idx
< field_path
->path_entry_count
- 1) {
1119 ret
= lttng_metadata_printf(session
, ", ");
1126 ret
= lttng_metadata_printf(session
, "]");
1132 static int ctf2_metadata_write_dynamic_length_array_field_class(
1133 struct lttng_kernel_session
*session
,
1134 const struct lttng_kernel_type_sequence
*type
,
1135 struct field_location_ctx
*field_location_ctx
)
1137 const struct lttng_kernel_type_common
*elem_type
;
1138 struct field_path
*field_path
;
1141 field_path
= field_path_resolve(field_location_ctx
, type
->length_name
);
1148 * Nested compound types: Only array of integers, structures, and
1149 * variants are currently supported.
1151 ret
= lttng_metadata_printf(session
,
1153 " \"type\": \"dynamic-length-array\",\n"
1154 " \"length-field-location\": ");
1158 ret
= print_field_location(session
, field_path
);
1162 if (type
->alignment
!= 0 && type
->alignment
!= 1) {
1163 ret
= lttng_metadata_printf(session
,
1164 ",\n\"minimum-alignment\": %u",
1165 type
->alignment
* CHAR_BIT
);
1170 ret
= lttng_metadata_printf(session
, ",\n\"element-field-class\":");
1174 elem_type
= type
->elem_type
;
1175 switch (elem_type
->type
) {
1176 case lttng_kernel_type_integer
:
1177 case lttng_kernel_type_struct
:
1178 case lttng_kernel_type_variant
:
1179 ret
= ctf2_metadata_write_field_class(session
, elem_type
, NULL
);
1188 ret
= lttng_metadata_printf(session
, "}\n");
1190 field_path_destroy(field_path
);
1194 static int ctf2_metadata_write_variant_field_class(
1195 struct lttng_kernel_session
*session
,
1196 const struct lttng_kernel_type_variant
*variant_type
,
1197 struct field_location_ctx
*field_location_ctx
)
1199 const char *tag_name
;
1200 struct field_path
*field_path
= NULL
;
1201 struct field_path_node
*field_path_node
;
1202 const struct lttng_kernel_type_enum
*enum_type
;
1203 struct ctf2_enum
*ctf2_enum
= NULL
;
1204 unsigned int variant_choice_idx
, variant_nr_choices
, enum_nr_entries
;
1207 tag_name
= variant_type
->tag_name
;
1209 field_path
= field_path_resolve(field_location_ctx
, tag_name
);
1215 ret
= lttng_metadata_printf(session
, "{"
1216 "\n\"type\": \"variant\","
1217 "\n\"selector-field-location\":");
1221 ret
= print_field_location(session
, field_path
);
1225 ret
= lttng_metadata_printf(session
, ",\n\"options\": [");
1229 field_path_node
= list_last_entry(&(field_path
->path
),
1230 struct field_path_node
, node
);
1231 if (!field_path_node
) {
1236 enum_type
= lttng_kernel_get_type_enum(field_path_node
->field
->type
);
1237 enum_nr_entries
= enum_type
->desc
->nr_entries
;
1239 variant_nr_choices
= variant_type
->nr_choices
;
1241 if (enum_nr_entries
!= variant_nr_choices
) {
1246 ctf2_enum
= ctf2_enum_create_from_type_enum(enum_type
);
1249 * Iterate over all the options of the variant, find the mapping matching
1250 * the option name in the selector enum. Once found, print all ranges
1251 * and the field class of this option.
1253 for (variant_choice_idx
= 0; variant_choice_idx
< variant_nr_choices
;
1254 variant_choice_idx
++) {
1255 const struct lttng_kernel_event_field
*var_opt
;
1256 struct ctf2_enum_mapping
*mapping
;
1258 var_opt
= variant_type
->choices
[variant_choice_idx
];
1260 list_for_each_entry (mapping
, &ctf2_enum
->mappings
, node
) {
1261 struct ctf2_enum_mapping_range
*mapping_range
;
1262 unsigned int range_idx
;
1265 * Omit the leading underscore when comparing enum
1268 if (strcmp(var_opt
->name
, &mapping
->name
[1]) != 0) {
1272 ret
= lttng_metadata_printf(
1275 "\n\"name\": \"_%s\","
1276 "\n\"selector-field-ranges\": [",
1282 list_for_each_entry (mapping_range
, &mapping
->ranges
,
1284 if (mapping_range
->start
.signedness
)
1285 ret
= lttng_metadata_printf(
1287 (long long)mapping_range
->start
1290 ret
= lttng_metadata_printf(
1292 mapping_range
->start
.value
);
1297 if (mapping_range
->end
.signedness
)
1298 ret
= lttng_metadata_printf(
1300 (long long)mapping_range
->end
1303 ret
= lttng_metadata_printf(
1305 mapping_range
->end
.value
);
1309 if (range_idx
< mapping
->nr_ranges
- 1) {
1310 ret
= lttng_metadata_printf(session
,
1319 ret
= lttng_metadata_printf(session
,
1320 " ], \"field-class\": ");
1324 ret
= ctf2_metadata_write_field_class(
1325 session
, var_opt
->type
, field_location_ctx
);
1329 ret
= lttng_metadata_printf(session
, "}");
1333 /* Was it the last one ? */
1334 if (variant_choice_idx
< variant_nr_choices
- 1) {
1335 ret
= lttng_metadata_printf(session
, ",");
1341 ret
= lttng_metadata_printf(session
, "] }");
1344 ctf2_enum_destroy(ctf2_enum
);
1345 field_path_destroy(field_path
);
1350 * Must be called with sessions_mutex held.
1353 ctf2_metadata_write_field_class(struct lttng_kernel_session
*session
,
1354 const struct lttng_kernel_type_common
*type
,
1355 struct field_location_ctx
*field_location_ctx
)
1359 switch (type
->type
) {
1360 case lttng_kernel_type_integer
:
1361 ret
= ctf2_metadata_write_integer_field_class(
1362 session
, lttng_kernel_get_type_integer(type
));
1364 case lttng_kernel_type_enum
:
1365 ret
= ctf2_metadata_write_enum_field_class(
1366 session
, lttng_kernel_get_type_enum(type
));
1368 case lttng_kernel_type_string
:
1369 ret
= ctf2_metadata_write_string_field_class(
1370 session
, lttng_kernel_get_type_string(type
));
1372 case lttng_kernel_type_struct
:
1373 ret
= ctf2_metadata_write_struct_field_class(
1374 session
, lttng_kernel_get_type_struct(type
),
1375 field_location_ctx
);
1377 case lttng_kernel_type_array
:
1378 ret
= ctf2_metadata_write_static_length_array_field_class(
1379 session
, lttng_kernel_get_type_array(type
));
1381 case lttng_kernel_type_sequence
:
1382 ret
= ctf2_metadata_write_dynamic_length_array_field_class(
1383 session
, lttng_kernel_get_type_sequence(type
),
1384 field_location_ctx
);
1386 case lttng_kernel_type_variant
:
1387 ret
= ctf2_metadata_write_variant_field_class(
1388 session
, lttng_kernel_get_type_variant(type
),
1389 field_location_ctx
);
1400 * Must be called with sessions_mutex held.
1403 ctf2_metadata_write_field(struct lttng_kernel_session
*session
,
1404 const struct lttng_kernel_event_field
*field
,
1405 struct field_location_ctx
*field_location_ctx
)
1409 ret
= lttng_metadata_printf(session
,
1411 "\n\"name\": \"%s\","
1412 "\n\"field-class\":",
1418 * Push a new scope only if we are entering a variant or struct field
1421 if (field_location_ctx
&&
1422 (field
->type
->type
== lttng_kernel_type_struct
||
1423 field
->type
->type
== lttng_kernel_type_variant
)) {
1424 ret
= field_location_stack_push(field_location_ctx
,
1425 SCOPE_STACK_NODE_TYPE_SCOPE
,
1426 field
->name
, field
);
1431 ret
= ctf2_metadata_write_field_class(session
, field
->type
,
1432 field_location_ctx
);
1435 "LTTng: CTF2: error producing metadata for field class \"%s\"\n",
1440 if (field_location_ctx
&&
1441 (field
->type
->type
== lttng_kernel_type_struct
||
1442 field
->type
->type
== lttng_kernel_type_variant
)) {
1443 field_location_stack_pop_n_elem(field_location_ctx
, 1);
1446 ret
= lttng_metadata_printf(session
, "\n}\n");
1452 static int ctf2_metadata_write_payload_field_class(
1453 struct lttng_kernel_session
*session
,
1454 struct lttng_kernel_event_recorder
*event_recorder
)
1456 const struct lttng_kernel_event_desc
*desc
=
1457 event_recorder
->priv
->parent
.desc
;
1458 struct field_location_ctx
*field_location_ctx
;
1462 ret
= lttng_metadata_printf(session
, "{"
1463 "\n\"type\": \"structure\","
1464 "\n\"member-classes\": [");
1468 field_location_ctx
= field_location_ctx_create();
1469 if (!field_location_ctx
) {
1472 "LTTng: CTF2: error allocating field location context\n");
1476 ret
= field_location_stack_push(field_location_ctx
,
1477 SCOPE_STACK_NODE_TYPE_SCOPE
,
1478 "event-record-payload", NULL
);
1480 goto destroy_field_loc
;
1482 for (i
= 0; i
< desc
->tp_class
->nr_fields
; i
++) {
1483 const struct lttng_kernel_event_field
*field
=
1484 desc
->tp_class
->fields
[i
];
1486 ret
= ctf2_metadata_write_field(session
, field
,
1487 field_location_ctx
);
1489 goto destroy_field_loc
;
1491 ret
= field_location_stack_push(field_location_ctx
,
1492 SCOPE_STACK_NODE_TYPE_FIELD
,
1493 field
->name
, field
);
1495 goto destroy_field_loc
;
1497 if (i
< desc
->tp_class
->nr_fields
- 1) {
1498 ret
= lttng_metadata_printf(session
, ", ");
1500 goto destroy_field_loc
;
1504 field_location_stack_pop_n_elem(field_location_ctx
,
1505 desc
->tp_class
->nr_fields
+ 1);
1507 ret
= lttng_metadata_printf(session
, "]\n}\n");
1510 field_location_ctx_destroy(field_location_ctx
);
1515 int ctf2_metadata_write_event_record_class_fragment(
1516 struct lttng_kernel_event_common
*event
)
1518 struct lttng_kernel_event_recorder
*event_recorder
;
1519 struct lttng_kernel_channel_buffer
*chan
;
1520 struct lttng_kernel_session
*session
;
1521 unsigned int nr_fields
;
1524 if (event
->type
!= LTTNG_KERNEL_EVENT_TYPE_RECORDER
)
1528 container_of(event
, struct lttng_kernel_event_recorder
, parent
);
1529 chan
= event_recorder
->chan
;
1530 session
= chan
->parent
.session
;
1532 if (event_recorder
->priv
->metadata_dumped
||
1533 !LTTNG_READ_ONCE(session
->active
))
1536 if (chan
->priv
->channel_type
== METADATA_CHANNEL
)
1539 lttng_metadata_begin(session
);
1541 ret
= ctf2_metadata_write_record_separator(session
);
1545 ret
= lttng_metadata_printf(
1548 "\n\"type\": \"event-record-class\","
1550 "\n\"name\": \"%s\","
1551 "\n\"data-stream-class-id\":%u",
1552 event_recorder
->priv
->id
,
1553 event_recorder
->priv
->parent
.desc
->event_name
,
1554 event_recorder
->chan
->priv
->id
);
1558 nr_fields
= event_recorder
->priv
->parent
.desc
->tp_class
->nr_fields
;
1560 ret
= lttng_metadata_printf(session
,
1561 ",\n\"payload-field-class\":");
1565 ret
= ctf2_metadata_write_payload_field_class(session
,
1569 "LTTng: CTF2: error producing metadata event record payload field class\n");
1574 ret
= lttng_metadata_printf(session
, "\n}\n");
1578 event_recorder
->priv
->metadata_dumped
= 1;
1581 lttng_metadata_end(session
);
1585 static int ctf2_metadata_write_data_stream_class_fragment(
1586 struct lttng_kernel_session
*session
,
1587 struct lttng_kernel_channel_buffer
*chan
)
1591 if (chan
->priv
->metadata_dumped
|| !LTTNG_READ_ONCE(session
->active
))
1594 if (chan
->priv
->channel_type
== METADATA_CHANNEL
)
1597 lttng_metadata_begin(session
);
1599 ret
= ctf2_metadata_write_record_separator(session
);
1603 ret
= lttng_metadata_printf(session
,
1605 "\n\"type\":\"data-stream-class\","
1607 "\n\"default-clock-class-name\": \"%s\","
1608 "\n\"packet-context-field-class\":",
1609 chan
->priv
->id
, trace_clock_name());
1613 ret
= ctf2_metadata_write_packet_context_field_class(session
, chan
);
1616 "LTTng: CTF2: error producing metadata stream class packet context field class\n");
1620 ret
= lttng_metadata_printf(session
,
1621 ",\n\"event-record-header-field-class\":");
1625 if (chan
->priv
->header_type
== 1) {
1626 ret
= ctf2_metadata_write_compact_event_header_field_class(
1630 "LTTng: CTF2: error producing metadata stream class compact event header field class\n");
1634 ret
= ctf2_metadata_write_large_event_header_field_class(
1638 "LTTng: CTF2: error producing metadata stream class large event header field class\n");
1643 if (chan
->priv
->ctx
) {
1644 ret
= lttng_metadata_printf(
1646 ",\n\"event-record-common-context-field-class\":\n");
1650 ret
= ctf2_metadata_write_common_context_field_class(
1651 session
, chan
->priv
->ctx
);
1654 "LTTng: CTF2: error producing metadata stream class common context field class\n");
1659 ret
= lttng_metadata_printf(session
, "\n}\n");
1661 chan
->priv
->metadata_dumped
= 1;
1664 lttng_metadata_end(session
);
1668 int ctf2_metadata_write(struct lttng_kernel_session
*session
)
1670 struct lttng_kernel_channel_buffer_private
*chan_priv
;
1671 struct lttng_kernel_event_recorder_private
*event_recorder_priv
;
1674 if (!LTTNG_READ_ONCE(session
->active
))
1677 lttng_metadata_begin(session
);
1679 if (session
->priv
->metadata_dumped
)
1682 ret
= ctf2_metadata_write_preamble_fragment(session
);
1685 "LTTng: CTF2: error producing metadata preamble fragment\n");
1689 ret
= ctf2_metadata_write_trace_class_fragment(session
);
1692 "LTTng: CTF2: error producing metadata trace class fragment\n");
1696 ret
= ctf2_metadata_write_clock_class_fragment(session
);
1699 "LTTng: CTF2: error producing metadata clock class fragment\n");
1704 list_for_each_entry (chan_priv
, &session
->priv
->chan
, node
) {
1705 ret
= ctf2_metadata_write_data_stream_class_fragment(
1706 session
, chan_priv
->pub
);
1709 "LTTng: CTF2: error producing metadata stream class fragment\n");
1713 list_for_each_entry (event_recorder_priv
, &session
->priv
->events
,
1715 ret
= ctf2_metadata_write_event_record_class_fragment(
1716 &event_recorder_priv
->pub
->parent
);
1719 "LTTng: CTF2: error producing metadata event class fragment\n");
1723 session
->priv
->metadata_dumped
= 1;
1726 lttng_metadata_end(session
);