Fix: translate-trace-ir-to-ctf-ir.c: dereference after `NULL` check
[babeltrace.git] / src / plugins / ctf / fs-sink / translate-trace-ir-to-ctf-ir.c
1 /*
2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
24 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
25 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
26 #include "logging/comp-logging.h"
27
28 #include <babeltrace2/babeltrace.h>
29 #include "common/macros.h"
30 #include "common/common.h"
31 #include "common/assert.h"
32 #include <stdio.h>
33 #include <stdbool.h>
34 #include <string.h>
35 #include <glib.h>
36
37 #include "fs-sink.h"
38 #include "fs-sink-ctf-meta.h"
39
40 struct field_path_elem {
41 uint64_t index_in_parent;
42 GString *name;
43
44 /* Weak */
45 const bt_field_class *ir_fc;
46
47 /* Weak */
48 struct fs_sink_ctf_field_class *parent_fc;
49 };
50
51 struct ctx {
52 bt_logging_level log_level;
53 bt_self_component *self_comp;
54
55 /* Weak */
56 struct fs_sink_ctf_stream_class *cur_sc;
57
58 /* Weak */
59 struct fs_sink_ctf_event_class *cur_ec;
60
61 bt_field_path_scope cur_scope;
62
63 /*
64 * Array of `struct field_path_elem` */
65 GArray *cur_path;
66 };
67
68 static inline
69 struct field_path_elem *cur_path_stack_at(struct ctx *ctx, uint64_t i)
70 {
71 BT_ASSERT(i < ctx->cur_path->len);
72 return &g_array_index(ctx->cur_path, struct field_path_elem, i);
73 }
74
75 static inline
76 struct field_path_elem *cur_path_stack_top(struct ctx *ctx)
77 {
78 BT_ASSERT(ctx->cur_path->len > 0);
79 return cur_path_stack_at(ctx, ctx->cur_path->len - 1);
80 }
81
82 static inline
83 bool is_reserved_member_name(const char *name, const char *reserved_name)
84 {
85 bool is_reserved = false;
86
87 if (strcmp(name, reserved_name) == 0) {
88 is_reserved = true;
89 goto end;
90 }
91
92 if (name[0] == '_' && strcmp(&name[1], reserved_name) == 0) {
93 is_reserved = true;
94 goto end;
95 }
96
97 end:
98 return is_reserved;
99 }
100
101 static const char *reserved_tsdl_keywords[] = {
102 "align",
103 "callsite",
104 "const",
105 "char",
106 "clock",
107 "double",
108 "enum",
109 "env",
110 "event",
111 "floating_point",
112 "float",
113 "integer",
114 "int",
115 "long",
116 "short",
117 "signed",
118 "stream",
119 "string",
120 "struct",
121 "trace",
122 "typealias",
123 "typedef",
124 "unsigned",
125 "variant",
126 "void",
127 "_Bool",
128 "_Complex",
129 "_Imaginary",
130 };
131
132 static inline
133 bool ist_valid_identifier(const char *name)
134 {
135 const char *at;
136 uint64_t i;
137 bool ist_valid = true;
138
139 /* Make sure the name is not a reserved keyword */
140 for (i = 0; i < sizeof(reserved_tsdl_keywords) / sizeof(*reserved_tsdl_keywords);
141 i++) {
142 if (strcmp(name, reserved_tsdl_keywords[i]) == 0) {
143 ist_valid = false;
144 goto end;
145 }
146 }
147
148 /* Make sure the name is not an empty string */
149 if (strlen(name) == 0) {
150 ist_valid = false;
151 goto end;
152 }
153
154 /* Make sure the name starts with a letter or `_` */
155 if (!isalpha(name[0]) && name[0] != '_') {
156 ist_valid = false;
157 goto end;
158 }
159
160 /* Make sure the name only contains letters, digits, and `_` */
161 for (at = name; *at != '\0'; at++) {
162 if (!isalnum(*at) && *at != '_') {
163 ist_valid = false;
164 goto end;
165 }
166 }
167
168 end:
169 return ist_valid;
170 }
171
172 static inline
173 bool must_protect_identifier(const char *name)
174 {
175 uint64_t i;
176 bool must_protect = false;
177
178 /* Protect a reserved keyword */
179 for (i = 0; i < sizeof(reserved_tsdl_keywords) / sizeof(*reserved_tsdl_keywords);
180 i++) {
181 if (strcmp(name, reserved_tsdl_keywords[i]) == 0) {
182 must_protect = true;
183 goto end;
184 }
185 }
186
187 /* Protect an identifier which already starts with `_` */
188 if (name[0] == '_') {
189 must_protect = true;
190 goto end;
191 }
192
193 end:
194 return must_protect;
195 }
196
197 static inline
198 int cur_path_stack_push(struct ctx *ctx,
199 uint64_t index_in_parent, const char *name,
200 bool force_protect_name, const bt_field_class *ir_fc,
201 struct fs_sink_ctf_field_class *parent_fc)
202 {
203 int ret = 0;
204 struct field_path_elem *field_path_elem;
205
206 g_array_set_size(ctx->cur_path, ctx->cur_path->len + 1);
207 field_path_elem = cur_path_stack_top(ctx);
208 field_path_elem->index_in_parent = index_in_parent;
209 field_path_elem->name = g_string_new(NULL);
210
211 if (name) {
212 if (force_protect_name) {
213 g_string_assign(field_path_elem->name, "_");
214 }
215
216 g_string_append(field_path_elem->name, name);
217
218 if (ctx->cur_scope == BT_FIELD_PATH_SCOPE_PACKET_CONTEXT) {
219 if (is_reserved_member_name(name, "packet_size") ||
220 is_reserved_member_name(name, "content_size") ||
221 is_reserved_member_name(name, "timestamp_begin") ||
222 is_reserved_member_name(name, "timestamp_end") ||
223 is_reserved_member_name(name, "events_discarded") ||
224 is_reserved_member_name(name, "packet_seq_num")) {
225 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
226 "or variant field class option name: name=\"%s\"",
227 name);
228 ret = -1;
229 goto end;
230 }
231 }
232
233 if (!ist_valid_identifier(field_path_elem->name->str)) {
234 ret = -1;
235 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
236 "or variant field class option name: name=\"%s\"",
237 field_path_elem->name->str);
238 goto end;
239 }
240 }
241
242 field_path_elem->ir_fc = ir_fc;
243 field_path_elem->parent_fc = parent_fc;
244
245 end:
246 return ret;
247 }
248
249 static inline
250 void cur_path_stack_pop(struct ctx *ctx)
251 {
252 struct field_path_elem *field_path_elem;
253
254 BT_ASSERT(ctx->cur_path->len > 0);
255 field_path_elem = cur_path_stack_top(ctx);
256
257 if (field_path_elem->name) {
258 g_string_free(field_path_elem->name, TRUE);
259 field_path_elem->name = NULL;
260 }
261
262 g_array_set_size(ctx->cur_path, ctx->cur_path->len - 1);
263 }
264
265 /*
266 * Creates a relative field ref (a single name) from IR field path
267 * `tgt_ir_field_path`.
268 *
269 * This function tries to locate the target field class recursively from
270 * the top to the bottom of the context's current path using only the
271 * target field class's own name. This is because many CTF reading tools
272 * do not support a relative field ref with more than one element, for
273 * example `prev_struct.len`.
274 *
275 * Returns a negative value if this resolving operation failed.
276 */
277 static
278 int create_relative_field_ref(struct ctx *ctx,
279 const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref,
280 struct fs_sink_ctf_field_class **user_tgt_fc)
281 {
282 int ret = 0;
283 struct fs_sink_ctf_field_class *tgt_fc = NULL;
284 uint64_t i;
285 int64_t si;
286 const char *tgt_fc_name = NULL;
287 struct field_path_elem *field_path_elem;
288
289 /* Get target field class's name */
290 switch (bt_field_path_get_root_scope(tgt_ir_field_path)) {
291 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
292 BT_ASSERT(ctx->cur_sc);
293 tgt_fc = ctx->cur_sc->packet_context_fc;
294 break;
295 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
296 BT_ASSERT(ctx->cur_sc);
297 tgt_fc = ctx->cur_sc->event_common_context_fc;
298 break;
299 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
300 BT_ASSERT(ctx->cur_ec);
301 tgt_fc = ctx->cur_ec->spec_context_fc;
302 break;
303 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
304 BT_ASSERT(ctx->cur_ec);
305 tgt_fc = ctx->cur_ec->payload_fc;
306 break;
307 default:
308 abort();
309 }
310
311 i = 0;
312
313 while (i < bt_field_path_get_item_count(tgt_ir_field_path)) {
314 const bt_field_path_item *fp_item =
315 bt_field_path_borrow_item_by_index_const(
316 tgt_ir_field_path, i);
317 struct fs_sink_ctf_named_field_class *named_fc = NULL;
318
319 BT_ASSERT(tgt_fc);
320 BT_ASSERT(fp_item);
321
322 switch (tgt_fc->type) {
323 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
324 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
325 BT_FIELD_PATH_ITEM_TYPE_INDEX);
326 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
327 (void *) tgt_fc,
328 bt_field_path_item_index_get_index(fp_item));
329 break;
330 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
331 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
332 BT_FIELD_PATH_ITEM_TYPE_INDEX);
333 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
334 (void *) tgt_fc,
335 bt_field_path_item_index_get_index(fp_item));
336 break;
337 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
338 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
339 {
340 struct fs_sink_ctf_field_class_array_base *array_base_fc =
341 (void *) tgt_fc;
342
343 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
344 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT);
345 tgt_fc = array_base_fc->elem_fc;
346 break;
347 }
348 default:
349 abort();
350 }
351
352 if (named_fc) {
353 tgt_fc = named_fc->fc;
354 tgt_fc_name = named_fc->name->str;
355 i++;
356 }
357 }
358
359 BT_ASSERT(tgt_fc);
360 BT_ASSERT(tgt_fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_INT);
361 BT_ASSERT(tgt_fc_name);
362
363 /* Find target field class having this name in current context */
364 for (si = ctx->cur_path->len - 1; si >= 0; si--) {
365 struct fs_sink_ctf_field_class *fc;
366 struct fs_sink_ctf_field_class_struct *struct_fc;
367 struct fs_sink_ctf_field_class_variant *var_fc;
368 struct fs_sink_ctf_named_field_class *named_fc;
369 uint64_t len;
370
371 field_path_elem = cur_path_stack_at(ctx, (uint64_t) si);
372 fc = field_path_elem->parent_fc;
373 if (!fc) {
374 /* Reached stack's bottom */
375 ret = -1;
376 goto end;
377 }
378
379 switch (fc->type) {
380 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
381 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
382 break;
383 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
384 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
385 continue;
386 default:
387 /* Not supported by TSDL 1.8 */
388 ret = -1;
389 goto end;
390 }
391
392 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
393 struct_fc = (void *) fc;
394 len = struct_fc->members->len;
395 } else {
396 var_fc = (void *) fc;
397 len = var_fc->options->len;
398 }
399
400 for (i = 0; i < len; i++) {
401 if (fc->type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
402 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
403 struct_fc, i);
404 } else {
405 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
406 var_fc, i);
407 }
408
409 if (strcmp(named_fc->name->str, tgt_fc_name) == 0) {
410 if (named_fc->fc == tgt_fc) {
411 g_string_assign(tgt_field_ref,
412 tgt_fc_name);
413
414 if (user_tgt_fc) {
415 *user_tgt_fc = tgt_fc;
416 }
417 } else {
418 /*
419 * Using only the target field
420 * class's name, we're not
421 * reaching the target field
422 * class. This is not supported
423 * by TSDL 1.8.
424 */
425 ret = -1;
426 }
427
428 goto end;
429 }
430 }
431 }
432
433 end:
434 return ret;
435 }
436
437 /*
438 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
439 *
440 * Returns a negative value if this resolving operation failed.
441 */
442 static
443 int create_absolute_field_ref(struct ctx *ctx,
444 const bt_field_path *tgt_ir_field_path, GString *tgt_field_ref,
445 struct fs_sink_ctf_field_class **user_tgt_fc)
446 {
447 int ret = 0;
448 struct fs_sink_ctf_field_class *fc = NULL;
449 uint64_t i;
450
451 switch (bt_field_path_get_root_scope(tgt_ir_field_path)) {
452 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
453 BT_ASSERT(ctx->cur_sc);
454 fc = ctx->cur_sc->packet_context_fc;
455 g_string_assign(tgt_field_ref, "stream.packet.context");
456 break;
457 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
458 BT_ASSERT(ctx->cur_sc);
459 fc = ctx->cur_sc->event_common_context_fc;
460 g_string_assign(tgt_field_ref, "stream.event.context");
461 break;
462 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
463 BT_ASSERT(ctx->cur_ec);
464 fc = ctx->cur_ec->spec_context_fc;
465 g_string_assign(tgt_field_ref, "event.context");
466 break;
467 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
468 BT_ASSERT(ctx->cur_ec);
469 fc = ctx->cur_ec->payload_fc;
470 g_string_assign(tgt_field_ref, "event.fields");
471 break;
472 default:
473 abort();
474 }
475
476 BT_ASSERT(fc);
477
478 for (i = 0; i < bt_field_path_get_item_count(tgt_ir_field_path); i++) {
479 const bt_field_path_item *fp_item =
480 bt_field_path_borrow_item_by_index_const(
481 tgt_ir_field_path, i);
482 struct fs_sink_ctf_named_field_class *named_fc = NULL;
483
484 if (bt_field_path_item_get_type(fp_item) !=
485 BT_FIELD_PATH_ITEM_TYPE_INDEX) {
486 /* Not supported by TSDL 1.8 */
487 ret = -1;
488 goto end;
489 }
490
491 switch (fc->type) {
492 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
493 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
494 BT_FIELD_PATH_ITEM_TYPE_INDEX);
495 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
496 (void *) fc,
497 bt_field_path_item_index_get_index(fp_item));
498 break;
499 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
500 BT_ASSERT(bt_field_path_item_get_type(fp_item) ==
501 BT_FIELD_PATH_ITEM_TYPE_INDEX);
502 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
503 (void *) fc,
504 bt_field_path_item_index_get_index(fp_item));
505 break;
506 default:
507 abort();
508 }
509
510 BT_ASSERT(named_fc);
511 g_string_append_c(tgt_field_ref, '.');
512 g_string_append(tgt_field_ref, named_fc->name->str);
513 fc = named_fc->fc;
514 }
515
516 if (user_tgt_fc) {
517 *user_tgt_fc = fc;
518 }
519
520 end:
521 return ret;
522 }
523
524 /*
525 * Resolves a target field class located at `tgt_ir_field_path`, writing
526 * the resolved field ref to `tgt_field_ref` and setting
527 * `*create_before` according to whether or not the target field must be
528 * created immediately before (in which case `tgt_field_ref` is
529 * irrelevant).
530 */
531 static
532 void resolve_field_class(struct ctx *ctx,
533 const bt_field_path *tgt_ir_field_path,
534 GString *tgt_field_ref, bool *create_before,
535 struct fs_sink_ctf_field_class **user_tgt_fc)
536 {
537 int ret;
538 bt_field_path_scope tgt_scope;
539
540 *create_before = false;
541
542 if (!tgt_ir_field_path) {
543 *create_before = true;
544 goto end;
545 }
546
547 tgt_scope = bt_field_path_get_root_scope(tgt_ir_field_path);
548
549 if (tgt_scope == ctx->cur_scope) {
550 /*
551 * Try, in this order:
552 *
553 * 1. Use a relative path, using only the target field
554 * class's name. This is what is the most commonly
555 * supported by popular CTF reading tools.
556 *
557 * 2. Use an absolute path. This could fail if there's
558 * an array field class from the current root's field
559 * class to the target field class.
560 *
561 * 3. Create the target field class before the
562 * requesting field class (fallback).
563 */
564 ret = create_relative_field_ref(ctx, tgt_ir_field_path,
565 tgt_field_ref, user_tgt_fc);
566 if (ret) {
567 ret = create_absolute_field_ref(ctx, tgt_ir_field_path,
568 tgt_field_ref, user_tgt_fc);
569 if (ret) {
570 *create_before = true;
571 ret = 0;
572 goto end;
573 }
574 }
575 } else {
576 ret = create_absolute_field_ref(ctx, tgt_ir_field_path,
577 tgt_field_ref, user_tgt_fc);
578
579 /* It must always work in previous scopes */
580 BT_ASSERT(ret == 0);
581 }
582
583 end:
584 return;
585 }
586
587 static
588 int translate_field_class(struct ctx *ctx);
589
590 static inline
591 void append_to_parent_field_class(struct ctx *ctx,
592 struct fs_sink_ctf_field_class *fc)
593 {
594 struct fs_sink_ctf_field_class *parent_fc =
595 cur_path_stack_top(ctx)->parent_fc;
596
597 switch (parent_fc->type) {
598 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
599 fs_sink_ctf_field_class_struct_append_member((void *) parent_fc,
600 cur_path_stack_top(ctx)->name->str, fc);
601 break;
602 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
603 fs_sink_ctf_field_class_variant_append_option((void *) parent_fc,
604 cur_path_stack_top(ctx)->name->str, fc);
605 break;
606 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
607 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
608 {
609 struct fs_sink_ctf_field_class_array_base *array_base_fc =
610 (void *) parent_fc;
611
612 BT_ASSERT(!array_base_fc->elem_fc);
613 array_base_fc->elem_fc = fc;
614 array_base_fc->base.alignment = fc->alignment;
615 break;
616 }
617 default:
618 abort();
619 }
620 }
621
622 static inline
623 void update_parent_field_class_alignment(struct ctx *ctx,
624 unsigned int alignment)
625 {
626 struct fs_sink_ctf_field_class *parent_fc =
627 cur_path_stack_top(ctx)->parent_fc;
628
629 switch (parent_fc->type) {
630 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
631 fs_sink_ctf_field_class_struct_align_at_least(
632 (void *) parent_fc, alignment);
633 break;
634 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
635 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
636 {
637 struct fs_sink_ctf_field_class_array_base *array_base_fc =
638 (void *) parent_fc;
639
640 array_base_fc->base.alignment = alignment;
641 break;
642 }
643 default:
644 break;
645 }
646 }
647
648 static inline
649 int translate_structure_field_class_members(struct ctx *ctx,
650 struct fs_sink_ctf_field_class_struct *struct_fc,
651 const bt_field_class *ir_fc)
652 {
653 int ret = 0;
654 uint64_t i;
655
656 for (i = 0; i < bt_field_class_structure_get_member_count(ir_fc); i++) {
657 const bt_field_class_structure_member *member;
658 const char *name;
659 const bt_field_class *memb_ir_fc;
660
661 member =
662 bt_field_class_structure_borrow_member_by_index_const(
663 ir_fc, i);
664 name = bt_field_class_structure_member_get_name(member);
665 memb_ir_fc = bt_field_class_structure_member_borrow_field_class_const(
666 member);
667 ret = cur_path_stack_push(ctx, i, name, true, memb_ir_fc,
668 (void *) struct_fc);
669 if (ret) {
670 BT_COMP_LOGE("Cannot translate structure field class member: "
671 "name=\"%s\"", name);
672 goto end;
673 }
674
675 ret = translate_field_class(ctx);
676 if (ret) {
677 BT_COMP_LOGE("Cannot translate structure field class member: "
678 "name=\"%s\"", name);
679 goto end;
680 }
681
682 cur_path_stack_pop(ctx);
683 }
684
685 end:
686 return ret;
687 }
688
689 static inline
690 int translate_structure_field_class(struct ctx *ctx)
691 {
692 int ret;
693 struct fs_sink_ctf_field_class_struct *fc =
694 fs_sink_ctf_field_class_struct_create_empty(
695 cur_path_stack_top(ctx)->ir_fc,
696 cur_path_stack_top(ctx)->index_in_parent);
697
698 BT_ASSERT(fc);
699 append_to_parent_field_class(ctx, (void *) fc);
700 ret = translate_structure_field_class_members(ctx, fc, fc->base.ir_fc);
701 if (ret) {
702 goto end;
703 }
704
705 update_parent_field_class_alignment(ctx, fc->base.alignment);
706
707 end:
708 return ret;
709 }
710
711 /*
712 * This function protects a given variant FC option name (with the `_`
713 * prefix) if required. On success, `name_buf->str` contains the variant
714 * FC option name to use (original option name or protected if
715 * required).
716 *
717 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
718 * close as possible to an original CTF trace as decoded by
719 * `src.ctf.fs`.
720 *
721 * This scenario is valid in CTF 1.8:
722 *
723 * enum {
724 * HELLO,
725 * MEOW
726 * } tag;
727 *
728 * variant <tag> {
729 * int HELLO;
730 * string MEOW;
731 * };
732 *
733 * Once in trace IR, the enumeration FC mapping names and variant FC
734 * option names are kept as is. For this reason, we don't want to
735 * protect the variant FC option names here (by prepending `_`): this
736 * would make the variant FC option name and the enumeration FC mapping
737 * name not match.
738 *
739 * This scenario is also valid in CTF 1.8:
740 *
741 * enum {
742 * _HELLO,
743 * MEOW
744 * } tag;
745 *
746 * variant <tag> {
747 * int _HELLO;
748 * string MEOW;
749 * };
750 *
751 * Once in trace IR, the enumeration FC mapping names are kept as is,
752 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
753 * for presentation, as recommended by CTF 1.8). When going back to
754 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
755 * the corresponding enumeration FC mapping name.
756 *
757 * This scenario is also valid in CTF 1.8:
758 *
759 * enum {
760 * __HELLO,
761 * MEOW
762 * } tag;
763 *
764 * variant <tag> {
765 * int __HELLO;
766 * string MEOW;
767 * };
768 *
769 * Once in trace IR, the enumeration FC mapping names are kept as is,
770 * but the `__HELLO` variant FC option name becomes `_HELLO`
771 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
772 * so that it becomes `__HELLO` to match the corresponding enumeration
773 * FC mapping name.
774 *
775 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
776 * FC mapping and a corresponding variant FC option. We can use that
777 * fact to find the original variant FC option names by matching variant
778 * FC options and enumeration FC mappings by range set.
779 */
780 static
781 int maybe_protect_variant_option_name(const bt_field_class *ir_var_fc,
782 const bt_field_class *ir_tag_fc, uint64_t opt_i,
783 GString *name_buf)
784 {
785 int ret = 0;
786 uint64_t i;
787 bt_field_class_type ir_var_fc_type;
788 const void *opt_ranges = NULL;
789 const char *mapping_label = NULL;
790 const char *ir_opt_name;
791 const bt_field_class_variant_option *base_var_opt;
792 bool force_protect = false;
793
794 ir_var_fc_type = bt_field_class_get_type(ir_var_fc);
795 base_var_opt = bt_field_class_variant_borrow_option_by_index_const(
796 ir_var_fc, opt_i);
797 BT_ASSERT(base_var_opt);
798 ir_opt_name = bt_field_class_variant_option_get_name(base_var_opt);
799 BT_ASSERT(ir_opt_name);
800
801 /*
802 * Check if the variant FC option name is required to be
803 * protected (reserved TSDL keyword or starts with `_`). In that
804 * case, the name of the selector FC mapping we find must match
805 * exactly the protected name.
806 */
807 force_protect = must_protect_identifier(ir_opt_name);
808 if (force_protect) {
809 g_string_assign(name_buf, "_");
810 g_string_append(name_buf, ir_opt_name);
811 } else {
812 g_string_assign(name_buf, ir_opt_name);
813 }
814
815 /* Borrow option's ranges */
816 if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR) {
817 /* No ranges: we're done */
818 goto end;
819 } if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR) {
820 const bt_field_class_variant_with_selector_unsigned_option *var_opt =
821 bt_field_class_variant_with_selector_unsigned_borrow_option_by_index_const(
822 ir_var_fc, opt_i);
823 opt_ranges =
824 bt_field_class_variant_with_selector_unsigned_option_borrow_ranges_const(
825 var_opt);
826 } else {
827 const bt_field_class_variant_with_selector_signed_option *var_opt =
828 bt_field_class_variant_with_selector_signed_borrow_option_by_index_const(
829 ir_var_fc, opt_i);
830 opt_ranges =
831 bt_field_class_variant_with_selector_signed_option_borrow_ranges_const(
832 var_opt);
833 }
834
835 /* Find corresponding mapping by range set in selector FC */
836 for (i = 0; i < bt_field_class_enumeration_get_mapping_count(ir_tag_fc);
837 i++) {
838 if (ir_var_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR) {
839 const bt_field_class_enumeration_mapping *mapping_base;
840 const bt_field_class_enumeration_unsigned_mapping *mapping;
841 const bt_integer_range_set_unsigned *mapping_ranges;
842
843 mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
844 ir_tag_fc, i);
845 mapping_ranges = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
846 mapping);
847
848 if (bt_integer_range_set_unsigned_compare(opt_ranges,
849 mapping_ranges)) {
850 /* We have a winner */
851 mapping_base =
852 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
853 mapping);
854 mapping_label =
855 bt_field_class_enumeration_mapping_get_label(
856 mapping_base);
857 break;
858 }
859 } else {
860 const bt_field_class_enumeration_mapping *mapping_base;
861 const bt_field_class_enumeration_signed_mapping *mapping;
862 const bt_integer_range_set_signed *mapping_ranges;
863
864 mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
865 ir_tag_fc, i);
866 mapping_ranges = bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
867 mapping);
868
869 if (bt_integer_range_set_signed_compare(opt_ranges,
870 mapping_ranges)) {
871 /* We have a winner */
872 mapping_base =
873 bt_field_class_enumeration_signed_mapping_as_mapping_const(
874 mapping);
875 mapping_label =
876 bt_field_class_enumeration_mapping_get_label(
877 mapping_base);
878 break;
879 }
880 }
881 }
882
883 if (!mapping_label) {
884 /* Range set not found: invalid selector for CTF 1.8 */
885 ret = -1;
886 goto end;
887 }
888
889 /*
890 * If the enumeration FC mapping name is not the same as the
891 * variant FC option name and we didn't protect already, try
892 * protecting the option name and check again.
893 */
894 if (strcmp(mapping_label, name_buf->str) != 0) {
895 if (force_protect) {
896 ret = -1;
897 goto end;
898 }
899
900 if (mapping_label[0] == '\0') {
901 ret = -1;
902 goto end;
903 }
904
905 g_string_assign(name_buf, "_");
906 g_string_append(name_buf, ir_opt_name);
907
908 if (strcmp(mapping_label, name_buf->str) != 0) {
909 ret = -1;
910 goto end;
911 }
912 }
913
914 end:
915 return ret;
916 }
917
918 static inline
919 int translate_variant_field_class(struct ctx *ctx)
920 {
921 int ret = 0;
922 uint64_t i;
923 struct fs_sink_ctf_field_class_variant *fc =
924 fs_sink_ctf_field_class_variant_create_empty(
925 cur_path_stack_top(ctx)->ir_fc,
926 cur_path_stack_top(ctx)->index_in_parent);
927 bt_field_class_type ir_fc_type;
928 const bt_field_path *ir_selector_field_path = NULL;
929 struct fs_sink_ctf_field_class *tgt_fc = NULL;
930 GString *name_buf = g_string_new(NULL);
931 bt_value *prot_opt_names = bt_value_array_create();
932 uint64_t opt_count;
933
934 BT_ASSERT(fc);
935 BT_ASSERT(name_buf);
936 BT_ASSERT(prot_opt_names);
937 ir_fc_type = bt_field_class_get_type(fc->base.ir_fc);
938 opt_count = bt_field_class_variant_get_option_count(fc->base.ir_fc);
939
940 if (ir_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR ||
941 ir_fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR) {
942 ir_selector_field_path = bt_field_class_variant_with_selector_borrow_selector_field_path_const(
943 fc->base.ir_fc);
944 BT_ASSERT(ir_selector_field_path);
945 }
946
947 /* Resolve tag field class before appending to parent */
948 resolve_field_class(ctx, ir_selector_field_path, fc->tag_ref,
949 &fc->tag_is_before, &tgt_fc);
950
951 if (ir_selector_field_path && tgt_fc) {
952 uint64_t mapping_count;
953 uint64_t option_count;
954
955 /* CTF 1.8: selector FC must be an enumeration FC */
956 bt_field_class_type type = bt_field_class_get_type(
957 tgt_fc->ir_fc);
958
959 if (type != BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION &&
960 type != BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION) {
961 fc->tag_is_before = true;
962 goto validate_opts;
963 }
964
965 /*
966 * Call maybe_protect_variant_option_name() for each
967 * option below. In that case we also want selector FC
968 * to contain as many mappings as the variant FC has
969 * options.
970 */
971 mapping_count = bt_field_class_enumeration_get_mapping_count(
972 tgt_fc->ir_fc);
973 option_count = bt_field_class_variant_get_option_count(
974 fc->base.ir_fc);
975
976 if (mapping_count != option_count) {
977 fc->tag_is_before = true;
978 goto validate_opts;
979 }
980 } else {
981 /*
982 * No compatible selector field class for CTF 1.8:
983 * create the appropriate selector field class.
984 */
985 fc->tag_is_before = true;
986 goto validate_opts;
987 }
988
989 validate_opts:
990 /*
991 * First pass: detect any option name clash with option name
992 * protection. In that case, we don't fail: just create the
993 * selector field class before the variant field class.
994 *
995 * After this, `prot_opt_names` contains the final option names,
996 * potentially protected if needed. They can still be invalid
997 * TSDL identifiers however; this will be checked by
998 * cur_path_stack_push().
999 */
1000 for (i = 0; i < opt_count; i++) {
1001 if (!fc->tag_is_before) {
1002 BT_ASSERT(tgt_fc->ir_fc);
1003 ret = maybe_protect_variant_option_name(fc->base.ir_fc,
1004 tgt_fc->ir_fc, i, name_buf);
1005 if (ret) {
1006 fc->tag_is_before = true;
1007 }
1008 }
1009
1010 ret = bt_value_array_append_string_element(prot_opt_names,
1011 name_buf->str);
1012 if (ret) {
1013 goto end;
1014 }
1015 }
1016
1017 for (i = 0; i < opt_count; i++) {
1018 uint64_t j;
1019 const bt_value *opt_name_a =
1020 bt_value_array_borrow_element_by_index_const(
1021 prot_opt_names, i);
1022
1023 for (j = 0; j < opt_count; j++) {
1024 const bt_value *opt_name_b;
1025
1026 if (i == j) {
1027 continue;
1028 }
1029
1030 opt_name_b =
1031 bt_value_array_borrow_element_by_index_const(
1032 prot_opt_names, j);
1033 if (bt_value_compare(opt_name_a, opt_name_b)) {
1034 /*
1035 * Variant FC option names are not
1036 * unique when protected.
1037 */
1038 fc->tag_is_before = true;
1039 goto append_to_parent;
1040 }
1041 }
1042 }
1043
1044 append_to_parent:
1045 append_to_parent_field_class(ctx, (void *) fc);
1046
1047 for (i = 0; i < opt_count; i++) {
1048 const bt_field_class_variant_option *opt;
1049 const bt_field_class *opt_ir_fc;
1050 const bt_value *prot_opt_name_val =
1051 bt_value_array_borrow_element_by_index_const(
1052 prot_opt_names, i);
1053 const char *prot_opt_name = bt_value_string_get(
1054 prot_opt_name_val);
1055
1056 BT_ASSERT(prot_opt_name);
1057 opt = bt_field_class_variant_borrow_option_by_index_const(
1058 fc->base.ir_fc, i);
1059 opt_ir_fc = bt_field_class_variant_option_borrow_field_class_const(
1060 opt);
1061
1062 /*
1063 * We don't ask cur_path_stack_push() to protect the
1064 * option name because it's already protected at this
1065 * point.
1066 */
1067 ret = cur_path_stack_push(ctx, i, prot_opt_name, false,
1068 opt_ir_fc, (void *) fc);
1069 if (ret) {
1070 BT_COMP_LOGE("Cannot translate variant field class option: "
1071 "name=\"%s\"", prot_opt_name);
1072 goto end;
1073 }
1074
1075 ret = translate_field_class(ctx);
1076 if (ret) {
1077 BT_COMP_LOGE("Cannot translate variant field class option: "
1078 "name=\"%s\"", prot_opt_name);
1079 goto end;
1080 }
1081
1082 cur_path_stack_pop(ctx);
1083 }
1084
1085 end:
1086 if (name_buf) {
1087 g_string_free(name_buf, TRUE);
1088 }
1089
1090 bt_value_put_ref(prot_opt_names);
1091 return ret;
1092 }
1093
1094 static inline
1095 int translate_static_array_field_class(struct ctx *ctx)
1096 {
1097 struct fs_sink_ctf_field_class_array *fc =
1098 fs_sink_ctf_field_class_array_create_empty(
1099 cur_path_stack_top(ctx)->ir_fc,
1100 cur_path_stack_top(ctx)->index_in_parent);
1101 const bt_field_class *elem_ir_fc =
1102 bt_field_class_array_borrow_element_field_class_const(
1103 fc->base.base.ir_fc);
1104 int ret;
1105
1106 BT_ASSERT(fc);
1107 append_to_parent_field_class(ctx, (void *) fc);
1108 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, elem_ir_fc,
1109 (void *) fc);
1110 if (ret) {
1111 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1112 goto end;
1113 }
1114
1115 ret = translate_field_class(ctx);
1116 if (ret) {
1117 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1118 goto end;
1119 }
1120
1121 cur_path_stack_pop(ctx);
1122 update_parent_field_class_alignment(ctx, fc->base.base.alignment);
1123
1124 end:
1125 return ret;
1126 }
1127
1128 static inline
1129 int translate_dynamic_array_field_class(struct ctx *ctx)
1130 {
1131 struct fs_sink_ctf_field_class_sequence *fc =
1132 fs_sink_ctf_field_class_sequence_create_empty(
1133 cur_path_stack_top(ctx)->ir_fc,
1134 cur_path_stack_top(ctx)->index_in_parent);
1135 const bt_field_class *elem_ir_fc =
1136 bt_field_class_array_borrow_element_field_class_const(
1137 fc->base.base.ir_fc);
1138 int ret;
1139
1140 BT_ASSERT(fc);
1141
1142 /* Resolve length field class before appending to parent */
1143 resolve_field_class(ctx,
1144 bt_field_class_array_dynamic_borrow_length_field_path_const(
1145 fc->base.base.ir_fc),
1146 fc->length_ref, &fc->length_is_before, NULL);
1147
1148 append_to_parent_field_class(ctx, (void *) fc);
1149 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, elem_ir_fc,
1150 (void *) fc);
1151 if (ret) {
1152 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1153 goto end;
1154 }
1155
1156 ret = translate_field_class(ctx);
1157 if (ret) {
1158 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1159 goto end;
1160 }
1161
1162 cur_path_stack_pop(ctx);
1163 update_parent_field_class_alignment(ctx, fc->base.base.alignment);
1164
1165 end:
1166 return ret;
1167 }
1168
1169 static inline
1170 int translate_integer_field_class(struct ctx *ctx)
1171 {
1172 struct fs_sink_ctf_field_class_int *fc =
1173 fs_sink_ctf_field_class_int_create(
1174 cur_path_stack_top(ctx)->ir_fc,
1175 cur_path_stack_top(ctx)->index_in_parent);
1176
1177 BT_ASSERT(fc);
1178 append_to_parent_field_class(ctx, (void *) fc);
1179 return 0;
1180 }
1181
1182 static inline
1183 int translate_real_field_class(struct ctx *ctx)
1184 {
1185 struct fs_sink_ctf_field_class_float *fc =
1186 fs_sink_ctf_field_class_float_create(
1187 cur_path_stack_top(ctx)->ir_fc,
1188 cur_path_stack_top(ctx)->index_in_parent);
1189
1190 BT_ASSERT(fc);
1191 append_to_parent_field_class(ctx, (void *) fc);
1192 return 0;
1193 }
1194
1195 static inline
1196 int translate_string_field_class(struct ctx *ctx)
1197 {
1198 struct fs_sink_ctf_field_class_string *fc =
1199 fs_sink_ctf_field_class_string_create(
1200 cur_path_stack_top(ctx)->ir_fc,
1201 cur_path_stack_top(ctx)->index_in_parent);
1202
1203 BT_ASSERT(fc);
1204 append_to_parent_field_class(ctx, (void *) fc);
1205 return 0;
1206 }
1207
1208 /*
1209 * Translates a field class, recursively.
1210 *
1211 * The field class's IR field class, parent field class, and index
1212 * within its parent are in the context's current path's top element
1213 * (cur_path_stack_top()).
1214 */
1215 static
1216 int translate_field_class(struct ctx *ctx)
1217 {
1218 int ret;
1219
1220 switch (bt_field_class_get_type(cur_path_stack_top(ctx)->ir_fc)) {
1221 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER:
1222 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER:
1223 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION:
1224 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION:
1225 ret = translate_integer_field_class(ctx);
1226 break;
1227 case BT_FIELD_CLASS_TYPE_REAL:
1228 ret = translate_real_field_class(ctx);
1229 break;
1230 case BT_FIELD_CLASS_TYPE_STRING:
1231 ret = translate_string_field_class(ctx);
1232 break;
1233 case BT_FIELD_CLASS_TYPE_STRUCTURE:
1234 ret = translate_structure_field_class(ctx);
1235 break;
1236 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
1237 ret = translate_static_array_field_class(ctx);
1238 break;
1239 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
1240 ret = translate_dynamic_array_field_class(ctx);
1241 break;
1242 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
1243 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
1244 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
1245 ret = translate_variant_field_class(ctx);
1246 break;
1247 default:
1248 abort();
1249 }
1250
1251 return ret;
1252 }
1253
1254 static
1255 int set_field_ref(struct fs_sink_ctf_field_class *fc, const char *fc_name,
1256 struct fs_sink_ctf_field_class *parent_fc)
1257 {
1258 int ret = 0;
1259 GString *field_ref = NULL;
1260 bool is_before;
1261 const char *tgt_type;
1262 struct fs_sink_ctf_field_class_struct *parent_struct_fc =
1263 (void *) parent_fc;
1264 uint64_t i;
1265 unsigned int suffix = 0;
1266
1267 if (!fc_name || !parent_fc ||
1268 parent_fc->type != FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
1269 /* Not supported */
1270 ret = -1;
1271 goto end;
1272 }
1273
1274 switch (fc->type) {
1275 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
1276 {
1277 struct fs_sink_ctf_field_class_sequence *seq_fc = (void *) fc;
1278
1279 field_ref = seq_fc->length_ref;
1280 is_before = seq_fc->length_is_before;
1281 tgt_type = "len";
1282 break;
1283 }
1284 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
1285 {
1286 struct fs_sink_ctf_field_class_variant *var_fc = (void *) fc;
1287
1288 field_ref = var_fc->tag_ref;
1289 is_before = var_fc->tag_is_before;
1290 tgt_type = "tag";
1291 break;
1292 }
1293 default:
1294 abort();
1295 }
1296
1297 BT_ASSERT(field_ref);
1298
1299 if (!is_before) {
1300 goto end;
1301 }
1302
1303 /* Initial field ref */
1304 g_string_printf(field_ref, "__%s_%s", fc_name, tgt_type);
1305
1306 /*
1307 * Make sure field ref does not clash with an existing field
1308 * class name within the same parent structure field class.
1309 */
1310 while (true) {
1311 bool name_ok = true;
1312
1313 for (i = 0; i < parent_struct_fc->members->len; i++) {
1314 struct fs_sink_ctf_named_field_class *named_fc =
1315 fs_sink_ctf_field_class_struct_borrow_member_by_index(
1316 parent_struct_fc, i);
1317
1318 if (strcmp(field_ref->str, named_fc->name->str) == 0) {
1319 /* Name clash */
1320 name_ok = false;
1321 break;
1322 }
1323 }
1324
1325 if (name_ok) {
1326 /* No clash: we're done */
1327 break;
1328 }
1329
1330 /* Append suffix and try again */
1331 g_string_printf(field_ref, "__%s_%s_%u", fc_name, tgt_type,
1332 suffix);
1333 suffix++;
1334 }
1335
1336 end:
1337 return ret;
1338 }
1339
1340 /*
1341 * This function recursively sets field refs of sequence and variant
1342 * field classes when they are immediately before, avoiding name clashes
1343 * with existing field class names.
1344 *
1345 * It can fail at this point if, for example, a sequence field class of
1346 * which to set the length's field ref has something else than a
1347 * structure field class as its parent: in this case, there's no
1348 * location to place the length field class immediately before the
1349 * sequence field class.
1350 */
1351 static
1352 int set_field_refs(struct fs_sink_ctf_field_class * const fc,
1353 const char *fc_name, struct fs_sink_ctf_field_class *parent_fc)
1354 {
1355 int ret = 0;
1356 enum fs_sink_ctf_field_class_type fc_type;
1357 BT_ASSERT(fc);
1358
1359 fc_type = fc->type;
1360
1361 switch (fc_type) {
1362 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT:
1363 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT:
1364 {
1365 uint64_t i;
1366 uint64_t len;
1367 struct fs_sink_ctf_field_class_struct *struct_fc;
1368 struct fs_sink_ctf_field_class_variant *var_fc = NULL;
1369 struct fs_sink_ctf_named_field_class *named_fc;
1370
1371 if (fc_type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
1372 struct_fc = (void *) fc;
1373 len = struct_fc->members->len;
1374 } else {
1375 var_fc = (void *) fc;
1376 len = var_fc->options->len;
1377 ret = set_field_ref(fc, fc_name, parent_fc);
1378 if (ret) {
1379 goto end;
1380 }
1381 }
1382
1383 for (i = 0; i < len; i++) {
1384 if (fc_type == FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT) {
1385 named_fc = fs_sink_ctf_field_class_struct_borrow_member_by_index(
1386 struct_fc, i);
1387 } else {
1388 named_fc = fs_sink_ctf_field_class_variant_borrow_option_by_index(
1389 var_fc, i);
1390 }
1391
1392 ret = set_field_refs(named_fc->fc, named_fc->name->str,
1393 fc);
1394 if (ret) {
1395 goto end;
1396 }
1397 }
1398
1399 break;
1400 }
1401 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY:
1402 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE:
1403 {
1404 struct fs_sink_ctf_field_class_array_base *array_base_fc =
1405 (void *) fc;
1406
1407 if (fc_type == FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE) {
1408 ret = set_field_ref(fc, fc_name, parent_fc);
1409 if (ret) {
1410 goto end;
1411 }
1412 }
1413
1414 ret = set_field_refs(array_base_fc->elem_fc, NULL, fc);
1415 if (ret) {
1416 goto end;
1417 }
1418
1419 break;
1420 }
1421 default:
1422 break;
1423 }
1424
1425 end:
1426 return ret;
1427 }
1428
1429 /*
1430 * This function translates a root scope trace IR field class to
1431 * a CTF IR field class.
1432 *
1433 * The resulting CTF IR field class is written to `*fc` so that it
1434 * exists as the parent object's (stream class or event class) true root
1435 * field class during the recursive translation for resolving purposes.
1436 * This is also why this function creates the empty structure field
1437 * class and then calls translate_structure_field_class_members() to
1438 * fill it.
1439 */
1440 static
1441 int translate_scope_field_class(struct ctx *ctx, bt_field_path_scope scope,
1442 struct fs_sink_ctf_field_class **fc,
1443 const bt_field_class *ir_fc)
1444 {
1445 int ret = 0;
1446
1447 if (!ir_fc) {
1448 goto end;
1449 }
1450
1451 BT_ASSERT(bt_field_class_get_type(ir_fc) ==
1452 BT_FIELD_CLASS_TYPE_STRUCTURE);
1453 BT_ASSERT(fc);
1454 *fc = (void *) fs_sink_ctf_field_class_struct_create_empty(
1455 ir_fc, UINT64_C(-1));
1456 BT_ASSERT(*fc);
1457 ctx->cur_scope = scope;
1458 BT_ASSERT(ctx->cur_path->len == 0);
1459 ret = cur_path_stack_push(ctx, UINT64_C(-1), NULL, false, ir_fc, NULL);
1460 if (ret) {
1461 BT_COMP_LOGE("Cannot translate scope structure field class: "
1462 "scope=%d", scope);
1463 goto end;
1464 }
1465
1466 ret = translate_structure_field_class_members(ctx, (void *) *fc, ir_fc);
1467 if (ret) {
1468 BT_COMP_LOGE("Cannot translate scope structure field class: "
1469 "scope=%d", scope);
1470 goto end;
1471 }
1472
1473 cur_path_stack_pop(ctx);
1474
1475 /* Set field refs for preceding targets */
1476 ret = set_field_refs(*fc, NULL, NULL);
1477
1478 end:
1479 return ret;
1480 }
1481
1482 static inline
1483 void ctx_init(struct ctx *ctx, struct fs_sink_comp *fs_sink)
1484 {
1485 memset(ctx, 0, sizeof(struct ctx));
1486 ctx->cur_path = g_array_new(FALSE, TRUE,
1487 sizeof(struct field_path_elem));
1488 BT_ASSERT(ctx->cur_path);
1489 ctx->log_level = fs_sink->log_level;
1490 ctx->self_comp = fs_sink->self_comp;
1491 }
1492
1493 static inline
1494 void ctx_fini(struct ctx *ctx)
1495 {
1496 if (ctx->cur_path) {
1497 g_array_free(ctx->cur_path, TRUE);
1498 ctx->cur_path = NULL;
1499 }
1500 }
1501
1502 static
1503 int translate_event_class(struct fs_sink_comp *fs_sink,
1504 struct fs_sink_ctf_stream_class *sc,
1505 const bt_event_class *ir_ec,
1506 struct fs_sink_ctf_event_class **out_ec)
1507 {
1508 int ret = 0;
1509 struct ctx ctx;
1510 struct fs_sink_ctf_event_class *ec;
1511
1512 BT_ASSERT(sc);
1513 BT_ASSERT(ir_ec);
1514
1515 ctx_init(&ctx, fs_sink);
1516 ec = fs_sink_ctf_event_class_create(sc, ir_ec);
1517 BT_ASSERT(ec);
1518 ctx.cur_sc = sc;
1519 ctx.cur_ec = ec;
1520 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT,
1521 &ec->spec_context_fc,
1522 bt_event_class_borrow_specific_context_field_class_const(
1523 ir_ec));
1524 if (ret) {
1525 goto end;
1526 }
1527
1528 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD,
1529 &ec->payload_fc,
1530 bt_event_class_borrow_payload_field_class_const(ir_ec));
1531 if (ret) {
1532 goto end;
1533 }
1534
1535 end:
1536 ctx_fini(&ctx);
1537 *out_ec = ec;
1538 return ret;
1539 }
1540
1541 BT_HIDDEN
1542 int try_translate_event_class_trace_ir_to_ctf_ir(
1543 struct fs_sink_comp *fs_sink,
1544 struct fs_sink_ctf_stream_class *sc,
1545 const bt_event_class *ir_ec,
1546 struct fs_sink_ctf_event_class **out_ec)
1547 {
1548 int ret = 0;
1549
1550 BT_ASSERT(sc);
1551 BT_ASSERT(ir_ec);
1552
1553 /* Check in hash table first */
1554 *out_ec = g_hash_table_lookup(sc->event_classes_from_ir, ir_ec);
1555 if (G_LIKELY(*out_ec)) {
1556 goto end;
1557 }
1558
1559 ret = translate_event_class(fs_sink, sc, ir_ec, out_ec);
1560
1561 end:
1562 return ret;
1563 }
1564
1565 bool default_clock_class_name_exists(struct fs_sink_ctf_trace *trace,
1566 const char *name)
1567 {
1568 bool exists = false;
1569 uint64_t i;
1570
1571 for (i = 0; i < trace->stream_classes->len; i++) {
1572 struct fs_sink_ctf_stream_class *sc =
1573 trace->stream_classes->pdata[i];
1574
1575 if (sc->default_clock_class_name->len == 0) {
1576 /* No default clock class */
1577 continue;
1578 }
1579
1580 if (strcmp(sc->default_clock_class_name->str, name) == 0) {
1581 exists = true;
1582 goto end;
1583 }
1584 }
1585
1586 end:
1587 return exists;
1588 }
1589
1590 static
1591 void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class *sc)
1592 {
1593 unsigned int suffix = 0;
1594 char buf[16];
1595
1596 g_string_assign(sc->default_clock_class_name, "");
1597 sprintf(buf, "default");
1598
1599 while (default_clock_class_name_exists(sc->trace, buf)) {
1600 sprintf(buf, "default%u", suffix);
1601 suffix++;
1602 }
1603
1604 g_string_assign(sc->default_clock_class_name, buf);
1605 }
1606
1607 static
1608 int translate_stream_class(struct fs_sink_comp *fs_sink,
1609 struct fs_sink_ctf_trace *trace,
1610 const bt_stream_class *ir_sc,
1611 struct fs_sink_ctf_stream_class **out_sc)
1612 {
1613 int ret = 0;
1614 struct ctx ctx;
1615
1616 BT_ASSERT(trace);
1617 BT_ASSERT(ir_sc);
1618 ctx_init(&ctx, fs_sink);
1619 *out_sc = fs_sink_ctf_stream_class_create(trace, ir_sc);
1620 BT_ASSERT(*out_sc);
1621
1622 /* Set default clock class's protected name, if any */
1623 if ((*out_sc)->default_clock_class) {
1624 const char *name = bt_clock_class_get_name(
1625 (*out_sc)->default_clock_class);
1626
1627 if (name) {
1628 /* Try original name, protected */
1629 g_string_assign((*out_sc)->default_clock_class_name,
1630 "");
1631
1632 if (must_protect_identifier(name)) {
1633 g_string_assign(
1634 (*out_sc)->default_clock_class_name,
1635 "_");
1636 }
1637
1638 g_string_assign((*out_sc)->default_clock_class_name,
1639 name);
1640 if (!ist_valid_identifier(
1641 (*out_sc)->default_clock_class_name->str)) {
1642 /* Invalid: create a new name */
1643 make_unique_default_clock_class_name(*out_sc);
1644 ret = 0;
1645 }
1646 } else {
1647 /* No name: create a name */
1648 make_unique_default_clock_class_name(*out_sc);
1649 }
1650 }
1651
1652 ctx.cur_sc = *out_sc;
1653 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT,
1654 &(*out_sc)->packet_context_fc,
1655 bt_stream_class_borrow_packet_context_field_class_const(ir_sc));
1656 if (ret) {
1657 goto error;
1658 }
1659
1660 if ((*out_sc)->packet_context_fc) {
1661 /*
1662 * Make sure the structure field class's alignment is
1663 * enough: 8 is what we use for our own special members
1664 * in the packet context.
1665 */
1666 fs_sink_ctf_field_class_struct_align_at_least(
1667 (void *) (*out_sc)->packet_context_fc, 8);
1668 }
1669
1670 ret = translate_scope_field_class(&ctx, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT,
1671 &(*out_sc)->event_common_context_fc,
1672 bt_stream_class_borrow_event_common_context_field_class_const(
1673 ir_sc));
1674 if (ret) {
1675 goto error;
1676 }
1677
1678 goto end;
1679
1680 error:
1681 fs_sink_ctf_stream_class_destroy(*out_sc);
1682 *out_sc = NULL;
1683
1684 end:
1685 ctx_fini(&ctx);
1686 return ret;
1687 }
1688
1689 BT_HIDDEN
1690 int try_translate_stream_class_trace_ir_to_ctf_ir(
1691 struct fs_sink_comp *fs_sink,
1692 struct fs_sink_ctf_trace *trace,
1693 const bt_stream_class *ir_sc,
1694 struct fs_sink_ctf_stream_class **out_sc)
1695 {
1696 int ret = 0;
1697 uint64_t i;
1698
1699 BT_ASSERT(trace);
1700 BT_ASSERT(ir_sc);
1701
1702 for (i = 0; i < trace->stream_classes->len; i++) {
1703 *out_sc = trace->stream_classes->pdata[i];
1704
1705 if ((*out_sc)->ir_sc == ir_sc) {
1706 goto end;
1707 }
1708 }
1709
1710 ret = translate_stream_class(fs_sink, trace, ir_sc, out_sc);
1711
1712 end:
1713 return ret;
1714 }
1715
1716 BT_HIDDEN
1717 struct fs_sink_ctf_trace *translate_trace_trace_ir_to_ctf_ir(
1718 struct fs_sink_comp *fs_sink, const bt_trace *ir_trace)
1719 {
1720 uint64_t count;
1721 uint64_t i;
1722 struct fs_sink_ctf_trace *trace = NULL;
1723
1724 /* Check that trace's environment is TSDL-compatible */
1725 count = bt_trace_get_environment_entry_count(ir_trace);
1726 for (i = 0; i < count; i++) {
1727 const char *name;
1728 const bt_value *val;
1729
1730 bt_trace_borrow_environment_entry_by_index_const(
1731 ir_trace, i, &name, &val);
1732
1733 if (!ist_valid_identifier(name)) {
1734 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, fs_sink->log_level,
1735 fs_sink->self_comp,
1736 "Unsupported trace class's environment entry name: "
1737 "name=\"%s\"", name);
1738 goto end;
1739 }
1740
1741 switch (bt_value_get_type(val)) {
1742 case BT_VALUE_TYPE_SIGNED_INTEGER:
1743 case BT_VALUE_TYPE_STRING:
1744 break;
1745 default:
1746 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, fs_sink->log_level,
1747 fs_sink->self_comp,
1748 "Unsupported trace class's environment entry value type: "
1749 "type=%s",
1750 bt_common_value_type_string(
1751 bt_value_get_type(val)));
1752 goto end;
1753 }
1754 }
1755
1756 trace = fs_sink_ctf_trace_create(ir_trace);
1757 BT_ASSERT(trace);
1758
1759 end:
1760 return trace;
1761 }
This page took 0.099099 seconds and 5 git commands to generate.