2da1c7490b5c7d7112a619f550c971358b370bb0
[babeltrace.git] / formats / ctf / ir / resolve.c
1 /*
2 * resolve.c
3 *
4 * Babeltrace - CTF IR: Type resolving internal
5 *
6 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
8 *
9 * Authors: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Philippe Proulx <pproulx@efficios.com>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * SOFTWARE.
29 */
30
31 #include <babeltrace/ctf-ir/event.h>
32 #include <babeltrace/ctf-ir/stream-class.h>
33 #include <babeltrace/ctf-ir/resolve-internal.h>
34 #include <babeltrace/ctf-ir/field-types.h>
35 #include <babeltrace/ctf-ir/field-path.h>
36 #include <babeltrace/ctf-ir/field-path-internal.h>
37 #include <babeltrace/ctf-ir/event-internal.h>
38 #include <babeltrace/ref.h>
39 #include <babeltrace/babeltrace-internal.h>
40 #include <babeltrace/values.h>
41 #include <limits.h>
42 #include <glib.h>
43
44 #define _printf_error(fmt, args...) \
45 printf_verbose("[resolving] " fmt, ## args)
46
47 typedef GPtrArray type_stack;
48
49 /*
50 * A stack frame.
51 *
52 * `type` contains a compound field type (structure, variant, array,
53 * or sequence) and `index` indicates the index of the field type in
54 * the upper frame (-1 for array and sequence field types).
55 *
56 * `type` is owned by the stack frame.
57 */
58 struct type_stack_frame {
59 struct bt_ctf_field_type *type;
60 int index;
61 };
62
63 /*
64 * The current context of the resolving engine.
65 *
66 * `scopes` contain the 6 CTF scope field types (see CTF, sect. 7.3.2)
67 * in the following order:
68 *
69 * * Packet header
70 * * Packet context
71 * * Event header
72 * * Stream event context
73 * * Event context
74 * * Event payload
75 */
76 struct resolve_context {
77 struct bt_value *environment;
78 struct bt_ctf_field_type *scopes[6];
79
80 /* Root scope being visited */
81 enum bt_ctf_scope root_scope;
82 type_stack *type_stack;
83 struct bt_ctf_field_type *cur_field_type;
84 };
85
86 /* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
87 static const char * const absolute_path_prefixes[] = {
88 [BT_CTF_SCOPE_ENV] = "env.",
89 [BT_CTF_SCOPE_TRACE_PACKET_HEADER] = "trace.packet.header.",
90 [BT_CTF_SCOPE_STREAM_PACKET_CONTEXT] = "stream.packet.context.",
91 [BT_CTF_SCOPE_STREAM_EVENT_HEADER] = "stream.event.header.",
92 [BT_CTF_SCOPE_STREAM_EVENT_CONTEXT] = "stream.event.context.",
93 [BT_CTF_SCOPE_EVENT_CONTEXT] = "event.context.",
94 [BT_CTF_SCOPE_EVENT_FIELDS] = "event.fields.",
95 };
96
97 /* Number of path tokens used for the absolute prefixes */
98 static const int absolute_path_prefix_ptoken_counts[] = {
99 [BT_CTF_SCOPE_ENV] = 1,
100 [BT_CTF_SCOPE_TRACE_PACKET_HEADER] = 3,
101 [BT_CTF_SCOPE_STREAM_PACKET_CONTEXT] = 3,
102 [BT_CTF_SCOPE_STREAM_EVENT_HEADER] = 3,
103 [BT_CTF_SCOPE_STREAM_EVENT_CONTEXT] = 3,
104 [BT_CTF_SCOPE_EVENT_CONTEXT] = 2,
105 [BT_CTF_SCOPE_EVENT_FIELDS] = 2,
106 };
107
108 /*
109 * Destroys a type stack frame.
110 */
111 static
112 void type_stack_destroy_notify(gpointer data)
113 {
114 struct type_stack_frame *frame = data;
115
116 BT_PUT(frame->type);
117 g_free(frame);
118 }
119
120 /*
121 * Creates a type stack.
122 *
123 * Return value is owned by the caller.
124 */
125 static
126 type_stack *type_stack_create(void)
127 {
128 return g_ptr_array_new_with_free_func(type_stack_destroy_notify);
129 }
130
131 /*
132 * Destroys a type stack.
133 */
134 static
135 void type_stack_destroy(type_stack *stack)
136 {
137 g_ptr_array_free(stack, TRUE);
138 }
139
140 /*
141 * Pushes a field type onto a type stack.
142 *
143 * `type` is owned by the caller (stack frame gets a new reference).
144 */
145 static
146 int type_stack_push(type_stack *stack, struct bt_ctf_field_type *type)
147 {
148 int ret = 0;
149 struct type_stack_frame *frame = NULL;
150
151 if (!stack || !type) {
152 ret = -1;
153 goto end;
154 }
155
156 frame = g_new0(struct type_stack_frame, 1);
157 if (!frame) {
158 ret = -1;
159 goto end;
160 }
161
162 frame->type = bt_get(type);
163 g_ptr_array_add(stack, frame);
164
165 end:
166 return ret;
167 }
168
169 /*
170 * Checks whether or not `stack` is empty.
171 */
172 static
173 bool type_stack_empty(type_stack *stack)
174 {
175 return stack->len == 0;
176 }
177
178 /*
179 * Returns the number of frames in `stack`.
180 */
181 static
182 size_t type_stack_size(type_stack *stack)
183 {
184 return stack->len;
185 }
186
187 /*
188 * Returns the top frame of `stack`.
189 *
190 * Return value is owned by `stack`.
191 */
192 static
193 struct type_stack_frame *type_stack_peek(type_stack *stack)
194 {
195 struct type_stack_frame *entry = NULL;
196
197 if (!stack || type_stack_empty(stack)) {
198 goto end;
199 }
200
201 entry = g_ptr_array_index(stack, stack->len - 1);
202 end:
203 return entry;
204 }
205
206 /*
207 * Returns the frame at index `index` in `stack`.
208 *
209 * Return value is owned by `stack`.
210 */
211 static
212 struct type_stack_frame *type_stack_at(type_stack *stack,
213 size_t index)
214 {
215 struct type_stack_frame *entry = NULL;
216
217 if (!stack || index >= stack->len) {
218 goto end;
219 }
220
221 entry = g_ptr_array_index(stack, index);
222
223 end:
224 return entry;
225 }
226
227 /*
228 * Removes the top frame of `stack`.
229 */
230 static
231 void type_stack_pop(type_stack *stack)
232 {
233 if (!type_stack_empty(stack)) {
234 /*
235 * This will call the frame's destructor and free it, as
236 * well as put its contained field type.
237 */
238 g_ptr_array_set_size(stack, stack->len - 1);
239 }
240 }
241
242 /*
243 * Returns the scope field type of `scope` in the context `ctx`.
244 *
245 * Return value is owned by `ctx` on success.
246 */
247 static
248 struct bt_ctf_field_type *get_type_from_ctx(struct resolve_context *ctx,
249 enum bt_ctf_ir_scope scope)
250 {
251 assert(scope >= BT_CTF_SCOPE_TRACE_PACKET_HEADER &&
252 scope <= BT_CTF_SCOPE_EVENT_FIELDS);
253
254 return ctx->scopes[scope - BT_CTF_SCOPE_TRACE_PACKET_HEADER];
255 }
256
257 /*
258 * Returns the CTF scope from a path string. May return
259 * CTF_NODE_UNKNOWN if the path is found to be relative.
260 */
261 static
262 enum bt_ctf_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
263 {
264 enum bt_ctf_scope scope;
265 enum bt_ctf_scope ret = BT_CTF_SCOPE_UNKNOWN;
266 const size_t prefixes_count = sizeof(absolute_path_prefixes) /
267 sizeof(*absolute_path_prefixes);
268
269 for (scope = BT_CTF_SCOPE_ENV; scope < BT_CTF_SCOPE_ENV +
270 prefixes_count; scope++) {
271 /*
272 * Chech if path string starts with a known absolute
273 * path prefix.
274 *
275 * Refer to CTF 7.3.2 STATIC AND DYNAMIC SCOPES.
276 */
277 if (strncmp(pathstr, absolute_path_prefixes[scope],
278 strlen(absolute_path_prefixes[scope]))) {
279 /* Prefix does not match: try the next one */
280 continue;
281 }
282
283 /* Found it! */
284 ret = scope;
285 goto end;
286 }
287
288 end:
289 return ret;
290 }
291
292 /*
293 * Destroys a path token.
294 */
295 static
296 void ptokens_destroy_func(gpointer ptoken, gpointer data)
297 {
298 g_string_free(ptoken, TRUE);
299 }
300
301 /*
302 * Destroys a path token list.
303 */
304 static
305 void ptokens_destroy(GList *ptokens)
306 {
307 if (!ptokens) {
308 return;
309 }
310
311 g_list_foreach(ptokens, ptokens_destroy_func, NULL);
312 g_list_free(ptokens);
313 }
314
315 /*
316 * Returns the string contained in a path token.
317 */
318 static
319 const char *ptoken_get_string(GList *ptoken)
320 {
321 GString *tokenstr = (GString *) ptoken->data;
322
323 return tokenstr->str;
324 }
325
326 /*
327 * Converts a path string to a path token list, that is, splits the
328 * individual words of a path string into a list of individual
329 * strings.
330 *
331 * Return value is owned by the caller on success.
332 */
333 static
334 GList *pathstr_to_ptokens(const char *pathstr)
335 {
336 const char *at = pathstr;
337 const char *last = at;
338 GList *ptokens = NULL;
339
340 for (;;) {
341 if (*at == '.' || *at == '\0') {
342 GString *tokenstr;
343
344 if (at == last) {
345 /* Error: empty token */
346 _printf_error("Empty token in path string at position %d\n",
347 (int) (at - pathstr));
348 goto error;
349 }
350
351 tokenstr = g_string_new(NULL);
352 g_string_append_len(tokenstr, last, at - last);
353 ptokens = g_list_append(ptokens, tokenstr);
354 last = at + 1;
355 }
356
357 if (*at == '\0') {
358 break;
359 }
360
361 at++;
362 }
363
364 return ptokens;
365
366 error:
367 ptokens_destroy(ptokens);
368 return NULL;
369 }
370
371 /*
372 * Converts a path token list to a field path object. The path token
373 * list is relative from `type`. The index of the source looking for
374 * its target within `type` is indicated by `src_index`. This can be
375 * `INT_MAX` if the source is contained in `type`.
376 *
377 * `ptokens` is owned by the caller. `field_path` is an output parameter
378 * owned by the caller that must be filled here. `type` is owned by the
379 * caller.
380 */
381 static
382 int ptokens_to_field_path(GList *ptokens, struct bt_ctf_field_path *field_path,
383 struct bt_ctf_field_type *type, int src_index)
384 {
385 int ret = 0;
386 GList *cur_ptoken = ptokens;
387 bool first_level_done = false;
388
389 /* Get our own reference */
390 bt_get(type);
391
392 /* Locate target */
393 while (cur_ptoken) {
394 int child_index;
395 struct bt_ctf_field_type *child_type;
396 const char *field_name = ptoken_get_string(cur_ptoken);
397 enum ctf_type_id type_id = bt_ctf_field_type_get_type_id(type);
398
399 /* Find to which index corresponds the current path token */
400 if (type_id == CTF_TYPE_ARRAY || type_id == CTF_TYPE_SEQUENCE) {
401 child_index = -1;
402 } else {
403 child_index = bt_ctf_field_type_get_field_index(type,
404 field_name);
405 if (child_index < 0) {
406 /*
407 * Error: field name does not exist or
408 * wrong current type.
409 */
410 _printf_error("Cannot get index of field type named \"%s\"\n",
411 field_name);
412 ret = -1;
413 goto end;
414 } else if (child_index > src_index &&
415 !first_level_done) {
416 _printf_error("Child type is located after source index (%d)\n",
417 src_index);
418 ret = -1;
419 goto end;
420 }
421
422 /* Next path token */
423 cur_ptoken = g_list_next(cur_ptoken);
424 first_level_done = true;
425 }
426
427 /* Create new field path entry */
428 g_array_append_val(field_path->indexes, child_index);
429
430 /* Get child field type */
431 child_type = bt_ctf_field_type_get_field_at_index(type,
432 child_index);
433 if (!child_type) {
434 _printf_error("Cannot get child type at index %d (field \"%s\")\n",
435 child_index, field_name);
436 ret = -1;
437 goto end;
438 }
439
440 /* Move child type to current type */
441 BT_MOVE(type, child_type);
442 }
443
444 end:
445 bt_put(type);
446 return ret;
447 }
448
449 /*
450 * Converts a known absolute path token list to a field path object
451 * within the resolving context `ctx`.
452 *
453 * `ptokens` is owned by the caller. `field_path` is an output parameter
454 * owned by the caller that must be filled here.
455 */
456 static
457 int absolute_ptokens_to_field_path(GList *ptokens,
458 struct bt_ctf_field_path *field_path,
459 struct resolve_context *ctx)
460 {
461 int ret = 0;
462 GList *cur_ptoken;
463 struct bt_ctf_field_type *type;
464
465 /* Skip absolute path tokens */
466 cur_ptoken = g_list_nth(ptokens,
467 absolute_path_prefix_ptoken_counts[field_path->root]);
468
469 /* Start with root type */
470 type = get_type_from_ctx(ctx, field_path->root);
471 if (!type) {
472 /* Error: root type is not available */
473 _printf_error("Root type with scope type %d is not available\n",
474 field_path->root);
475 ret = -1;
476 goto end;
477 }
478
479 /* Locate target */
480 ret = ptokens_to_field_path(cur_ptoken, field_path, type, INT_MAX);
481
482 end:
483 return ret;
484 }
485
486 /*
487 * Converts a known relative path token list to a field path object
488 * within the resolving context `ctx`.
489 *
490 * `ptokens` is owned by the caller. `field_path` is an output parameter
491 * owned by the caller that must be filled here.
492 */
493 static
494 int relative_ptokens_to_field_path(GList *ptokens,
495 struct bt_ctf_field_path *field_path,
496 struct resolve_context *ctx)
497 {
498 int ret = 0;
499 int parent_pos_in_stack;
500 struct bt_ctf_field_path *tail_field_path = bt_ctf_field_path_create();
501
502 if (!tail_field_path) {
503 _printf_error("Cannot create field path\n");
504 ret = -1;
505 goto end;
506 }
507
508 parent_pos_in_stack = type_stack_size(ctx->type_stack) - 1;
509
510 while (parent_pos_in_stack >= 0) {
511 struct bt_ctf_field_type *parent_type =
512 type_stack_at(ctx->type_stack,
513 parent_pos_in_stack)->type;
514 int cur_index = type_stack_at(ctx->type_stack,
515 parent_pos_in_stack)->index;
516
517 /* Locate target from current parent type */
518 ret = ptokens_to_field_path(ptokens, tail_field_path,
519 parent_type, cur_index);
520 if (ret) {
521 /* Not found... yet */
522 bt_ctf_field_path_clear(tail_field_path);
523 } else {
524 /* Found: stitch tail field path to head field path */
525 int i = 0;
526 int tail_field_path_len =
527 tail_field_path->indexes->len;
528
529 while (true) {
530 struct bt_ctf_field_type *cur_type =
531 type_stack_at(ctx->type_stack, i)->type;
532 int index = type_stack_at(
533 ctx->type_stack, i)->index;
534
535 if (cur_type == parent_type) {
536 break;
537 }
538
539 g_array_append_val(field_path->indexes,
540 index);
541 i++;
542 }
543
544 for (i = 0; i < tail_field_path_len; i++) {
545 int index = g_array_index(
546 tail_field_path->indexes,
547 int, i);
548
549 g_array_append_val(field_path->indexes,
550 index);
551 }
552 break;
553 }
554
555 parent_pos_in_stack--;
556 }
557
558 if (parent_pos_in_stack < 0) {
559 /* Not found: look in previous scopes */
560 field_path->root--;
561
562 while (field_path->root >= BT_CTF_SCOPE_TRACE_PACKET_HEADER) {
563 struct bt_ctf_field_type *root_type;
564 bt_ctf_field_path_clear(field_path);
565
566 root_type = get_type_from_ctx(ctx, field_path->root);
567 if (!root_type) {
568 field_path->root--;
569 continue;
570 }
571
572 /* Locate target in previous scope */
573 ret = ptokens_to_field_path(ptokens, field_path,
574 root_type, INT_MAX);
575 if (ret) {
576 /* Not found yet */
577 field_path->root--;
578 continue;
579 }
580
581 /* Found */
582 break;
583 }
584 }
585
586 end:
587 BT_PUT(tail_field_path);
588 return ret;
589 }
590
591 /*
592 * Converts a path string to a field path object within the resolving
593 * context `ctx`.
594 *
595 * Return value is owned by the caller on success.
596 */
597 static
598 struct bt_ctf_field_path *pathstr_to_field_path(const char *pathstr,
599 struct resolve_context *ctx)
600 {
601 int ret;
602 enum bt_ctf_ir_scope root_scope;
603 GList *ptokens = NULL;
604 struct bt_ctf_field_path *field_path = NULL;
605
606 /* Create field path */
607 field_path = bt_ctf_field_path_create();
608 if (!field_path) {
609 _printf_error("Cannot create field path\n");
610 ret = -1;
611 goto end;
612 }
613
614 /* Convert path string to path tokens */
615 ptokens = pathstr_to_ptokens(pathstr);
616 if (!ptokens) {
617 _printf_error("Cannot convert path string \"%s\" to path tokens\n",
618 pathstr);
619 ret = -1;
620 goto end;
621 }
622
623 /* Absolute or relative path? */
624 root_scope = get_root_scope_from_absolute_pathstr(pathstr);
625
626 if (root_scope == BT_CTF_SCOPE_UNKNOWN) {
627 /* Relative path: start with current root scope */
628 field_path->root = ctx->root_scope;
629 ret = relative_ptokens_to_field_path(ptokens, field_path, ctx);
630 if (ret) {
631 _printf_error("Cannot get relative field path of path string \"%s\"\n",
632 pathstr);
633 _printf_error(" Starting at root scope %d, finished at root scope %d\n",
634 ctx->root_scope, field_path->root);
635 goto end;
636 }
637 } else if (root_scope == BT_CTF_SCOPE_ENV) {
638 _printf_error("Sequence field types referring the trace environment are not supported as of this version\n");
639 ret = -1;
640 goto end;
641 } else {
642 /* Absolute path: use found root scope */
643 field_path->root = root_scope;
644 ret = absolute_ptokens_to_field_path(ptokens, field_path, ctx);
645 if (ret) {
646 _printf_error("Cannot get absolute field path of path string \"%s\"\n",
647 pathstr);
648 _printf_error(" Looking in root scope %d\n", root_scope);
649 goto end;
650 }
651 }
652
653 end:
654 if (ret) {
655 BT_PUT(field_path);
656 }
657
658 ptokens_destroy(ptokens);
659
660 return field_path;
661 }
662
663 /*
664 * Retrieves a field type by following the field path `field_path` in
665 * the resolving context `ctx`.
666 *
667 * Return value is owned by the caller on success.
668 */
669 static
670 struct bt_ctf_field_type *field_path_to_field_type(
671 struct bt_ctf_field_path *field_path,
672 struct resolve_context *ctx)
673 {
674 int i;
675 struct bt_ctf_field_type *type;
676
677 /* Start with root type */
678 type = get_type_from_ctx(ctx, field_path->root);
679 bt_get(type);
680 if (!type) {
681 /* Error: root type is not available */
682 _printf_error("Root type with scope type %d is not available\n",
683 field_path->root);
684 goto error;
685 }
686
687 /* Locate target */
688 for (i = 0; i < field_path->indexes->len; i++) {
689 struct bt_ctf_field_type *child_type;
690 int child_index =
691 g_array_index(field_path->indexes, int, i);
692
693 /* Get child field type */
694 child_type = bt_ctf_field_type_get_field_at_index(type,
695 child_index);
696 if (!child_type) {
697 _printf_error("Cannot get field type field at index %d\n",
698 child_index);
699 goto error;
700 }
701
702 /* Move child type to current type */
703 BT_MOVE(type, child_type);
704 }
705
706 return type;
707
708 error:
709 BT_PUT(type);
710 return type;
711 }
712
713 /*
714 * Returns the equivalent field path object of the context type stack.
715 *
716 * Return value is owned by the caller on success.
717 */
718 static
719 struct bt_ctf_field_path *get_ctx_stack_field_path(struct resolve_context *ctx)
720 {
721 int i;
722 struct bt_ctf_field_path *field_path;
723
724 /* Create field path */
725 field_path = bt_ctf_field_path_create();
726 if (!field_path) {
727 _printf_error("Cannot create field path\n");
728 goto error;
729 }
730
731 field_path->root = ctx->root_scope;
732
733 for (i = 0; i < type_stack_size(ctx->type_stack); i++) {
734 struct type_stack_frame *frame;
735
736 frame = type_stack_at(ctx->type_stack, i);
737 g_array_append_val(field_path->indexes, frame->index);
738 }
739
740 return field_path;
741
742 error:
743 BT_PUT(field_path);
744 return field_path;
745 }
746
747 /*
748 * Returns the lowest common ancestor of two field path objects
749 * having the same root scope.
750 *
751 * `field_path1` and `field_path2` are owned by the caller.
752 */
753 static
754 int get_field_paths_lca_index(struct bt_ctf_field_path *field_path1,
755 struct bt_ctf_field_path *field_path2)
756 {
757 int lca_index = 0;
758 int field_path1_len, field_path2_len;
759
760 /*
761 * Start from both roots and find the first mismatch.
762 */
763 assert(field_path1->root == field_path2->root);
764 field_path1_len = field_path1->indexes->len;
765 field_path2_len = field_path2->indexes->len;
766
767 while (true) {
768 int target_index, ctx_index;
769
770 if (lca_index == field_path2_len ||
771 lca_index == field_path1_len) {
772 /*
773 * This means that both field paths never split.
774 * This is invalid because the target cannot be
775 * an ancestor of the source.
776 */
777 _printf_error("In source and target: one is an ancestor of the other\n");
778 lca_index = -1;
779 break;
780 }
781
782 target_index = g_array_index(field_path1->indexes, int,
783 lca_index);
784 ctx_index = g_array_index(field_path2->indexes, int,
785 lca_index);
786
787 if (target_index != ctx_index) {
788 /* LCA index is the previous */
789 break;
790 }
791
792 lca_index++;
793 }
794
795 return lca_index;
796 }
797
798 /*
799 * Validates a target field path.
800 *
801 * `target_field_path` and `target_type` are owned by the caller.
802 */
803 static
804 int validate_target_field_path(struct bt_ctf_field_path *target_field_path,
805 struct bt_ctf_field_type *target_type,
806 struct resolve_context *ctx)
807 {
808 int ret = 0;
809 struct bt_ctf_field_path *ctx_field_path;
810 int target_field_path_len = target_field_path->indexes->len;
811 int lca_index;
812 int ctx_cur_field_type_id;
813 int target_type_id;
814
815 /* Get context field path */
816 ctx_field_path = get_ctx_stack_field_path(ctx);
817 if (!ctx_field_path) {
818 _printf_error("Cannot get source field path\n");
819 ret = -1;
820 goto end;
821 }
822
823 /*
824 * Make sure the target is not a root.
825 */
826 if (target_field_path_len == 0) {
827 _printf_error("Target field path's length is 0 (targeting the root)\n");
828 ret = -1;
829 goto end;
830 }
831
832 /*
833 * Make sure the root of the target field path is not located
834 * after the context field path's root.
835 */
836 if (target_field_path->root > ctx_field_path->root) {
837 _printf_error("Target is located after source\n");
838 ret = -1;
839 goto end;
840 }
841
842 if (target_field_path->root == ctx_field_path->root) {
843 int target_index, ctx_index;
844
845 /*
846 * Find the index of the lowest common ancestor of both field
847 * paths.
848 */
849 lca_index = get_field_paths_lca_index(target_field_path,
850 ctx_field_path);
851 if (lca_index < 0) {
852 _printf_error("Cannot get least common ancestor\n");
853 ret = -1;
854 goto end;
855 }
856
857 /*
858 * Make sure the target field path is located before the
859 * context field path.
860 */
861 target_index = g_array_index(target_field_path->indexes,
862 int, lca_index);
863 ctx_index = g_array_index(ctx_field_path->indexes,
864 int, lca_index);
865
866 if (target_index >= ctx_index) {
867 _printf_error("Target index (%d) is greater or equal to source index (%d) in LCA\n",
868 target_index, ctx_index);
869 ret = -1;
870 goto end;
871 }
872 }
873
874 /*
875 * Make sure the target type has the right type and properties.
876 */
877 ctx_cur_field_type_id = bt_ctf_field_type_get_type_id(
878 ctx->cur_field_type);
879 target_type_id = bt_ctf_field_type_get_type_id(target_type);
880
881 if (ctx_cur_field_type_id == CTF_TYPE_VARIANT) {
882 if (target_type_id != CTF_TYPE_ENUM) {
883 _printf_error("Variant type's tag field type is not an enumeration\n");
884 ret = -1;
885 goto end;
886 }
887 } else if (ctx_cur_field_type_id == CTF_TYPE_SEQUENCE) {
888 if (target_type_id != CTF_TYPE_INTEGER ||
889 bt_ctf_field_type_integer_get_signed(
890 target_type)) {
891 _printf_error("Sequence type's length field type is not an unsigned integer\n");
892 ret = -1;
893 goto end;
894 }
895 } else {
896 assert(false);
897 }
898
899 end:
900 BT_PUT(ctx_field_path);
901 return ret;
902 }
903
904 /*
905 * Resolves a variant or sequence field type `type`.
906 *
907 * `type` is owned by the caller.
908 */
909 static
910 int resolve_sequence_or_variant_type(struct bt_ctf_field_type *type,
911 struct resolve_context *ctx)
912 {
913 int ret = 0;
914 const char *pathstr;
915 int type_id = bt_ctf_field_type_get_type_id(type);
916 struct bt_ctf_field_path *target_field_path = NULL;
917 struct bt_ctf_field_type *target_type = NULL;
918
919 /* Get path string */
920 switch (type_id) {
921 case CTF_TYPE_SEQUENCE:
922 pathstr =
923 bt_ctf_field_type_sequence_get_length_field_name(type);
924 break;
925 case CTF_TYPE_VARIANT:
926 pathstr =
927 bt_ctf_field_type_variant_get_tag_name(type);
928 break;
929 default:
930 assert(false);
931 ret = -1;
932 goto end;
933 }
934
935 /* Get target field path out of path string */
936 target_field_path = pathstr_to_field_path(pathstr, ctx);
937 if (!target_field_path) {
938 _printf_error("Cannot get target field path for path string \"%s\"\n",
939 pathstr);
940 ret = -1;
941 goto end;
942 }
943
944 /* Get target field type */
945 target_type = field_path_to_field_type(target_field_path, ctx);
946 if (!target_type) {
947 _printf_error("Cannot get target field type for path string \"%s\"\n",
948 pathstr);
949 ret = -1;
950 goto end;
951 }
952
953 ret = validate_target_field_path(target_field_path, target_type, ctx);
954 if (ret) {
955 _printf_error("Invalid target field path for path string \"%s\"\n",
956 pathstr);
957 goto end;
958 }
959
960 /* Set target field path and target field type */
961 if (type_id == CTF_TYPE_SEQUENCE) {
962 ret = bt_ctf_field_type_sequence_set_length_field_path(
963 type, target_field_path);
964 if (ret) {
965 _printf_error("Cannot set sequence field type's length field path\n");
966 goto end;
967 }
968 } else if (type_id == CTF_TYPE_VARIANT) {
969 ret = bt_ctf_field_type_variant_set_tag_field_path(
970 type, target_field_path);
971 if (ret) {
972 _printf_error("Cannot set variant field type's tag field path\n");
973 goto end;
974 }
975
976 ret = bt_ctf_field_type_variant_set_tag_field_type(
977 type, target_type);
978 if (ret) {
979 _printf_error("Cannot set variant field type's tag field type\n");
980 goto end;
981 }
982 } else {
983 assert(false);
984 }
985
986 end:
987 BT_PUT(target_field_path);
988 BT_PUT(target_type);
989 return ret;
990 }
991
992 /*
993 * Resolves a field type `type`.
994 *
995 * `type` is owned by the caller.
996 */
997 static
998 int resolve_type(struct bt_ctf_field_type *type, struct resolve_context *ctx)
999 {
1000 int ret = 0;
1001 int type_id;
1002
1003 if (!type) {
1004 /* Type is not available; still valid */
1005 goto end;
1006 }
1007
1008 type_id = bt_ctf_field_type_get_type_id(type);
1009 ctx->cur_field_type = type;
1010
1011 /* Resolve sequence/variant field type */
1012 switch (type_id) {
1013 case CTF_TYPE_SEQUENCE:
1014 case CTF_TYPE_VARIANT:
1015 ret = resolve_sequence_or_variant_type(type, ctx);
1016 if (ret) {
1017 _printf_error("Cannot resolve sequence or variant field type's length/tag\n");
1018 goto end;
1019 }
1020 break;
1021 default:
1022 break;
1023 }
1024
1025 /* Recurse into compound types */
1026 switch (type_id) {
1027 case CTF_TYPE_STRUCT:
1028 case CTF_TYPE_VARIANT:
1029 case CTF_TYPE_SEQUENCE:
1030 case CTF_TYPE_ARRAY:
1031 {
1032 int field_count, f_index;
1033
1034 ret = type_stack_push(ctx->type_stack, type);
1035 if (ret) {
1036 _printf_error("Cannot push field type on type stack\n");
1037 _printf_error(" Stack size: %zu\n",
1038 type_stack_size(ctx->type_stack));
1039 goto end;
1040 }
1041
1042 field_count = bt_ctf_field_type_get_field_count(type);
1043 if (field_count < 0) {
1044 _printf_error("Cannot get field type field count\n");
1045 ret = field_count;
1046 goto end;
1047 }
1048
1049 for (f_index = 0; f_index < field_count; f_index++) {
1050 struct bt_ctf_field_type *child_type =
1051 bt_ctf_field_type_get_field_at_index(type,
1052 f_index);
1053
1054 if (!child_type) {
1055 _printf_error("Cannot get field type field at index %d/%d\n",
1056 f_index, field_count);
1057 ret = -1;
1058 goto end;
1059 }
1060
1061 if (type_id == CTF_TYPE_ARRAY ||
1062 type_id == CTF_TYPE_SEQUENCE) {
1063 type_stack_peek(ctx->type_stack)->index = -1;
1064 } else {
1065 type_stack_peek(ctx->type_stack)->index =
1066 f_index;
1067 }
1068
1069 ret = resolve_type(child_type, ctx);
1070 BT_PUT(child_type);
1071 if (ret) {
1072 goto end;
1073 }
1074 }
1075
1076 type_stack_pop(ctx->type_stack);
1077 break;
1078 }
1079 default:
1080 break;
1081 }
1082
1083 end:
1084 return ret;
1085 }
1086
1087 /*
1088 * Resolves the root field type corresponding to the scope `root_scope`.
1089 */
1090 static
1091 int resolve_root_type(enum bt_ctf_scope root_scope, struct resolve_context *ctx)
1092 {
1093 int ret;
1094
1095 assert(type_stack_size(ctx->type_stack) == 0);
1096 ctx->root_scope = root_scope;
1097 ret = resolve_type(get_type_from_ctx(ctx, root_scope), ctx);
1098 ctx->root_scope = BT_CTF_SCOPE_UNKNOWN;
1099
1100 return ret;
1101 }
1102
1103 BT_HIDDEN
1104 int bt_ctf_resolve_types(
1105 struct bt_value *environment,
1106 struct bt_ctf_field_type *packet_header_type,
1107 struct bt_ctf_field_type *packet_context_type,
1108 struct bt_ctf_field_type *event_header_type,
1109 struct bt_ctf_field_type *stream_event_ctx_type,
1110 struct bt_ctf_field_type *event_context_type,
1111 struct bt_ctf_field_type *event_payload_type,
1112 enum bt_ctf_resolve_flag flags)
1113 {
1114 int ret = 0;
1115 struct resolve_context ctx = {
1116 .environment = environment,
1117 .scopes = {
1118 packet_header_type,
1119 packet_context_type,
1120 event_header_type,
1121 stream_event_ctx_type,
1122 event_context_type,
1123 event_payload_type,
1124 },
1125 .root_scope = BT_CTF_SCOPE_UNKNOWN,
1126 };
1127
1128 /* Initialize type stack */
1129 ctx.type_stack = type_stack_create();
1130 if (!ctx.type_stack) {
1131 printf_error("Cannot create type stack\n");
1132 ret = -1;
1133 goto end;
1134 }
1135
1136 /* Resolve packet header type */
1137 if (flags & BT_CTF_RESOLVE_FLAG_PACKET_HEADER) {
1138 ret = resolve_root_type(BT_CTF_SCOPE_TRACE_PACKET_HEADER, &ctx);
1139 if (ret) {
1140 _printf_error("Cannot resolve trace packet header type\n");
1141 goto end;
1142 }
1143 }
1144
1145 /* Resolve packet context type */
1146 if (flags & BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT) {
1147 ret = resolve_root_type(BT_CTF_SCOPE_STREAM_PACKET_CONTEXT, &ctx);
1148 if (ret) {
1149 _printf_error("Cannot resolve stream packet context type\n");
1150 goto end;
1151 }
1152 }
1153
1154 /* Resolve event header type */
1155 if (flags & BT_CTF_RESOLVE_FLAG_EVENT_HEADER) {
1156 ret = resolve_root_type(BT_CTF_SCOPE_STREAM_EVENT_HEADER, &ctx);
1157 if (ret) {
1158 _printf_error("Cannot resolve stream event header type\n");
1159 goto end;
1160 }
1161 }
1162
1163 /* Resolve stream event context type */
1164 if (flags & BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX) {
1165 ret = resolve_root_type(BT_CTF_SCOPE_STREAM_EVENT_CONTEXT, &ctx);
1166 if (ret) {
1167 _printf_error("Cannot resolve stream event context type\n");
1168 goto end;
1169 }
1170 }
1171
1172 /* Resolve event context type */
1173 if (flags & BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT) {
1174 ret = resolve_root_type(BT_CTF_SCOPE_EVENT_CONTEXT, &ctx);
1175 if (ret) {
1176 _printf_error("Cannot resolve event context type\n");
1177 goto end;
1178 }
1179 }
1180
1181 /* Resolve event payload type */
1182 if (flags & BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD) {
1183 ret = resolve_root_type(BT_CTF_SCOPE_EVENT_FIELDS, &ctx);
1184 if (ret) {
1185 _printf_error("Cannot resolve event payload type\n");
1186 goto end;
1187 }
1188 }
1189
1190 end:
1191 type_stack_destroy(ctx.type_stack);
1192
1193 return ret;
1194 }
This page took 0.054528 seconds and 3 git commands to generate.