Move to kernel style SPDX license identifiers
[babeltrace.git] / src / plugins / ctf / common / metadata / ctf-meta-resolve.c
CommitLineData
44c440bc 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
44c440bc 3 *
0235b0db
MJ
4 * Copyright 2016-2018 Philippe Proulx <pproulx@efficios.com>
5 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
44c440bc
PP
6 */
7
f7b785ac 8#define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
0746848c 9#define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
350ad6c1 10#define BT_LOG_TAG "PLUGIN/CTF/META/RESOLVE"
d9c39b0a 11#include "logging/comp-logging.h"
44c440bc 12
3fadfbc0 13#include <babeltrace2/babeltrace.h>
91d81473 14#include "common/macros.h"
578e048b
MJ
15#include "common/assert.h"
16#include "common/common.h"
44c440bc 17#include <glib.h>
c4f23e30 18#include <stdbool.h>
44c440bc
PP
19#include <stdint.h>
20#include <string.h>
21#include <inttypes.h>
22#include <limits.h>
23#include <stdlib.h>
24#include <glib.h>
25
26#include "ctf-meta-visitors.h"
f7b785ac 27#include "logging.h"
44c440bc 28
5cd6d0e5 29typedef GPtrArray field_class_stack;
44c440bc
PP
30
31/*
32 * A stack frame.
33 *
5cd6d0e5
PP
34 * `fc` contains a compound field class (structure, variant, array,
35 * or sequence) and `index` indicates the index of the field class in
36 * the upper frame (-1 for array and sequence field classes). `name`
37 * indicates the name of the field class in the upper frame (empty
38 * string for array and sequence field classes).
44c440bc 39 */
5cd6d0e5
PP
40struct field_class_stack_frame {
41 struct ctf_field_class *fc;
44c440bc
PP
42 int64_t index;
43};
44
45/*
46 * The current context of the resolving engine.
47 */
48struct resolve_context {
0746848c 49 bt_logging_level log_level;
f7b785ac 50 bt_self_component *self_comp;
44c440bc
PP
51 struct ctf_trace_class *tc;
52 struct ctf_stream_class *sc;
53 struct ctf_event_class *ec;
54
55 struct {
5cd6d0e5
PP
56 struct ctf_field_class *packet_header;
57 struct ctf_field_class *packet_context;
58 struct ctf_field_class *event_header;
59 struct ctf_field_class *event_common_context;
60 struct ctf_field_class *event_spec_context;
61 struct ctf_field_class *event_payload;
44c440bc
PP
62 } scopes;
63
64 /* Root scope being visited */
83ebb7f1 65 enum ctf_scope root_scope;
5cd6d0e5
PP
66 field_class_stack *field_class_stack;
67 struct ctf_field_class *cur_fc;
44c440bc
PP
68};
69
70/* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
71static const char * const absolute_path_prefixes[] = {
83ebb7f1
PP
72 [CTF_SCOPE_PACKET_HEADER] = "trace.packet.header.",
73 [CTF_SCOPE_PACKET_CONTEXT] = "stream.packet.context.",
74 [CTF_SCOPE_EVENT_HEADER] = "stream.event.header.",
75 [CTF_SCOPE_EVENT_COMMON_CONTEXT] = "stream.event.context.",
76 [CTF_SCOPE_EVENT_SPECIFIC_CONTEXT] = "event.context.",
77 [CTF_SCOPE_EVENT_PAYLOAD] = "event.fields.",
44c440bc
PP
78};
79
80/* Number of path tokens used for the absolute prefixes */
81static const uint64_t absolute_path_prefix_ptoken_counts[] = {
83ebb7f1
PP
82 [CTF_SCOPE_PACKET_HEADER] = 3,
83 [CTF_SCOPE_PACKET_CONTEXT] = 3,
84 [CTF_SCOPE_EVENT_HEADER] = 3,
85 [CTF_SCOPE_EVENT_COMMON_CONTEXT] = 3,
86 [CTF_SCOPE_EVENT_SPECIFIC_CONTEXT] = 2,
87 [CTF_SCOPE_EVENT_PAYLOAD] = 2,
44c440bc
PP
88};
89
90static
5cd6d0e5 91void destroy_field_class_stack_frame(struct field_class_stack_frame *frame)
44c440bc
PP
92{
93 if (!frame) {
94 return;
95 }
96
97 g_free(frame);
98}
99
100/*
5cd6d0e5 101 * Creates a class stack.
44c440bc
PP
102 */
103static
5cd6d0e5 104field_class_stack *field_class_stack_create(void)
44c440bc
PP
105{
106 return g_ptr_array_new_with_free_func(
5cd6d0e5 107 (GDestroyNotify) destroy_field_class_stack_frame);
44c440bc
PP
108}
109
110/*
5cd6d0e5 111 * Destroys a class stack.
44c440bc
PP
112 */
113static
5cd6d0e5 114void field_class_stack_destroy(field_class_stack *stack)
44c440bc
PP
115{
116 if (stack) {
117 g_ptr_array_free(stack, TRUE);
118 }
119}
120
121/*
5cd6d0e5 122 * Pushes a field class onto a class stack.
44c440bc
PP
123 */
124static
0746848c
PP
125int field_class_stack_push(field_class_stack *stack, struct ctf_field_class *fc,
126 struct resolve_context *ctx)
44c440bc
PP
127{
128 int ret = 0;
5cd6d0e5 129 struct field_class_stack_frame *frame = NULL;
44c440bc 130
5cd6d0e5 131 if (!stack || !fc) {
f7b785ac 132 BT_COMP_LOGE("Invalid parameter: stack or field class is NULL.");
44c440bc
PP
133 ret = -1;
134 goto end;
135 }
136
5cd6d0e5 137 frame = g_new0(struct field_class_stack_frame, 1);
44c440bc 138 if (!frame) {
f7b785ac 139 BT_COMP_LOGE_STR("Failed to allocate one field class stack frame.");
44c440bc
PP
140 ret = -1;
141 goto end;
142 }
143
f7b785ac 144 BT_COMP_LOGD("Pushing field class on context's stack: "
5cd6d0e5
PP
145 "fc-addr=%p, stack-size-before=%u", fc, stack->len);
146 frame->fc = fc;
44c440bc
PP
147 g_ptr_array_add(stack, frame);
148
149end:
150 return ret;
151}
152
153/*
154 * Checks whether or not `stack` is empty.
155 */
156static
5cd6d0e5 157bool field_class_stack_empty(field_class_stack *stack)
44c440bc
PP
158{
159 return stack->len == 0;
160}
161
162/*
163 * Returns the number of frames in `stack`.
164 */
165static
5cd6d0e5 166size_t field_class_stack_size(field_class_stack *stack)
44c440bc
PP
167{
168 return stack->len;
169}
170
171/*
172 * Returns the top frame of `stack`.
173 */
174static
5cd6d0e5 175struct field_class_stack_frame *field_class_stack_peek(field_class_stack *stack)
44c440bc 176{
8fe10fa8
SM
177 BT_ASSERT(stack);
178 BT_ASSERT(!field_class_stack_empty(stack));
44c440bc 179
8fe10fa8 180 return g_ptr_array_index(stack, stack->len - 1);
44c440bc
PP
181}
182
183/*
184 * Returns the frame at index `index` in `stack`.
185 */
186static
5cd6d0e5 187struct field_class_stack_frame *field_class_stack_at(field_class_stack *stack,
44c440bc
PP
188 size_t index)
189{
8fe10fa8
SM
190 BT_ASSERT(stack);
191 BT_ASSERT(index < stack->len);
44c440bc 192
8fe10fa8 193 return g_ptr_array_index(stack, index);
44c440bc
PP
194}
195
196/*
197 * Removes the top frame of `stack`.
198 */
199static
0746848c
PP
200void field_class_stack_pop(field_class_stack *stack,
201 struct resolve_context *ctx)
44c440bc 202{
5cd6d0e5 203 if (!field_class_stack_empty(stack)) {
44c440bc
PP
204 /*
205 * This will call the frame's destructor and free it, as
5cd6d0e5 206 * well as put its contained field class.
44c440bc 207 */
f7b785ac 208 BT_COMP_LOGD("Popping context's stack: stack-size-before=%u",
44c440bc
PP
209 stack->len);
210 g_ptr_array_set_size(stack, stack->len - 1);
211 }
212}
213
214/*
5cd6d0e5 215 * Returns the scope field class of `scope` in the context `ctx`.
44c440bc
PP
216 */
217static
5cd6d0e5 218struct ctf_field_class *borrow_class_from_ctx(struct resolve_context *ctx,
83ebb7f1 219 enum ctf_scope scope)
44c440bc
PP
220{
221 switch (scope) {
83ebb7f1 222 case CTF_SCOPE_PACKET_HEADER:
44c440bc 223 return ctx->scopes.packet_header;
83ebb7f1 224 case CTF_SCOPE_PACKET_CONTEXT:
44c440bc 225 return ctx->scopes.packet_context;
83ebb7f1 226 case CTF_SCOPE_EVENT_HEADER:
44c440bc 227 return ctx->scopes.event_header;
83ebb7f1 228 case CTF_SCOPE_EVENT_COMMON_CONTEXT:
44c440bc 229 return ctx->scopes.event_common_context;
83ebb7f1 230 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT:
44c440bc 231 return ctx->scopes.event_spec_context;
83ebb7f1 232 case CTF_SCOPE_EVENT_PAYLOAD:
44c440bc
PP
233 return ctx->scopes.event_payload;
234 default:
498e7994 235 bt_common_abort();
44c440bc
PP
236 }
237
238 return NULL;
239}
240
241/*
242 * Returns the CTF scope from a path string. May return -1 if the path
243 * is found to be relative.
244 */
245static
0746848c
PP
246enum ctf_scope get_root_scope_from_absolute_pathstr(const char *pathstr,
247 struct resolve_context *ctx)
44c440bc 248{
83ebb7f1 249 enum ctf_scope scope;
d7fd2938 250 enum ctf_scope ret = CTF_SCOPE_PACKET_UNKNOWN;
44c440bc
PP
251 const size_t prefixes_count = sizeof(absolute_path_prefixes) /
252 sizeof(*absolute_path_prefixes);
253
83ebb7f1 254 for (scope = CTF_SCOPE_PACKET_HEADER; scope < CTF_SCOPE_PACKET_HEADER +
44c440bc
PP
255 prefixes_count; scope++) {
256 /*
d7fd2938 257 * Check if path string starts with a known absolute
44c440bc
PP
258 * path prefix.
259 *
260 * Refer to CTF 7.3.2 STATIC AND DYNAMIC SCOPES.
261 */
262 if (strncmp(pathstr, absolute_path_prefixes[scope],
263 strlen(absolute_path_prefixes[scope]))) {
264 /* Prefix does not match: try the next one */
f7b785ac 265 BT_COMP_LOGD("Prefix does not match: trying the next one: "
44c440bc
PP
266 "path=\"%s\", path-prefix=\"%s\", scope=%s",
267 pathstr, absolute_path_prefixes[scope],
d4928fcd 268 ctf_scope_string(scope));
44c440bc
PP
269 continue;
270 }
271
272 /* Found it! */
273 ret = scope;
f7b785ac 274 BT_COMP_LOGD("Found root scope from absolute path: "
44c440bc 275 "path=\"%s\", scope=%s", pathstr,
d4928fcd 276 ctf_scope_string(scope));
44c440bc
PP
277 goto end;
278 }
279
280end:
281 return ret;
282}
283
284/*
285 * Destroys a path token.
286 */
287static
288void ptokens_destroy_func(gpointer ptoken, gpointer data)
289{
290 g_string_free(ptoken, TRUE);
291}
292
293/*
294 * Destroys a path token list.
295 */
296static
297void ptokens_destroy(GList *ptokens)
298{
299 if (!ptokens) {
300 return;
301 }
302
303 g_list_foreach(ptokens, ptokens_destroy_func, NULL);
304 g_list_free(ptokens);
305}
306
307/*
308 * Returns the string contained in a path token.
309 */
310static
311const char *ptoken_get_string(GList *ptoken)
312{
313 GString *tokenstr = (GString *) ptoken->data;
314
315 return tokenstr->str;
316}
317
318/*
319 * Converts a path string to a path token list, that is, splits the
320 * individual words of a path string into a list of individual
321 * strings.
322 */
323static
0746848c 324GList *pathstr_to_ptokens(const char *pathstr, struct resolve_context *ctx)
44c440bc
PP
325{
326 const char *at = pathstr;
327 const char *last = at;
328 GList *ptokens = NULL;
329
330 for (;;) {
331 if (*at == '.' || *at == '\0') {
332 GString *tokenstr;
333
334 if (at == last) {
335 /* Error: empty token */
f7b785ac 336 BT_COMP_LOGE("Empty path token: path=\"%s\", pos=%u",
44c440bc
PP
337 pathstr, (unsigned int) (at - pathstr));
338 goto error;
339 }
340
341 tokenstr = g_string_new(NULL);
342 g_string_append_len(tokenstr, last, at - last);
343 ptokens = g_list_append(ptokens, tokenstr);
344 last = at + 1;
345 }
346
347 if (*at == '\0') {
348 break;
349 }
350
351 at++;
352 }
353
354 return ptokens;
355
356error:
357 ptokens_destroy(ptokens);
358 return NULL;
359}
360
361/*
362 * Converts a path token list to a field path object. The path token
5cd6d0e5 363 * list is relative from `fc`. The index of the source looking for its
45c51519
PP
364 * target within `fc` is indicated by `src_index`. This can be
365 * `INT64_MAX` if the source is contained in `fc`.
44c440bc
PP
366 *
367 * `field_path` is an output parameter owned by the caller that must be
368 * filled here.
369 */
370static
371int ptokens_to_field_path(GList *ptokens, struct ctf_field_path *field_path,
0746848c
PP
372 struct ctf_field_class *fc, int64_t src_index,
373 struct resolve_context *ctx)
44c440bc
PP
374{
375 int ret = 0;
376 GList *cur_ptoken = ptokens;
377 bool first_level_done = false;
378
379 /* Locate target */
380 while (cur_ptoken) {
381 int64_t child_index;
5cd6d0e5 382 struct ctf_field_class *child_fc;
44c440bc
PP
383 const char *ft_name = ptoken_get_string(cur_ptoken);
384
f7b785ac 385 BT_COMP_LOGD("Current path token: token=\"%s\"", ft_name);
44c440bc
PP
386
387 /* Find to which index corresponds the current path token */
864cad70
PP
388 if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY ||
389 fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) {
44c440bc
PP
390 child_index = -1;
391 } else {
392 child_index =
45c51519 393 ctf_field_class_compound_get_field_class_index_from_orig_name(
5cd6d0e5 394 fc, ft_name);
44c440bc
PP
395 if (child_index < 0) {
396 /*
397 * Error: field name does not exist or
5cd6d0e5 398 * wrong current class.
44c440bc 399 */
f7b785ac 400 BT_COMP_LOGD("Cannot get index of field class: "
44c440bc
PP
401 "field-name=\"%s\", "
402 "src-index=%" PRId64 ", "
403 "child-index=%" PRId64 ", "
404 "first-level-done=%d",
405 ft_name, src_index, child_index,
406 first_level_done);
407 ret = -1;
408 goto end;
409 } else if (child_index > src_index &&
410 !first_level_done) {
f7b785ac 411 BT_COMP_LOGD("Child field class is located after source field class: "
44c440bc
PP
412 "field-name=\"%s\", "
413 "src-index=%" PRId64 ", "
414 "child-index=%" PRId64 ", "
415 "first-level-done=%d",
416 ft_name, src_index, child_index,
417 first_level_done);
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 ctf_field_path_append_index(field_path, child_index);
429
5cd6d0e5
PP
430 /* Get child field class */
431 child_fc = ctf_field_class_compound_borrow_field_class_by_index(
432 fc, child_index);
433 BT_ASSERT(child_fc);
44c440bc 434
5cd6d0e5
PP
435 /* Move child class to current class */
436 fc = child_fc;
44c440bc
PP
437 }
438
439end:
440 return ret;
441}
442
443/*
444 * Converts a known absolute path token list to a field path object
445 * within the resolving context `ctx`.
446 *
447 * `field_path` is an output parameter owned by the caller that must be
448 * filled here.
449 */
450static
451int absolute_ptokens_to_field_path(GList *ptokens,
452 struct ctf_field_path *field_path,
453 struct resolve_context *ctx)
454{
455 int ret = 0;
456 GList *cur_ptoken;
5cd6d0e5 457 struct ctf_field_class *fc;
44c440bc
PP
458
459 /*
460 * Make sure we're not referring to a scope within a translated
461 * object.
462 */
463 switch (field_path->root) {
83ebb7f1 464 case CTF_SCOPE_PACKET_HEADER:
44c440bc 465 if (ctx->tc->is_translated) {
f7b785ac 466 BT_COMP_LOGE("Trace class is already translated: "
44c440bc 467 "root-scope=%s",
d4928fcd 468 ctf_scope_string(field_path->root));
44c440bc
PP
469 ret = -1;
470 goto end;
471 }
472
473 break;
83ebb7f1
PP
474 case CTF_SCOPE_PACKET_CONTEXT:
475 case CTF_SCOPE_EVENT_HEADER:
476 case CTF_SCOPE_EVENT_COMMON_CONTEXT:
44c440bc 477 if (!ctx->sc) {
f7b785ac 478 BT_COMP_LOGE("No current stream class: "
44c440bc 479 "root-scope=%s",
d4928fcd 480 ctf_scope_string(field_path->root));
44c440bc
PP
481 ret = -1;
482 goto end;
483 }
484
485 if (ctx->sc->is_translated) {
f7b785ac 486 BT_COMP_LOGE("Stream class is already translated: "
44c440bc 487 "root-scope=%s",
d4928fcd 488 ctf_scope_string(field_path->root));
44c440bc
PP
489 ret = -1;
490 goto end;
491 }
492
493 break;
83ebb7f1
PP
494 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT:
495 case CTF_SCOPE_EVENT_PAYLOAD:
44c440bc 496 if (!ctx->ec) {
f7b785ac 497 BT_COMP_LOGE("No current event class: "
44c440bc 498 "root-scope=%s",
d4928fcd 499 ctf_scope_string(field_path->root));
44c440bc
PP
500 ret = -1;
501 goto end;
502 }
503
504 if (ctx->ec->is_translated) {
f7b785ac 505 BT_COMP_LOGE("Event class is already translated: "
44c440bc 506 "root-scope=%s",
d4928fcd 507 ctf_scope_string(field_path->root));
44c440bc
PP
508 ret = -1;
509 goto end;
510 }
511
512 break;
513
514 default:
498e7994 515 bt_common_abort();
44c440bc
PP
516 }
517
518 /* Skip absolute path tokens */
519 cur_ptoken = g_list_nth(ptokens,
520 absolute_path_prefix_ptoken_counts[field_path->root]);
521
5cd6d0e5
PP
522 /* Start with root class */
523 fc = borrow_class_from_ctx(ctx, field_path->root);
524 if (!fc) {
525 /* Error: root class is not available */
f7b785ac 526 BT_COMP_LOGE("Root field class is not available: "
44c440bc 527 "root-scope=%s",
d4928fcd 528 ctf_scope_string(field_path->root));
44c440bc
PP
529 ret = -1;
530 goto end;
531 }
532
533 /* Locate target */
0746848c 534 ret = ptokens_to_field_path(cur_ptoken, field_path, fc, INT64_MAX, ctx);
44c440bc
PP
535
536end:
537 return ret;
538}
539
540/*
541 * Converts a known relative path token list to a field path object
542 * within the resolving context `ctx`.
543 *
544 * `field_path` is an output parameter owned by the caller that must be
545 * filled here.
546 */
547static
548int relative_ptokens_to_field_path(GList *ptokens,
549 struct ctf_field_path *field_path, struct resolve_context *ctx)
550{
551 int ret = 0;
552 int64_t parent_pos_in_stack;
553 struct ctf_field_path tail_field_path;
554
555 ctf_field_path_init(&tail_field_path);
5cd6d0e5 556 parent_pos_in_stack = field_class_stack_size(ctx->field_class_stack) - 1;
44c440bc
PP
557
558 while (parent_pos_in_stack >= 0) {
5cd6d0e5
PP
559 struct ctf_field_class *parent_class =
560 field_class_stack_at(ctx->field_class_stack,
561 parent_pos_in_stack)->fc;
562 int64_t cur_index = field_class_stack_at(ctx->field_class_stack,
44c440bc
PP
563 parent_pos_in_stack)->index;
564
f7b785ac 565 BT_COMP_LOGD("Locating target field class from current parent field class: "
5cd6d0e5 566 "parent-pos=%" PRId64 ", parent-fc-addr=%p, "
44c440bc 567 "cur-index=%" PRId64,
5cd6d0e5 568 parent_pos_in_stack, parent_class, cur_index);
44c440bc 569
5cd6d0e5 570 /* Locate target from current parent class */
44c440bc 571 ret = ptokens_to_field_path(ptokens, &tail_field_path,
0746848c 572 parent_class, cur_index, ctx);
44c440bc
PP
573 if (ret) {
574 /* Not found... yet */
f7b785ac 575 BT_COMP_LOGD_STR("Not found at this point.");
44c440bc
PP
576 ctf_field_path_clear(&tail_field_path);
577 } else {
578 /* Found: stitch tail field path to head field path */
579 uint64_t i = 0;
580 size_t tail_field_path_len =
581 tail_field_path.path->len;
582
583 while (BT_TRUE) {
5cd6d0e5
PP
584 struct ctf_field_class *cur_class =
585 field_class_stack_at(
586 ctx->field_class_stack, i)->fc;
587 int64_t index = field_class_stack_at(
588 ctx->field_class_stack, i)->index;
44c440bc 589
5cd6d0e5 590 if (cur_class == parent_class) {
44c440bc
PP
591 break;
592 }
593
594 ctf_field_path_append_index(field_path,
595 index);
596 i++;
597 }
598
599 for (i = 0; i < tail_field_path_len; i++) {
600 int64_t index =
601 ctf_field_path_borrow_index_by_index(
602 &tail_field_path, i);
603
604 ctf_field_path_append_index(field_path,
605 (int64_t) index);
606 }
607 break;
608 }
609
610 parent_pos_in_stack--;
611 }
612
613 if (parent_pos_in_stack < 0) {
614 /* Not found */
615 ret = -1;
616 }
617
618 ctf_field_path_fini(&tail_field_path);
619 return ret;
620}
621
622/*
623 * Converts a path string to a field path object within the resolving
624 * context `ctx`.
625 */
626static
627int pathstr_to_field_path(const char *pathstr,
628 struct ctf_field_path *field_path, struct resolve_context *ctx)
629{
630 int ret = 0;
83ebb7f1 631 enum ctf_scope root_scope;
44c440bc
PP
632 GList *ptokens = NULL;
633
634 /* Convert path string to path tokens */
0746848c 635 ptokens = pathstr_to_ptokens(pathstr, ctx);
44c440bc 636 if (!ptokens) {
f7b785ac 637 BT_COMP_LOGE("Cannot convert path string to path tokens: "
44c440bc
PP
638 "path=\"%s\"", pathstr);
639 ret = -1;
640 goto end;
641 }
642
643 /* Absolute or relative path? */
0746848c 644 root_scope = get_root_scope_from_absolute_pathstr(pathstr, ctx);
44c440bc 645
d7fd2938 646 if (root_scope == CTF_SCOPE_PACKET_UNKNOWN) {
44c440bc
PP
647 /* Relative path: start with current root scope */
648 field_path->root = ctx->root_scope;
f7b785ac 649 BT_COMP_LOGD("Detected relative path: starting with current root scope: "
d4928fcd 650 "scope=%s", ctf_scope_string(field_path->root));
44c440bc
PP
651 ret = relative_ptokens_to_field_path(ptokens, field_path, ctx);
652 if (ret) {
f7b785ac 653 BT_COMP_LOGE("Cannot get relative field path of path string: "
44c440bc 654 "path=\"%s\", start-scope=%s, end-scope=%s",
d4928fcd
FD
655 pathstr, ctf_scope_string(ctx->root_scope),
656 ctf_scope_string(field_path->root));
44c440bc
PP
657 goto end;
658 }
659 } else {
660 /* Absolute path: use found root scope */
661 field_path->root = root_scope;
f7b785ac 662 BT_COMP_LOGD("Detected absolute path: using root scope: "
d4928fcd 663 "scope=%s", ctf_scope_string(field_path->root));
44c440bc
PP
664 ret = absolute_ptokens_to_field_path(ptokens, field_path, ctx);
665 if (ret) {
f7b785ac 666 BT_COMP_LOGE("Cannot get absolute field path of path string: "
44c440bc 667 "path=\"%s\", root-scope=%s",
d4928fcd 668 pathstr, ctf_scope_string(root_scope));
44c440bc
PP
669 goto end;
670 }
671 }
672
ef267d12 673 if (BT_LOG_ON_TRACE && ret == 0) {
44c440bc
PP
674 GString *field_path_pretty = ctf_field_path_string(field_path);
675 const char *field_path_pretty_str =
676 field_path_pretty ? field_path_pretty->str : NULL;
677
f7b785ac 678 BT_COMP_LOGD("Found field path: path=\"%s\", field-path=\"%s\"",
44c440bc
PP
679 pathstr, field_path_pretty_str);
680
681 if (field_path_pretty) {
682 g_string_free(field_path_pretty, TRUE);
683 }
684 }
685
686end:
687 ptokens_destroy(ptokens);
688 return ret;
689}
690
691/*
5cd6d0e5 692 * Retrieves a field class by following the field path `field_path` in
44c440bc
PP
693 * the resolving context `ctx`.
694 */
695static
5cd6d0e5 696struct ctf_field_class *field_path_to_field_class(
44c440bc
PP
697 struct ctf_field_path *field_path, struct resolve_context *ctx)
698{
699 uint64_t i;
5cd6d0e5 700 struct ctf_field_class *fc;
44c440bc 701
5cd6d0e5
PP
702 /* Start with root class */
703 fc = borrow_class_from_ctx(ctx, field_path->root);
704 if (!fc) {
705 /* Error: root class is not available */
f7b785ac 706 BT_COMP_LOGE("Root field class is not available: root-scope=%s",
d4928fcd 707 ctf_scope_string(field_path->root));
44c440bc
PP
708 goto end;
709 }
710
711 /* Locate target */
712 for (i = 0; i < field_path->path->len; i++) {
5cd6d0e5 713 struct ctf_field_class *child_fc;
44c440bc
PP
714 int64_t child_index =
715 ctf_field_path_borrow_index_by_index(field_path, i);
716
5cd6d0e5
PP
717 /* Get child field class */
718 child_fc = ctf_field_class_compound_borrow_field_class_by_index(
719 fc, child_index);
720 BT_ASSERT(child_fc);
44c440bc 721
5cd6d0e5
PP
722 /* Move child class to current class */
723 fc = child_fc;
44c440bc
PP
724 }
725
726end:
5cd6d0e5 727 return fc;
44c440bc
PP
728}
729
730/*
5cd6d0e5 731 * Fills the equivalent field path object of the context class stack.
44c440bc
PP
732 */
733static
734void get_ctx_stack_field_path(struct resolve_context *ctx,
735 struct ctf_field_path *field_path)
736{
737 uint64_t i;
738
739 BT_ASSERT(field_path);
740 field_path->root = ctx->root_scope;
741 ctf_field_path_clear(field_path);
742
5cd6d0e5
PP
743 for (i = 0; i < field_class_stack_size(ctx->field_class_stack); i++) {
744 struct field_class_stack_frame *frame =
745 field_class_stack_at(ctx->field_class_stack, i);
44c440bc
PP
746
747 ctf_field_path_append_index(field_path, frame->index);
748 }
749}
750
751/*
752 * Returns the index of the lowest common ancestor of two field path
753 * objects having the same root scope.
754 */
7c7301d5 755static
44c440bc 756int64_t get_field_paths_lca_index(struct ctf_field_path *field_path1,
0746848c
PP
757 struct ctf_field_path *field_path2,
758 struct resolve_context *ctx)
44c440bc
PP
759{
760 int64_t lca_index = 0;
761 uint64_t field_path1_len, field_path2_len;
762
ef267d12 763 if (BT_LOG_ON_TRACE) {
44c440bc
PP
764 GString *field_path1_pretty =
765 ctf_field_path_string(field_path1);
766 GString *field_path2_pretty =
767 ctf_field_path_string(field_path2);
768 const char *field_path1_pretty_str =
769 field_path1_pretty ? field_path1_pretty->str : NULL;
770 const char *field_path2_pretty_str =
771 field_path2_pretty ? field_path2_pretty->str : NULL;
772
f7b785ac 773 BT_COMP_LOGD("Finding lowest common ancestor (LCA) between two field paths: "
44c440bc
PP
774 "field-path-1=\"%s\", field-path-2=\"%s\"",
775 field_path1_pretty_str, field_path2_pretty_str);
776
777 if (field_path1_pretty) {
778 g_string_free(field_path1_pretty, TRUE);
779 }
780
781 if (field_path2_pretty) {
782 g_string_free(field_path2_pretty, TRUE);
783 }
784 }
785
786 /*
787 * Start from both roots and find the first mismatch.
788 */
789 BT_ASSERT(field_path1->root == field_path2->root);
790 field_path1_len = field_path1->path->len;
791 field_path2_len = field_path2->path->len;
792
793 while (true) {
794 int64_t target_index, ctx_index;
795
796 if (lca_index == (int64_t) field_path2_len ||
797 lca_index == (int64_t) field_path1_len) {
798 /*
799 * This means that both field paths never split.
800 * This is invalid because the target cannot be
801 * an ancestor of the source.
802 */
f7b785ac 803 BT_COMP_LOGE("Source field class is an ancestor of target field class or vice versa: "
44c440bc
PP
804 "lca-index=%" PRId64 ", "
805 "field-path-1-len=%" PRIu64 ", "
806 "field-path-2-len=%" PRIu64,
807 lca_index, field_path1_len, field_path2_len);
808 lca_index = -1;
809 break;
810 }
811
812 target_index = ctf_field_path_borrow_index_by_index(field_path1,
813 lca_index);
814 ctx_index = ctf_field_path_borrow_index_by_index(field_path2,
815 lca_index);
816
817 if (target_index != ctx_index) {
818 /* LCA index is the previous */
819 break;
820 }
821
822 lca_index++;
823 }
824
f7b785ac 825 BT_COMP_LOGD("Found LCA: lca-index=%" PRId64, lca_index);
44c440bc
PP
826 return lca_index;
827}
828
829/*
830 * Validates a target field path.
831 */
832static
833int validate_target_field_path(struct ctf_field_path *target_field_path,
5cd6d0e5 834 struct ctf_field_class *target_fc,
44c440bc
PP
835 struct resolve_context *ctx)
836{
837 int ret = 0;
838 struct ctf_field_path ctx_field_path;
839 uint64_t target_field_path_len = target_field_path->path->len;
840 int64_t lca_index;
841
842 /* Get context field path */
843 ctf_field_path_init(&ctx_field_path);
844 get_ctx_stack_field_path(ctx, &ctx_field_path);
845
846 /*
847 * Make sure the target is not a root.
848 */
849 if (target_field_path_len == 0) {
f7b785ac 850 BT_COMP_LOGE_STR("Target field path's length is 0 (targeting the root).");
44c440bc
PP
851 ret = -1;
852 goto end;
853 }
854
855 /*
856 * Make sure the root of the target field path is not located
857 * after the context field path's root.
858 */
859 if (target_field_path->root > ctx_field_path.root) {
f7b785ac 860 BT_COMP_LOGE("Target field class is located after source field class: "
44c440bc 861 "target-root=%s, source-root=%s",
d4928fcd
FD
862 ctf_scope_string(target_field_path->root),
863 ctf_scope_string(ctx_field_path.root));
44c440bc
PP
864 ret = -1;
865 goto end;
866 }
867
868 if (target_field_path->root == ctx_field_path.root) {
869 int64_t target_index, ctx_index;
870
871 /*
872 * Find the index of the lowest common ancestor of both field
873 * paths.
874 */
875 lca_index = get_field_paths_lca_index(target_field_path,
0746848c 876 &ctx_field_path, ctx);
44c440bc 877 if (lca_index < 0) {
f7b785ac 878 BT_COMP_LOGE_STR("Cannot get least common ancestor.");
44c440bc
PP
879 ret = -1;
880 goto end;
881 }
882
883 /*
884 * Make sure the target field path is located before the
885 * context field path.
886 */
887 target_index = ctf_field_path_borrow_index_by_index(
888 target_field_path, (uint64_t) lca_index);
889 ctx_index = ctf_field_path_borrow_index_by_index(
890 &ctx_field_path, (uint64_t) lca_index);
891
892 if (target_index >= ctx_index) {
f7b785ac 893 BT_COMP_LOGE("Target field class's index is greater than or equal to source field class's index in LCA: "
44c440bc
PP
894 "lca-index=%" PRId64 ", "
895 "target-index=%" PRId64 ", "
896 "source-index=%" PRId64,
897 lca_index, target_index, ctx_index);
898 ret = -1;
899 goto end;
900 }
901 }
902
903 /*
5cd6d0e5 904 * Make sure the target class has the right class and properties.
44c440bc 905 */
864cad70
PP
906 switch (ctx->cur_fc->type) {
907 case CTF_FIELD_CLASS_TYPE_VARIANT:
908 if (target_fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
f7b785ac 909 BT_COMP_LOGE("Variant field class's tag field class is not an enumeration field class: "
5cd6d0e5 910 "tag-fc-addr=%p, tag-fc-id=%d",
864cad70 911 target_fc, target_fc->type);
44c440bc
PP
912 ret = -1;
913 goto end;
914 }
915 break;
864cad70 916 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
44c440bc 917 {
5cd6d0e5 918 struct ctf_field_class_int *int_fc = (void *) target_fc;
44c440bc 919
864cad70
PP
920 if (target_fc->type != CTF_FIELD_CLASS_TYPE_INT &&
921 target_fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
f7b785ac 922 BT_COMP_LOGE("Sequence field class's length field class is not an unsigned integer field class: "
5cd6d0e5 923 "length-fc-addr=%p, length-fc-id=%d",
864cad70 924 target_fc, target_fc->type);
44c440bc
PP
925 ret = -1;
926 goto end;
927 }
928
5cd6d0e5 929 if (int_fc->is_signed) {
f7b785ac 930 BT_COMP_LOGE("Sequence field class's length field class is not an unsigned integer field class: "
5cd6d0e5 931 "length-fc-addr=%p, length-fc-id=%d",
864cad70 932 target_fc, target_fc->type);
44c440bc
PP
933 ret = -1;
934 goto end;
935 }
936 break;
937 }
938 default:
498e7994 939 bt_common_abort();
44c440bc
PP
940 }
941
942end:
943 ctf_field_path_fini(&ctx_field_path);
944 return ret;
945}
946
947/*
5cd6d0e5 948 * Resolves a variant or sequence field class `fc`.
44c440bc
PP
949 */
950static
5cd6d0e5 951int resolve_sequence_or_variant_field_class(struct ctf_field_class *fc,
44c440bc
PP
952 struct resolve_context *ctx)
953{
954 int ret = 0;
955 const char *pathstr;
956 struct ctf_field_path target_field_path;
5cd6d0e5 957 struct ctf_field_class *target_fc = NULL;
44c440bc
PP
958 GString *target_field_path_pretty = NULL;
959 const char *target_field_path_pretty_str;
960
961 ctf_field_path_init(&target_field_path);
962
963 /* Get path string */
864cad70
PP
964 switch (fc->type) {
965 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
44c440bc 966 {
5cd6d0e5
PP
967 struct ctf_field_class_sequence *seq_fc = (void *) fc;
968 pathstr = seq_fc->length_ref->str;
44c440bc
PP
969 break;
970 }
864cad70 971 case CTF_FIELD_CLASS_TYPE_VARIANT:
44c440bc 972 {
5cd6d0e5
PP
973 struct ctf_field_class_variant *var_fc = (void *) fc;
974 pathstr = var_fc->tag_ref->str;
44c440bc
PP
975 break;
976 }
977 default:
498e7994 978 bt_common_abort();
44c440bc
PP
979 }
980
981 if (!pathstr) {
f7b785ac 982 BT_COMP_LOGE_STR("Cannot get path string.");
44c440bc
PP
983 ret = -1;
984 goto end;
985 }
986
987 /* Get target field path out of path string */
988 ret = pathstr_to_field_path(pathstr, &target_field_path, ctx);
989 if (ret) {
f7b785ac 990 BT_COMP_LOGE("Cannot get target field path for path string: "
44c440bc
PP
991 "path=\"%s\"", pathstr);
992 goto end;
993 }
994
995 target_field_path_pretty = ctf_field_path_string(
996 &target_field_path);
997 target_field_path_pretty_str =
998 target_field_path_pretty ? target_field_path_pretty->str : NULL;
999
5cd6d0e5
PP
1000 /* Get target field class */
1001 target_fc = field_path_to_field_class(&target_field_path, ctx);
1002 if (!target_fc) {
f7b785ac 1003 BT_COMP_LOGE("Cannot get target field class for path string: "
44c440bc
PP
1004 "path=\"%s\", target-field-path=\"%s\"",
1005 pathstr, target_field_path_pretty_str);
1006 ret = -1;
1007 goto end;
1008 }
1009
1010 ret = validate_target_field_path(&target_field_path,
5cd6d0e5 1011 target_fc, ctx);
44c440bc 1012 if (ret) {
f7b785ac 1013 BT_COMP_LOGE("Invalid target field path for path string: "
44c440bc
PP
1014 "path=\"%s\", target-field-path=\"%s\"",
1015 pathstr, target_field_path_pretty_str);
1016 goto end;
1017 }
1018
5cd6d0e5 1019 /* Set target field path and target field class */
864cad70
PP
1020 switch (fc->type) {
1021 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
44c440bc 1022 {
5cd6d0e5 1023 struct ctf_field_class_sequence *seq_fc = (void *) fc;
44c440bc 1024
5cd6d0e5 1025 ctf_field_path_copy_content(&seq_fc->length_path,
44c440bc 1026 &target_field_path);
5cd6d0e5 1027 seq_fc->length_fc = (void *) target_fc;
44c440bc
PP
1028 break;
1029 }
864cad70 1030 case CTF_FIELD_CLASS_TYPE_VARIANT:
44c440bc 1031 {
5cd6d0e5 1032 struct ctf_field_class_variant *var_fc = (void *) fc;
44c440bc 1033
5cd6d0e5 1034 ctf_field_path_copy_content(&var_fc->tag_path,
44c440bc 1035 &target_field_path);
5cd6d0e5
PP
1036 ctf_field_class_variant_set_tag_field_class(var_fc,
1037 (void *) target_fc);
44c440bc
PP
1038 break;
1039 }
1040 default:
498e7994 1041 bt_common_abort();
44c440bc
PP
1042 }
1043
1044end:
1045 if (target_field_path_pretty) {
1046 g_string_free(target_field_path_pretty, TRUE);
1047 }
1048
1049 ctf_field_path_fini(&target_field_path);
1050 return ret;
1051}
1052
1053/*
5cd6d0e5 1054 * Resolves a field class `fc`.
44c440bc
PP
1055 */
1056static
5cd6d0e5 1057int resolve_field_class(struct ctf_field_class *fc, struct resolve_context *ctx)
44c440bc
PP
1058{
1059 int ret = 0;
1060
5cd6d0e5
PP
1061 if (!fc) {
1062 /* Field class is not available; still valid */
44c440bc
PP
1063 goto end;
1064 }
1065
5cd6d0e5 1066 ctx->cur_fc = fc;
44c440bc 1067
5cd6d0e5 1068 /* Resolve sequence/variant field class */
864cad70
PP
1069 switch (fc->type) {
1070 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
1071 case CTF_FIELD_CLASS_TYPE_VARIANT:
5cd6d0e5 1072 ret = resolve_sequence_or_variant_field_class(fc, ctx);
44c440bc 1073 if (ret) {
f7b785ac 1074 BT_COMP_LOGE("Cannot resolve sequence field class's length or variant field class's tag: "
5cd6d0e5 1075 "ret=%d, fc-addr=%p", ret, fc);
44c440bc
PP
1076 goto end;
1077 }
1078
1079 break;
1080 default:
1081 break;
1082 }
1083
5cd6d0e5 1084 /* Recurse into compound classes */
864cad70
PP
1085 switch (fc->type) {
1086 case CTF_FIELD_CLASS_TYPE_STRUCT:
1087 case CTF_FIELD_CLASS_TYPE_VARIANT:
1088 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
1089 case CTF_FIELD_CLASS_TYPE_ARRAY:
44c440bc
PP
1090 {
1091 uint64_t i;
1092 uint64_t field_count =
5cd6d0e5 1093 ctf_field_class_compound_get_field_class_count(fc);
44c440bc 1094
0746848c 1095 ret = field_class_stack_push(ctx->field_class_stack, fc, ctx);
44c440bc 1096 if (ret) {
f7b785ac 1097 BT_COMP_LOGE("Cannot push field class on context's stack: "
5cd6d0e5 1098 "fc-addr=%p", fc);
44c440bc
PP
1099 goto end;
1100 }
1101
1102 for (i = 0; i < field_count; i++) {
5cd6d0e5
PP
1103 struct ctf_field_class *child_fc =
1104 ctf_field_class_compound_borrow_field_class_by_index(
1105 fc, i);
44c440bc 1106
5cd6d0e5 1107 BT_ASSERT(child_fc);
44c440bc 1108
864cad70
PP
1109 if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY||
1110 fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) {
5cd6d0e5
PP
1111 field_class_stack_peek(
1112 ctx->field_class_stack)->index = -1;
44c440bc 1113 } else {
5cd6d0e5
PP
1114 field_class_stack_peek(
1115 ctx->field_class_stack)->index =
44c440bc
PP
1116 (int64_t) i;
1117 }
1118
f7b785ac 1119 BT_COMP_LOGD("Resolving field class's child field class: "
5cd6d0e5 1120 "parent-fc-addr=%p, child-fc-addr=%p, "
44c440bc 1121 "index=%" PRIu64 ", count=%" PRIu64,
5cd6d0e5
PP
1122 fc, child_fc, i, field_count);
1123 ret = resolve_field_class(child_fc, ctx);
44c440bc
PP
1124 if (ret) {
1125 goto end;
1126 }
1127 }
1128
0746848c 1129 field_class_stack_pop(ctx->field_class_stack, ctx);
44c440bc
PP
1130 break;
1131 }
1132 default:
1133 break;
1134 }
1135
1136end:
1137 return ret;
1138}
1139
1140/*
5cd6d0e5 1141 * Resolves the root field class corresponding to the scope `root_scope`.
44c440bc
PP
1142 */
1143static
83ebb7f1 1144int resolve_root_class(enum ctf_scope root_scope, struct resolve_context *ctx)
44c440bc
PP
1145{
1146 int ret;
1147
5cd6d0e5 1148 BT_ASSERT(field_class_stack_size(ctx->field_class_stack) == 0);
44c440bc 1149 ctx->root_scope = root_scope;
5cd6d0e5 1150 ret = resolve_field_class(borrow_class_from_ctx(ctx, root_scope), ctx);
44c440bc
PP
1151 ctx->root_scope = -1;
1152 return ret;
1153}
1154
1155static
5cd6d0e5 1156int resolve_event_class_field_classes(struct resolve_context *ctx,
44c440bc
PP
1157 struct ctf_event_class *ec)
1158{
1159 int ret = 0;
1160
1161 BT_ASSERT(!ctx->scopes.event_spec_context);
1162 BT_ASSERT(!ctx->scopes.event_payload);
1163
1164 if (ec->is_translated) {
1165 goto end;
1166 }
1167
1168 ctx->ec = ec;
5cd6d0e5 1169 ctx->scopes.event_spec_context = ec->spec_context_fc;
83ebb7f1 1170 ret = resolve_root_class(CTF_SCOPE_EVENT_COMMON_CONTEXT, ctx);
44c440bc 1171 if (ret) {
f7b785ac 1172 BT_COMP_LOGE("Cannot resolve event specific context field class: "
44c440bc
PP
1173 "ret=%d", ret);
1174 goto end;
1175 }
1176
5cd6d0e5 1177 ctx->scopes.event_payload = ec->payload_fc;
83ebb7f1 1178 ret = resolve_root_class(CTF_SCOPE_EVENT_PAYLOAD, ctx);
44c440bc 1179 if (ret) {
f7b785ac 1180 BT_COMP_LOGE("Cannot resolve event payload field class: "
44c440bc
PP
1181 "ret=%d", ret);
1182 goto end;
1183 }
1184
1185end:
1186 ctx->scopes.event_spec_context = NULL;
1187 ctx->scopes.event_payload = NULL;
1188 ctx->ec = NULL;
1189 return ret;
1190}
1191
1192static
5cd6d0e5 1193int resolve_stream_class_field_classes(struct resolve_context *ctx,
44c440bc
PP
1194 struct ctf_stream_class *sc)
1195{
1196 int ret = 0;
1197 uint64_t i;
1198
1199 BT_ASSERT(!ctx->scopes.packet_context);
1200 BT_ASSERT(!ctx->scopes.event_header);
1201 BT_ASSERT(!ctx->scopes.event_common_context);
1202 ctx->sc = sc;
1203
1204 if (!sc->is_translated) {
5cd6d0e5 1205 ctx->scopes.packet_context = sc->packet_context_fc;
83ebb7f1 1206 ret = resolve_root_class(CTF_SCOPE_PACKET_CONTEXT, ctx);
44c440bc 1207 if (ret) {
f7b785ac 1208 BT_COMP_LOGE("Cannot resolve packet context field class: "
44c440bc
PP
1209 "ret=%d", ret);
1210 goto end;
1211 }
1212
5cd6d0e5 1213 ctx->scopes.event_header = sc->event_header_fc;
83ebb7f1 1214 ret = resolve_root_class(CTF_SCOPE_EVENT_HEADER, ctx);
44c440bc 1215 if (ret) {
f7b785ac 1216 BT_COMP_LOGE("Cannot resolve event header field class: "
44c440bc
PP
1217 "ret=%d", ret);
1218 goto end;
1219 }
1220
5cd6d0e5 1221 ctx->scopes.event_common_context = sc->event_common_context_fc;
83ebb7f1 1222 ret = resolve_root_class(CTF_SCOPE_EVENT_SPECIFIC_CONTEXT, ctx);
44c440bc 1223 if (ret) {
f7b785ac 1224 BT_COMP_LOGE("Cannot resolve event common context field class: "
44c440bc
PP
1225 "ret=%d", ret);
1226 goto end;
1227 }
1228 }
1229
5cd6d0e5
PP
1230 ctx->scopes.packet_context = sc->packet_context_fc;
1231 ctx->scopes.event_header = sc->event_header_fc;
1232 ctx->scopes.event_common_context = sc->event_common_context_fc;
44c440bc
PP
1233
1234 for (i = 0; i < sc->event_classes->len; i++) {
1235 struct ctf_event_class *ec = sc->event_classes->pdata[i];
1236
5cd6d0e5 1237 ret = resolve_event_class_field_classes(ctx, ec);
44c440bc 1238 if (ret) {
f7b785ac 1239 BT_COMP_LOGE("Cannot resolve event class's field classes: "
44c440bc
PP
1240 "ec-id=%" PRIu64 ", ec-name=\"%s\"",
1241 ec->id, ec->name->str);
1242 goto end;
1243 }
1244 }
1245
1246end:
1247 ctx->scopes.packet_context = NULL;
1248 ctx->scopes.event_header = NULL;
1249 ctx->scopes.event_common_context = NULL;
1250 ctx->sc = NULL;
1251 return ret;
1252}
1253
1254BT_HIDDEN
0746848c 1255int ctf_trace_class_resolve_field_classes(struct ctf_trace_class *tc,
f7b785ac 1256 struct meta_log_config *log_cfg)
44c440bc
PP
1257{
1258 int ret = 0;
1259 uint64_t i;
0746848c 1260 struct resolve_context local_ctx = {
f7b785ac
PP
1261 .log_level = log_cfg->log_level,
1262 .self_comp = log_cfg->self_comp,
44c440bc
PP
1263 .tc = tc,
1264 .sc = NULL,
1265 .ec = NULL,
1266 .scopes = {
5cd6d0e5 1267 .packet_header = tc->packet_header_fc,
44c440bc
PP
1268 .packet_context = NULL,
1269 .event_header = NULL,
1270 .event_common_context = NULL,
1271 .event_spec_context = NULL,
1272 .event_payload = NULL,
1273 },
83ebb7f1 1274 .root_scope = CTF_SCOPE_PACKET_HEADER,
5cd6d0e5 1275 .cur_fc = NULL,
44c440bc 1276 };
0746848c 1277 struct resolve_context *ctx = &local_ctx;
44c440bc 1278
5cd6d0e5 1279 /* Initialize class stack */
0746848c
PP
1280 ctx->field_class_stack = field_class_stack_create();
1281 if (!ctx->field_class_stack) {
f7b785ac 1282 BT_COMP_LOGE_STR("Cannot create field class stack.");
44c440bc
PP
1283 ret = -1;
1284 goto end;
1285 }
1286
1287 if (!tc->is_translated) {
0746848c
PP
1288 ctx->scopes.packet_header = tc->packet_header_fc;
1289 ret = resolve_root_class(CTF_SCOPE_PACKET_HEADER, ctx);
44c440bc 1290 if (ret) {
f7b785ac 1291 BT_COMP_LOGE("Cannot resolve packet header field class: "
44c440bc
PP
1292 "ret=%d", ret);
1293 goto end;
1294 }
1295 }
1296
0746848c 1297 ctx->scopes.packet_header = tc->packet_header_fc;
44c440bc
PP
1298
1299 for (i = 0; i < tc->stream_classes->len; i++) {
1300 struct ctf_stream_class *sc = tc->stream_classes->pdata[i];
1301
0746848c 1302 ret = resolve_stream_class_field_classes(ctx, sc);
44c440bc 1303 if (ret) {
f7b785ac 1304 BT_COMP_LOGE("Cannot resolve stream class's field classes: "
44c440bc
PP
1305 "sc-id=%" PRIu64, sc->id);
1306 goto end;
1307 }
1308 }
1309
1310end:
0746848c 1311 field_class_stack_destroy(ctx->field_class_stack);
44c440bc
PP
1312 return ret;
1313}
This page took 0.115649 seconds and 4 git commands to generate.