2 * Copyright 2016-2018 - Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
16 #define BT_LOG_TAG "PLUGIN-CTF-METADATA-META-RESOLVE"
19 #include <babeltrace2/babeltrace.h>
20 #include <babeltrace2/babeltrace-internal.h>
21 #include <babeltrace2/assert-internal.h>
22 #include <babeltrace2/common-internal.h>
31 #include "ctf-meta-visitors.h"
33 typedef GPtrArray field_class_stack
;
38 * `fc` contains a compound field class (structure, variant, array,
39 * or sequence) and `index` indicates the index of the field class in
40 * the upper frame (-1 for array and sequence field classes). `name`
41 * indicates the name of the field class in the upper frame (empty
42 * string for array and sequence field classes).
44 struct field_class_stack_frame
{
45 struct ctf_field_class
*fc
;
50 * The current context of the resolving engine.
52 struct resolve_context
{
53 struct ctf_trace_class
*tc
;
54 struct ctf_stream_class
*sc
;
55 struct ctf_event_class
*ec
;
58 struct ctf_field_class
*packet_header
;
59 struct ctf_field_class
*packet_context
;
60 struct ctf_field_class
*event_header
;
61 struct ctf_field_class
*event_common_context
;
62 struct ctf_field_class
*event_spec_context
;
63 struct ctf_field_class
*event_payload
;
66 /* Root scope being visited */
67 enum ctf_scope root_scope
;
68 field_class_stack
*field_class_stack
;
69 struct ctf_field_class
*cur_fc
;
72 /* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
73 static const char * const absolute_path_prefixes
[] = {
74 [CTF_SCOPE_PACKET_HEADER
] = "trace.packet.header.",
75 [CTF_SCOPE_PACKET_CONTEXT
] = "stream.packet.context.",
76 [CTF_SCOPE_EVENT_HEADER
] = "stream.event.header.",
77 [CTF_SCOPE_EVENT_COMMON_CONTEXT
] = "stream.event.context.",
78 [CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
] = "event.context.",
79 [CTF_SCOPE_EVENT_PAYLOAD
] = "event.fields.",
82 /* Number of path tokens used for the absolute prefixes */
83 static const uint64_t absolute_path_prefix_ptoken_counts
[] = {
84 [CTF_SCOPE_PACKET_HEADER
] = 3,
85 [CTF_SCOPE_PACKET_CONTEXT
] = 3,
86 [CTF_SCOPE_EVENT_HEADER
] = 3,
87 [CTF_SCOPE_EVENT_COMMON_CONTEXT
] = 3,
88 [CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
] = 2,
89 [CTF_SCOPE_EVENT_PAYLOAD
] = 2,
93 void destroy_field_class_stack_frame(struct field_class_stack_frame
*frame
)
103 * Creates a class stack.
106 field_class_stack
*field_class_stack_create(void)
108 return g_ptr_array_new_with_free_func(
109 (GDestroyNotify
) destroy_field_class_stack_frame
);
113 * Destroys a class stack.
116 void field_class_stack_destroy(field_class_stack
*stack
)
119 g_ptr_array_free(stack
, TRUE
);
124 * Pushes a field class onto a class stack.
127 int field_class_stack_push(field_class_stack
*stack
, struct ctf_field_class
*fc
)
130 struct field_class_stack_frame
*frame
= NULL
;
133 BT_LOGE("Invalid parameter: stack or field class is NULL.");
138 frame
= g_new0(struct field_class_stack_frame
, 1);
140 BT_LOGE_STR("Failed to allocate one field class stack frame.");
145 BT_LOGV("Pushing field class on context's stack: "
146 "fc-addr=%p, stack-size-before=%u", fc
, stack
->len
);
148 g_ptr_array_add(stack
, frame
);
155 * Checks whether or not `stack` is empty.
158 bool field_class_stack_empty(field_class_stack
*stack
)
160 return stack
->len
== 0;
164 * Returns the number of frames in `stack`.
167 size_t field_class_stack_size(field_class_stack
*stack
)
173 * Returns the top frame of `stack`.
176 struct field_class_stack_frame
*field_class_stack_peek(field_class_stack
*stack
)
178 struct field_class_stack_frame
*entry
= NULL
;
180 if (!stack
|| field_class_stack_empty(stack
)) {
184 entry
= g_ptr_array_index(stack
, stack
->len
- 1);
190 * Returns the frame at index `index` in `stack`.
193 struct field_class_stack_frame
*field_class_stack_at(field_class_stack
*stack
,
196 struct field_class_stack_frame
*entry
= NULL
;
198 if (!stack
|| index
>= stack
->len
) {
202 entry
= g_ptr_array_index(stack
, index
);
209 * Removes the top frame of `stack`.
212 void field_class_stack_pop(field_class_stack
*stack
)
214 if (!field_class_stack_empty(stack
)) {
216 * This will call the frame's destructor and free it, as
217 * well as put its contained field class.
219 BT_LOGV("Popping context's stack: stack-size-before=%u",
221 g_ptr_array_set_size(stack
, stack
->len
- 1);
226 * Returns the scope field class of `scope` in the context `ctx`.
229 struct ctf_field_class
*borrow_class_from_ctx(struct resolve_context
*ctx
,
230 enum ctf_scope scope
)
233 case CTF_SCOPE_PACKET_HEADER
:
234 return ctx
->scopes
.packet_header
;
235 case CTF_SCOPE_PACKET_CONTEXT
:
236 return ctx
->scopes
.packet_context
;
237 case CTF_SCOPE_EVENT_HEADER
:
238 return ctx
->scopes
.event_header
;
239 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
240 return ctx
->scopes
.event_common_context
;
241 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
242 return ctx
->scopes
.event_spec_context
;
243 case CTF_SCOPE_EVENT_PAYLOAD
:
244 return ctx
->scopes
.event_payload
;
253 * Returns the CTF scope from a path string. May return -1 if the path
254 * is found to be relative.
257 enum ctf_scope
get_root_scope_from_absolute_pathstr(const char *pathstr
)
259 enum ctf_scope scope
;
260 enum ctf_scope ret
= -1;
261 const size_t prefixes_count
= sizeof(absolute_path_prefixes
) /
262 sizeof(*absolute_path_prefixes
);
264 for (scope
= CTF_SCOPE_PACKET_HEADER
; scope
< CTF_SCOPE_PACKET_HEADER
+
265 prefixes_count
; scope
++) {
267 * Chech if path string starts with a known absolute
270 * Refer to CTF 7.3.2 STATIC AND DYNAMIC SCOPES.
272 if (strncmp(pathstr
, absolute_path_prefixes
[scope
],
273 strlen(absolute_path_prefixes
[scope
]))) {
274 /* Prefix does not match: try the next one */
275 BT_LOGV("Prefix does not match: trying the next one: "
276 "path=\"%s\", path-prefix=\"%s\", scope=%s",
277 pathstr
, absolute_path_prefixes
[scope
],
278 ctf_scope_string(scope
));
284 BT_LOGV("Found root scope from absolute path: "
285 "path=\"%s\", scope=%s", pathstr
,
286 ctf_scope_string(scope
));
295 * Destroys a path token.
298 void ptokens_destroy_func(gpointer ptoken
, gpointer data
)
300 g_string_free(ptoken
, TRUE
);
304 * Destroys a path token list.
307 void ptokens_destroy(GList
*ptokens
)
313 g_list_foreach(ptokens
, ptokens_destroy_func
, NULL
);
314 g_list_free(ptokens
);
318 * Returns the string contained in a path token.
321 const char *ptoken_get_string(GList
*ptoken
)
323 GString
*tokenstr
= (GString
*) ptoken
->data
;
325 return tokenstr
->str
;
329 * Converts a path string to a path token list, that is, splits the
330 * individual words of a path string into a list of individual
334 GList
*pathstr_to_ptokens(const char *pathstr
)
336 const char *at
= pathstr
;
337 const char *last
= at
;
338 GList
*ptokens
= NULL
;
341 if (*at
== '.' || *at
== '\0') {
345 /* Error: empty token */
346 BT_LOGE("Empty path token: path=\"%s\", pos=%u",
347 pathstr
, (unsigned int) (at
- pathstr
));
351 tokenstr
= g_string_new(NULL
);
352 g_string_append_len(tokenstr
, last
, at
- last
);
353 ptokens
= g_list_append(ptokens
, tokenstr
);
367 ptokens_destroy(ptokens
);
372 * Converts a path token list to a field path object. The path token
373 * list is relative from `fc`. The index of the source looking for its
374 * target within `fc` is indicated by `src_index`. This can be `INT64_MAX`
375 * if the source is contained in `fc`.
377 * `field_path` is an output parameter owned by the caller that must be
381 int ptokens_to_field_path(GList
*ptokens
, struct ctf_field_path
*field_path
,
382 struct ctf_field_class
*fc
, int64_t src_index
)
385 GList
*cur_ptoken
= ptokens
;
386 bool first_level_done
= false;
391 struct ctf_field_class
*child_fc
;
392 const char *ft_name
= ptoken_get_string(cur_ptoken
);
394 BT_LOGV("Current path token: token=\"%s\"", ft_name
);
396 /* Find to which index corresponds the current path token */
397 if (fc
->type
== CTF_FIELD_CLASS_TYPE_ARRAY
||
398 fc
->type
== CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
402 ctf_field_class_compound_get_field_class_index_from_name(
404 if (child_index
< 0) {
406 * Error: field name does not exist or
407 * wrong current class.
409 BT_LOGV("Cannot get index of field class: "
410 "field-name=\"%s\", "
411 "src-index=%" PRId64
", "
412 "child-index=%" PRId64
", "
413 "first-level-done=%d",
414 ft_name
, src_index
, child_index
,
418 } else if (child_index
> src_index
&&
420 BT_LOGV("Child field class is located after source field class: "
421 "field-name=\"%s\", "
422 "src-index=%" PRId64
", "
423 "child-index=%" PRId64
", "
424 "first-level-done=%d",
425 ft_name
, src_index
, child_index
,
431 /* Next path token */
432 cur_ptoken
= g_list_next(cur_ptoken
);
433 first_level_done
= true;
436 /* Create new field path entry */
437 ctf_field_path_append_index(field_path
, child_index
);
439 /* Get child field class */
440 child_fc
= ctf_field_class_compound_borrow_field_class_by_index(
444 /* Move child class to current class */
453 * Converts a known absolute path token list to a field path object
454 * within the resolving context `ctx`.
456 * `field_path` is an output parameter owned by the caller that must be
460 int absolute_ptokens_to_field_path(GList
*ptokens
,
461 struct ctf_field_path
*field_path
,
462 struct resolve_context
*ctx
)
466 struct ctf_field_class
*fc
;
469 * Make sure we're not referring to a scope within a translated
472 switch (field_path
->root
) {
473 case CTF_SCOPE_PACKET_HEADER
:
474 if (ctx
->tc
->is_translated
) {
475 BT_LOGE("Trace class is already translated: "
477 ctf_scope_string(field_path
->root
));
483 case CTF_SCOPE_PACKET_CONTEXT
:
484 case CTF_SCOPE_EVENT_HEADER
:
485 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
487 BT_LOGE("No current stream class: "
489 ctf_scope_string(field_path
->root
));
494 if (ctx
->sc
->is_translated
) {
495 BT_LOGE("Stream class is already translated: "
497 ctf_scope_string(field_path
->root
));
503 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
504 case CTF_SCOPE_EVENT_PAYLOAD
:
506 BT_LOGE("No current event class: "
508 ctf_scope_string(field_path
->root
));
513 if (ctx
->ec
->is_translated
) {
514 BT_LOGE("Event class is already translated: "
516 ctf_scope_string(field_path
->root
));
527 /* Skip absolute path tokens */
528 cur_ptoken
= g_list_nth(ptokens
,
529 absolute_path_prefix_ptoken_counts
[field_path
->root
]);
531 /* Start with root class */
532 fc
= borrow_class_from_ctx(ctx
, field_path
->root
);
534 /* Error: root class is not available */
535 BT_LOGE("Root field class is not available: "
537 ctf_scope_string(field_path
->root
));
543 ret
= ptokens_to_field_path(cur_ptoken
, field_path
, fc
, INT64_MAX
);
550 * Converts a known relative path token list to a field path object
551 * within the resolving context `ctx`.
553 * `field_path` is an output parameter owned by the caller that must be
557 int relative_ptokens_to_field_path(GList
*ptokens
,
558 struct ctf_field_path
*field_path
, struct resolve_context
*ctx
)
561 int64_t parent_pos_in_stack
;
562 struct ctf_field_path tail_field_path
;
564 ctf_field_path_init(&tail_field_path
);
565 parent_pos_in_stack
= field_class_stack_size(ctx
->field_class_stack
) - 1;
567 while (parent_pos_in_stack
>= 0) {
568 struct ctf_field_class
*parent_class
=
569 field_class_stack_at(ctx
->field_class_stack
,
570 parent_pos_in_stack
)->fc
;
571 int64_t cur_index
= field_class_stack_at(ctx
->field_class_stack
,
572 parent_pos_in_stack
)->index
;
574 BT_LOGV("Locating target field class from current parent field class: "
575 "parent-pos=%" PRId64
", parent-fc-addr=%p, "
576 "cur-index=%" PRId64
,
577 parent_pos_in_stack
, parent_class
, cur_index
);
579 /* Locate target from current parent class */
580 ret
= ptokens_to_field_path(ptokens
, &tail_field_path
,
581 parent_class
, cur_index
);
583 /* Not found... yet */
584 BT_LOGV_STR("Not found at this point.");
585 ctf_field_path_clear(&tail_field_path
);
587 /* Found: stitch tail field path to head field path */
589 size_t tail_field_path_len
=
590 tail_field_path
.path
->len
;
593 struct ctf_field_class
*cur_class
=
594 field_class_stack_at(
595 ctx
->field_class_stack
, i
)->fc
;
596 int64_t index
= field_class_stack_at(
597 ctx
->field_class_stack
, i
)->index
;
599 if (cur_class
== parent_class
) {
603 ctf_field_path_append_index(field_path
,
608 for (i
= 0; i
< tail_field_path_len
; i
++) {
610 ctf_field_path_borrow_index_by_index(
611 &tail_field_path
, i
);
613 ctf_field_path_append_index(field_path
,
619 parent_pos_in_stack
--;
622 if (parent_pos_in_stack
< 0) {
627 ctf_field_path_fini(&tail_field_path
);
632 * Converts a path string to a field path object within the resolving
636 int pathstr_to_field_path(const char *pathstr
,
637 struct ctf_field_path
*field_path
, struct resolve_context
*ctx
)
640 enum ctf_scope root_scope
;
641 GList
*ptokens
= NULL
;
643 /* Convert path string to path tokens */
644 ptokens
= pathstr_to_ptokens(pathstr
);
646 BT_LOGE("Cannot convert path string to path tokens: "
647 "path=\"%s\"", pathstr
);
652 /* Absolute or relative path? */
653 root_scope
= get_root_scope_from_absolute_pathstr(pathstr
);
655 if (root_scope
== -1) {
656 /* Relative path: start with current root scope */
657 field_path
->root
= ctx
->root_scope
;
658 BT_LOGV("Detected relative path: starting with current root scope: "
659 "scope=%s", ctf_scope_string(field_path
->root
));
660 ret
= relative_ptokens_to_field_path(ptokens
, field_path
, ctx
);
662 BT_LOGE("Cannot get relative field path of path string: "
663 "path=\"%s\", start-scope=%s, end-scope=%s",
664 pathstr
, ctf_scope_string(ctx
->root_scope
),
665 ctf_scope_string(field_path
->root
));
669 /* Absolute path: use found root scope */
670 field_path
->root
= root_scope
;
671 BT_LOGV("Detected absolute path: using root scope: "
672 "scope=%s", ctf_scope_string(field_path
->root
));
673 ret
= absolute_ptokens_to_field_path(ptokens
, field_path
, ctx
);
675 BT_LOGE("Cannot get absolute field path of path string: "
676 "path=\"%s\", root-scope=%s",
677 pathstr
, ctf_scope_string(root_scope
));
682 if (BT_LOG_ON_VERBOSE
&& ret
== 0) {
683 GString
*field_path_pretty
= ctf_field_path_string(field_path
);
684 const char *field_path_pretty_str
=
685 field_path_pretty
? field_path_pretty
->str
: NULL
;
687 BT_LOGV("Found field path: path=\"%s\", field-path=\"%s\"",
688 pathstr
, field_path_pretty_str
);
690 if (field_path_pretty
) {
691 g_string_free(field_path_pretty
, TRUE
);
696 ptokens_destroy(ptokens
);
701 * Retrieves a field class by following the field path `field_path` in
702 * the resolving context `ctx`.
705 struct ctf_field_class
*field_path_to_field_class(
706 struct ctf_field_path
*field_path
, struct resolve_context
*ctx
)
709 struct ctf_field_class
*fc
;
711 /* Start with root class */
712 fc
= borrow_class_from_ctx(ctx
, field_path
->root
);
714 /* Error: root class is not available */
715 BT_LOGE("Root field class is not available: root-scope=%s",
716 ctf_scope_string(field_path
->root
));
721 for (i
= 0; i
< field_path
->path
->len
; i
++) {
722 struct ctf_field_class
*child_fc
;
723 int64_t child_index
=
724 ctf_field_path_borrow_index_by_index(field_path
, i
);
726 /* Get child field class */
727 child_fc
= ctf_field_class_compound_borrow_field_class_by_index(
731 /* Move child class to current class */
740 * Fills the equivalent field path object of the context class stack.
743 void get_ctx_stack_field_path(struct resolve_context
*ctx
,
744 struct ctf_field_path
*field_path
)
748 BT_ASSERT(field_path
);
749 field_path
->root
= ctx
->root_scope
;
750 ctf_field_path_clear(field_path
);
752 for (i
= 0; i
< field_class_stack_size(ctx
->field_class_stack
); i
++) {
753 struct field_class_stack_frame
*frame
=
754 field_class_stack_at(ctx
->field_class_stack
, i
);
756 ctf_field_path_append_index(field_path
, frame
->index
);
761 * Returns the index of the lowest common ancestor of two field path
762 * objects having the same root scope.
764 int64_t get_field_paths_lca_index(struct ctf_field_path
*field_path1
,
765 struct ctf_field_path
*field_path2
)
767 int64_t lca_index
= 0;
768 uint64_t field_path1_len
, field_path2_len
;
770 if (BT_LOG_ON_VERBOSE
) {
771 GString
*field_path1_pretty
=
772 ctf_field_path_string(field_path1
);
773 GString
*field_path2_pretty
=
774 ctf_field_path_string(field_path2
);
775 const char *field_path1_pretty_str
=
776 field_path1_pretty
? field_path1_pretty
->str
: NULL
;
777 const char *field_path2_pretty_str
=
778 field_path2_pretty
? field_path2_pretty
->str
: NULL
;
780 BT_LOGV("Finding lowest common ancestor (LCA) between two field paths: "
781 "field-path-1=\"%s\", field-path-2=\"%s\"",
782 field_path1_pretty_str
, field_path2_pretty_str
);
784 if (field_path1_pretty
) {
785 g_string_free(field_path1_pretty
, TRUE
);
788 if (field_path2_pretty
) {
789 g_string_free(field_path2_pretty
, TRUE
);
794 * Start from both roots and find the first mismatch.
796 BT_ASSERT(field_path1
->root
== field_path2
->root
);
797 field_path1_len
= field_path1
->path
->len
;
798 field_path2_len
= field_path2
->path
->len
;
801 int64_t target_index
, ctx_index
;
803 if (lca_index
== (int64_t) field_path2_len
||
804 lca_index
== (int64_t) field_path1_len
) {
806 * This means that both field paths never split.
807 * This is invalid because the target cannot be
808 * an ancestor of the source.
810 BT_LOGE("Source field class is an ancestor of target field class or vice versa: "
811 "lca-index=%" PRId64
", "
812 "field-path-1-len=%" PRIu64
", "
813 "field-path-2-len=%" PRIu64
,
814 lca_index
, field_path1_len
, field_path2_len
);
819 target_index
= ctf_field_path_borrow_index_by_index(field_path1
,
821 ctx_index
= ctf_field_path_borrow_index_by_index(field_path2
,
824 if (target_index
!= ctx_index
) {
825 /* LCA index is the previous */
832 BT_LOGV("Found LCA: lca-index=%" PRId64
, lca_index
);
837 * Validates a target field path.
840 int validate_target_field_path(struct ctf_field_path
*target_field_path
,
841 struct ctf_field_class
*target_fc
,
842 struct resolve_context
*ctx
)
845 struct ctf_field_path ctx_field_path
;
846 uint64_t target_field_path_len
= target_field_path
->path
->len
;
849 /* Get context field path */
850 ctf_field_path_init(&ctx_field_path
);
851 get_ctx_stack_field_path(ctx
, &ctx_field_path
);
854 * Make sure the target is not a root.
856 if (target_field_path_len
== 0) {
857 BT_LOGE_STR("Target field path's length is 0 (targeting the root).");
863 * Make sure the root of the target field path is not located
864 * after the context field path's root.
866 if (target_field_path
->root
> ctx_field_path
.root
) {
867 BT_LOGE("Target field class is located after source field class: "
868 "target-root=%s, source-root=%s",
869 ctf_scope_string(target_field_path
->root
),
870 ctf_scope_string(ctx_field_path
.root
));
875 if (target_field_path
->root
== ctx_field_path
.root
) {
876 int64_t target_index
, ctx_index
;
879 * Find the index of the lowest common ancestor of both field
882 lca_index
= get_field_paths_lca_index(target_field_path
,
885 BT_LOGE_STR("Cannot get least common ancestor.");
891 * Make sure the target field path is located before the
892 * context field path.
894 target_index
= ctf_field_path_borrow_index_by_index(
895 target_field_path
, (uint64_t) lca_index
);
896 ctx_index
= ctf_field_path_borrow_index_by_index(
897 &ctx_field_path
, (uint64_t) lca_index
);
899 if (target_index
>= ctx_index
) {
900 BT_LOGE("Target field class's index is greater than or equal to source field class's index in LCA: "
901 "lca-index=%" PRId64
", "
902 "target-index=%" PRId64
", "
903 "source-index=%" PRId64
,
904 lca_index
, target_index
, ctx_index
);
911 * Make sure the target class has the right class and properties.
913 switch (ctx
->cur_fc
->type
) {
914 case CTF_FIELD_CLASS_TYPE_VARIANT
:
915 if (target_fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
916 BT_LOGE("Variant field class's tag field class is not an enumeration field class: "
917 "tag-fc-addr=%p, tag-fc-id=%d",
918 target_fc
, target_fc
->type
);
923 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
925 struct ctf_field_class_int
*int_fc
= (void *) target_fc
;
927 if (target_fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
928 target_fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
929 BT_LOGE("Sequence field class's length field class is not an unsigned integer field class: "
930 "length-fc-addr=%p, length-fc-id=%d",
931 target_fc
, target_fc
->type
);
936 if (int_fc
->is_signed
) {
937 BT_LOGE("Sequence field class's length field class is not an unsigned integer field class: "
938 "length-fc-addr=%p, length-fc-id=%d",
939 target_fc
, target_fc
->type
);
950 ctf_field_path_fini(&ctx_field_path
);
955 * Resolves a variant or sequence field class `fc`.
958 int resolve_sequence_or_variant_field_class(struct ctf_field_class
*fc
,
959 struct resolve_context
*ctx
)
963 struct ctf_field_path target_field_path
;
964 struct ctf_field_class
*target_fc
= NULL
;
965 GString
*target_field_path_pretty
= NULL
;
966 const char *target_field_path_pretty_str
;
968 ctf_field_path_init(&target_field_path
);
970 /* Get path string */
972 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
974 struct ctf_field_class_sequence
*seq_fc
= (void *) fc
;
975 pathstr
= seq_fc
->length_ref
->str
;
978 case CTF_FIELD_CLASS_TYPE_VARIANT
:
980 struct ctf_field_class_variant
*var_fc
= (void *) fc
;
981 pathstr
= var_fc
->tag_ref
->str
;
989 BT_LOGE_STR("Cannot get path string.");
994 /* Get target field path out of path string */
995 ret
= pathstr_to_field_path(pathstr
, &target_field_path
, ctx
);
997 BT_LOGE("Cannot get target field path for path string: "
998 "path=\"%s\"", pathstr
);
1002 target_field_path_pretty
= ctf_field_path_string(
1003 &target_field_path
);
1004 target_field_path_pretty_str
=
1005 target_field_path_pretty
? target_field_path_pretty
->str
: NULL
;
1007 /* Get target field class */
1008 target_fc
= field_path_to_field_class(&target_field_path
, ctx
);
1010 BT_LOGE("Cannot get target field class for path string: "
1011 "path=\"%s\", target-field-path=\"%s\"",
1012 pathstr
, target_field_path_pretty_str
);
1017 ret
= validate_target_field_path(&target_field_path
,
1020 BT_LOGE("Invalid target field path for path string: "
1021 "path=\"%s\", target-field-path=\"%s\"",
1022 pathstr
, target_field_path_pretty_str
);
1026 /* Set target field path and target field class */
1028 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1030 struct ctf_field_class_sequence
*seq_fc
= (void *) fc
;
1032 ctf_field_path_copy_content(&seq_fc
->length_path
,
1033 &target_field_path
);
1034 seq_fc
->length_fc
= (void *) target_fc
;
1037 case CTF_FIELD_CLASS_TYPE_VARIANT
:
1039 struct ctf_field_class_variant
*var_fc
= (void *) fc
;
1041 ctf_field_path_copy_content(&var_fc
->tag_path
,
1042 &target_field_path
);
1043 ctf_field_class_variant_set_tag_field_class(var_fc
,
1044 (void *) target_fc
);
1052 if (target_field_path_pretty
) {
1053 g_string_free(target_field_path_pretty
, TRUE
);
1056 ctf_field_path_fini(&target_field_path
);
1061 * Resolves a field class `fc`.
1064 int resolve_field_class(struct ctf_field_class
*fc
, struct resolve_context
*ctx
)
1069 /* Field class is not available; still valid */
1075 /* Resolve sequence/variant field class */
1077 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1078 case CTF_FIELD_CLASS_TYPE_VARIANT
:
1079 ret
= resolve_sequence_or_variant_field_class(fc
, ctx
);
1081 BT_LOGE("Cannot resolve sequence field class's length or variant field class's tag: "
1082 "ret=%d, fc-addr=%p", ret
, fc
);
1091 /* Recurse into compound classes */
1093 case CTF_FIELD_CLASS_TYPE_STRUCT
:
1094 case CTF_FIELD_CLASS_TYPE_VARIANT
:
1095 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1096 case CTF_FIELD_CLASS_TYPE_ARRAY
:
1099 uint64_t field_count
=
1100 ctf_field_class_compound_get_field_class_count(fc
);
1102 ret
= field_class_stack_push(ctx
->field_class_stack
, fc
);
1104 BT_LOGE("Cannot push field class on context's stack: "
1109 for (i
= 0; i
< field_count
; i
++) {
1110 struct ctf_field_class
*child_fc
=
1111 ctf_field_class_compound_borrow_field_class_by_index(
1114 BT_ASSERT(child_fc
);
1116 if (fc
->type
== CTF_FIELD_CLASS_TYPE_ARRAY
||
1117 fc
->type
== CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1118 field_class_stack_peek(
1119 ctx
->field_class_stack
)->index
= -1;
1121 field_class_stack_peek(
1122 ctx
->field_class_stack
)->index
=
1126 BT_LOGV("Resolving field class's child field class: "
1127 "parent-fc-addr=%p, child-fc-addr=%p, "
1128 "index=%" PRIu64
", count=%" PRIu64
,
1129 fc
, child_fc
, i
, field_count
);
1130 ret
= resolve_field_class(child_fc
, ctx
);
1136 field_class_stack_pop(ctx
->field_class_stack
);
1148 * Resolves the root field class corresponding to the scope `root_scope`.
1151 int resolve_root_class(enum ctf_scope root_scope
, struct resolve_context
*ctx
)
1155 BT_ASSERT(field_class_stack_size(ctx
->field_class_stack
) == 0);
1156 ctx
->root_scope
= root_scope
;
1157 ret
= resolve_field_class(borrow_class_from_ctx(ctx
, root_scope
), ctx
);
1158 ctx
->root_scope
= -1;
1163 int resolve_event_class_field_classes(struct resolve_context
*ctx
,
1164 struct ctf_event_class
*ec
)
1168 BT_ASSERT(!ctx
->scopes
.event_spec_context
);
1169 BT_ASSERT(!ctx
->scopes
.event_payload
);
1171 if (ec
->is_translated
) {
1176 ctx
->scopes
.event_spec_context
= ec
->spec_context_fc
;
1177 ret
= resolve_root_class(CTF_SCOPE_EVENT_COMMON_CONTEXT
, ctx
);
1179 BT_LOGE("Cannot resolve event specific context field class: "
1184 ctx
->scopes
.event_payload
= ec
->payload_fc
;
1185 ret
= resolve_root_class(CTF_SCOPE_EVENT_PAYLOAD
, ctx
);
1187 BT_LOGE("Cannot resolve event payload field class: "
1193 ctx
->scopes
.event_spec_context
= NULL
;
1194 ctx
->scopes
.event_payload
= NULL
;
1200 int resolve_stream_class_field_classes(struct resolve_context
*ctx
,
1201 struct ctf_stream_class
*sc
)
1206 BT_ASSERT(!ctx
->scopes
.packet_context
);
1207 BT_ASSERT(!ctx
->scopes
.event_header
);
1208 BT_ASSERT(!ctx
->scopes
.event_common_context
);
1211 if (!sc
->is_translated
) {
1212 ctx
->scopes
.packet_context
= sc
->packet_context_fc
;
1213 ret
= resolve_root_class(CTF_SCOPE_PACKET_CONTEXT
, ctx
);
1215 BT_LOGE("Cannot resolve packet context field class: "
1220 ctx
->scopes
.event_header
= sc
->event_header_fc
;
1221 ret
= resolve_root_class(CTF_SCOPE_EVENT_HEADER
, ctx
);
1223 BT_LOGE("Cannot resolve event header field class: "
1228 ctx
->scopes
.event_common_context
= sc
->event_common_context_fc
;
1229 ret
= resolve_root_class(CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
, ctx
);
1231 BT_LOGE("Cannot resolve event common context field class: "
1237 ctx
->scopes
.packet_context
= sc
->packet_context_fc
;
1238 ctx
->scopes
.event_header
= sc
->event_header_fc
;
1239 ctx
->scopes
.event_common_context
= sc
->event_common_context_fc
;
1241 for (i
= 0; i
< sc
->event_classes
->len
; i
++) {
1242 struct ctf_event_class
*ec
= sc
->event_classes
->pdata
[i
];
1244 ret
= resolve_event_class_field_classes(ctx
, ec
);
1246 BT_LOGE("Cannot resolve event class's field classes: "
1247 "ec-id=%" PRIu64
", ec-name=\"%s\"",
1248 ec
->id
, ec
->name
->str
);
1254 ctx
->scopes
.packet_context
= NULL
;
1255 ctx
->scopes
.event_header
= NULL
;
1256 ctx
->scopes
.event_common_context
= NULL
;
1262 int ctf_trace_class_resolve_field_classes(struct ctf_trace_class
*tc
)
1266 struct resolve_context ctx
= {
1271 .packet_header
= tc
->packet_header_fc
,
1272 .packet_context
= NULL
,
1273 .event_header
= NULL
,
1274 .event_common_context
= NULL
,
1275 .event_spec_context
= NULL
,
1276 .event_payload
= NULL
,
1278 .root_scope
= CTF_SCOPE_PACKET_HEADER
,
1282 /* Initialize class stack */
1283 ctx
.field_class_stack
= field_class_stack_create();
1284 if (!ctx
.field_class_stack
) {
1285 BT_LOGE_STR("Cannot create field class stack.");
1290 if (!tc
->is_translated
) {
1291 ctx
.scopes
.packet_header
= tc
->packet_header_fc
;
1292 ret
= resolve_root_class(CTF_SCOPE_PACKET_HEADER
, &ctx
);
1294 BT_LOGE("Cannot resolve packet header field class: "
1300 ctx
.scopes
.packet_header
= tc
->packet_header_fc
;
1302 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
1303 struct ctf_stream_class
*sc
= tc
->stream_classes
->pdata
[i
];
1305 ret
= resolve_stream_class_field_classes(&ctx
, sc
);
1307 BT_LOGE("Cannot resolve stream class's field classes: "
1308 "sc-id=%" PRIu64
, sc
->id
);
1314 field_class_stack_destroy(ctx
.field_class_stack
);